diff --git a/.forgejo/workflows/ci.yaml b/.forgejo/workflows/ci.yaml
index 62803d3919e50f38bbede449a85e32ff422f90e6..963223f4d95e9d2e65cc3106cfeb8d50d4a3a56f 100644
--- a/.forgejo/workflows/ci.yaml
+++ b/.forgejo/workflows/ci.yaml
@@ -93,7 +93,7 @@ jobs:
fetch-depth: 0
- name: Build and Test
run: sh ci/aarch64-macos-debug.sh
- timeout-minutes: 180
+ timeout-minutes: 240
aarch64-macos-release:
runs-on: [self-hosted, aarch64-macos]
steps:
@@ -157,7 +157,7 @@ jobs:
fetch-depth: 0
- name: Build and Test
run: sh ci/riscv64-linux-debug.sh
- timeout-minutes: 720
+ timeout-minutes: 840
riscv64-linux-release:
if: github.event_name != 'pull_request'
runs-on: [self-hosted, riscv64-linux]
diff --git a/.gitattributes b/.gitattributes
index b9cb5340b1a941e1d897dab5240b0f820de611dd..8abf9c1f5e1a4108f0bcb7c44be0d3269007aef3 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -11,6 +11,7 @@ lib/std/compress/lzma/testdata/** binary
lib/std/compress/xz/testdata/** binary
lib/std/crypto/codecs/asn1/der/testdata/** binary
lib/std/tar/testdata/** binary
+lib/std/zip/testdata/** binary
src/Package/Fetch/testdata/** binary
src/Package/Fetch/git/testdata/** binary
diff --git a/.mailmap b/.mailmap
index e91a8c6c1a4482c099a1c06530f25a1e90550e6a..811ce2b2e7cc998e305320396eca63789ad24ad7 100644
--- a/.mailmap
+++ b/.mailmap
@@ -108,3 +108,6 @@ saurabh
saurabh
xEgoist <101279047+xEgoist@users.noreply.github.com>
zenith391 <39484230+zenith391@users.noreply.github.com>
+xtex
+xtex
+xtex
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f40634b7e20ab9b8f8ea1fc9cda5ac5978a93e30..3211a15d4ddeeb9fe0ffa834482aa4e8ad486621 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -342,7 +342,7 @@ set(ZIG_STAGE2_SOURCES
src/Package/Module.zig
src/RangeSet.zig
src/Sema.zig
- src/Sema/bitcast.zig
+ src/Sema/reinterpret.zig
src/Sema/comptime_ptr_access.zig
src/Sema/type_resolution.zig
src/Type.zig
@@ -678,10 +678,8 @@ set(BUILD_ZIG2_ARGS
-femit-bin="${ZIG2_C_SOURCE}"
-target "${ZIG_HOST_TARGET_TRIPLE}"
--dep "build_options"
- --dep "aro"
"-Mroot=src/main.zig"
"-Mbuild_options=${ZIG_CONFIG_ZIG_OUT}"
- "-Maro=lib/compiler/aro/aro.zig"
)
add_custom_command(
diff --git a/bootstrap.c b/bootstrap.c
index bc7ba46ed72a0f2221b89d423f9f63185abc2341..50297f34fdc429cdc75f1f338c4a9cd7d5aea5ab 100644
--- a/bootstrap.c
+++ b/bootstrap.c
@@ -202,10 +202,8 @@ int main(int argc, char **argv) {
"--name", "zig2", "-femit-bin=zig2.c",
"-target", host_triple,
"--dep", "build_options",
- "--dep", "aro",
"-Mroot=src/main.zig",
"-Mbuild_options=config.zig",
- "-Maro=lib/compiler/aro/aro.zig",
NULL,
};
print_and_run(child_argv);
diff --git a/build.zig b/build.zig
index c914d0f161f818a493d933c77dba7884258a4921..ebf163bf5c136a61ecad9120c75c4215cdd8345e 100644
--- a/build.zig
+++ b/build.zig
@@ -70,6 +70,23 @@ pub fn build(b: *std.Build) !void {
b.getInstallStep().dependOn(&install_std_docs.step);
}
+ const update_cpu_features = b.addExecutable(.{
+ .name = "update-cpu-features",
+ .root_module = b.createModule(.{
+ .root_source_file = b.path("tools/update_cpu_features.zig"),
+ .target = b.graph.host,
+ .imports = &.{.{
+ .name = "spirv_spec",
+ .module = b.createModule(.{
+ .root_source_file = b.path("src/codegen/spirv/spec.zig"),
+ .target = b.graph.host,
+ }),
+ }},
+ }),
+ });
+ const run_update_cpu_features = b.addRunArtifact(update_cpu_features);
+ run_update_cpu_features.addPassthruArgs();
+
if (flat) {
b.installFile("LICENSE", "LICENSE");
b.installFile("README.md", "README.md");
@@ -85,6 +102,9 @@ pub fn build(b: *std.Build) !void {
docs_step.dependOn(langref_step);
docs_step.dependOn(std_docs_step);
+ const update_cpu_features_step = b.step("update-cpu-features", "Update CPU Features");
+ update_cpu_features_step.dependOn(&run_update_cpu_features.step);
+
const no_matrix = b.option(bool, "no-matrix", "Limit test matrix to exactly one target configuration") orelse false;
const fuzz_only = b.option(bool, "fuzz-only", "Limit test matrix to one target suitable for fuzzing") orelse false;
const skip_debug = b.option(bool, "skip-debug", "Main test suite skips debug builds") orelse false;
@@ -142,24 +162,9 @@ pub fn build(b: *std.Build) !void {
.install_dir = if (flat) .prefix else .lib,
.install_subdir = if (flat) "lib" else "zig",
.exclude_extensions = &[_][]const u8{
- // exclude files from lib/std/compress/testdata
- ".gz",
- ".z.0",
- ".z.9",
- ".zst.3",
- ".zst.19",
- "rfc1951.txt",
- "rfc1952.txt",
- "rfc8478.txt",
// exclude files from lib/std/compress/flate/testdata
".expect",
- ".expect-noinput",
- ".golden",
".input",
- "compress-e.txt",
- "compress-gettysburg.txt",
- "compress-pi.txt",
- "rfc1951.txt",
// exclude files from lib/std/compress/lzma/testdata
".lzma",
// exclude files from lib/std/compress/xz/testdata
@@ -168,6 +173,8 @@ pub fn build(b: *std.Build) !void {
".tzif",
// exclude files from lib/std/tar/testdata
".tar",
+ // exclude files from lib/std/zip/testdata
+ ".zip",
// others
"README.md",
},
@@ -216,7 +223,6 @@ pub fn build(b: *std.Build) !void {
const use_llvm = b.option(bool, "use-llvm", "Use the llvm backend");
exe.use_llvm = use_llvm;
- exe.use_lld = use_llvm;
if (no_bin) {
b.getInstallStep().dependOn(&exe.step);
@@ -250,7 +256,6 @@ pub fn build(b: *std.Build) !void {
const is_debug = optimize == .Debug;
const enable_debug_extensions = b.option(bool, "debug-extensions", "Enable commands and options useful for debugging the compiler") orelse is_debug;
const enable_logging = b.option(bool, "log", "Enable debug logging with --debug-log") orelse is_debug;
- const enable_link_snapshots = b.option(bool, "link-snapshot", "Whether to enable linker state snapshots") orelse false;
const opt_version_string = b.option([]const u8, "version-string", "Override Zig version string. Default is to find out with git.");
const version_slice = if (opt_version_string) |version| version else v: {
@@ -366,7 +371,6 @@ pub fn build(b: *std.Build) !void {
exe_options.addOption(bool, "enable_debug_extensions", enable_debug_extensions);
exe_options.addOption(bool, "enable_logging", enable_logging);
- exe_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots);
exe_options.addOption(bool, "enable_tracy", tracy != null);
exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack);
exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation);
@@ -623,6 +627,15 @@ pub fn build(b: *std.Build) !void {
.skip_llvm = skip_llvm,
.max_rss = 3_300_000_000,
}));
+ test_step.dependOn(tests.addLinkTests(b, .{
+ .test_target_filters = test_target_filters,
+ .test_filters = test_filters,
+ .optimize_modes = optimize_modes,
+ .skip_non_native = skip_non_native,
+ .skip_windows = skip_windows,
+ .skip_llvm = skip_llvm,
+ .max_rss = 100_000_000,
+ }));
test_step.dependOn(tests.addStackTraceTests(b, test_filters, skip_non_native));
test_step.dependOn(tests.addErrorTraceTests(b, test_filters, optimize_modes, skip_non_native));
test_step.dependOn(tests.addCliTests(b));
@@ -662,6 +675,26 @@ pub fn build(b: *std.Build) !void {
update_mingw_step.dependOn(&b.addFail("The -Dmingw-src=... option is required for this step").step);
}
+ const check_mingw_step = b.step("check-mingw", "Checks for mingw preprocessor regressions");
+ const mingw_preprocessor_mod = b.createModule(.{
+ .root_source_file = b.path("src/libs/mingw/Preprocessor.zig"),
+ .target = target,
+ });
+
+ const check_mingw_exe = b.addExecutable(.{
+ .name = "check_mingw",
+ .root_module = b.createModule(.{
+ .target = b.graph.host,
+ .root_source_file = b.path("tools/check_mingw.zig"),
+ .imports = &.{
+ .{ .name = "preprocessor", .module = mingw_preprocessor_mod },
+ },
+ }),
+ });
+ const check_mingw_run = b.addRunArtifact(check_mingw_exe);
+ check_mingw_run.addDirectoryArg(b.path("lib/libc/mingw"));
+ check_mingw_step.dependOn(&check_mingw_run.step);
+
const test_incremental_step = b.step("test-incremental", "Run the incremental compilation test cases");
try tests.addIncrementalTests(b, test_incremental_step, test_filters);
if (!skip_test_incremental) test_step.dependOn(test_incremental_step);
@@ -698,7 +731,6 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
exe_options.addOption(std.SemanticVersion, "semver", semver);
exe_options.addOption(bool, "enable_debug_extensions", false);
exe_options.addOption(bool, "enable_logging", false);
- exe_options.addOption(bool, "enable_link_snapshots", false);
exe_options.addOption(bool, "enable_tracy", false);
exe_options.addOption(bool, "enable_tracy_callstack", false);
exe_options.addOption(bool, "enable_tracy_allocation", false);
@@ -764,12 +796,6 @@ fn addCompilerMod(b: *std.Build, options: AddCompilerModOptions) *std.Build.Modu
.valgrind = options.valgrind,
});
- const aro_mod = b.createModule(.{
- .root_source_file = b.path("lib/compiler/aro/aro.zig"),
- });
-
- compiler_mod.addImport("aro", aro_mod);
-
return compiler_mod;
}
diff --git a/ci/aarch64-freebsd-debug.sh b/ci/aarch64-freebsd-debug.sh
index a4cdc95d92961889301003d9176cc20a10029d5a..f84a683771b456066ce5c7997b12bae71aac27bb 100755
--- a/ci/aarch64-freebsd-debug.sh
+++ b/ci/aarch64-freebsd-debug.sh
@@ -46,7 +46,7 @@ stage3-debug/bin/zig build test docs \
-Dskip-non-native \
--search-prefix "$PREFIX" \
--zig-lib-dir "$PWD/../lib" \
- --test-timeout 2m
+ --test-timeout 4m
stage3-debug/bin/zig build \
--prefix stage4-debug \
diff --git a/ci/aarch64-freebsd-release.sh b/ci/aarch64-freebsd-release.sh
index 9d99e6e515911dfb7d9756d32ce08a0d1d1201f7..e008d4ee81fb11bdeac967f93965d7bffb754c5d 100755
--- a/ci/aarch64-freebsd-release.sh
+++ b/ci/aarch64-freebsd-release.sh
@@ -46,7 +46,7 @@ stage3-release/bin/zig build test docs \
-Dskip-non-native \
--search-prefix "$PREFIX" \
--zig-lib-dir "$PWD/../lib" \
- --test-timeout 2m
+ --test-timeout 4m
# Ensure that stage3 and stage4 are byte-for-byte identical.
stage3-release/bin/zig build \
diff --git a/ci/x86_64-linux-debug-llvm.sh b/ci/x86_64-linux-debug-llvm.sh
index 8036ca4ab27031c324d3c604d75d75647ef23f3f..3ec4cf0738a24af69c0198e53eefc4268e9e7319 100755
--- a/ci/x86_64-linux-debug-llvm.sh
+++ b/ci/x86_64-linux-debug-llvm.sh
@@ -11,7 +11,7 @@ CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.17.0-dev.203+073889523"
PREFIX="$HOME/deps/$CACHE_BASENAME"
ZIG="$PREFIX/bin/zig"
-export PATH="$HOME/deps/wasmtime-v44.0.0-x86_64-linux:$HOME/deps/qemu-linux-x86_64-11.0.1/bin:$HOME/local/bin:$PATH"
+export PATH="$HOME/deps/wasmtime-v46.0.1-x86_64-linux:$HOME/deps/qemu-linux-x86_64-11.0.1/bin:$HOME/local/bin:$PATH"
# Override the cache directories because they won't actually help other CI runs
# which will be testing alternate versions of zig, and ultimately would just
@@ -51,7 +51,7 @@ stage3-debug/bin/zig build \
stage3-debug/bin/zig build test docs \
--maxrss ${ZSF_MAX_RSS:-0} \
-Dlldb=$HOME/deps/lldb-zig/Debug-7c1090fd46/bin/lldb \
- -Dlibc-test-path=$HOME/deps/libc-test-f2bac77 \
+ -Dlibc-test-path=$HOME/deps/libc-test-b95fe84 \
-fqemu \
--libc-runtimes $HOME/deps/glibc-2.43-musl-1.2.5 \
-fwasmtime \
diff --git a/ci/x86_64-linux-debug.sh b/ci/x86_64-linux-debug.sh
index 68a3468381086b8eae635eefc1f09ef7f190fbb3..040fd17723babb49607d83c130e8791c7aa610c0 100755
--- a/ci/x86_64-linux-debug.sh
+++ b/ci/x86_64-linux-debug.sh
@@ -11,7 +11,7 @@ CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.17.0-dev.203+073889523"
PREFIX="$HOME/deps/$CACHE_BASENAME"
ZIG="$PREFIX/bin/zig"
-export PATH="$HOME/deps/wasmtime-v44.0.0-x86_64-linux:$HOME/deps/qemu-linux-x86_64-11.0.1/bin:$HOME/local/bin:$PATH"
+export PATH="$HOME/deps/wasmtime-v46.0.1-x86_64-linux:$HOME/deps/qemu-linux-x86_64-11.0.1/bin:$HOME/local/bin:$PATH"
# Override the cache directories because they won't actually help other CI runs
# which will be testing alternate versions of zig, and ultimately would just
diff --git a/ci/x86_64-linux-release.sh b/ci/x86_64-linux-release.sh
index 4753a1dd61123f3e7ffb3b63d8023e092b375ae2..a0dd4770f5a91537fbc13bef025eb6a9ae477941 100755
--- a/ci/x86_64-linux-release.sh
+++ b/ci/x86_64-linux-release.sh
@@ -11,7 +11,7 @@ CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.17.0-dev.203+073889523"
PREFIX="$HOME/deps/$CACHE_BASENAME"
ZIG="$PREFIX/bin/zig"
-export PATH="$HOME/deps/wasmtime-v44.0.0-x86_64-linux:$HOME/deps/qemu-linux-x86_64-11.0.1/bin:$HOME/local/bin:$PATH"
+export PATH="$HOME/deps/wasmtime-v46.0.1-x86_64-linux:$HOME/deps/qemu-linux-x86_64-11.0.1/bin:$HOME/local/bin:$PATH"
# Override the cache directories because they won't actually help other CI runs
# which will be testing alternate versions of zig, and ultimately would just
@@ -59,7 +59,7 @@ stage3-release/bin/zig build \
stage3-release/bin/zig build test docs \
--maxrss ${ZSF_MAX_RSS:-0} \
-Dlldb=$HOME/deps/lldb-zig/Release-7c1090fd46/bin/lldb \
- -Dlibc-test-path=$HOME/deps/libc-test-f2bac77 \
+ -Dlibc-test-path=$HOME/deps/libc-test-b95fe84 \
-fqemu \
--libc-runtimes $HOME/deps/glibc-2.43-musl-1.2.5 \
-fwasmtime \
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 9b178fae44ef0634c2714d7f8618b1a208e62000..123ef1e2edad916ca00f45644dcc5f4f0352b009 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -315,7 +315,7 @@
0.9.1 |
0.10.1 |
0.11.0 |
- 0.12.0 |
+ 0.12.1 |
0.13.0 |
0.14.1 |
0.15.2 |
@@ -1955,7 +1955,7 @@ or
TODO talk about C ABI interop
TODO consider suggesting std.MultiArrayList
- {#see_also|@splat|@shuffle|@select|@reduce#}
+ {#see_also|@splat|@shuffle|@select|@reduce|Slicing by Length#}
{#header_open|Relationship with Arrays#}
Vectors and {#link|Arrays#} each have a well-defined bit layout
@@ -2150,6 +2150,24 @@ or
{#see_also|Pointers|for|Arrays#}
+ {#header_open|Slicing by Length#}
+
Even though Zig only has syntax for slicing based on start and end indices, by slicing twice,
+ one can express a slice by length operation.
+ The pattern {#syntax#}[a .. a + b]{#endsyntax#} is always better expressed
+ {#syntax#}[a..][0..b]{#endsyntax#} because:
+
+ Slices are represented in memory as a pointer and length. Despite
+ syntactically appearing as twice the work, it is actually one less
+ subtraction in machine code.
+ If {#syntax#}a{#endsyntax#} is known at runtime and
+ {#syntax#}b{#endsyntax#} is known at {#link|comptime#}, the former
+ results in a slice but the latter results in a single-item
+ {#link|pointer|Pointers#} to an {#link|array|Arrays#}, a generally more
+ safe type because the length is compile-time known.
+
+ {#code|slicing_by_length.zig#}
+ {#header_close#}
+
{#header_open|Sentinel-Terminated Slices#}
The syntax {#syntax#}[:x]T{#endsyntax#} is a slice which has a runtime-known length
@@ -5792,6 +5810,50 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
Returns an {#link|enum#} type with the properties specified by the arguments.
{#header_close#}
+ {#header_open|@SpirvType#}
+ {#syntax#}@SpirvType(comptime options: std.lang.Type.Spirv) type{#endsyntax#}
+
+ Returns a SPIR-V type with the properties specified by the arguments.
+
+
+
+
+
+ Tag
+ SPIR-V Equivalent
+ Description
+
+
+
+
+ .sampler
+ OpTypeSampler
+ An opaque sampler
+
+
+ .image
+ OpTypeImage
+ An opaque image
+
+
+ .sampled_image
+ OpTypeSampledImage
+ An opaque image combined with a sampler
+
+
+ .runtime_array
+ OpTypeRuntimeArray
+
+ An array whose length is determined at runtime.
+ The resulting type supports indexing and exposes a {#syntax#}.len{#endsyntax#} field.
+ It may only appear as the last field of an {#link|extern struct#}.
+
+
+
+
+
+ {#header_close#}
+
{#header_open|@typeInfo#}
{#syntax#}@typeInfo(comptime T: type) std.lang.Type{#endsyntax#}
@@ -8035,7 +8097,7 @@ PrefixTypeOp
/ ArrayTypeStart
SuffixOp
- <- LBRACKET Expr (DOT2 (Expr? (COLON Expr)?)?)? RBRACKET
+ <- LBRACKET Expr (DOT2 Expr? (COLON Expr)?)? RBRACKET
/ DOT IDENTIFIER
/ DOTASTERISK
/ DOTQUESTIONMARK
@@ -8193,7 +8255,7 @@ BUILTINIDENTIFIER <- '@'[A-Za-z_][A-Za-z0-9_]* skip
AMPERSAND <- '&' ![=] skip
AMPERSANDEQUAL <- '&=' skip
-ASTERISK <- '*' ![*%=|] skip
+ASTERISK <- '*' ![%=|] skip
ASTERISKEQUAL <- '*=' skip
ASTERISKPERCENT <- '*%' ![=] skip
ASTERISKPERCENTEQUAL <- '*%=' skip
diff --git a/doc/langref/destructuring_mixed.zig b/doc/langref/destructuring_mixed.zig
index d2bef4388b7a25b20cd464b357683d2195567a6e..d75157c8cc465996edd167001039d872fadf17b8 100644
--- a/doc/langref/destructuring_mixed.zig
+++ b/doc/langref/destructuring_mixed.zig
@@ -15,7 +15,7 @@ pub fn main() void {
// You can use _ to throw away unwanted values.
_, x, _ = tuple;
- print("x = {}", .{x});
+ print("x = {}\n", .{x});
}
// exe=succeed
diff --git a/doc/langref/slicing_by_length.zig b/doc/langref/slicing_by_length.zig
new file mode 100644
index 0000000000000000000000000000000000000000..abb7d9394fd3978f694e9a58796a65926584e087
--- /dev/null
+++ b/doc/langref/slicing_by_length.zig
@@ -0,0 +1,12 @@
+const expectEqual = @import("std").testing.expectEqual;
+
+test "example" {
+ var array = [_]i32{ 1, 2, 3, 4 };
+ var runtime_start: usize = 1;
+ _ = &runtime_start;
+ const length = 2;
+ const array_ptr_len = array[runtime_start..][0..length];
+ try expectEqual(*[length]i32, @TypeOf(array_ptr_len));
+}
+
+// test
diff --git a/doc/langref/test_basic_slices.zig b/doc/langref/test_basic_slices.zig
index 28013148352eba7c5b9e6c0849e778c1ebc0b5ed..d627b7d0a6c1347ccebbf2f773de59630c91d063 100644
--- a/doc/langref/test_basic_slices.zig
+++ b/doc/langref/test_basic_slices.zig
@@ -21,15 +21,6 @@ test "basic slices" {
const array_ptr = array[0..array.len];
try expectEqual(*[array.len]i32, @TypeOf(array_ptr));
- // You can perform a slice-by-length by slicing twice. This allows the compiler
- // to perform some optimisations like recognising a comptime-known length when
- // the start position is only known at runtime.
- var runtime_start: usize = 1;
- _ = &runtime_start;
- const length = 2;
- const array_ptr_len = array[runtime_start..][0..length];
- try expectEqual(*[length]i32, @TypeOf(array_ptr_len));
-
// Using the address-of operator on a slice gives a single-item pointer.
try expectEqual(*i32, @TypeOf(&slice[0]));
// Using the `ptr` field gives a many-item pointer.
diff --git a/doc/langref/test_packed_structs.zig b/doc/langref/test_packed_structs.zig
index 7e46f852a0a5cfda15a4432d5d3f8ebd710f315f..1fe918eefa23500a409d6228fbe789768de21564 100644
--- a/doc/langref/test_packed_structs.zig
+++ b/doc/langref/test_packed_structs.zig
@@ -26,16 +26,8 @@ fn doTheTest() !void {
try expectEqual(0x1, divided.quarter4);
const ordered: [2]u8 = @bitCast(full);
- switch (native_endian) {
- .big => {
- try expectEqual(0x12, ordered[0]);
- try expectEqual(0x34, ordered[1]);
- },
- .little => {
- try expectEqual(0x34, ordered[0]);
- try expectEqual(0x12, ordered[1]);
- },
- }
+ try expectEqual(0x34, ordered[0]);
+ try expectEqual(0x12, ordered[1]);
}
// test
diff --git a/doc/langref/test_pointer_casting.zig b/doc/langref/test_pointer_casting.zig
index 0a3fde2efe6675c1d142f97ccc67ffdce56bee22..f3de7ca48645626635220db9e300d69a48a62cd0 100644
--- a/doc/langref/test_pointer_casting.zig
+++ b/doc/langref/test_pointer_casting.zig
@@ -1,18 +1,22 @@
const std = @import("std");
+const native_endian = @import("builtin").target.cpu.arch.endian();
const expectEqual = std.testing.expectEqual;
test "pointer casting" {
- const bytes align(@alignOf(u32)) = [_]u8{ 0x12, 0x12, 0x12, 0x12 };
+ const bytes: [4]u8 align(@alignOf(u32)) = .{ 0x10, 0x20, 0x30, 0x40 };
const u32_ptr: *const u32 = @ptrCast(&bytes);
- try expectEqual(0x12121212, u32_ptr.*);
- // Even this example is contrived - there are better ways to do the above than
- // pointer casting. For example, using a slice narrowing cast:
- const u32_value = std.mem.bytesAsSlice(u32, bytes[0..])[0];
- try expectEqual(0x12121212, u32_value);
+ // Because we directly reinterpreted bytes of memory, the `u32` value we
+ // load from `u32_ptr` depends on the target endian:
+ switch (native_endian) {
+ .little => try expectEqual(0x40302010, u32_ptr.*),
+ .big => try expectEqual(0x10203040, u32_ptr.*),
+ }
- // And even another way, the most straightforward way to do it:
- try expectEqual(0x12121212, @as(u32, @bitCast(bytes)));
+ // To instead reinterpret the logical bit representation of `bytes` with no
+ // dependency on the target endian, use `@bitCast`, which always places
+ // earlier array elements into less-significant bits:
+ try expectEqual(0x40302010, @as(u32, @bitCast(bytes)));
}
test "pointer child type" {
diff --git a/lib/build-web/fuzz.zig b/lib/build-web/fuzz.zig
index e8753702020c1e41e5326cf6ab54911fa61f0cd0..3f9d692169e04b620e3f9368242b49c72a49ee92 100644
--- a/lib/build-web/fuzz.zig
+++ b/lib/build-web/fuzz.zig
@@ -22,7 +22,7 @@ pub fn sourceIndexMessage(msg_bytes: []u8) error{OutOfMemory}!void {
js.requestSources();
const Header = abi.fuzz.SourceIndexHeader;
- const header: Header = @bitCast(msg_bytes[0..@sizeOf(Header)].*);
+ const header: *align(1) const Header = @ptrCast(msg_bytes[0..@sizeOf(Header)]);
const directories_start = @sizeOf(Header);
const directories_end = directories_start + header.directories_len * @sizeOf(Coverage.String);
@@ -81,7 +81,7 @@ pub fn coverageUpdateMessage(msg_bytes: []u8) error{OutOfMemory}!void {
var entry_points: std.ArrayList(SourceLocationIndex) = .empty;
pub fn entryPointsMessage(msg_bytes: []u8) error{OutOfMemory}!void {
- const header: abi.fuzz.EntryPointHeader = @bitCast(msg_bytes[0..@sizeOf(abi.fuzz.EntryPointHeader)].*);
+ const header: *align(1) const abi.fuzz.EntryPointHeader = @ptrCast(msg_bytes[0..@sizeOf(abi.fuzz.EntryPointHeader)]);
const slis: []align(1) const SourceLocationIndex = @ptrCast(msg_bytes[@sizeOf(abi.fuzz.EntryPointHeader)..]);
assert(slis.len == header.locsLen());
try entry_points.resize(gpa, slis.len);
@@ -285,10 +285,10 @@ fn updateStats() error{OutOfMemory}!void {
, .{
hdr.n_runs,
hdr.unique_runs,
- @as(f64, @floatFromInt(hdr.unique_runs)) / @as(f64, @floatFromInt(hdr.n_runs)),
+ @as(f64, @floatFromInt(hdr.unique_runs)) / @as(f64, @floatFromInt(hdr.n_runs)) * 100,
covered_src_locs,
total_src_locs,
- @as(f64, @floatFromInt(covered_src_locs)) / @as(f64, @floatFromInt(total_src_locs)),
+ @as(f64, @floatFromInt(covered_src_locs)) / @as(f64, @floatFromInt(total_src_locs)) * 100,
avg_speed,
});
defer gpa.free(html);
diff --git a/lib/c/math.zig b/lib/c/math.zig
index fe6832f55b783f243436abcf47169295c8c2c014..b1ff37c04e0f454024a0e5e45590cecb34bb0df1 100644
--- a/lib/c/math.zig
+++ b/lib/c/math.zig
@@ -37,6 +37,7 @@ comptime {
symbol(&hypotf, "hypotf");
symbol(&hypotl, "hypotl");
symbol(&lrintl, "lrintl");
+ symbol(&lroundl, "lroundl");
symbol(&modfl, "modfl");
symbol(&rintl, "rintl");
}
@@ -76,6 +77,8 @@ comptime {
symbol(&log1pf, "log1pf");
symbol(&lrint, "lrint");
symbol(&lrintf, "lrintf");
+ symbol(&lround, "lround");
+ symbol(&lroundf, "lroundf");
symbol(&modf, "modf");
symbol(&nan, "nan");
symbol(&nanf, "nanf");
@@ -278,6 +281,18 @@ fn lrintl(x: c_longdouble) callconv(.c) c_long {
return @trunc(rintl(x));
}
+fn lround(x: f64) callconv(.c) c_long {
+ return @round(x);
+}
+
+fn lroundf(x: f32) callconv(.c) c_long {
+ return @round(x);
+}
+
+fn lroundl(x: c_longdouble) callconv(.c) c_long {
+ return @round(x);
+}
+
fn modfGeneric(comptime T: type, x: T, iptr: *T) T {
if (math.isNegativeInf(x)) {
iptr.* = -math.inf(T);
diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig
index cd3e43d332b2acb21ac76a8828d9426aba9a60d5..c31ba826d00a25807284c75e2209388d5e17b4d7 100644
--- a/lib/compiler/Maker.zig
+++ b/lib/compiler/Maker.zig
@@ -49,7 +49,7 @@ web_server: if (!builtin.single_threaded) ?WebServer else ?noreturn,
/// Allocated into `gpa`.
memory_blocked_steps: std.ArrayList(Configuration.Step.Index),
/// Allocated into `gpa`.
-step_stack: std.AutoArrayHashMapUnmanaged(Configuration.Step.Index, void),
+step_stack: std.array_hash_map.Auto(Configuration.Step.Index, void),
pkg_config: PkgConfig,
error_style: ErrorStyle,
@@ -481,7 +481,7 @@ pub fn main(init: process.Init.Minimal) !void {
// maker process fails or crashes and it's helpful to be able to repeat
// execution of the command line or otherwise inspect the configuration file.
const c = &configuration;
- var top_level_steps: std.StringArrayHashMapUnmanaged(Configuration.Step.Index) = .empty;
+ var top_level_steps: std.array_hash_map.String(Configuration.Step.Index) = .empty;
for (configuration.steps, 0..) |*conf_step, step_index_usize| {
if (conf_step.owner != .root) continue;
const step_index: Configuration.Step.Index = @enumFromInt(step_index_usize);
@@ -1217,7 +1217,7 @@ fn printTreeStep(
step_index: Configuration.Step.Index,
stderr: Io.Terminal,
parent_node: *PrintNode,
- step_stack: *std.AutoArrayHashMapUnmanaged(Configuration.Step.Index, void),
+ step_stack: *std.array_hash_map.Auto(Configuration.Step.Index, void),
) !void {
const writer = stderr.writer;
const first = step_stack.swapRemove(step_index);
@@ -1502,7 +1502,7 @@ fn printChildNodePrefix(stderr: Io.Terminal) !void {
fn constructGraphAndCheckForDependencyLoop(
maker: *Maker,
step_index: Configuration.Step.Index,
- step_stack: *std.AutoArrayHashMapUnmanaged(Configuration.Step.Index, void),
+ step_stack: *std.array_hash_map.Auto(Configuration.Step.Index, void),
rand: std.Random,
) error{ DependencyLoopDetected, OutOfMemory }!void {
const c = &maker.scanned_config.configuration;
diff --git a/lib/compiler/Maker/Fuzz.zig b/lib/compiler/Maker/Fuzz.zig
index 2160befc08df2fb7f896d0f37b522e838cf7d331..44c3ccd2705799819cf189ae28053ddc9dce3583 100644
--- a/lib/compiler/Maker/Fuzz.zig
+++ b/lib/compiler/Maker/Fuzz.zig
@@ -27,7 +27,7 @@ prog_node: std.Progress.Node,
/// Protects `coverage_files`.
coverage_mutex: Io.Mutex,
-coverage_files: std.AutoArrayHashMapUnmanaged(u64, CoverageMap),
+coverage_files: std.array_hash_map.Auto(u64, CoverageMap),
queue_mutex: Io.Mutex,
queue_cond: Io.Condition,
@@ -273,7 +273,7 @@ pub fn serveSourcesTar(fuzz: *Fuzz, req: *std.http.Server.Request) !void {
defer arena_state.deinit();
const arena = arena_state.allocator();
- const DedupTable = std.ArrayHashMapUnmanaged(Build.Cache.Path, void, Build.Cache.Path.TableAdapter, false);
+ const DedupTable = std.array_hash_map.Custom(Build.Cache.Path, void, Build.Cache.Path.TableAdapter, false);
var dedup_table: DedupTable = .empty;
defer dedup_table.deinit(gpa);
diff --git a/lib/compiler/Maker/ScannedConfig.zig b/lib/compiler/Maker/ScannedConfig.zig
index c1e1ff18a90ba79e2331eae052deb4db61e5d164..e52e26279c19eee4b955ea0d6deba574bca47abe 100644
--- a/lib/compiler/Maker/ScannedConfig.zig
+++ b/lib/compiler/Maker/ScannedConfig.zig
@@ -8,7 +8,7 @@ const Serializer = std.zon.Serializer;
const Graph = @import("Graph.zig");
configuration: Configuration,
-top_level_steps: std.StringArrayHashMapUnmanaged(Configuration.Step.Index),
+top_level_steps: std.array_hash_map.String(Configuration.Step.Index),
path: []const u8,
pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {
@@ -324,7 +324,7 @@ pub fn printUsage(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void {
\\ '--webui' when no limit is specified.
\\ --time-report Force full rebuild and provide detailed information on
\\ compilation time of Zig source code (implies '--webui')
- \\ -fincremental Enable incremental compilation
+ \\ -fincremental Enable incremental compilation
\\ -fno-incremental Disable incremental compilation
\\
\\Package Management Options:
diff --git a/lib/compiler/Maker/Step.zig b/lib/compiler/Maker/Step.zig
index 6a6f5c1cf3718c2dce6c957283e528d7b0844ac4..40d82db57f6afbacc468e038f5c1e9f1487f15d9 100644
--- a/lib/compiler/Maker/Step.zig
+++ b/lib/compiler/Maker/Step.zig
@@ -180,7 +180,7 @@ pub const Inputs = struct {
.table = .{},
};
- pub const Table = std.ArrayHashMapUnmanaged(Path, Files, Path.TableAdapter, false);
+ pub const Table = std.array_hash_map.Custom(Path, Files, Path.TableAdapter, false);
/// The special file name "." means any changes inside the directory.
pub const Files = std.ArrayList([]const u8);
diff --git a/lib/compiler/Maker/Step/Compile.zig b/lib/compiler/Maker/Step/Compile.zig
index 99b9374ef98678462ba6441cccb0481ccd8d8b32..69dae4610f8a10f70d25316da2a4bfec6234d63a 100644
--- a/lib/compiler/Maker/Step/Compile.zig
+++ b/lib/compiler/Maker/Step/Compile.zig
@@ -45,12 +45,14 @@ pub fn make(
try lowerZigArgs(arena, compile, compile_index, maker, progress_node, &argv, false);
+ const incremental = conf_comp.flags4.incremental.toBool() orelse graph.incremental == true;
+
const maybe_output_dir = Step.evalZigProcess(
compile_index,
maker,
argv.items,
progress_node,
- (graph.incremental == true) and (maker.watch or maker.web_server != null),
+ incremental and (maker.watch or maker.web_server != null),
) catch |err| switch (err) {
error.NeedCompileErrorCheck => {
try checkCompileErrors(arena, maker, compile_index);
@@ -119,9 +121,9 @@ fn updateGeneratedFile(
/// List of importable modules in a compilation's module graph, including
/// the root module. The root module is guaranteed to be first.
-const ModuleList = std.AutoArrayHashMapUnmanaged(Configuration.Module.Index, Configuration.String);
+const ModuleList = std.array_hash_map.Auto(Configuration.Module.Index, Configuration.String);
/// Keyed on the first key in the module list.
-pub const ModuleGraph = std.ArrayHashMapUnmanaged(ModuleList, void, ModuleListContext, false);
+pub const ModuleGraph = std.array_hash_map.Custom(ModuleList, void, ModuleListContext, false);
const ModuleListContext = struct {
pub fn eql(ctx: @This(), a: ModuleList, b: ModuleList) bool {
@@ -221,8 +223,8 @@ fn lowerZigArgs(
// module, along with any C compiler arguments that need to be passed
// to the compiler for each module individually as reported by
// pkg-config.
- var seen_system_libs: std.AutoArrayHashMapUnmanaged(Configuration.String, []const []const u8) = .empty;
- var frameworks: std.AutoArrayHashMapUnmanaged(Configuration.String, Configuration.Module.Framework.Flags) = .empty;
+ var seen_system_libs: std.array_hash_map.Auto(Configuration.String, []const []const u8) = .empty;
+ var frameworks: std.array_hash_map.Auto(Configuration.String, Configuration.Module.Framework.Flags) = .empty;
var module_graph: ModuleGraph = .empty;
var prev_has_cflags = false;
@@ -767,18 +769,6 @@ fn lowerZigArgs(
try zig_args.append(gpa, if (enabled) "--enable-new-dtags" else "--disable-new-dtags");
}
- if (conf_comp.flags3.kind == .@"test" and conf_comp.exec_cmd_args.slice.len != 0) {
- for (conf_comp.exec_cmd_args.slice) |cmd_arg| {
- try zig_args.ensureUnusedCapacity(gpa, 2);
- if (cmd_arg.slice(conf)) |arg| {
- zig_args.appendAssumeCapacity("--test-cmd");
- zig_args.appendAssumeCapacity(arg);
- } else {
- zig_args.appendAssumeCapacity("--test-cmd-bin");
- }
- }
- }
-
if (graph.sysroot) |sysroot| try zig_args.appendSlice(gpa, &.{ "--sysroot", sysroot });
// -I and -L arguments that appear after the last --mod argument apply to all modules.
@@ -861,7 +851,7 @@ fn lowerZigArgs(
"--error-limit", try allocPrint(arena, "{d}", .{err_limit}),
};
- try addFlag(gpa, zig_args, "incremental", graph.incremental);
+ try addFlag(gpa, zig_args, "incremental", conf_comp.flags4.incremental.toBool() orelse graph.incremental);
try zig_args.append(gpa, "--listen=-");
@@ -984,6 +974,11 @@ fn addFlag(gpa: Allocator, args: *std.ArrayList([]const u8), comptime name: []co
try args.append(gpa, if (cond) "-f" ++ name else "-fno-" ++ name);
}
+fn addArchFlag(gpa: Allocator, args: *std.ArrayList([]const u8), comptime name: []const u8, opt: ?bool) !void {
+ const cond = opt orelse return;
+ try args.append(gpa, if (cond) "-m" ++ name else "-mno-" ++ name);
+}
+
fn checkCompileErrors(arena: Allocator, maker: *Maker, step_index: Configuration.Step.Index) Step.ExtendedMakeError!void {
const step = maker.stepByIndex(step_index);
const conf = &maker.scanned_config.configuration;
@@ -1121,8 +1116,8 @@ fn moduleNeedsCliArg(mod: *const Configuration.Module, conf: *const Configuratio
}
const CliNamedModules = struct {
- modules: std.AutoArrayHashMapUnmanaged(Configuration.Module.Index, void),
- names: std.StringArrayHashMapUnmanaged(void),
+ modules: std.array_hash_map.Auto(Configuration.Module.Index, void),
+ names: std.array_hash_map.String(void),
/// Traverse the whole dependency graph and give every module a unique
/// name, ideally one named after what it's called somewhere in the graph.
@@ -1172,7 +1167,7 @@ pub fn getCompileDependencies(
start: Configuration.Step.Index,
chase_dynamic: bool,
) ![]const Configuration.Step.Index {
- var compiles: std.AutoArrayHashMapUnmanaged(Configuration.Step.Index, void) = .empty;
+ var compiles: std.array_hash_map.Auto(Configuration.Step.Index, void) = .empty;
var compiles_i: usize = 0;
try compiles.putNoClobber(arena, start, {});
@@ -1249,9 +1244,9 @@ fn appendModuleFlags(
try addFlag(gpa, zig_args, "fuzz", m.flags.fuzz.toBool());
try addFlag(gpa, zig_args, "valgrind", m.flags2.valgrind.toBool());
try addFlag(gpa, zig_args, "PIC", m.flags2.pic.toBool());
- try addFlag(gpa, zig_args, "red-zone", m.flags2.red_zone.toBool());
try addFlag(gpa, zig_args, "no-builtin", m.flags2.no_builtin.toBool());
+ try addArchFlag(gpa, zig_args, "red-zone", m.flags2.red_zone.toBool());
{
try zig_args.ensureUnusedCapacity(gpa, 6);
diff --git a/lib/compiler/Maker/Step/Run.zig b/lib/compiler/Maker/Step/Run.zig
index 8b30753ecacc8b25c016286f6b110c13ed6f318c..9ca0b0071ef85554d51f6e2ee328f7bd93d29760 100644
--- a/lib/compiler/Maker/Step/Run.zig
+++ b/lib/compiler/Maker/Step/Run.zig
@@ -65,6 +65,12 @@ pub fn make(
}
}
+ for (conf_run.preopen_names.slice, conf_run.preopen_paths.slice) |name, path| {
+ man.hash.addBytesZ(name.slice(conf));
+ const cwd_path = try maker.resolveLazyPathIndex(arena, path, run_index);
+ man.hash.addBytes(try cwd_path.toString(arena));
+ }
+
man.hash.add(graph.fuzzing);
man.hash.add(conf_run.flags.color);
man.hash.add(conf_run.flags.disable_zig_progress);
@@ -87,8 +93,9 @@ pub fn make(
const suffix = if (arg.suffix.value) |p| p.slice(conf) else "";
const file_path = try maker.resolveLazyPathIndex(arena, arg.path.value.?, run_index);
argv_list.appendAssumeCapacity(try mem.concat(arena, u8, &.{
- prefix, try convertPathArg(arena, run_index, maker, file_path), suffix,
+ prefix, try convertPathArg(arena, run_index, maker, file_path, arg.flags.make_absolute), suffix,
}));
+ man.hash.add(arg.flags.make_absolute);
man.hash.addBytesZ(prefix);
man.hash.addBytesZ(suffix);
_ = try man.addFilePath(file_path, null);
@@ -98,9 +105,10 @@ pub fn make(
const suffix = if (arg.suffix.value) |p| p.slice(conf) else "";
const file_path = try maker.resolveLazyPathIndex(arena, arg.path.value.?, run_index);
const resolved_arg = try mem.concat(arena, u8, &.{
- prefix, try convertPathArg(arena, run_index, maker, file_path), suffix,
+ prefix, try convertPathArg(arena, run_index, maker, file_path, arg.flags.make_absolute), suffix,
});
argv_list.appendAssumeCapacity(resolved_arg);
+ man.hash.add(arg.flags.make_absolute);
man.hash.addBytes(resolved_arg);
},
.file_content => {
@@ -142,9 +150,12 @@ pub fn make(
const file_path = producer_make_comp.installed_path orelse maker.generatedPath(producer.generated_bin.value.?).*;
argv_list.appendAssumeCapacity(try mem.concat(arena, u8, &.{
- prefix, try convertPathArg(arena, run_index, maker, file_path), suffix,
+ prefix, try convertPathArg(arena, run_index, maker, file_path, arg.flags.make_absolute), suffix,
}));
+ man.hash.add(arg.flags.make_absolute);
+ man.hash.addBytesZ(prefix);
+ man.hash.addBytesZ(suffix);
_ = try man.addFilePath(file_path, null);
},
.output_file, .output_directory => {
@@ -152,6 +163,7 @@ pub fn make(
const suffix = if (arg.suffix.value) |p| p.slice(conf) else "";
const basename = arg.basename.value.?.slice(conf);
+ man.hash.add(arg.flags.make_absolute);
man.hash.addBytesZ(prefix);
man.hash.addBytesZ(basename);
man.hash.addBytesZ(suffix);
@@ -181,7 +193,7 @@ pub fn make(
man.hash.add(conf_run.flags.test_runner_mode);
if (conf_run.flags.test_runner_mode) {
- const cache_dir_string = try convertPathArg(arena, run_index, maker, .{ .root_dir = cache_root });
+ const cache_dir_string = try convertPathArg(arena, run_index, maker, .{ .root_dir = cache_root }, false);
try argv_list.ensureUnusedCapacity(gpa, 3);
argv_list.appendAssumeCapacity(try allocPrint(arena, "--cache-dir={s}", .{cache_dir_string}));
@@ -1552,7 +1564,7 @@ pub fn rerunInFuzzMode(
const suffix = if (arg.suffix.value) |p| p.slice(conf) else "";
const file_path = try maker.resolveLazyPathIndex(arena, arg.path.value.?, run_index);
argv_list.appendAssumeCapacity(try mem.concat(arena, u8, &.{
- prefix, try convertPathArg(arena, run_index, maker, file_path), suffix,
+ prefix, try convertPathArg(arena, run_index, maker, file_path, arg.flags.make_absolute), suffix,
}));
},
.path_directory => {
@@ -1560,7 +1572,7 @@ pub fn rerunInFuzzMode(
const suffix = if (arg.suffix.value) |p| p.slice(conf) else "";
const file_path = try maker.resolveLazyPathIndex(arena, arg.path.value.?, run_index);
const resolved_arg = try mem.concat(arena, u8, &.{
- prefix, try convertPathArg(arena, run_index, maker, file_path), suffix,
+ prefix, try convertPathArg(arena, run_index, maker, file_path, arg.flags.make_absolute), suffix,
});
argv_list.appendAssumeCapacity(resolved_arg);
},
@@ -1602,7 +1614,7 @@ pub fn rerunInFuzzMode(
producer_make_comp.installed_path orelse
maker.generatedPath(producer.generated_bin.value.?).*;
argv_list.appendAssumeCapacity(try mem.concat(arena, u8, &.{
- prefix, try convertPathArg(arena, run_index, maker, file_path), suffix,
+ prefix, try convertPathArg(arena, run_index, maker, file_path, arg.flags.make_absolute), suffix,
}));
},
.output_file => unreachable,
@@ -1612,7 +1624,7 @@ pub fn rerunInFuzzMode(
}
if (conf_run.flags.test_runner_mode) {
- const cache_dir_string = try convertPathArg(arena, run_index, maker, .{ .root_dir = cache_root });
+ const cache_dir_string = try convertPathArg(arena, run_index, maker, .{ .root_dir = cache_root }, false);
try argv_list.ensureUnusedCapacity(gpa, 3);
argv_list.appendAssumeCapacity(try allocPrint(arena, "--cache-dir={s}", .{cache_dir_string}));
@@ -1688,7 +1700,7 @@ fn populateGeneratedPathsCreateDirs(
maker.generatedPath(arg.generated.value.?).* = generated_path;
- const arg_output_path = try convertPathArg(arena, run_index, maker, generated_path);
+ const arg_output_path = try convertPathArg(arena, run_index, maker, generated_path, arg.flags.make_absolute);
argv[placeholder.index] = try mem.concat(arena, u8, &.{ prefix, arg_output_path, suffix });
}
}
@@ -1906,9 +1918,15 @@ fn runCommand(
},
.wasmtime => |bin_name| {
if (graph.enable_wasmtime) {
- try interp_argv.ensureUnusedCapacity(arena, 3 + argv.len);
+ try interp_argv.ensureUnusedCapacity(arena, 3 + argv.len + conf_run.preopen_names.slice.len);
interp_argv.appendAssumeCapacity(bin_name);
interp_argv.appendAssumeCapacity("--dir=.");
+ for (conf_run.preopen_names.slice, conf_run.preopen_paths.slice) |name, lazy_path| {
+ const path = try maker.resolveLazyPath(arena, lazy_path.get(conf), run_index);
+ path.root_dir.handle.createDirPath(io, path.subPathOrDot()) catch |e|
+ return step.fail(maker, "failed creating directory {f}: {t}", .{ path, e });
+ interp_argv.appendAssumeCapacity(try allocPrint(arena, "--dir={f}::{s}", .{ path, name.slice(conf) }));
+ }
// Wasmtime doeesn't inherit environment variables from the parent process
// by default. '-S inherit-env' was added in Wasmtime version 20.
interp_argv.appendAssumeCapacity("-Sinherit-env");
@@ -2100,6 +2118,67 @@ fn runCommand(
});
}
}
+ const snapshots: []const ?struct {
+ path: Cache.Path,
+ result: enum { stderr, stdout },
+ } = &.{
+ if (conf_run.expect_stderr_snapshot.value) |path| .{
+ .path = try maker.resolveLazyPathIndex(arena, path, run_index),
+ .result = .stderr,
+ } else null,
+ if (conf_run.expect_stdout_snapshot.value) |path| .{
+ .path = try maker.resolveLazyPathIndex(arena, path, run_index),
+ .result = .stdout,
+ } else null,
+ };
+ for (snapshots) |opt_snapshot| {
+ const snapshot = opt_snapshot orelse continue;
+
+ const file = snapshot.path.root_dir.handle.openFile(io, snapshot.path.sub_path, .{}) catch |err|
+ return step.fail(maker, "unable to open snapshot file {f}: {t}", .{ snapshot.path, err });
+ defer file.close(io);
+
+ var file_reader = file.reader(io, &.{});
+ const snapshot_contents = file_reader.interface.allocRemaining(gpa, .unlimited) catch |err|
+ return step.fail(maker, "unable to read snapshot file {f}: {t}", .{ snapshot.path, err });
+ defer gpa.free(snapshot_contents);
+
+ const result = switch (snapshot.result) {
+ .stderr => generic_result.stderr.?,
+ .stdout => generic_result.stdout.?,
+ };
+ if (std.mem.findDiff(u8, snapshot_contents, result)) |diff_index| {
+ var diff_line_number: usize = 1;
+
+ for (snapshot_contents[0..diff_index]) |value| {
+ if (value == '\n') diff_line_number += 1;
+ }
+
+ return step.fail(maker,
+ \\
+ \\========= snapshot file: =========
+ \\{f}
+ \\========= contained: =============
+ \\{s}
+ \\========= {t} output was: ========
+ \\{s}
+ \\==================================
+ \\first difference on line {d}:
+ \\expected:
+ \\{f}
+ \\found:
+ \\{f}
+ , .{
+ snapshot.path,
+ snapshot_contents,
+ snapshot.result,
+ result,
+ diff_line_number,
+ fmtSnapshotIndicatorLine(snapshot_contents, diff_index),
+ fmtSnapshotIndicatorLine(result, diff_index),
+ });
+ }
+ }
},
else => {
// On failure, report captured stderr like normal standard error output.
@@ -2113,6 +2192,38 @@ fn runCommand(
}
}
+const FmtIndicatorLine = struct {
+ buf: []const u8,
+ index: usize,
+};
+
+fn fmtSnapshotIndicatorLine(buf: []const u8, index: usize) std.fmt.Alt(
+ FmtIndicatorLine,
+ snapshotIndicatorLine,
+) {
+ return .{ .data = .{ .buf = buf, .index = index } };
+}
+
+fn snapshotIndicatorLine(line: FmtIndicatorLine, w: *std.Io.Writer) std.Io.Writer.Error!void {
+ const line_begin_index = if (std.mem.lastIndexOfScalar(u8, line.buf[0..line.index], '\n')) |line_begin|
+ line_begin + 1
+ else
+ 0;
+ const line_end_index = if (std.mem.findScalar(u8, line.buf[line.index..], '\n')) |line_end|
+ (line.index + line_end)
+ else
+ line.buf.len;
+
+ try w.writeAll(line.buf[line_begin_index..line_end_index]);
+ try w.writeByte('\n');
+ try w.splatByteAll(' ', line_end_index - line_begin_index);
+ try w.writeByte('\n');
+ if (line.index >= line.buf.len)
+ try w.writeAll("^ (end of file)")
+ else
+ try w.print("^ ('\\x{x:0>2}')\n", .{line.buf[line.index]});
+}
+
const EvalGenericResult = struct {
term: process.Child.Term,
stdout: ?[]const u8,
@@ -2195,6 +2306,7 @@ fn spawnChildAndCollect(
};
if (conf_run.flags.stdio == .zig_test) {
+ try setColorEnvironmentVariables(&conf_run, environ_map, graph.stderr_mode.?);
const started: Io.Clock.Timestamp = .now(io, .awake);
const result = evalZigTest(run, run_index, maker, progress_node, spawn_options, fuzz_context) catch |err| switch (err) {
error.Canceled => |e| return e,
@@ -2283,18 +2395,29 @@ fn setColorEnvironmentVariables(
}
fn checksContainStdout(conf_run: *const Configuration.Step.Run) bool {
- return conf_run.expect_stdout_exact.value != null or conf_run.expect_stdout_match.slice.len != 0;
+ return conf_run.expect_stdout_exact.value != null or
+ conf_run.expect_stdout_match.slice.len != 0 or
+ conf_run.expect_stdout_snapshot.value != null;
}
fn checksContainStderr(conf_run: *const Configuration.Step.Run) bool {
- return conf_run.expect_stderr_exact.value != null or conf_run.expect_stderr_match.slice.len != 0;
+ return conf_run.expect_stderr_exact.value != null or
+ conf_run.expect_stderr_match.slice.len != 0 or
+ conf_run.expect_stderr_snapshot.value != null;
}
-/// If `path` is cwd-relative, make it relative to the cwd of the child instead.
+/// If `path` is absolute, return it unchanged. If `make_absolute` is true, make it absolute.
+/// Otherwise, make it relative to the cwd of the child.
///
-/// Whenever a path is included in the argv of a child, it should be put through this function first
-/// to make sure the child doesn't see paths relative to a cwd other than its own.
-fn convertPathArg(arena: Allocator, run_index: Configuration.Step.Index, maker: *Maker, path: Path) ![]const u8 {
+/// Whenever a path is included in the argv of a child, it should be put through this function
+/// first.
+fn convertPathArg(
+ arena: Allocator,
+ run_index: Configuration.Step.Index,
+ maker: *Maker,
+ path: Path,
+ make_absolute: bool,
+) ![]const u8 {
const conf = &maker.scanned_config.configuration;
const conf_step = run_index.ptr(conf);
const conf_run = conf_step.extended.get(conf.extra).run;
@@ -2305,6 +2428,11 @@ fn convertPathArg(arena: Allocator, run_index: Configuration.Step.Index, maker:
// Absolute paths don't need changing.
return path_str;
}
+
+ if (make_absolute) {
+ return Dir.path.join(arena, &.{ graph.cache.cwd, path_str });
+ }
+
const child_cwd_rel: []const u8 = rel: {
const child_lazy_cwd = conf_run.cwd.value orelse break :rel path_str;
const child_cwd = try maker.resolveLazyPathIndexAbs(arena, child_lazy_cwd, run_index);
diff --git a/lib/compiler/Maker/Step/TranslateC.zig b/lib/compiler/Maker/Step/TranslateC.zig
index d9bbd6ad4cb2b20deaf3da3f74cc56409a491598..11b30e89b6ec6a677e04df4622bee15a3a4c0bd2 100644
--- a/lib/compiler/Maker/Step/TranslateC.zig
+++ b/lib/compiler/Maker/Step/TranslateC.zig
@@ -66,7 +66,7 @@ pub fn make(
var prev_search_strategy: std.Build.Module.SystemLib.SearchStrategy = .paths_first;
var prev_preferred_link_mode: std.builtin.LinkMode = .dynamic;
- var seen_system_libs: std.AutoArrayHashMapUnmanaged(Configuration.String, []const []const u8) = .empty;
+ var seen_system_libs: std.array_hash_map.Auto(Configuration.String, []const []const u8) = .empty;
for (conf_tc.system_libs.slice) |system_lib_index| {
const system_lib = system_lib_index.get(conf);
diff --git a/lib/compiler/Maker/Watch.zig b/lib/compiler/Maker/Watch.zig
index 603b9c911d696ad94f0ea5d250df07236cec78d6..fb8bca122804d0ba963f3827e29f38d69b40444e 100644
--- a/lib/compiler/Maker/Watch.zig
+++ b/lib/compiler/Maker/Watch.zig
@@ -27,11 +27,11 @@ pub const have_impl = Os != void;
/// interested in noticing changes to.
///
/// Value is generation.
-const DirTable = std.ArrayHashMapUnmanaged(Cache.Path, void, Cache.Path.TableAdapter, false);
+const DirTable = std.array_hash_map.Custom(Cache.Path, void, Cache.Path.TableAdapter, false);
/// Special key of "." means any changes in this directory trigger the steps.
-const ReactionSet = std.StringArrayHashMapUnmanaged(StepSet);
-const StepSet = std.AutoArrayHashMapUnmanaged(Configuration.Step.Index, Generation);
+const ReactionSet = std.array_hash_map.String(StepSet);
+const StepSet = std.array_hash_map.Auto(Configuration.Step.Index, Generation);
const Generation = u8;
@@ -46,10 +46,10 @@ const Os = switch (builtin.os.tag) {
handle_table: HandleTable,
/// fanotify file descriptors are keyed by mount id since marks
/// are limited to a single filesystem.
- poll_fds: std.AutoArrayHashMapUnmanaged(MountId, posix.pollfd),
+ poll_fds: std.array_hash_map.Auto(MountId, posix.pollfd),
const MountId = i32;
- const HandleTable = std.ArrayHashMapUnmanaged(FileHandle, struct { mount_id: MountId, reaction_set: ReactionSet }, FileHandle.Adapter, false);
+ const HandleTable = std.array_hash_map.Custom(FileHandle, struct { mount_id: MountId, reaction_set: ReactionSet }, FileHandle.Adapter, false);
const fan_mask: std.os.linux.fanotify.MarkMask = .{
.CLOSE_WRITE = true,
@@ -314,7 +314,7 @@ const Os = switch (builtin.os.tag) {
const windows = std.os.windows;
/// Keyed differently but indexes correspond 1:1 with `dir_table`.
- handle_table: std.ArrayHashMapUnmanaged(*Directory, void, Directory.TableAdapter, false),
+ handle_table: std.array_hash_map.Custom(*Directory, void, Directory.TableAdapter, false),
ready_dirs: std.DoublyLinkedList,
const FileId = struct {
diff --git a/lib/compiler/aro/aro/Compilation.zig b/lib/compiler/aro/aro/Compilation.zig
index 978bbcffc8ea121ebbcdfd7bda6c9dfcd24e636d..f1dc72ae86c5f15611e77cbdbf69a28339d2b275 100644
--- a/lib/compiler/aro/aro/Compilation.zig
+++ b/lib/compiler/aro/aro/Compilation.zig
@@ -140,7 +140,7 @@ io: Io,
cwd: std.Io.Dir,
diagnostics: *Diagnostics,
-sources: std.StringArrayHashMapUnmanaged(Source) = .empty,
+sources: std.array_hash_map.String(Source) = .empty,
source_aliases: std.ArrayList(Source) = .empty,
/// Allocated into `gpa`, but keys are externally managed.
search_path: std.ArrayList(Include) = .empty,
@@ -159,7 +159,7 @@ builtins: Builtins = .{},
string_interner: StringInterner = .{},
interner: Interner = .{},
type_store: TypeStore = .{},
-pragma_handlers: std.StringArrayHashMapUnmanaged(*Pragma) = .empty,
+pragma_handlers: std.array_hash_map.String(*Pragma) = .empty,
/// If this is not null, the directory containing the specified Source will be searched for includes
/// Used by MS extensions which allow searching for includes relative to the directory of the main source file.
ms_cwd_source_id: ?Source.Id = null,
diff --git a/lib/compiler/aro/aro/DepFile.zig b/lib/compiler/aro/aro/DepFile.zig
index a8f8d7cbaebe944adff461abadd38d3396fbf117..ba8d5c92b58e7d403544cc2a020e5420add2d979 100644
--- a/lib/compiler/aro/aro/DepFile.zig
+++ b/lib/compiler/aro/aro/DepFile.zig
@@ -6,7 +6,7 @@ pub const Format = enum { make, nmake };
const DepFile = @This();
target: []const u8,
-deps: std.StringArrayHashMapUnmanaged(void) = .empty,
+deps: std.array_hash_map.String(void) = .empty,
format: Format,
pub fn deinit(d: *DepFile, gpa: Allocator) void {
diff --git a/lib/compiler/aro/aro/Preprocessor.zig b/lib/compiler/aro/aro/Preprocessor.zig
index 6b52492e7d9a09a1650c7ffdf27cd6ffd09cdad4..2018da7bd023d347fdedccfadf029a25140b4054 100644
--- a/lib/compiler/aro/aro/Preprocessor.zig
+++ b/lib/compiler/aro/aro/Preprocessor.zig
@@ -23,7 +23,7 @@ const Tree = @import("Tree.zig");
const Token = Tree.Token;
const TokenWithExpansionLocs = Tree.TokenWithExpansionLocs;
-const DefineMap = std.StringArrayHashMapUnmanaged(Macro);
+const DefineMap = std.array_hash_map.String(Macro);
const RawTokenList = std.ArrayList(RawToken);
const max_include_depth = 200;
diff --git a/lib/compiler/aro/aro/StringInterner.zig b/lib/compiler/aro/aro/StringInterner.zig
index e22ec23a467f20fcba6184628fc9ddddbb45a626..021bd3f602438587c91d8db63de450ba58098d65 100644
--- a/lib/compiler/aro/aro/StringInterner.zig
+++ b/lib/compiler/aro/aro/StringInterner.zig
@@ -19,7 +19,7 @@ pub const StringId = enum(u32) {
}
};
-table: std.StringArrayHashMapUnmanaged(void) = .empty,
+table: std.array_hash_map.String(void) = .empty,
pub fn deinit(si: *StringInterner, allocator: mem.Allocator) void {
si.table.deinit(allocator);
diff --git a/lib/compiler/aro/backend/Interner.zig b/lib/compiler/aro/backend/Interner.zig
index 027c411d637cf35c2534dd8f8b22128ac927cbbe..6a7fe6fd0772d478ac9ff0d30cbeb7064819cee8 100644
--- a/lib/compiler/aro/backend/Interner.zig
+++ b/lib/compiler/aro/backend/Interner.zig
@@ -8,7 +8,7 @@ const Limb = std.math.big.Limb;
const Interner = @This();
-map: std.AutoArrayHashMapUnmanaged(void, void) = .empty,
+map: std.array_hash_map.Auto(void, void) = .empty,
items: std.MultiArrayList(struct {
tag: Tag,
data: u32,
diff --git a/lib/compiler/aro/backend/Ir.zig b/lib/compiler/aro/backend/Ir.zig
index ae4fa2a6d30fb4910b9409f0f11b6acf1256cdec..f35eca40f7af811593b8a4161ad8d575f44609ce 100644
--- a/lib/compiler/aro/backend/Ir.zig
+++ b/lib/compiler/aro/backend/Ir.zig
@@ -7,7 +7,7 @@ const Object = @import("Object.zig");
const Ir = @This();
interner: *Interner,
-decls: std.StringArrayHashMapUnmanaged(Decl),
+decls: std.array_hash_map.String(Decl),
pub const Decl = struct {
instructions: std.MultiArrayList(Inst),
@@ -26,7 +26,7 @@ pub const Builder = struct {
arena: std.heap.ArenaAllocator,
interner: *Interner,
- decls: std.StringArrayHashMapUnmanaged(Decl) = .empty,
+ decls: std.array_hash_map.String(Decl) = .empty,
instructions: std.MultiArrayList(Ir.Inst) = .empty,
body: std.ArrayList(Ref) = .empty,
alloc_count: u32 = 0,
@@ -181,7 +181,7 @@ pub const Renderer = struct {
ir: *const Ir,
errors: ErrorList = .{},
- pub const ErrorList = std.StringArrayHashMapUnmanaged([]const u8);
+ pub const ErrorList = std.array_hash_map.String([]const u8);
pub const Error = Allocator.Error || error{LowerFail};
@@ -380,7 +380,7 @@ const REF = std.Io.Terminal.Color.bright_blue;
const LITERAL = std.Io.Terminal.Color.bright_green;
const ATTRIBUTE = std.Io.Terminal.Color.bright_yellow;
-const RefMap = std.AutoArrayHashMapUnmanaged(Ref, void);
+const RefMap = std.array_hash_map.Auto(Ref, void);
pub const DumpError = std.Io.Terminal.SetColorError || std.mem.Allocator.Error;
diff --git a/lib/compiler/configurer.zig b/lib/compiler/configurer.zig
index cdd86f87d4ae8f5fb8fb770424b6da7a5e810a5a..f044dc311945d20b330d472553ad5dded0d3138f 100644
--- a/lib/compiler/configurer.zig
+++ b/lib/compiler/configurer.zig
@@ -160,10 +160,10 @@ pub fn main(init: process.Init.Minimal) !void {
const Serialize = struct {
arena: Allocator,
wc: *Configuration.Wip,
- module_map: std.AutoArrayHashMapUnmanaged(*std.Build.Module, Configuration.Module.Index) = .empty,
- package_map: std.AutoArrayHashMapUnmanaged(*std.Build, Configuration.Package.Index) = .empty,
+ module_map: std.array_hash_map.Auto(*std.Build.Module, Configuration.Module.Index) = .empty,
+ package_map: std.array_hash_map.Auto(*std.Build, Configuration.Package.Index) = .empty,
/// Index corresponds to `Configuration.steps` index.
- step_map: std.AutoArrayHashMapUnmanaged(*Step, void) = .empty,
+ step_map: std.array_hash_map.Auto(*Step, void) = .empty,
fn builderToPackage(s: *Serialize, b: *std.Build) !Configuration.Package.Index {
if (b.pkg_hash.len == 0) return .root;
@@ -312,15 +312,16 @@ const Serialize = struct {
.flags = .{
.tag = .artifact,
.prefix = a.prefix.len != 0,
- .suffix = false,
+ .suffix = a.suffix.len != 0,
.basename = false,
.path = false,
.producer = true,
.generated = false,
.dep_file = false,
+ .make_absolute = a.make_absolute,
},
.prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null },
- .suffix = .{ .value = null },
+ .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null },
.basename = .{ .value = null },
.path = .{ .value = null },
.producer = .{ .value = stepIndex(s, &a.artifact.step) },
@@ -330,15 +331,16 @@ const Serialize = struct {
.flags = .{
.tag = .path_file,
.prefix = a.prefix.len != 0,
- .suffix = false,
+ .suffix = a.suffix.len != 0,
.basename = false,
.path = true,
.producer = false,
.generated = false,
.dep_file = false,
+ .make_absolute = a.make_absolute,
},
.prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null },
- .suffix = .{ .value = null },
+ .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null },
.basename = .{ .value = null },
.path = .{ .value = try addLazyPath(s, a.lazy_path) },
.producer = .{ .value = null },
@@ -354,6 +356,7 @@ const Serialize = struct {
.producer = false,
.generated = false,
.dep_file = false,
+ .make_absolute = a.make_absolute,
},
.prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null },
.suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null },
@@ -366,15 +369,16 @@ const Serialize = struct {
.flags = .{
.tag = .file_content,
.prefix = a.prefix.len != 0,
- .suffix = false,
+ .suffix = a.suffix.len != 0,
.basename = false,
.path = true,
.producer = false,
.generated = false,
.dep_file = false,
+ .make_absolute = false,
},
.prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null },
- .suffix = .{ .value = null },
+ .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null },
.basename = .{ .value = null },
.path = .{ .value = try addLazyPath(s, a.lazy_path) },
.producer = .{ .value = null },
@@ -390,6 +394,7 @@ const Serialize = struct {
.producer = false,
.generated = false,
.dep_file = false,
+ .make_absolute = false,
},
.prefix = .{ .value = try wc.addString(a) },
.suffix = .{ .value = null },
@@ -402,15 +407,16 @@ const Serialize = struct {
.flags = .{
.tag = .output_file,
.prefix = a.prefix.len != 0,
- .suffix = false,
+ .suffix = a.suffix.len != 0,
.basename = a.basename.len != 0,
.path = false,
.producer = false,
.generated = true,
.dep_file = tag == .output_file_dep,
+ .make_absolute = a.make_absolute,
},
.prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null },
- .suffix = .{ .value = null },
+ .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null },
.basename = .{ .value = if (a.basename.len != 0) try wc.addString(a.basename) else null },
.path = .{ .value = null },
.producer = .{ .value = null },
@@ -420,15 +426,16 @@ const Serialize = struct {
.flags = .{
.tag = .output_directory,
.prefix = a.prefix.len != 0,
- .suffix = false,
+ .suffix = a.suffix.len != 0,
.basename = a.basename.len != 0,
.path = false,
.producer = false,
.generated = true,
.dep_file = false,
+ .make_absolute = a.make_absolute,
},
.prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null },
- .suffix = .{ .value = null },
+ .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null },
.basename = .{ .value = if (a.basename.len != 0) try wc.addString(a.basename) else null },
.path = .{ .value = null },
.producer = .{ .value = null },
@@ -444,6 +451,7 @@ const Serialize = struct {
.producer = false,
.generated = false,
.dep_file = false,
+ .make_absolute = false,
},
.prefix = .{ .value = null },
.suffix = .{ .value = null },
@@ -668,7 +676,6 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
},
.compile => e: {
const c: *Step.Compile = @fieldParentPtr("step", step);
- const exec_cmd_args: []const ?[]const u8 = c.exec_cmd_args orelse &.{};
const installed_headers: []u32 = try arena.alloc(u32, c.installed_headers.items.len);
for (installed_headers, c.installed_headers.items) |*dst, src| switch (src) {
.file => |file| {
@@ -695,7 +702,6 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
break :e try wc.addExtraErased(Configuration.Step.Compile, .{
.flags = .{
.filters_len = c.filters.len != 0,
- .exec_cmd_args_len = exec_cmd_args.len != 0,
.installed_headers_len = installed_headers.len != 0,
.force_undefined_symbols_len = c.force_undefined_symbols.entries.len != 0,
@@ -797,6 +803,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
.generated_llvm_bc = c.generated_llvm_bc != .none,
.generated_llvm_ir = c.generated_llvm_ir != .none,
.generated_h = c.generated_h != .none,
+ .incremental = .init(c.incremental),
},
.root_module = try s.addModule(c.root_module),
.root_name = try wc.addString(c.name),
@@ -828,7 +835,6 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
.none, .fast, .uuid, .sha1, .md5 => null,
} else null },
.filters = .{ .slice = try s.initStringList(c.filters) },
- .exec_cmd_args = .{ .slice = try s.initOptionalStringList(exec_cmd_args) },
.installed_headers = .initErased(installed_headers),
.force_undefined_symbols = .{ .slice = try s.initStringList(c.force_undefined_symbols.keys()) },
.expect_errors = .{ .u = if (c.expect_errors) |x| switch (x) {
@@ -1005,6 +1011,8 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
status: Configuration.Step.Run.ExpectTermStatus,
value: u32,
} = null;
+ var expect_stderr_snapshot: ?Configuration.LazyPath.Index = null;
+ var expect_stdout_snapshot: ?Configuration.LazyPath.Index = null;
switch (run.stdio) {
.check => |checks| for (checks.items) |check| switch (check) {
.expect_stderr_exact => |bytes| expect_stderr_exact = try wc.addBytes(bytes),
@@ -1021,6 +1029,8 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
.stopped => |x| .{ .status = .stopped, .value = @intFromEnum(x) },
.unknown => |x| .{ .status = .unknown, .value = x },
},
+ .expect_stderr_snapshot => |path| expect_stderr_snapshot = try s.addLazyPath(path),
+ .expect_stdout_snapshot => |path| expect_stdout_snapshot = try s.addLazyPath(path),
},
else => {},
}
@@ -1060,17 +1070,21 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
.expect_stdout_match = expect_stdout_match.items.len != 0,
.expect_term = expect_term != null,
.expect_term_status = if (expect_term) |t| t.status else .exited,
+ .expect_stderr_snapshot = expect_stderr_snapshot != null,
+ .expect_stdout_snapshot = expect_stdout_snapshot != null,
},
.file_inputs = .{ .slice = try s.initLazyPathList(run.file_inputs.items) },
.args = .{ .slice = try s.initArgsList(run.argv.items) },
.cwd = .{ .value = try s.addOptionalLazyPath(run.cwd) },
+ .preopen_names = .{ .slice = try s.initStringList(run.preopens.keys()) },
+ .preopen_paths = .{ .slice = try s.initLazyPathList(run.preopens.values()) },
.captured_stdout = .{ .value = if (run.captured_stdout) |cs| .{
- .basename = try wc.addString(cs.output.basename),
- .generated_file = cs.output.generated_file,
+ .basename = try wc.addString(cs.basename),
+ .generated_file = cs.generated_file,
} else null },
.captured_stderr = .{ .value = if (run.captured_stderr) |cs| .{
- .basename = try wc.addString(cs.output.basename),
- .generated_file = cs.output.generated_file,
+ .basename = try wc.addString(cs.basename),
+ .generated_file = cs.generated_file,
} else null },
.environ_map = .{ .value = try s.addEnvironMap(run.environ_map) },
.expect_term_value = .{ .value = if (expect_term) |t| t.value else null },
@@ -1080,6 +1094,8 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
.expect_stdout_exact = .{ .value = if (expect_stdout_exact) |bytes| bytes else null },
.expect_stderr_match = .{ .slice = expect_stderr_match.items },
.expect_stdout_match = .{ .slice = expect_stdout_match.items },
+ .expect_stderr_snapshot = .{ .value = expect_stderr_snapshot orelse null },
+ .expect_stdout_snapshot = .{ .value = expect_stdout_snapshot orelse null },
.stdin = .{ .u = switch (run.stdin) {
.none => .none,
.bytes => |bytes| .{ .bytes = try wc.addBytes(bytes) },
diff --git a/lib/compiler/objdump.zig b/lib/compiler/objdump.zig
index d2af9c09c6e6e344794d0aaaa26f45efc2ce5d4c..c3f6f5e8a7a444862b1396427fcf589805725942 100644
--- a/lib/compiler/objdump.zig
+++ b/lib/compiler/objdump.zig
@@ -4,19 +4,149 @@ const fatal = std.process.fatal;
const mem = std.mem;
const assert = std.debug.assert;
+const builtin = @import("builtin");
+const native_endian = builtin.cpu.arch.endian();
+
var stdout_buffer: [4000]u8 = undefined;
+const Options = struct {
+ exports: bool,
+ exports_sort: bool,
+ file_headers: bool,
+ imports: bool,
+ input_path: []const u8,
+ member_filters: []const []const u8 = &.{},
+ member_headers: bool,
+ elements: std.enums.EnumArray(Element, bool),
+ redact: std.enums.EnumArray(FieldKind, bool),
+ relocs: bool,
+ section_filters: []const []const u8 = &.{},
+ section_headers: bool,
+ symbol_filters: []const []const u8 = &.{},
+ strings: bool,
+ symbols: bool,
+ tls: bool,
+
+ // Coff-specific
+ linker_member: ?std.coff.ArchiveMemberHeader.Kind,
+};
+
+const FieldKind = enum {
+ va,
+ rva,
+ ord,
+ size,
+};
+
+const Element = enum {
+ @"file-type",
+ @"header-name",
+ @"member-path",
+ newlines,
+ @"table-header",
+};
+
pub fn main(init: std.process.Init) !void {
const io = init.io;
const args = try init.minimal.args.toSlice(init.arena.allocator());
+ const arena = init.arena.allocator();
- var opt_input_path: ?[]const u8 = null;
var i: usize = 1;
+
+ var opt_exports: ?bool = null;
+ var opt_exports_sort: ?bool = null;
+ var opt_file_headers: ?bool = null;
+ var opt_imports: ?bool = null;
+ var opt_input_path: ?[]const u8 = null;
+ var opt_linker_member: ?std.coff.ArchiveMemberHeader.Kind = null;
+ var opt_member_headers: ?bool = null;
+ var any_elements = false;
+ var elements: ?@FieldType(Options, "elements") = null;
+ var redact: @FieldType(Options, "redact") = .initFill(false);
+ var opt_relocs: ?bool = null;
+ var opt_section_headers: ?bool = null;
+ var opt_strings: ?bool = null;
+ var opt_symbols: ?bool = null;
+ var opt_tls: ?bool = null;
+ var section_filters: std.ArrayList([]const u8) = .empty;
+ var symbol_filters: std.ArrayList([]const u8) = .empty;
+ var member_filters: std.ArrayList([]const u8) = .empty;
while (i < args.len) : (i += 1) {
const arg = args[i];
if (mem.startsWith(u8, arg, "-")) {
if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
return Io.File.stdout().writeStreamingAll(io, usage);
+ } else if (mem.eql(u8, arg, "--all-headers")) {
+ opt_file_headers = true;
+ opt_linker_member = .second_linker;
+ opt_member_headers = true;
+ opt_section_headers = true;
+ opt_symbols = true;
+ opt_relocs = true;
+ } else if (mem.startsWith(u8, arg, "--exports")) {
+ opt_exports = true;
+ opt_linker_member = .second_linker;
+ if (mem.eql(u8, arg["--exports".len..], "=sort"))
+ opt_exports_sort = true;
+ } else if (mem.eql(u8, arg, "--file-headers")) {
+ opt_file_headers = true;
+ } else if (mem.eql(u8, arg, "--imports")) {
+ opt_imports = true;
+ } else if (mem.startsWith(u8, arg, "--linker-member")) {
+ if (mem.eql(u8, arg["--linker-member".len..], "=1"))
+ opt_linker_member = .first_linker
+ else if (mem.eql(u8, arg["--linker-member".len..], "=longnames"))
+ opt_linker_member = .longnames
+ else
+ opt_linker_member = .second_linker;
+ } else if (mem.eql(u8, arg, "--member-headers")) {
+ opt_member_headers = true;
+ } else if (mem.startsWith(u8, arg, "--elements=")) {
+ any_elements = true;
+ var split = std.mem.splitScalar(u8, arg["--elements=".len..], ',');
+ while (split.next()) |element| {
+ const kind, const add = if (element.len > 0 and element[0] == '-')
+ .{ element[1..], false }
+ else
+ .{ element, true };
+
+ if (elements == null) elements = .initFill(false);
+ if (std.meta.stringToEnum(Element, kind)) |format_kind| {
+ elements.?.set(format_kind, add);
+ } else if (std.mem.eql(u8, kind, "all")) {
+ elements.? = .initFill(add);
+ } else {
+ fatal("unrecognized element: '{s}'", .{kind});
+ }
+ }
+ } else if (mem.startsWith(u8, arg, "--only-member=")) {
+ (try member_filters.addOne(arena)).* = try arena.dupe(u8, arg["--only-member=".len..]);
+ } else if (mem.startsWith(u8, arg, "--only-section=")) {
+ (try section_filters.addOne(arena)).* = try arena.dupe(u8, arg["--only-section=".len..]);
+ } else if (mem.startsWith(u8, arg, "--only-symbol=")) {
+ (try symbol_filters.addOne(arena)).* = try arena.dupe(u8, arg["--only-symbol=".len..]);
+ } else if (mem.startsWith(u8, arg, "--redact=")) {
+ const kind = arg["--redact=".len..];
+ if (std.meta.stringToEnum(FieldKind, kind)) |field_kind| {
+ redact.set(field_kind, true);
+ } else if (std.mem.eql(u8, kind, "all")) {
+ redact = .initFill(true);
+ } else {
+ fatal("unrecognized redaction kind: {s}", .{kind});
+ }
+ } else if (mem.eql(u8, arg, "--relocs")) {
+ opt_relocs = true;
+ } else if (mem.eql(u8, arg, "--section-headers")) {
+ opt_section_headers = true;
+ } else if (mem.eql(u8, arg, "-s") or mem.eql(u8, arg, "--snapshot")) {
+ elements = .initFill(false);
+ redact = .initFill(true);
+ } else if (mem.eql(u8, arg, "--strings")) {
+ opt_strings = true;
+ } else if (mem.eql(u8, arg, "--symbols")) {
+ opt_symbols = true;
+ } else if (mem.eql(u8, arg, "--tls")) {
+ opt_tls = true;
} else {
fatal("unrecognized argument: {s}", .{arg});
}
@@ -27,42 +157,134 @@ pub fn main(init: std.process.Init) !void {
}
}
- const input_path = opt_input_path orelse fatal("missing input file path positional argument", .{});
+ const opts: Options = .{
+ .input_path = opt_input_path orelse fatal("missing input file path positional argument", .{}),
+ .exports = opt_exports orelse false,
+ .exports_sort = opt_exports_sort orelse false,
+ .file_headers = opt_file_headers orelse false,
+ .imports = opt_imports orelse false,
+ .linker_member = opt_linker_member,
+ .member_filters = member_filters.items,
+ .member_headers = opt_member_headers orelse false,
+ .elements = elements orelse .initFill(true),
+ .redact = redact,
+ .relocs = opt_relocs orelse false,
+ .section_filters = section_filters.items,
+ .section_headers = opt_section_headers orelse false,
+ .strings = opt_strings orelse false,
+ .symbol_filters = symbol_filters.items,
+ .symbols = opt_symbols orelse false,
+ .tls = opt_tls orelse false,
+ };
- var file = std.Io.Dir.cwd().openFile(io, input_path, .{}) catch |err|
- fatal("failed to open {s}: {t}", .{ input_path, err });
+ var file = std.Io.Dir.cwd().openFile(io, opts.input_path, .{}) catch |err|
+ fatal("failed to open {s}: {t}", .{ opts.input_path, err });
defer file.close(io);
- var buffer: [4000]u8 = undefined;
+ var buffer: [4096]u8 = undefined;
var file_reader = file.reader(io, &buffer);
var stdout_writer = std.Io.File.stdout().writerStreaming(io, &stdout_buffer);
- dump(&file_reader.interface, &stdout_writer.interface) catch |err| switch (err) {
+
+ const ctx: DumpContext = .{
+ .gpa = init.gpa,
+ .opts = &opts,
+ .fr = &file_reader,
+ .w = &stdout_writer.interface,
+ };
+
+ dump(&ctx) catch |err| switch (err) {
error.ReadFailed => return file_reader.err.?,
error.WriteFailed => return stdout_writer.err.?,
- error.UnknownFile => fatal("unrecognized file: {s}", .{input_path}),
+ error.UnknownFile => fatal("unrecognized file: {s}", .{opts.input_path}),
+ error.ParseFailure => {},
else => |e| return e,
};
try stdout_writer.flush();
}
-fn dump(r: *Io.Reader, w: *Io.Writer) !void {
+fn dump(d: *const DumpContext) !void {
+ const r = &d.fr.interface;
try r.fill(4);
elf: {
if (!mem.eql(u8, r.buffered()[0..4], std.elf.MAGIC)) break :elf;
- return elf.dump(r, w);
+ return elf.dump(r, d.w);
}
macho: {
if (mem.readInt(u32, r.buffered()[0..4], .little) != std.macho.MH_MAGIC_64) break :macho;
- return macho.dump(r, w);
+ return macho.dump(r, d.w);
}
wasm: {
comptime assert(std.wasm.magic.len == 4);
if (!mem.eql(u8, r.buffered()[0..4], &std.wasm.magic)) break :wasm;
- return wasm.dump(r, w);
+ return wasm.dump(r, d.w);
+ }
+ coff: {
+ const ext = std.fs.path.extension(d.opts.input_path);
+ const basename = std.fs.path.basename(d.opts.input_path);
+ if (std.mem.eql(u8, ext, ".exe") or std.mem.eql(u8, ext, ".dll")) {
+ if (!mem.eql(u8, r.buffered()[0..2], "MZ")) break :coff;
+ try r.discardAll(std.coff.pe_pointer_offset);
+ const sig_offset = try r.takeInt(u32, .little);
+ try d.fr.seekTo(sig_offset);
+ const sig = try r.take(4);
+
+ if (!std.mem.eql(u8, sig, std.coff.pe_signature)) {
+ try d.w.print("invalid PE signature: {x}", .{sig});
+ return error.ParseFailure;
+ }
+
+ if (d.element(.@"file-type")) {
+ try d.w.print("{s}: PE/COFF image\n\n", .{basename});
+ if (d.element(.newlines)) try d.w.writeByte('\n');
+ }
+
+ return coff.dumpObject(d, true, basename);
+ } else if (std.mem.eql(u8, ext, ".lib")) {
+ r.fill(std.coff.archive_signature.len) catch break :coff;
+ if (!mem.eql(u8, r.buffered()[0..std.coff.archive_signature.len], std.coff.archive_signature)) break :coff;
+ if (d.element(.@"file-type")) {
+ try d.w.print("{s}: COFF archive\n", .{basename});
+ if (d.element(.newlines)) try d.w.writeByte('\n');
+ }
+
+ return coff.dumpArchive(d);
+ } else if (std.mem.eql(u8, ext, ".obj")) {
+ if (d.element(.@"file-type")) {
+ try d.w.print("{s}: COFF object\n", .{basename});
+ if (d.element(.newlines)) try d.w.writeByte('\n');
+ }
+
+ return coff.dumpObject(d, false, basename);
+ }
}
return error.UnknownFile;
}
+const DumpContext = struct {
+ gpa: std.mem.Allocator,
+ opts: *const Options,
+ fr: *Io.File.Reader,
+ w: *Io.Writer,
+
+ fn element(self: *const DumpContext, e: Element) bool {
+ return self.opts.elements.get(e);
+ }
+
+ fn redacted(self: *const DumpContext, opt_kind: ?FieldKind) bool {
+ const kind = opt_kind orelse return false;
+ return self.opts.redact.get(kind);
+ }
+
+ fn failParse(
+ ctx: *const DumpContext,
+ comptime fmt: []const u8,
+ args: anytype,
+ ) noreturn {
+ std.log.err("error parsing '{s}'", .{std.fs.path.basename(ctx.opts.input_path)});
+ fatal(fmt, args);
+ }
+};
+
const elf = struct {
fn dump(r: *Io.Reader, w: *Io.Writer) !void {
_ = r;
@@ -84,10 +306,1478 @@ const wasm = struct {
}
};
+const coff = struct {
+ const DIRECTORY_ENTRY = std.coff.IMAGE.DIRECTORY_ENTRY;
+
+ const Section = struct {
+ header: std.coff.SectionHeader,
+ name: []const u8,
+
+ fn rvaFileOffset(section: *const Section, rva: u32) !u32 {
+ if (rva < section.header.virtual_address or
+ rva >= section.header.virtual_address + section.header.size_of_raw_data)
+ return error.OutOfBounds;
+
+ return section.header.pointer_to_raw_data + (rva - section.header.virtual_address);
+ }
+ };
+
+ const ArchiveHeader = struct {
+ name: []const u8,
+ date: u40,
+ user_id: u20,
+ group_id: u20,
+ file_mode: u24,
+ size: u34,
+
+ pub fn fromRaw(d: *const DumpContext, raw_header: *const std.coff.ArchiveMemberHeader, opt_longnames: ?[]const u8) @This() {
+ const name = raw_header.parseName(opt_longnames) catch |err| switch (err) {
+ error.BadName => d.failParse("malformed member name: '{s}'", .{&raw_header.name}),
+ error.NoLongNames => d.failParse("member uses a long name, but there was no longnames member", .{}),
+ };
+
+ return .{
+ .name = name,
+ .date = raw_header.parseDate() catch |err|
+ d.failParse("unable to parse date '{s}' in member '{s}': {t}", .{ raw_header.date, name, err }),
+ .user_id = raw_header.parseUserId() catch |err|
+ d.failParse("unable to parse user_id '{s}' in member '{s}': {t}", .{ raw_header.user_id, name, err }),
+ .group_id = raw_header.parseGroupId() catch |err|
+ d.failParse("unable to parse group_id '{s}' in member '{s}': {t}", .{ raw_header.group_id, name, err }),
+ .file_mode = raw_header.parseFileMode() catch |err|
+ d.failParse("unable to parse file_mode '{s}' in member '{s}': {t}", .{ raw_header.file_mode, name, err }),
+ .size = raw_header.parseSize() catch |err|
+ d.failParse("unable to parse size '{s}' in member '{s}': {t}", .{ raw_header.size, name, err }),
+ };
+ }
+ };
+
+ fn dumpArchive(d: *const DumpContext) !void {
+ const gpa = d.gpa;
+ const fr = d.fr;
+ const w = d.w;
+
+ const r = &fr.interface;
+ r.toss(std.coff.archive_signature.len);
+
+ const Member = struct {
+ offset: u32,
+ order: ?u32,
+ };
+
+ var members: std.ArrayList(Member) = .empty;
+ defer members.deinit(gpa);
+ var symbol_member_indices: std.ArrayList(u32) = .empty;
+ defer symbol_member_indices.deinit(gpa);
+
+ var opt_expected_kind: ?std.coff.ArchiveMemberHeader.Kind = .first_linker;
+ var opt_longnames: ?[]const u8 = null;
+ defer if (opt_longnames) |l| gpa.free(l);
+
+ var pos = fr.logicalPos();
+ const size = try fr.getSize();
+ while (pos < size) : (pos = fr.logicalPos()) {
+ if ((pos & 1) != 0) try r.discardAll(1);
+ const raw_header = try r.takeStruct(std.coff.ArchiveMemberHeader, .little);
+ const header: ArchiveHeader = .fromRaw(d, &raw_header, opt_longnames);
+
+ if (!std.mem.eql(u8, &raw_header.end_of_header, std.coff.archive_end_of_header))
+ return d.failParse("malformed end-of-header field in member '{s}': {x}", .{ header.name, raw_header.end_of_header });
+
+ const dump_header =
+ (d.opts.member_headers and filterMatches(d.opts.member_filters, header.name)) or
+ (d.opts.linker_member == opt_expected_kind);
+
+ if (dump_header)
+ try dumpArchiveHeader(d, &header, @intCast(pos));
+
+ const member_end = fr.logicalPos() + header.size;
+ if (member_end > size)
+ return d.failParse("out-of-bounds length 0x{x} in member '{s}'", .{ header.size, header.name });
+
+ if (opt_expected_kind) |expected_kind| switch (expected_kind) {
+ .first_linker => {
+ if (!std.mem.eql(u8, header.name, "/"))
+ return d.failParse("expected first linker member, found '{s}'", .{header.name});
+
+ const num_symbols = try r.takeInt(u32, .big);
+ if (dump_header)
+ try w.print(
+ \\{t: >16} type
+ \\ | {d} symbols
+ \\
+ , .{ expected_kind, num_symbols });
+
+ if (d.opts.linker_member == .first_linker) {
+ if (d.element(.@"table-header"))
+ try w.writeAll(
+ \\
+ \\Archive symbols:
+ \\& Member Symbol
+ \\
+ );
+
+ const offsets = try r.readAlloc(gpa, num_symbols * 4);
+ defer gpa.free(offsets);
+
+ for (0..num_symbols) |symbol_i| {
+ const symbol = r.takeDelimiter(0) catch |err|
+ return d.failParse("unable to read first linker member string table: {t}", .{err});
+
+ if (!filterMatches(d.opts.symbol_filters, symbol.?))
+ continue;
+
+ const offset = std.mem.readInt(u32, offsets[symbol_i * 4 ..][0..4], .big);
+ try w.print("{f} {s}\n", .{
+ fmtIntField(d, offset, .{ .kind = .va }),
+ symbol.?,
+ });
+ }
+ }
+ if (dump_header and d.element(.newlines)) try w.writeByte('\n');
+
+ try fr.seekTo(member_end);
+ opt_expected_kind = .second_linker;
+ continue;
+ },
+ .second_linker => {
+ if (!std.mem.eql(u8, header.name, "/"))
+ return d.failParse("expected second linker member, found '{s}'", .{header.name});
+
+ const num_members = try r.takeInt(u32, .little);
+ pos = fr.logicalPos();
+ if (pos + num_members * @sizeOf(u32) > member_end)
+ return d.failParse("invalid member count 0x{x} in second linker member", .{num_members});
+
+ try members.ensureTotalCapacity(gpa, num_members);
+ for (0..num_members) |_|
+ members.addOneAssumeCapacity().* = .{
+ .offset = try r.takeInt(u32, .little),
+ .order = null,
+ };
+
+ const num_symbols = try r.takeInt(u32, .little);
+ pos = fr.logicalPos();
+ if (pos + num_symbols * @sizeOf(u16) > member_end)
+ return d.failParse("invalid symbol count 0x{x} in second linker member", .{num_symbols});
+
+ if (dump_header)
+ try w.print(
+ \\{t: >16} type
+ \\ | {f} symbols
+ \\ | {f} members
+ \\
+ , .{
+ expected_kind,
+ fmtIntField(d, num_symbols, .{ .kind = .size, .width = .auto }),
+ fmtIntField(d, num_members, .{ .kind = .size, .width = .auto }),
+ });
+
+ try symbol_member_indices.ensureTotalCapacity(gpa, num_symbols);
+ for (0..num_symbols) |order| {
+ const index = (try r.takeInt(u16, .little)) - 1;
+ if (index >= members.items.len)
+ return d.failParse("invalid member index 0x{x} in seconds linker member indices array", .{index});
+
+ symbol_member_indices.addOneAssumeCapacity().* = index;
+
+ if (members.items[index].order == null)
+ members.items[index].order = @intCast(order);
+ }
+
+ if (d.opts.exports and d.opts.exports_sort) {
+ std.sort.pdq(Member, members.items, {}, struct {
+ fn lessThan(ctx: void, lhs: Member, rhs: Member) bool {
+ _ = ctx;
+ if (lhs.order == null and rhs.order == null)
+ return lhs.offset < rhs.offset
+ else if (lhs.order) |lhs_order|
+ return if (rhs.order) |rhs_order| lhs_order < rhs_order else false
+ else if (rhs.order) |rhs_order|
+ return if (lhs.order) |lhs_order| lhs_order < rhs_order else true
+ else
+ unreachable;
+ }
+ }.lessThan);
+ }
+
+ if (d.opts.linker_member == .second_linker) {
+ if (d.element(.@"table-header"))
+ try w.writeAll(
+ \\
+ \\Archive Symbols:
+ \\& Member Symbol
+ \\
+ );
+
+ pos = fr.logicalPos();
+ var symbol_i: u32 = 0;
+ while (pos < member_end and symbol_i < num_symbols) : ({
+ pos = fr.logicalPos();
+ symbol_i += 1;
+ }) {
+ const symbol_name = if (r.takeDelimiter(0) catch |err| switch (err) {
+ error.StreamTooLong => null,
+ else => |e| return e,
+ }) |n| n else return d.failParse("unterminated string found in second linker member", .{});
+
+ if (!filterMatches(d.opts.symbol_filters, symbol_name))
+ continue;
+
+ try w.print("{f} {s}\n", .{
+ fmtIntField(
+ d,
+ members.items[symbol_member_indices.items[symbol_i]].offset,
+ .{ .kind = .va },
+ ),
+ symbol_name,
+ });
+ }
+
+ if (symbol_i != num_symbols)
+ return d.failParse(
+ " expected {d} entries in second linker member string table, but found {d}",
+ .{ num_symbols, symbol_i },
+ );
+ }
+
+ if (d.element(.newlines)) try w.writeByte('\n');
+ try fr.seekTo(member_end);
+ opt_expected_kind = .longnames;
+ continue;
+ },
+ .longnames => {
+ // This member is optional
+ if (std.mem.eql(u8, header.name, "//")) {
+ opt_longnames = try r.readAlloc(gpa, header.size);
+ if (dump_header)
+ try w.print("{t: >16} type\n", .{expected_kind});
+
+ if (d.opts.linker_member == .longnames) {
+ if (d.element(.@"table-header"))
+ try w.print(
+ \\
+ \\Longnames (0x{x} bytes):
+ \\
+ , .{opt_longnames.?.len});
+
+ var lr = Io.Reader.fixed(opt_longnames.?);
+ while (try lr.takeDelimiter(0)) |str| {
+ try w.writeAll(str);
+ try w.writeByte('\n');
+ }
+ }
+
+ if (d.element(.newlines)) try w.writeByte('\n');
+ }
+
+ opt_expected_kind = null;
+ break;
+ },
+ else => unreachable,
+ };
+ }
+
+ if (opt_expected_kind) |expected_kind| switch (expected_kind) {
+ .first_linker => d.failParse("missing first linker member", .{}),
+ .second_linker => d.failParse("missing second linker member", .{}),
+ else => {},
+ };
+
+ for (members.items, 0..) |member, member_i| {
+ fr.seekTo(member.offset) catch |err|
+ d.failParse("unable to read member {d} at offset 0x{x}: {t}", .{ member_i, member.offset, err });
+
+ const raw_header = try r.takeStruct(std.coff.ArchiveMemberHeader, .little);
+ const header: ArchiveHeader = .fromRaw(d, &raw_header, opt_longnames);
+ if (!filterMatches(d.opts.member_filters, header.name)) continue;
+
+ const member_sig = try r.peek(4);
+ const machine: std.coff.IMAGE.FILE.MACHINE =
+ @enumFromInt(std.mem.readInt(u16, member_sig[0..2], .little));
+ const sig = std.mem.readInt(u16, member_sig[2..4], .little);
+
+ const is_imp_lib = machine == std.coff.IMAGE.FILE.MACHINE.UNKNOWN and sig == 0xffff;
+ if (d.opts.member_headers)
+ try dumpArchiveHeader(d, &header, member.offset);
+
+ if (d.opts.member_headers or (d.opts.exports and is_imp_lib)) {
+ if (is_imp_lib) {
+ const imp_header = try r.takeStruct(std.coff.ImportHeader, .little);
+ const sym_name = (try r.takeDelimiter(0)).?;
+ const imp_dll = (try r.takeDelimiter(0)).?;
+
+ if (!filterMatches(d.opts.symbol_filters, sym_name))
+ continue;
+
+ if (d.element(.@"header-name"))
+ try w.writeAll("\nImport header:\n");
+
+ try dumpHeader(d, std.coff.ImportHeader, &imp_header, struct {
+ pub fn sig1(_: *const DumpContext, _: *const std.coff.ImportHeader) !void {}
+ pub fn sig2(_: *const DumpContext, _: *const std.coff.ImportHeader) !void {}
+ pub fn types(id: *const DumpContext, h: *const std.coff.ImportHeader) !void {
+ try id.w.print(
+ \\{t: >16} import_type
+ \\{t: >16} name_type
+ \\
+ , .{ h.types.type, h.types.name_type });
+ }
+ });
+
+ const imp_name = imp_name: switch (imp_header.types.name_type) {
+ .NAME_NOPREFIX,
+ .NAME_UNDECORATE,
+ => |tag| {
+ var imp_name = std.mem.trimStart(u8, sym_name, "?@_");
+ if (tag == .NAME_UNDECORATE)
+ imp_name = std.mem.sliceTo(imp_name, '@');
+ break :imp_name imp_name;
+ },
+ else => sym_name,
+ };
+
+ try w.print(
+ \\ symbol name | {s}
+ \\ import name | {s}
+ \\ dll | {s}
+ \\
+ , .{
+ sym_name,
+ imp_name,
+ imp_dll,
+ });
+ } else {
+ try w.writeAll(" COFF object type\n");
+ }
+ if (d.element(.newlines)) try w.writeByte('\n');
+ }
+
+ if (is_imp_lib) continue;
+ if (d.opts.section_headers or
+ d.opts.file_headers or
+ d.opts.relocs or
+ d.opts.strings or
+ d.opts.symbols)
+ {
+ const member_name = if (d.element(.@"member-path"))
+ header.name
+ else
+ std.fs.path.basename(header.name);
+
+ if (d.element(.@"file-type")) {
+ try w.print("{s}({s}): COFF object\n", .{
+ std.fs.path.basename(d.opts.input_path),
+ member_name,
+ });
+ if (d.element(.newlines)) try w.writeByte('\n');
+ }
+ try dumpObject(d, false, member_name);
+ }
+ }
+ }
+
+ fn dumpObject(
+ d: *const DumpContext,
+ is_image: bool,
+ obj_name: []const u8,
+ ) !void {
+ const gpa = d.gpa;
+ const fr = d.fr;
+ const w = d.w;
+
+ const file_location = fr.logicalPos();
+ const r = &fr.interface;
+ const header = r.takeStruct(std.coff.Header, .little) catch |err|
+ return d.failParse("unable to read COFF header: {t}", .{err});
+
+ if (d.opts.file_headers) {
+ if (d.element(.@"header-name")) try w.writeAll("COFF Header:\n");
+ try dumpHeader(d, std.coff.Header, &header, struct {});
+ if (d.element(.newlines)) try w.writeByte('\n');
+ }
+
+ switch (header.machine) {
+ _ => return d.failParse("unknown machine type: {x}", .{header.machine}),
+ else => {},
+ }
+
+ var known_dirs: [DIRECTORY_ENTRY.len]std.coff.ImageDataDirectory = undefined;
+ const needs_data_dirs =
+ d.opts.exports or
+ d.opts.imports or
+ d.opts.tls;
+
+ const ImageInfo = struct {
+ data_dirs: []const std.coff.ImageDataDirectory,
+ magic: std.coff.OptionalHeader.Magic,
+ image_base: u64,
+ };
+
+ const image_info: ?ImageInfo = if (header.size_of_optional_header > 0) image_info: {
+ if (!d.opts.file_headers and !needs_data_dirs) {
+ try fr.seekBy(header.size_of_optional_header);
+ break :image_info null;
+ }
+
+ if (d.opts.file_headers and d.element(.@"header-name"))
+ try w.writeAll("COFF Optional Header:\n");
+
+ const magic: std.coff.OptionalHeader.Magic = @enumFromInt(try r.peekInt(u16, .little));
+ const num_directory_entries, const image_base = switch (magic) {
+ inline .PE32, .@"PE32+" => |v| num_data_dirs: {
+ const OptionalHeader = if (v == .PE32)
+ std.coff.OptionalHeader.PE32
+ else
+ std.coff.OptionalHeader.@"PE32+";
+
+ const optional_header = r.takeStruct(OptionalHeader, .little) catch |err|
+ return d.failParse("unable to read optional header: {t}", .{err});
+
+ if (d.opts.file_headers) {
+ try dumpHeader(d, OptionalHeader, &optional_header, struct {
+ pub fn base_of_code(id: *const DumpContext, h: *const std.coff.OptionalHeader) !void {
+ const base = @as(*const OptionalHeader, @ptrCast(@alignCast(h))).image_base;
+ try dumpRvaField(id, @src().fn_name, h.base_of_code, base);
+ }
+
+ pub fn address_of_entry_point(id: *const DumpContext, h: *const std.coff.OptionalHeader) !void {
+ const base = @as(*const OptionalHeader, @ptrCast(@alignCast(h))).image_base;
+ try dumpRvaField(id, @src().fn_name, h.base_of_code, base);
+ }
+
+ pub fn major_linker_version(id: *const DumpContext, h: *const std.coff.OptionalHeader) !void {
+ try dumpVersionField(id.w, "linker_version", h.major_linker_version, h.minor_linker_version);
+ }
+ pub fn minor_linker_version(_: *const DumpContext, _: *const std.coff.OptionalHeader) !void {}
+
+ pub fn major_operating_system_version(id: *const DumpContext, h: *const OptionalHeader) !void {
+ try dumpVersionField(
+ id.w,
+ "operating_system_version",
+ h.major_operating_system_version,
+ h.minor_operating_system_version,
+ );
+ }
+ pub fn minor_operating_system_version(_: *const DumpContext, _: *const OptionalHeader) !void {}
+
+ pub fn major_image_version(id: *const DumpContext, h: *const OptionalHeader) !void {
+ try dumpVersionField(id.w, "image_version", h.major_image_version, h.minor_image_version);
+ }
+ pub fn minor_image_version(_: *const DumpContext, _: *const OptionalHeader) !void {}
+
+ pub fn major_subsystem_version(id: *const DumpContext, h: *const OptionalHeader) !void {
+ try dumpVersionField(id.w, "subsystem_version", h.major_subsystem_version, h.minor_subsystem_version);
+ }
+ pub fn minor_subsystem_version(_: *const DumpContext, _: *const OptionalHeader) !void {}
+ });
+ if (d.element(.newlines)) try w.writeByte('\n');
+ }
+
+ break :num_data_dirs .{
+ optional_header.number_of_rva_and_sizes,
+ optional_header.image_base,
+ };
+ },
+ else => return d.failParse("invalid optional header magic number: {x}", .{magic}),
+ };
+
+ if (d.opts.file_headers and d.element(.@"header-name"))
+ try w.writeAll("Data Directories:\n");
+
+ for (0..num_directory_entries) |dir_i| {
+ const dir = r.takeStruct(std.coff.ImageDataDirectory, .little) catch |err|
+ return d.failParse("unable to read data directory {x}: {t}", .{ dir_i, err });
+
+ if (dir_i < known_dirs.len)
+ known_dirs[dir_i] = dir;
+
+ if (d.opts.file_headers)
+ try w.print(
+ "{x: >16} {x: >8} {t}\n",
+ .{ dir.virtual_address, dir.size, @as(DIRECTORY_ENTRY, @enumFromInt(dir_i)) },
+ );
+ }
+ if (d.opts.file_headers and d.element(.newlines)) try w.writeByte('\n');
+
+ break :image_info .{
+ .data_dirs = known_dirs[0..@min(known_dirs.len, num_directory_entries)],
+ .magic = magic,
+ .image_base = image_base,
+ };
+ } else if (is_image) {
+ return d.failParse("image did not contain an optional header", .{});
+ } else null;
+
+ // Section names in images don't use the string table, as they must fit inline in the header
+ const load_string_table = (d.opts.strings or !is_image) and header.pointer_to_symbol_table > 0;
+ const string_table = if (load_string_table) string_table: {
+ const pos = fr.logicalPos();
+ fr.seekTo(file_location + header.pointer_to_symbol_table + header.number_of_symbols * std.coff.Symbol.sizeOf()) catch |err|
+ return d.failParse("unable to seek to string table: {t}", .{err});
+
+ const string_table_len = r.peekInt(u32, .little) catch |err|
+ return d.failParse("unable to read string table length: {t}", .{err});
+
+ const table = r.readAlloc(gpa, string_table_len) catch |err|
+ return d.failParse("unable to read string table: {t}", .{err});
+
+ try fr.seekTo(pos);
+ break :string_table table;
+ } else &.{};
+ defer gpa.free(string_table);
+
+ if (d.opts.strings) {
+ if (d.element(.@"table-header"))
+ try w.print(
+ \\String Table (0x{x} bytes):
+ \\
+ , .{string_table.len});
+
+ var sr = Io.Reader.fixed(string_table[@sizeOf(u32)..]);
+ while (try sr.takeDelimiter(0)) |str| {
+ try w.writeAll(str);
+ try w.writeByte('\n');
+ }
+
+ if (d.element(.newlines)) try w.writeByte('\n');
+ }
+
+ var sections: std.ArrayList(Section) = .empty;
+ defer sections.deinit(gpa);
+ var sections_with_data: u16 = 0;
+
+ const load_sections =
+ d.opts.section_headers or
+ d.opts.symbols or
+ d.opts.relocs or
+ needs_data_dirs;
+
+ if (load_sections) {
+ if (d.opts.section_headers and d.element(.@"table-header"))
+ try w.print(
+ \\Sections in '{s}':
+ \\Num Name RVA Virt Size Data Size & Data & Relocs & Lines # Relocs # Lines Flags
+ \\
+ , .{obj_name});
+
+ try sections.resize(gpa, header.number_of_sections);
+ for (sections.items, 0..) |*section, section_i| {
+ section.header = r.takeStruct(std.coff.SectionHeader, .little) catch |err|
+ return d.failParse("unable to read section header {x}: {t}", .{ section_i, err });
+ section.name = headerName(§ion.header.name, string_table) catch |err| switch (err) {
+ error.Overflow,
+ error.InvalidCharacter,
+ => return d.failParse("unable to parse section name offset '{s}': {t}", .{
+ section.name,
+ err,
+ }),
+ error.OutOfBounds => return d.failParse("section name offset '{s}' was out of bounds (>= {x})", .{
+ section.name,
+ string_table.len,
+ }),
+ };
+
+ sections_with_data += @intFromBool(section.header.size_of_raw_data > 0);
+ if (d.opts.section_headers) {
+ if (!filterMatches(d.opts.section_filters, section.name)) continue;
+ const raw_name = std.mem.sliceTo(§ion.header.name, 0);
+ try w.print(
+ "{x: >3} {s: <8} {f} {f} {f} {f} {f} {f} {f} {f} {x:0>8} |",
+ .{
+ section_i + 1,
+ raw_name,
+ fmtIntField(d, section.header.virtual_address, .{ .kind = .va }),
+ fmtIntField(d, section.header.virtual_size, .{ .kind = .size, .width = .{ .explicit = 9 } }),
+ fmtIntField(d, section.header.size_of_raw_data, .{ .kind = .size, .width = .{ .explicit = 9 } }),
+ fmtIntField(d, section.header.pointer_to_raw_data, .{ .kind = .va }),
+ fmtIntField(d, section.header.pointer_to_relocations, .{ .kind = .va }),
+ fmtIntField(d, section.header.pointer_to_linenumbers, .{ .kind = .va }),
+ fmtIntField(d, section.header.number_of_relocations, .{ .kind = .va }),
+ fmtIntField(d, section.header.number_of_linenumbers, .{ .kind = .va }),
+ @as(u32, @bitCast(section.header.flags)),
+ },
+ );
+
+ try dumpFlags(w, "{s}", std.coff.SectionHeader.Flags, §ion.header.flags, 1);
+ if (section.name.len > 8)
+ try w.print("\n | {s}", .{section.name});
+
+ try w.writeByte('\n');
+ }
+ }
+
+ if (d.opts.section_headers and d.element(.newlines)) try w.writeByte('\n');
+ }
+
+ var symbols: std.ArrayList(struct {
+ name: []const u8,
+ section_number: std.coff.SectionNumber,
+ }) = .empty;
+ defer symbols.deinit(gpa);
+
+ var name_arena: std.heap.ArenaAllocator = .init(gpa);
+ defer name_arena.deinit();
+
+ if (d.opts.relocs)
+ try symbols.ensureUnusedCapacity(gpa, header.number_of_symbols);
+
+ if (d.opts.symbols or d.opts.relocs) {
+ if (header.pointer_to_symbol_table > 0) {
+ fr.seekTo(file_location + header.pointer_to_symbol_table) catch |err|
+ return d.failParse("unable to seek to symbol table: {t}", .{err});
+
+ if (d.opts.symbols and d.element(.@"table-header"))
+ try w.print(
+ \\Symbols in '{s}':
+ \\ Ord Value Sect Type Storage Name
+ \\
+ , .{obj_name});
+
+ const symbol_size = std.coff.Symbol.sizeOf();
+ var symbol_i: u32 = 0;
+ while (symbol_i < header.number_of_symbols) {
+ var symbol: std.coff.Symbol = undefined;
+ const symbol_bytes = r.take(symbol_size) catch |err|
+ return d.failParse("unable to read symbol {x}: {t}", .{ symbol_i, err });
+
+ @memcpy(std.mem.asBytes(&symbol)[0..symbol_size], symbol_bytes);
+ if (native_endian != .little)
+ std.mem.byteSwapAllFields(std.coff.Symbol, &symbol);
+
+ const aux_symbols = if (symbol.number_of_aux_symbols > 0)
+ try r.take(symbol_size * symbol.number_of_aux_symbols)
+ else
+ &.{};
+ defer symbol_i += symbol.number_of_aux_symbols + 1;
+
+ const name = if (std.mem.eql(u8, symbol.name[0..4], "\x00\x00\x00\x00")) name: {
+ const index = std.mem.readInt(u32, symbol.name[4..], .little);
+ if (index >= string_table.len)
+ return d.failParse("invalid name offset for symbol {x} ({x} >= {x})", .{
+ symbol_i,
+ index,
+ string_table.len,
+ });
+ break :name std.mem.sliceTo(string_table[index..], 0);
+ } else try name_arena.allocator().dupe(u8, std.mem.sliceTo(&symbol.name, 0));
+
+ if (d.opts.relocs)
+ symbols.appendNTimesAssumeCapacity(.{
+ .name = name,
+ .section_number = symbol.section_number,
+ }, 1 + symbol.number_of_aux_symbols);
+
+ if (!d.opts.symbols or !filterMatches(d.opts.symbol_filters, name))
+ continue;
+
+ try w.print("{f} {x:0>8} ", .{
+ fmtIntField(d, @as(u16, @intCast(symbol_i)), .{ .kind = .ord }),
+ symbol.value,
+ });
+ try switch (symbol.section_number) {
+ .UNDEFINED => w.writeAll("UNDEF"),
+ .ABSOLUTE => w.writeAll(" ABS"),
+ .DEBUG => w.writeAll("DEBUG"),
+ else => |v| {
+ const backing = @intFromEnum(v);
+ const fmt = "{x: >5}";
+ if (backing >= 0)
+ try w.print(fmt, .{@as(u15, @intCast(backing))})
+ else
+ try w.print(fmt, .{backing});
+ },
+ };
+
+ try w.print("{t: >5}", .{symbol.type.base_type});
+ if (switch (symbol.type.complex_type) {
+ .NULL => " ",
+ .POINTER => "* ",
+ .FUNCTION => "()",
+ .ARRAY => "[]",
+ else => null,
+ }) |suffix| try w.writeAll(suffix) else try w.print("{x}", .{symbol.type.complex_type});
+
+ try w.print("{t: >16} | {s}\n", .{ symbol.storage_class, name });
+
+ for (0..symbol.number_of_aux_symbols) |aux_i| {
+ _ = aux_i;
+ try w.writeAll(" |");
+
+ if (symbol.storage_class == .EXTERNAL and
+ symbol.type == std.coff.SymType{
+ .complex_type = .FUNCTION,
+ .base_type = .NULL,
+ } and
+ @intFromEnum(symbol.section_number) > 0)
+ {
+ try w.writeAll("TODO function aux symbol");
+ } else if (symbol.type == std.coff.SymType{
+ .complex_type = .FUNCTION,
+ .base_type = .NULL,
+ } and
+ (std.mem.eql(u8, name, ".bf") or std.mem.eql(u8, name, ".ef")))
+ {
+ try w.writeAll("TODO bf / ef aux symbol");
+ } else if (symbol.storage_class == .WEAK_EXTERNAL and symbol.section_number == .UNDEFINED) {
+ if (symbol.value != 0)
+ return d.failParse(
+ "invalid value 0x{x} for weak external symbol 0x{x}",
+ .{ symbol.value, symbol_i },
+ );
+
+ var weak_external: std.coff.WeakExternalDefinition = undefined;
+ @memcpy(std.mem.asBytes(&weak_external)[0..symbol_size], aux_symbols[0..symbol_size]);
+ if (native_endian != .little)
+ std.mem.byteSwapAllFields(std.coff.WeakExternalDefinition, &weak_external);
+
+ if (weak_external.tag_index >= header.number_of_symbols)
+ return d.failParse(
+ "invalid tag_index 0x{x} for weak external symbol 0x{x}",
+ .{ weak_external.tag_index, symbol_i },
+ );
+
+ if (d.redacted(.ord))
+ try w.print(" Weak External [falls back to relative ordinal {x:0>8} via {t}]", .{
+ @as(i64, weak_external.tag_index) - symbol_i,
+ weak_external.flag,
+ })
+ else
+ try w.print(" Weak External [falls back to ordinal {x:0>8} via {t}]", .{
+ weak_external.tag_index,
+ weak_external.flag,
+ });
+ } else if (symbol.storage_class == .FILE) {
+ if (!std.mem.eql(u8, name, ".file")) {
+ try w.print(" !! unexpected symbol name '{s}' for file symbol 0x{x}", .{ name, symbol_i });
+ continue;
+ }
+
+ const filename = std.mem.sliceTo(aux_symbols, 0);
+ try w.print(" File '{s}'", .{filename});
+ break;
+ } else if (symbol.storage_class == .STATIC and
+ symbol.type == std.coff.SymType{
+ .complex_type = .NULL,
+ .base_type = .NULL,
+ } and
+ symbol.value == 0 and
+ switch (symbol.section_number) {
+ .UNDEFINED, .DEBUG, .ABSOLUTE => false,
+ else => |sn| @intFromEnum(sn) > 0,
+ })
+ {
+ const section_i: u15 = @intCast(@intFromEnum(symbol.section_number) - 1);
+ try w.writeAll(" Section ");
+
+ if (section_i >= sections.items.len) {
+ try w.print(" !! invalid section number: {x}", .{section_i});
+ continue;
+ }
+
+ var section_def: std.coff.SectionDefinition = undefined;
+ @memcpy(std.mem.asBytes(§ion_def)[0..symbol_size], aux_symbols[0..symbol_size]);
+ if (native_endian != .little)
+ std.mem.byteSwapAllFields(std.coff.SectionDefinition, §ion_def);
+
+ const section = §ions.items[section_i];
+ if (section_def.number_of_relocations != section.header.number_of_relocations) {
+ try w.print(
+ " !! relocation count did not match section header: {d} vs {d}",
+ .{ section_def.number_of_relocations, section.header.number_of_relocations },
+ );
+ continue;
+ }
+
+ if (section_def.number_of_linenumbers != section.header.number_of_linenumbers) {
+ try w.print(
+ " !! line number count did not match section header: {d} vs {d}",
+ .{ section_def.number_of_linenumbers, section.header.number_of_linenumbers },
+ );
+ continue;
+ }
+
+ try w.print(" [size {f} chksum {x:0>8} relocs {x:0>4} lines {x:0>4}]", .{
+ fmtIntField(d, section_def.length, .{ .kind = .size, .zero_fill = true }),
+ section_def.checksum,
+ section_def.number_of_relocations,
+ section_def.number_of_linenumbers,
+ });
+
+ switch (section_def.selection) {
+ .NONE => {},
+ else => |selection| {
+ try w.print(" COMDAT({t}", .{selection});
+ if (selection == .ASSOCIATIVE)
+ try w.print("->{x}", .{section_def.number});
+ try w.writeAll(")");
+ },
+ }
+ }
+
+ try w.writeByte('\n');
+ }
+ }
+
+ if (d.opts.symbols and d.element(.newlines)) try w.writeByte('\n');
+ } else if (d.opts.symbols) {
+ try w.writeAll("No symbol table found\n");
+ }
+ }
+
+ if (d.opts.relocs) {
+ const relocation_size = std.coff.Relocation.sizeOf();
+
+ for (sections.items, 0..) |section, section_i| {
+ if (section.header.pointer_to_relocations == 0) continue;
+
+ if (d.element(.@"table-header"))
+ try w.print(
+ \\Relocs for section {x} '{s}' in {s}:
+ \\ Offset Type Symbol -> Sect Name
+ \\
+ , .{ section_i + 1, section.name, obj_name });
+
+ fr.seekTo(file_location + section.header.pointer_to_relocations) catch |err|
+ return d.failParse("unable to seek to section {x} relocation table: {t}", .{ section_i + 1, err });
+
+ for (0..section.header.number_of_relocations) |reloc_i| {
+ var reloc: std.coff.Relocation = undefined;
+ @memcpy(std.mem.asBytes(&reloc)[0..relocation_size], try r.take(relocation_size));
+ if (native_endian != .little)
+ std.mem.byteSwapAllFields(std.coff.Relocation, &reloc);
+
+ const sym = &symbols.items[reloc.symbol_table_index];
+ if (!filterMatches(d.opts.symbol_filters, sym.name))
+ continue;
+
+ try w.print("{f} ", .{
+ fmtIntField(d, reloc.virtual_address, .{ .kind = .va, .zero_fill = true }),
+ });
+ switch (header.machine) {
+ _ => unreachable,
+ inline else => |m| switch (m.RelocationType()) {
+ void => try w.writeAll("(unknown arch)"),
+ else => |RelocationType| try w.print(
+ "{t: <17} ",
+ .{@as(RelocationType, @enumFromInt(reloc.type))},
+ ),
+ },
+ }
+
+ if (reloc.symbol_table_index >= symbols.items.len)
+ return d.failParse(
+ "reloc {x} in section {x} has out-of-bounds symbol index {x}",
+ .{ reloc_i, section_i + 1, reloc.symbol_table_index },
+ );
+
+ try w.print("{f} {f} | {s}\n", .{
+ fmtIntField(d, reloc.symbol_table_index, .{ .kind = .ord }),
+ fmtSectionNumber(sym.section_number),
+ sym.name,
+ });
+ }
+ if (d.element(.newlines)) try w.writeByte('\n');
+ }
+ }
+
+ // Sections indices with raw data, sorted by RVA
+ const rva_index = if (needs_data_dirs) rva_index: {
+ const rva_index = try gpa.alloc(u16, sections_with_data);
+ var indices_i: u16 = 0;
+ for (sections.items, 0..) |*section, i| {
+ if (section.header.size_of_raw_data == 0) continue;
+ rva_index[indices_i] = @intCast(i);
+ indices_i += 1;
+ }
+
+ const Context = struct {
+ indices: []u16,
+ sections: []const Section,
+
+ pub fn lessThan(ctx: @This(), lhs: usize, rhs: usize) bool {
+ return ctx.sections[ctx.indices[lhs]].header.virtual_address <
+ ctx.sections[ctx.indices[rhs]].header.virtual_address;
+ }
+
+ pub fn swap(ctx: @This(), lhs: usize, rhs: usize) void {
+ std.mem.swap(u16, &ctx.indices[lhs], &ctx.indices[rhs]);
+ }
+ };
+
+ std.sort.pdqContext(0, rva_index.len, Context{
+ .indices = rva_index,
+ .sections = sections.items,
+ });
+
+ break :rva_index rva_index;
+ } else &.{};
+ defer gpa.free(rva_index);
+
+ if (d.opts.exports) exports: {
+ if (try seekToDataDirectory(
+ d,
+ rva_index,
+ sections.items,
+ (image_info orelse {
+ try w.writeAll("COFF objects do not contain an export data directory");
+ break :exports;
+ }).data_dirs,
+ .EXPORT,
+ )) |section_index| {
+ const export_dir = r.takeStruct(std.coff.ExportDirectoryTable, .little) catch |err|
+ return d.failParse("unable to read export directory: {t}", .{err});
+
+ try w.print("Export directory:\n", .{});
+ try dumpHeader(d, std.coff.ExportDirectoryTable, &export_dir, struct {
+ pub fn major_version(id: *const DumpContext, h: *const std.coff.ExportDirectoryTable) !void {
+ try dumpVersionField(id.w, "version", h.major_version, h.minor_version);
+ }
+ pub fn minor_version(_: *const DumpContext, _: *const std.coff.ExportDirectoryTable) !void {}
+ });
+
+ const section = sections.items[section_index];
+ const name_loc = section.rvaFileOffset(export_dir.name_rva) catch
+ return d.failParse(
+ "export name rva 0x{x} was not within the export section",
+ .{export_dir.name_rva},
+ );
+
+ const eat_loc = section.rvaFileOffset(export_dir.export_address_table_rva) catch
+ return d.failParse(
+ "export address table rva 0x{x} was not within the export section",
+ .{export_dir.export_address_table_rva},
+ );
+
+ const name_pointer_loc = section.rvaFileOffset(export_dir.name_pointer_table_rva) catch
+ return d.failParse(
+ "export name pointer table rva 0x{x} was not within the export section",
+ .{export_dir.name_pointer_table_rva},
+ );
+
+ const ord_loc = section.rvaFileOffset(export_dir.ordinal_table_rva) catch
+ return d.failParse(
+ "export ordinal table rva 0x{x} was not within the export section",
+ .{export_dir.ordinal_table_rva},
+ );
+
+ // All the variable length fields should be contained within this directory.
+ // Read it entirely to avoid needing to seek per-name when iterating.
+ const dir = image_info.?.data_dirs[@intFromEnum(DIRECTORY_ENTRY.EXPORT)];
+ const dir_end_rva = dir.virtual_address + dir.size;
+ const dir_loc = fr.logicalPos();
+ const dir_slice = try r.readAlloc(gpa, dir.size);
+ defer gpa.free(dir_slice);
+
+ const dll_name = std.mem.sliceTo(dir_slice[name_loc - dir_loc ..], 0);
+ if (d.element(.@"table-header"))
+ try w.print(
+ \\
+ \\Exports from {s}:
+ \\ Ord Hint RVA Name
+ \\
+ , .{dll_name});
+
+ const name_pointers = dir_slice[name_pointer_loc - dir_loc ..][0 .. export_dir.number_of_names * @sizeOf(u32)];
+ const ords = dir_slice[ord_loc - dir_loc ..][0 .. export_dir.number_of_names * @sizeOf(u16)];
+ const addrs = dir_slice[eat_loc - dir_loc ..][0 .. export_dir.number_of_entries * @sizeOf(u32)];
+ const name_rva_to_offset = dir.virtual_address + @sizeOf(std.coff.ExportDirectoryTable);
+ for (0..export_dir.number_of_names) |name_i| {
+ const name_rva = std.mem.readInt(u32, name_pointers[name_i * @sizeOf(u32) ..][0..@sizeOf(u32)], .little);
+ const name = std.mem.sliceTo(dir_slice[name_rva - name_rva_to_offset ..], 0);
+ if (!filterMatches(d.opts.symbol_filters, name))
+ continue;
+
+ const ord = std.mem.readInt(u16, ords[name_i * @sizeOf(u16) ..][0..@sizeOf(u16)], .little);
+ const addr = std.mem.readInt(u32, addrs[@as(u32, ord) * @sizeOf(u32) ..][0..@sizeOf(u32)], .little);
+
+ try w.print("{f} {f} ", .{
+ fmtIntField(d, @as(u16, @intCast(export_dir.ordinal_base + ord)), .{ .kind = .ord }),
+ fmtIntField(d, @as(u16, @intCast(name_i)), .{ .kind = .ord }),
+ });
+ const is_forwarder = addr >= dir.virtual_address and addr < dir_end_rva;
+ if (is_forwarder) {
+ try w.writeAll("forwards");
+ } else {
+ try w.print("{f}", .{fmtIntField(d, addr, .{ .kind = .rva })});
+ }
+
+ try w.print(" | {s}", .{name});
+ if (is_forwarder)
+ try w.print(" -> {s}", .{std.mem.sliceTo(dir_slice[addr - name_rva_to_offset ..], 0)});
+ try w.writeByte('\n');
+ }
+ }
+ }
+
+ if (d.opts.imports) imports: {
+ if (try seekToDataDirectory(
+ d,
+ rva_index,
+ sections.items,
+ (image_info orelse {
+ try w.writeAll("COFF objects do not contain an import data directory");
+ break :imports;
+ }).data_dirs,
+ .IMPORT,
+ )) |_| {
+ const Entry = std.coff.ImportDirectoryEntry;
+ var directory_entries: std.ArrayList(Entry) = .empty;
+ defer directory_entries.deinit(gpa);
+ while (true) {
+ const entry = r.takeStruct(Entry, .little) catch |err|
+ return d.failParse(
+ "unable to read import directory entry {x}: {t}",
+ .{ directory_entries.items.len, err },
+ );
+
+ if (std.mem.allEqual(u8, std.mem.asBytes(&entry), 0)) break;
+ (try directory_entries.addOne(gpa)).* = entry;
+ }
+
+ for (directory_entries.items) |entry| {
+ const name_section = sectionContainingRva(
+ rva_index,
+ sections.items,
+ entry.name_rva,
+ ) orelse
+ return d.failParse(
+ "import directory entry name rva 0x{x} was not found in any section",
+ .{entry.name_rva},
+ );
+
+ const name_loc = sections.items[name_section].rvaFileOffset(
+ entry.name_rva,
+ ) catch unreachable;
+ fr.seekTo(name_loc) catch |err|
+ return d.failParse(
+ "unable to seek to import directory entry name at 0x{x}: {t}",
+ .{ name_loc, err },
+ );
+
+ const dll_name = (try r.takeDelimiter(0)).?;
+
+ if (d.element(.@"header-name"))
+ try w.print("Import table entry for {s}:\n", .{dll_name});
+ try dumpHeader(d, Entry, &entry, struct {});
+
+ if (d.element(.@"table-header"))
+ try w.print(
+ \\
+ \\ Ord Hint Name
+ \\
+ , .{});
+
+ const ilt_section = sectionContainingRva(
+ rva_index,
+ sections.items,
+ entry.import_lookup_table_rva,
+ ) orelse
+ return d.failParse(
+ "import directory entry ilt rva 0x{x} was not found in any section",
+ .{entry.import_lookup_table_rva},
+ );
+
+ const ilt_loc = sections.items[ilt_section].rvaFileOffset(
+ entry.import_lookup_table_rva,
+ ) catch unreachable;
+ fr.seekTo(ilt_loc) catch |err|
+ return d.failParse(
+ "unable to seek to import directory ilt at 0x{x}: {t}",
+ .{ ilt_loc, err },
+ );
+
+ switch (image_info.?.magic) {
+ _ => try w.writeAll("(unknown magic)"),
+ inline else => |m| {
+ const TableEntry = std.coff.ImportLookupTableEntry(m);
+ const null_entry: TableEntry = @bitCast(@as(@typeInfo(TableEntry).@"struct".backing_integer.?, 0));
+
+ var ilt_entries: std.ArrayList(TableEntry) = .empty;
+ defer ilt_entries.deinit(gpa);
+ while (true) {
+ const table_entry = r.takeStruct(TableEntry, .little) catch |err|
+ return d.failParse(
+ "unable to read ilt entry {s}:{x}: {t}",
+ .{ dll_name, ilt_entries.items.len, err },
+ );
+ if (table_entry == null_entry) break;
+ (try ilt_entries.addOne(gpa)).* = table_entry;
+ }
+
+ for (ilt_entries.items, 0..) |ilt_entry, ilt_entry_i| {
+ if (ilt_entry.is_ordinal) {
+ try w.print("{x: >4}", .{ilt_entry.payload.ordinal.ordinal});
+ } else {
+ const hint_section = sectionContainingRva(
+ rva_index,
+ sections.items,
+ ilt_entry.payload.hint_name_rva,
+ ) orelse
+ return d.failParse(
+ "import directory ilt entry 0x{x}'s hint rva 0x{x} was not found in any section",
+ .{ ilt_entry_i, ilt_entry.payload.hint_name_rva },
+ );
+
+ const hint_loc = sections.items[hint_section].rvaFileOffset(
+ ilt_entry.payload.hint_name_rva,
+ ) catch unreachable;
+ fr.seekTo(hint_loc) catch |err|
+ return d.failParse(
+ "unable to seek to ilt entry 0x{x}'s hint at 0x{x}: {t}",
+ .{ ilt_entry_i, hint_loc, err },
+ );
+
+ const hint = r.takeInt(u16, .little) catch |err|
+ return d.failParse(
+ "unable to read import directory ilt entry 0x{x}'s hint: {t}",
+ .{ ilt_entry_i, err },
+ );
+
+ const name = r.takeDelimiter(0) catch |err|
+ return d.failParse(
+ "unable to read import directory ilt entry 0x{x}'s name: {t}",
+ .{ ilt_entry_i, err },
+ );
+
+ try w.print(" {x: >4} | {s}\n", .{ hint, name.? });
+ }
+ }
+ if (d.element(.newlines)) try w.writeByte('\n');
+ },
+ }
+ }
+ }
+ }
+
+ if (d.opts.tls) tls: {
+ if (try seekToDataDirectory(
+ d,
+ rva_index,
+ sections.items,
+ (image_info orelse {
+ try w.writeAll("COFF objects do not contain a TLS data directory");
+ break :tls;
+ }).data_dirs,
+ .TLS,
+ )) |_| {
+ switch (image_info.?.magic) {
+ _ => try w.writeAll("(unknown magic)"),
+ inline else => |m| {
+ const TlsDirectoryEntry = std.coff.TlsDirectoryEntry(m);
+ const tls_entry = r.takeStruct(TlsDirectoryEntry, .little) catch |err|
+ return d.failParse("unable to read tls directory: {t}", .{err});
+
+ try w.writeAll("TLS Directory:\n");
+ try dumpHeader(d, TlsDirectoryEntry, &tls_entry, struct {});
+
+ try w.writeAll(" | ");
+ if (tls_entry.characteristics.alignment == .NONE) {
+ try w.writeAll("Alignment not specified");
+ } else {
+ try w.print(
+ "Alignment: {d}",
+ .{tls_entry.characteristics.alignment.toByteUnits().?},
+ );
+ }
+
+ try w.writeAll(
+ \\
+ \\
+ \\TLS Callbacks:
+ \\ Address
+ \\
+ );
+
+ const callbacks_rva: u32 = @intCast(tls_entry.callbacks_va - image_info.?.image_base);
+ const section_index = sectionContainingRva(
+ rva_index,
+ sections.items,
+ callbacks_rva,
+ ) orelse
+ return d.failParse(
+ "tls callbacks rva 0x{x} was not found in any section",
+ .{callbacks_rva},
+ );
+
+ const callbacks_loc = sections.items[section_index]
+ .rvaFileOffset(callbacks_rva) catch unreachable;
+
+ fr.seekTo(callbacks_loc) catch |err|
+ return d.failParse(
+ "unable to seek to tls callbacks array at offset 0x{x}: {t}",
+ .{ callbacks_loc, err },
+ );
+
+ while (true) {
+ const callback_va = r.takeInt(@FieldType(TlsDirectoryEntry, "callbacks_va"), .little) catch |err|
+ return d.failParse(
+ "unable to read tls callbacks array: {t}",
+ .{err},
+ );
+
+ try w.print("{f}\n", .{fmtIntField(d, callback_va, .{ .kind = .va })});
+ if (callback_va == 0) break;
+ }
+ if (d.element(.newlines)) try w.writeByte('\n');
+ },
+ }
+ }
+ }
+ }
+
+ fn seekToDataDirectory(
+ d: *const DumpContext,
+ rva_index: []const u16,
+ sections: []const Section,
+ data_dirs: []const std.coff.ImageDataDirectory,
+ entry: DIRECTORY_ENTRY,
+ ) !?u16 {
+ if (@intFromEnum(entry) < data_dirs.len) blk: {
+ const rva = data_dirs[@intFromEnum(entry)].virtual_address;
+ if (rva == 0) break :blk;
+
+ const section_index = sectionContainingRva(rva_index, sections, rva) orelse
+ return d.failParse(
+ "{t} directory rva 0x{x} was not found in any section",
+ .{ entry, rva },
+ );
+
+ const file_offset = sections[section_index].rvaFileOffset(rva) catch unreachable;
+ d.fr.seekTo(file_offset) catch |err|
+ return d.failParse(
+ "unable to seek to {t} directory at offset 0x{x}: {t}",
+ .{ entry, file_offset, err },
+ );
+
+ return section_index;
+ }
+
+ try d.w.print("{t} directory was not present in optional header\n", .{entry});
+ return null;
+ }
+
+ fn sectionContainingRva(
+ /// Indices into `sections` sorted by rva
+ indices: []const u16,
+ sections: []const Section,
+ rva: u32,
+ ) ?u16 {
+ const Context = struct {
+ rva: u32,
+ sections: []const Section,
+
+ fn order(ctx: @This(), section_index: u16) std.math.Order {
+ const h = &ctx.sections[section_index].header;
+ if (ctx.rva < h.virtual_address) return .lt;
+ const end = h.virtual_address + h.size_of_raw_data;
+ if (ctx.rva >= end) return .gt;
+ return .eq;
+ }
+ };
+
+ const indices_index = std.sort.binarySearch(u16, indices, Context{
+ .rva = rva,
+ .sections = sections,
+ }, Context.order) orelse return null;
+ return @intCast(indices[indices_index]);
+ }
+
+ fn headerName(raw: *const [8]u8, string_table: []const u8) ![]const u8 {
+ return if (raw[0] == '/') name: {
+ const name_offset = try std.fmt.parseUnsigned(u24, std.mem.sliceTo(raw[1..], 0), 10);
+ if (name_offset >= string_table.len)
+ return error.OutOfBounds;
+
+ break :name std.mem.sliceTo(string_table[name_offset..], 0);
+ } else std.mem.sliceTo(raw, 0);
+ }
+
+ fn fmtSectionNumber(section_number: std.coff.SectionNumber) std.fmt.Alt(std.coff.SectionNumber, sectionNumberString) {
+ return .{ .data = section_number };
+ }
+
+ fn sectionNumberString(section_number: std.coff.SectionNumber, w: *std.Io.Writer) std.Io.Writer.Error!void {
+ try switch (section_number) {
+ .UNDEFINED => w.writeAll("UNDEF"),
+ .ABSOLUTE => w.writeAll(" ABS"),
+ .DEBUG => w.writeAll("DEBUG"),
+ else => |v| {
+ const backing = @intFromEnum(v);
+ const fmt = "{x: >5}";
+ if (backing >= 0)
+ try w.print(fmt, .{@as(u15, @intCast(backing))})
+ else
+ try w.print(fmt, .{backing});
+ },
+ };
+ }
+
+ const FormatIntField = struct {
+ val: ?u64,
+ width: ?usize,
+ zero_fill: bool,
+ };
+
+ fn fmtIntField(
+ d: *const DumpContext,
+ val: anytype,
+ params: struct {
+ kind: ?FieldKind = null,
+ width: union(enum) {
+ fit_max,
+ auto,
+ explicit: usize,
+ } = .fit_max,
+ zero_fill: bool = false,
+ },
+ ) std.fmt.Alt(FormatIntField, intFieldString) {
+ return .{
+ .data = .{
+ .val = if (d.redacted(params.kind)) null else val,
+ .width = switch (params.width) {
+ .fit_max => @typeInfo(@TypeOf(val)).int.bits / 4,
+ .auto => null,
+ .explicit => |w| w,
+ },
+ .zero_fill = params.zero_fill,
+ },
+ };
+ }
+
+ fn intFieldString(field: FormatIntField, w: *std.Io.Writer) std.Io.Writer.Error!void {
+ if (field.val) |val| {
+ try w.printInt(val, 16, .lower, .{
+ .width = field.width,
+ .alignment = .right,
+ .fill = if (field.zero_fill) '0' else ' ',
+ });
+ } else try w.splatByteAll('x', field.width orelse 1);
+ }
+
+ fn dumpFlags(w: *Io.Writer, comptime fmt: []const u8, comptime T: type, flags: *const T, cols: u32) !void {
+ const s = @typeInfo(T).@"struct";
+ inline for (s.field_names, s.field_types) |field_name, field_type| {
+ if (field_type == bool and @field(flags, field_name)) {
+ try w.splatByteAll(' ', cols);
+ try w.print(fmt, .{field_name});
+ }
+ }
+ }
+
+ fn dumpArchiveHeader(d: *const DumpContext, header: *const ArchiveHeader, pos: u32) !void {
+ if (d.element(.@"header-name"))
+ try d.w.print("Archive member at offset 0x{x}: '{s}'\n", .{ pos, header.name });
+ try dumpHeader(d, ArchiveHeader, header, struct {
+ pub fn name(_: *const DumpContext, _: *const ArchiveHeader) !void {}
+ pub fn file_mode(id: *const DumpContext, h: *const ArchiveHeader) !void {
+ try id.w.print("{o: >16} file_mode\n", .{h.file_mode});
+ }
+ });
+ }
+
+ fn fieldKind(name: []const u8) ?FieldKind {
+ if (std.mem.endsWith(u8, name, "_rva"))
+ return .rva;
+ if (std.mem.endsWith(u8, name, "_va") or
+ std.mem.endsWith(u8, name, "_address") or
+ std.mem.startsWith(u8, name, "pointer_"))
+ return .va;
+ if (std.mem.startsWith(u8, name, "number_") or
+ std.mem.startsWith(u8, name, "size"))
+ return .size;
+ if (std.mem.startsWith(u8, name, "hint"))
+ return .ord;
+ return null;
+ }
+
+ fn dumpHeader(
+ d: *const DumpContext,
+ comptime T: type,
+ header: *const T,
+ Custom: type,
+ ) !void {
+ const s = @typeInfo(T).@"struct";
+ inline for (s.field_names, s.field_types) |field_name, field_type| {
+ const val = &@field(header, field_name);
+ if (@hasDecl(Custom, field_name)) {
+ try @field(Custom, field_name)(d, header);
+ } else {
+ switch (@typeInfo(field_type)) {
+ .int => try d.w.print("{f} {s}\n", .{ fmtIntField(d, val.*, .{
+ .kind = comptime fieldKind(field_name),
+ .width = .{ .explicit = 16 },
+ }), field_name }),
+ .@"enum" => try d.w.print("{x: >16} {s} ({t})\n", .{ val.*, field_name, val.* }),
+ .@"struct" => |s_field| {
+ switch (s_field.layout) {
+ .auto,
+ .@"extern",
+ => try dumpHeader(d, field_type, val, Custom),
+ .@"packed" => {
+ try d.w.print("{x: >16} {s}\n", .{ @as(s_field.backing_integer.?, @bitCast(val.*)), field_name });
+ try dumpFlags(d.w, "| {s}\n", field_type, val, 15);
+ },
+ }
+ },
+ else => unreachable,
+ }
+ }
+ }
+ }
+
+ fn dumpVersionField(w: *Io.Writer, name: []const u8, major: anytype, minor: anytype) !void {
+ try w.print("{d: >13}.{x:0<2} {s}\n", .{ major, minor, name });
+ }
+
+ fn dumpRvaField(d: *const DumpContext, name: []const u8, rva: u64, base: u64) !void {
+ try d.w.print("{f} {s} ({f})\n", .{
+ fmtIntField(d, rva, .{ .kind = .rva }),
+ name,
+ fmtIntField(d, base + rva, .{ .kind = .va }),
+ });
+ }
+};
+
+fn filterMatches(filters: []const []const u8, val: []const u8) bool {
+ return for (filters) |filter| {
+ if (std.mem.containsAtLeast(u8, val, 1, filter)) break true;
+ } else filters.len == 0;
+}
+
const usage =
\\Usage: zig objdump [options] file
\\
\\Options:
- \\ -h, --help Print this help and exit
- \\
+ \\ -h, --help Print this help and exit
+ \\ --all-headers Alias for --file-headers --linker-member=2 --member-headers --section-headers --relocs --symbols
+ \\ --exports[=sort] Display exported symbols.
+ \\ In the case of COFF import libraries, displays the symbol list and import headers.
+ \\ Specify =sort to optionally sort the import headers by symbol name.
+ \\ --file-headers Display file-format specific headers
+ \\ --imports Display imported symbols
+ \\ --linker-member[=1|2|longnames] (Coff) Display contents of the specified archive linker member (default 2)
+ \\ --member-headers Display archive member headers
+ \\ --elements=[e1],[e2],-[e3],... Select which formatting elements are displayed. Intended for snapshot testing.
+ \\ file-type File type summary
+ \\ header-name Name that precedes a header block
+ \\ member-path Display full member paths. If removed, only basenames will be used.
+ \\ newlines Newlines between output sections
+ \\ table-header Table headers with column names
+ \\ all (default) All of the above
+ \\ --only-member=[name] Only consider archive members names that contain [name]. Can be specified multiple times.
+ \\ --only-section=[name] Only consider section names that contain [name]. Can be specified multiple times.
+ \\ --only-symbol=[name] Only consider symbol names that contain [name]. Can be specified multiple times.
+ \\ --redact=[kind] Redact the specified field kind. Intended for snapshot testing.
+ \\ rva Relative virtual addresses
+ \\ va Virtual addresses and file offsets
+ \\ ord Symbol ordinals / hints
+ \\ size Sizes and lengths
+ \\ all All of the above
+ \\ --relocs Display relocations
+ \\ -s, --snapshot Alias for --redact=all --elements=-all
+ \\ --section-headers Display section headers
+ \\ --strings Display string tables
+ \\ --symbols Display symbol tables
+ \\ --tls Display TLS information
;
diff --git a/lib/compiler/reduce/Walk.zig b/lib/compiler/reduce/Walk.zig
index 955eed53259a8bf8802ca8301f35266ade07d37c..1873c23d77f6c08230e69743e5b6db09285284f4 100644
--- a/lib/compiler/reduce/Walk.zig
+++ b/lib/compiler/reduce/Walk.zig
@@ -44,7 +44,7 @@ pub const Transformation = union(enum) {
imported_string: []const u8,
/// Identifier names that must be renamed in the inlined code or else
/// will cause ambiguous reference errors.
- in_scope_names: std.StringArrayHashMapUnmanaged(void),
+ in_scope_names: std.array_hash_map.String(void),
};
};
@@ -723,7 +723,7 @@ fn walkBuiltinCall(
try w.transformations.append(.{ .inline_imported_file = .{
.builtin_call_node = call_node,
.imported_string = imported_string,
- .in_scope_names = try std.StringArrayHashMapUnmanaged(void).init(
+ .in_scope_names = try std.array_hash_map.String(void).init(
w.arena,
w.in_scope_names.keys(),
&.{},
diff --git a/lib/compiler/resinator/cli.zig b/lib/compiler/resinator/cli.zig
index f35e70ce6cccdd726d01426ba8c11216f94b81b1..276b03af412368ac49ba27eeca4d4dff562d5798 100644
--- a/lib/compiler/resinator/cli.zig
+++ b/lib/compiler/resinator/cli.zig
@@ -15,7 +15,7 @@ pub const usage_string_after_command_name =
\\ [options] [--] []
\\
\\The sequence -- can be used to signify when to stop parsing options.
- \\This is necessary when the input path begins with a forward slash.
+ \\This avoids ambiguity when the input path begins with a forward slash.
\\
\\Supported option prefixes are /, -, and --, so e.g. /h, -h, and --h all work.
\\Drop-in compatible with the Microsoft Resource Compiler.
@@ -159,7 +159,7 @@ pub const Options = struct {
default_language_id: ?u16 = null,
default_code_page: ?SupportedCodePage = null,
verbose: bool = false,
- symbols: std.StringArrayHashMapUnmanaged(SymbolValue) = .empty,
+ symbols: std.array_hash_map.String(SymbolValue) = .empty,
null_terminate_string_table_strings: bool = false,
max_string_literal_codepoints: u15 = lex.default_max_string_literal_codepoints,
silent_duplicate_control_ids: bool = false,
diff --git a/lib/compiler/resinator/compile.zig b/lib/compiler/resinator/compile.zig
index c8c11b58707d7c8a2ae03fea8c5db8424af4b7e8..fc814576ac5e9e86a7510d8ef2542a60078cebfa 100644
--- a/lib/compiler/resinator/compile.zig
+++ b/lib/compiler/resinator/compile.zig
@@ -2746,7 +2746,7 @@ pub const Compiler = struct {
// 1. Any permutation that does not have PRELOAD in it just uses the
// default flags.
const initial_flags = flags.*;
- var flags_set = std.enums.EnumSet(rc.CommonResourceAttributes).empty;
+ var flags_set: std.enums.EnumSet(rc.CommonResourceAttributes) = .empty;
for (tokens) |token| {
const attribute = rc.CommonResourceAttributes.map.get(token.slice(source)).?;
flags_set.insert(attribute);
@@ -2769,7 +2769,7 @@ pub const Compiler = struct {
// 3. If none of DISCARDABLE, SHARED, or PURE is specified, then PRELOAD
// implies `flags &= ~SHARED` and LOADONCALL implies `flags |= SHARED`
const shared_set = comptime blk: {
- var set = std.enums.EnumSet(rc.CommonResourceAttributes).empty;
+ var set: std.enums.EnumSet(rc.CommonResourceAttributes) = .empty;
set.insert(.discardable);
set.insert(.shared);
set.insert(.pure);
@@ -3049,7 +3049,7 @@ pub const StringTablesByLanguage = struct {
/// when the first STRINGTABLE for the language was defined, and all blocks for a given
/// language are written contiguously.
/// Using an ArrayHashMap here gives us this property for free.
- tables: std.AutoArrayHashMapUnmanaged(res.Language, StringTable) = .empty,
+ tables: std.array_hash_map.Auto(res.Language, StringTable) = .empty,
pub fn deinit(self: *StringTablesByLanguage, allocator: Allocator) void {
self.tables.deinit(allocator);
@@ -3080,7 +3080,7 @@ pub const StringTable = struct {
/// was added to the block (i.e. `STRINGTABLE { 16 "b" 0 "a" }` would then get written
/// with block ID 2 (the one with "b") first and block ID 1 (the one with "a") second).
/// Using an ArrayHashMap here gives us this property for free.
- blocks: std.AutoArrayHashMapUnmanaged(u16, Block) = .empty,
+ blocks: std.array_hash_map.Auto(u16, Block) = .empty,
pub const Block = struct {
strings: std.ArrayList(Token) = .empty,
diff --git a/lib/compiler/resinator/cvtres.zig b/lib/compiler/resinator/cvtres.zig
index 84364cea9fc0199e8ba35cd03301c4f4b1573bd6..52f3a70ca0b4162ae5fc2248c29205b686ce56bb 100644
--- a/lib/compiler/resinator/cvtres.zig
+++ b/lib/compiler/resinator/cvtres.zig
@@ -383,7 +383,7 @@ pub fn writeCoff(
fn writeSymbol(writer: *std.Io.Writer, symbol: std.coff.Symbol) !void {
try writer.writeAll(&symbol.name);
try writer.writeInt(u32, symbol.value, .little);
- try writer.writeInt(u16, @intFromEnum(symbol.section_number), .little);
+ try writer.writeInt(i16, @intFromEnum(symbol.section_number), .little);
try writer.writeInt(u8, @intFromEnum(symbol.type.base_type), .little);
try writer.writeInt(u8, @intFromEnum(symbol.type.complex_type), .little);
try writer.writeInt(u8, @intFromEnum(symbol.storage_class), .little);
@@ -439,9 +439,9 @@ pub const ResourceDataEntry = extern struct {
/// type -> name -> language
const ResourceTree = struct {
- type_to_name_map: std.ArrayHashMapUnmanaged(NameOrOrdinal, NameToLanguageMap, NameOrOrdinalHashContext, true),
- rsrc_string_table: std.ArrayHashMapUnmanaged(NameOrOrdinal, void, NameOrOrdinalHashContext, true),
- deduplicated_data: std.StringArrayHashMapUnmanaged(u32),
+ type_to_name_map: std.array_hash_map.Custom(NameOrOrdinal, NameToLanguageMap, NameOrOrdinalHashContext, true),
+ rsrc_string_table: std.array_hash_map.Custom(NameOrOrdinal, void, NameOrOrdinalHashContext, true),
+ deduplicated_data: std.array_hash_map.String(u32),
data_offsets: std.ArrayList(u32),
rsrc02_len: u32,
coff_options: CoffOptions,
@@ -451,8 +451,8 @@ const ResourceTree = struct {
resource: *const Resource,
original_index: usize,
};
- const LanguageToResourceMap = std.AutoArrayHashMapUnmanaged(Language, RelocatableResource);
- const NameToLanguageMap = std.ArrayHashMapUnmanaged(NameOrOrdinal, LanguageToResourceMap, NameOrOrdinalHashContext, true);
+ const LanguageToResourceMap = std.array_hash_map.Auto(Language, RelocatableResource);
+ const NameToLanguageMap = std.array_hash_map.Custom(NameOrOrdinal, LanguageToResourceMap, NameOrOrdinalHashContext, true);
const NameOrOrdinalHashContext = struct {
pub fn hash(self: @This(), v: NameOrOrdinal) u32 {
diff --git a/lib/compiler/resinator/source_mapping.zig b/lib/compiler/resinator/source_mapping.zig
index 7e3bc88e1da4f68447159ef8dd14fc7d27c8c37d..8ae4a70dd0a4afef5c7f346a864693a9dfc799c5 100644
--- a/lib/compiler/resinator/source_mapping.zig
+++ b/lib/compiler/resinator/source_mapping.zig
@@ -636,6 +636,10 @@ fn parseFilename(allocator: Allocator, str: []const u8) error{ OutOfMemory, Inva
if (escape_val != 0) escape_val = std.math.mul(u8, @as(u8, @intCast(escape_val)), 16) catch return error.InvalidString;
escape_val = std.math.add(u8, @as(u8, @intCast(escape_val)), digit) catch return error.InvalidString;
escape_len += 1;
+ if (escape_len == 2) {
+ filename.appendAssumeCapacity(@intCast(escape_val));
+ state = .string;
+ }
},
else => {
if (escape_len == 0) return error.InvalidString;
@@ -706,6 +710,7 @@ fn testParseFilename(expected: []const u8, input: []const u8) !void {
test parseFilename {
try testParseFilename("'\"?\\\t\n\r\x11", "\\'\\\"\\?\\\\\\t\\n\\r\\x11");
try testParseFilename("\xABz\x53", "\\xABz\\123");
+ try testParseFilename("\xABCDEF", "\\xABCDEF");
try testParseFilename("⚡⚡", "\\u26A1\\U000026A1");
try std.testing.expectError(error.InvalidString, parseFilename(std.testing.allocator, "\""));
try std.testing.expectError(error.InvalidString, parseFilename(std.testing.allocator, "\\"));
@@ -713,7 +718,6 @@ test parseFilename {
try std.testing.expectError(error.InvalidString, parseFilename(std.testing.allocator, "\\U"));
try std.testing.expectError(error.InvalidString, parseFilename(std.testing.allocator, "\\x"));
try std.testing.expectError(error.InvalidString, parseFilename(std.testing.allocator, "\\xZZ"));
- try std.testing.expectError(error.InvalidString, parseFilename(std.testing.allocator, "\\xABCDEF"));
try std.testing.expectError(error.InvalidString, parseFilename(std.testing.allocator, "\\777"));
}
diff --git a/lib/compiler/translate-c/Scope.zig b/lib/compiler/translate-c/Scope.zig
index 9e5f715600179973b8e0394e6a723e5f59ad2ba7..80817634314b1e366a06b7b09e9b0bced31bdf1a 100644
--- a/lib/compiler/translate-c/Scope.zig
+++ b/lib/compiler/translate-c/Scope.zig
@@ -7,7 +7,7 @@ const Translator = @import("Translator.zig");
const Scope = @This();
-pub const SymbolTable = std.StringArrayHashMapUnmanaged(ast.Node);
+pub const SymbolTable = std.array_hash_map.String(ast.Node);
pub const AliasList = std.ArrayList(struct {
alias: []const u8,
name: []const u8,
@@ -18,7 +18,7 @@ pub const ContainerMemberFns = struct {
container_decl_ptr: *ast.Node,
member_fns: std.ArrayList(*ast.Payload.Func) = .empty,
};
-pub const ContainerMemberFnsHashMap = std.ArrayHashMapUnmanaged(
+pub const ContainerMemberFnsHashMap = std.array_hash_map.Custom(
aro.QualType,
ContainerMemberFns,
struct {
@@ -79,7 +79,7 @@ pub const Block = struct {
/// will be used. This maps the variable's name to the Discard payload, so that if
/// the variable is subsequently referenced we can indicate that the discard should
/// be skipped during the intermediate AST -> Zig AST render step.
- variable_discards: std.StringArrayHashMapUnmanaged(*ast.Payload.Discard),
+ variable_discards: std.array_hash_map.String(*ast.Payload.Discard),
/// When the block corresponds to a function, keep track of the return type
/// so that the return expression can be cast, if necessary
@@ -209,7 +209,7 @@ pub const Root = struct {
base: Scope,
translator: *Translator,
sym_table: SymbolTable,
- blank_macros: std.StringArrayHashMapUnmanaged(void),
+ blank_macros: std.array_hash_map.String(void),
nodes: std.ArrayList(ast.Node),
container_member_fns_map: ContainerMemberFnsHashMap,
@@ -267,7 +267,7 @@ pub const Root = struct {
const gpa = root.translator.gpa;
const arena = root.translator.arena;
- var member_names: std.StringArrayHashMapUnmanaged(void) = .empty;
+ var member_names: std.array_hash_map.String(void) = .empty;
defer member_names.deinit(gpa);
for (root.container_member_fns_map.keys(), root.container_member_fns_map.values()) |container_qt, members| {
// Get the container name
diff --git a/lib/compiler/translate-c/Translator.zig b/lib/compiler/translate-c/Translator.zig
index 9e27ee5e387dba6f072220bec6f64e3d0105e382..794be9361e530a25fa4da4f40693bf432838cef5 100644
--- a/lib/compiler/translate-c/Translator.zig
+++ b/lib/compiler/translate-c/Translator.zig
@@ -106,7 +106,7 @@ global_scope: *Scope.Root,
mangle_count: u32 = 0,
/// Table of declarations for enum, struct, union and typedef types.
-type_decls: std.AutoArrayHashMapUnmanaged(Node.Index, []const u8) = .empty,
+type_decls: std.array_hash_map.Auto(Node.Index, []const u8) = .empty,
/// Table of record decls that have been demoted to opaques.
opaque_demotes: std.HashMapUnmanaged(QualType, void, QualTypeHashContext, std.hash_map.default_max_load_percentage) = .empty,
/// Table of unnamed enums and records that are child types of typedefs.
@@ -123,7 +123,7 @@ anonymous_record_field_names: std.HashMapUnmanaged(
/// a list of names that we found by visiting all the top level decls without
/// translating them. The other maps are updated as we translate; this one is updated
/// up front in a pre-processing step.
-global_names: std.StringArrayHashMapUnmanaged(void) = .empty,
+global_names: std.array_hash_map.String(void) = .empty,
/// This is similar to `global_names`, but contains names which we would
/// *like* to use, but do not strictly *have* to if they are unavailable.
@@ -132,11 +132,11 @@ global_names: std.StringArrayHashMapUnmanaged(void) = .empty,
/// may be mangled.
/// This is distinct from `global_names` so we can detect at a type
/// declaration whether or not the name is available.
-weak_global_names: std.StringArrayHashMapUnmanaged(void) = .empty,
+weak_global_names: std.array_hash_map.String(void) = .empty,
/// Set of identifiers known to refer to typedef declarations.
/// Used when parsing macros.
-typedefs: std.StringArrayHashMapUnmanaged(void) = .empty,
+typedefs: std.array_hash_map.String(void) = .empty,
/// The lhs lval of a compound assignment expression.
compound_assign_dummy: ?ZigNode = null,
diff --git a/lib/compiler_rt.zig b/lib/compiler_rt.zig
index 04370b2fd86f6febda129b81a516173f3f8f6e1d..73bb514565d0ee57ed721b7b366ebea209cff107 100644
--- a/lib/compiler_rt.zig
+++ b/lib/compiler_rt.zig
@@ -404,10 +404,6 @@ pub const want_ppc_abi = builtin.cpu.arch.isPowerPC();
pub const want_float_exceptions = !builtin.cpu.arch.isWasm();
-// Libcalls that involve u128 on Windows x86-64 are expected by LLVM to use the
-// calling convention of @Vector(2, u64), rather than what's standard.
-pub const want_windows_v2u64_abi = builtin.os.tag == .windows and builtin.cpu.arch == .x86_64 and !ofmt_c;
-
/// This governs whether to use these symbol names for f16/f32 conversions
/// rather than the standard names:
/// * __gnu_f2h_ieee
diff --git a/lib/compiler_rt/divdf3.zig b/lib/compiler_rt/divdf3.zig
index 489c556186e2b3c2edd865efc26adcbf16b2e179..3ad767dbf2292d403aa0e2aafbdaf20f80ff9571 100644
--- a/lib/compiler_rt/divdf3.zig
+++ b/lib/compiler_rt/divdf3.zig
@@ -4,7 +4,7 @@
const std = @import("std");
const compiler_rt = @import("../compiler_rt.zig");
-const symbol = @import("../compiler_rt.zig").symbol;
+const symbol = compiler_rt.symbol;
const normalize = compiler_rt.normalize;
const wideMultiply = compiler_rt.wideMultiply;
@@ -189,14 +189,13 @@ inline fn div(a: f64, b: f64) f64 {
const writtenExponent = quotientExponent +% exponentBias;
+ const round = @intFromBool((residual << 1) >= bSignificand);
+
if (writtenExponent >= maxExponent) {
// If we have overflowed the exponent, return infinity.
return @bitCast(infRep | quotientSign);
} else if (writtenExponent < 1) {
if (writtenExponent == 0) {
- // Check whether the rounded result is normal.
- const round = @intFromBool((residual << 1) > bSignificand);
- // Clear the implicit bit.
var absResult = quotient & significandMask;
// Round.
absResult += round;
@@ -205,11 +204,16 @@ inline fn div(a: f64, b: f64) f64 {
return @bitCast(absResult | quotientSign);
}
}
- // Flush denormals to zero. In the future, it would be nice to add
- // code to round them correctly.
- return @bitCast(quotientSign);
+
+ const roundedQuotient = quotient +% round;
+ const shiftAmount: u32 = @intCast(1 - writtenExponent);
+ if (shiftAmount > significandBits + 1) {
+ return @bitCast(quotientSign);
+ }
+
+ const denormQuotient = roundedQuotient >> @as(std.math.Log2Int(Z), @intCast(shiftAmount));
+ return @bitCast((denormQuotient & significandMask) | quotientSign);
} else {
- const round = @intFromBool((residual << 1) > bSignificand);
// Clear the implicit bit
var absResult = quotient & significandMask;
// Insert the exponent
diff --git a/lib/compiler_rt/divdf3_test.zig b/lib/compiler_rt/divdf3_test.zig
index 1524f9833fef3a4eb2022e302ee7d697f32b4797..45de9b27ef794706fc6e0e297f4289be3ae549fc 100644
--- a/lib/compiler_rt/divdf3_test.zig
+++ b/lib/compiler_rt/divdf3_test.zig
@@ -2,8 +2,15 @@
//
// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/test/builtins/Unit/divdf3_test.c
+const std = @import("std");
+const math = std.math;
+const testing = std.testing;
+
const __divdf3 = @import("divdf3.zig").__divdf3;
-const testing = @import("std").testing;
+
+const nanRep: u64 = @as(u64, @bitCast(math.nan(f64)));
+const infRep: u64 = @as(u64, @bitCast(math.inf(f64)));
+const negInfRep: u64 = @as(u64, @bitCast(-math.inf(f64)));
fn compareResultD(result: f64, expected: u64) bool {
const rep: u64 = @bitCast(result);
@@ -12,7 +19,7 @@ fn compareResultD(result: f64, expected: u64) bool {
return true;
}
// test other possible NaN representation(signal NaN)
- else if (expected == 0x7ff8000000000000) {
+ else if (expected == nanRep) {
if ((rep & 0x7ff0000000000000) == 0x7ff0000000000000 and
(rep & 0xfffffffffffff) > 0)
{
@@ -32,4 +39,28 @@ test "divdf3" {
try test__divdf3(1.0, 3.0, 0x3fd5555555555555);
try test__divdf3(4.450147717014403e-308, 2.0, 0x10000000000000);
try test__divdf3(1.0, 0x1.fffffffffffffp-1, 0x3ff0000000000001);
+
+ try test__divdf3(math.nan(f64), 1.0, nanRep);
+ try test__divdf3(1.0, math.nan(f64), nanRep);
+
+ try test__divdf3(math.inf(f64), 1.0, infRep);
+ try test__divdf3(-math.inf(f64), 1.0, negInfRep);
+ try test__divdf3(1.0, math.inf(f64), 0x0000000000000000);
+ try test__divdf3(1.0, -math.inf(f64), 0x8000000000000000);
+
+ try test__divdf3(math.inf(f64), math.inf(f64), nanRep);
+ try test__divdf3(0.0, 0.0, nanRep);
+ try test__divdf3(-0.0, 0.0, nanRep);
+
+ try test__divdf3(0.0, 1.0, 0x0000000000000000);
+ try test__divdf3(-0.0, 1.0, 0x8000000000000000);
+ try test__divdf3(1.0, 0.0, infRep);
+ try test__divdf3(1.0, -0.0, negInfRep);
+
+ try test__divdf3(0x1p-1022, 0x1p52, 0x0000000000000001);
+ try test__divdf3(-0x1p-1022, 0x1p52, 0x8000000000000001);
+ try test__divdf3(0x1p-1022, -0x1p52, 0x8000000000000001);
+
+ try test__divdf3(1.0, 0x1p1023, 0x0008000000000000);
+ try test__divdf3(-1.0, 0x1p1023, 0x8008000000000000);
}
diff --git a/lib/compiler_rt/divsf3.zig b/lib/compiler_rt/divsf3.zig
index dc017dbde1fee6973e140a25e9b416f701460459..c0fbcb92b743fff4e12db533d7694210e7ebb0a2 100644
--- a/lib/compiler_rt/divsf3.zig
+++ b/lib/compiler_rt/divsf3.zig
@@ -5,7 +5,7 @@
const std = @import("std");
const compiler_rt = @import("../compiler_rt.zig");
-const symbol = @import("../compiler_rt.zig").symbol;
+const symbol = compiler_rt.symbol;
const normalize = compiler_rt.normalize;
comptime {
@@ -170,14 +170,14 @@ inline fn div(a: f32, b: f32) f32 {
const writtenExponent = quotientExponent +% exponentBias;
+ const round = @intFromBool((residual << 1) >= bSignificand);
+
if (writtenExponent >= maxExponent) {
// If we have overflowed the exponent, return infinity.
return @bitCast(infRep | quotientSign);
} else if (writtenExponent < 1) {
if (writtenExponent == 0) {
// Check whether the rounded result is normal.
- const round = @intFromBool((residual << 1) > bSignificand);
- // Clear the implicit bit.
var absResult = quotient & significandMask;
// Round.
absResult += round;
@@ -186,11 +186,16 @@ inline fn div(a: f32, b: f32) f32 {
return @bitCast(absResult | quotientSign);
}
}
- // Flush denormals to zero. In the future, it would be nice to add
- // code to round them correctly.
- return @bitCast(quotientSign);
+
+ const roundedQuotient = quotient +% round;
+ const shiftAmount: u32 = @intCast(1 - writtenExponent);
+ if (shiftAmount > significandBits + 1) {
+ return @bitCast(quotientSign);
+ }
+
+ const denormQuotient = roundedQuotient >> @as(std.math.Log2Int(Z), @intCast(shiftAmount));
+ return @bitCast((denormQuotient & significandMask) | quotientSign);
} else {
- const round = @intFromBool((residual << 1) > bSignificand);
// Clear the implicit bit
var absResult = quotient & significandMask;
// Insert the exponent
diff --git a/lib/compiler_rt/divsf3_test.zig b/lib/compiler_rt/divsf3_test.zig
index 1af93bc77c80e2c97020d2dd63b17a421a86293e..c457915e49cd41986f1470b2f868398cfad855e9 100644
--- a/lib/compiler_rt/divsf3_test.zig
+++ b/lib/compiler_rt/divsf3_test.zig
@@ -2,8 +2,15 @@
//
// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/test/builtins/Unit/divsf3_test.c
+const std = @import("std");
+const math = std.math;
+const testing = std.testing;
+
const __divsf3 = @import("divsf3.zig").__divsf3;
-const testing = @import("std").testing;
+
+const nanRep: u32 = @as(u32, @bitCast(math.nan(f32)));
+const infRep: u32 = @as(u32, @bitCast(math.inf(f32)));
+const negInfRep: u32 = @as(u32, @bitCast(-math.inf(f32)));
fn compareResultF(result: f32, expected: u32) bool {
const rep: u32 = @bitCast(result);
@@ -12,7 +19,7 @@ fn compareResultF(result: f32, expected: u32) bool {
return true;
}
// test other possible NaN representation(signal NaN)
- else if (expected == 0x7fc00000) {
+ else if (expected == nanRep) {
if ((rep & 0x7f800000) == 0x7f800000 and
(rep & 0x7fffff) > 0)
{
@@ -32,4 +39,28 @@ test "divsf3" {
try test__divsf3(1.0, 3.0, 0x3EAAAAAB);
try test__divsf3(2.3509887e-38, 2.0, 0x00800000);
try test__divsf3(1.0, 0x1.fffffep-1, 0x3f800001);
+
+ try test__divsf3(math.nan(f32), 1.0, nanRep);
+ try test__divsf3(1.0, math.nan(f32), nanRep);
+
+ try test__divsf3(math.inf(f32), 1.0, infRep);
+ try test__divsf3(-math.inf(f32), 1.0, negInfRep);
+ try test__divsf3(1.0, math.inf(f32), 0x00000000);
+ try test__divsf3(1.0, -math.inf(f32), 0x80000000);
+
+ try test__divsf3(math.inf(f32), math.inf(f32), nanRep);
+ try test__divsf3(0.0, 0.0, nanRep);
+ try test__divsf3(-0.0, 0.0, nanRep);
+
+ try test__divsf3(0.0, 1.0, 0x00000000);
+ try test__divsf3(-0.0, 1.0, 0x80000000);
+ try test__divsf3(1.0, 0.0, infRep);
+ try test__divsf3(1.0, -0.0, negInfRep);
+
+ try test__divsf3(0x1p-126, 0x1p23, 0x00000001);
+ try test__divsf3(-0x1p-126, 0x1p23, 0x80000001);
+ try test__divsf3(0x1p-126, -0x1p23, 0x80000001);
+
+ try test__divsf3(1.0, 0x1p127, 0x00400000);
+ try test__divsf3(-1.0, 0x1p127, 0x80400000);
}
diff --git a/lib/compiler_rt/divtf3_test.zig b/lib/compiler_rt/divtf3_test.zig
index 4573d2ed85a6d7581a230ccfe5264de463a57ea6..4d10e5c39d7dc61b1c317364750757148635543d 100644
--- a/lib/compiler_rt/divtf3_test.zig
+++ b/lib/compiler_rt/divtf3_test.zig
@@ -30,14 +30,19 @@ fn test__divtf3(a: f128, b: f128, expectedHi: u64, expectedLo: u64) !void {
}
test "divtf3" {
- // NaN / any = NaN
try test__divtf3(math.nan(f128), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0);
- // inf / any(except inf and nan) = inf
+ try test__divtf3(0x1.23456789abcdefp+5, math.nan(f128), 0x7fff800000000000, 0);
try test__divtf3(math.inf(f128), 0x1.23456789abcdefp+5, 0x7fff000000000000, 0);
- // inf / inf = nan
+ try test__divtf3(-math.inf(f128), 0x1.23456789abcdefp+5, 0xffff000000000000, 0);
+ try test__divtf3(0x1.23456789abcdefp+5, math.inf(f128), 0, 0);
+ try test__divtf3(0x1.23456789abcdefp+5, -math.inf(f128), 0x8000000000000000, 0);
try test__divtf3(math.inf(f128), math.inf(f128), 0x7fff800000000000, 0);
- // inf / nan = nan
- try test__divtf3(math.inf(f128), math.nan(f128), 0x7fff800000000000, 0);
+ try test__divtf3(0.0, 0.0, 0x7fff800000000000, 0);
+ try test__divtf3(-0.0, 0.0, 0x7fff800000000000, 0);
+ try test__divtf3(0.0, 1.0, 0, 0);
+ try test__divtf3(-0.0, 1.0, 0x8000000000000000, 0);
+ try test__divtf3(1.0, 0.0, 0x7fff000000000000, 0);
+ try test__divtf3(1.0, -0.0, 0xffff000000000000, 0);
try test__divtf3(0x1.a23b45362464523375893ab4cdefp+5, 0x1.eedcbaba3a94546558237654321fp-1, 0x4004b0b72924d407, 0x0717e84356c6eba2);
try test__divtf3(0x1.a2b34c56d745382f9abf2c3dfeffp-50, 0x1.ed2c3ba15935332532287654321fp-9, 0x3fd5b2af3f828c9b, 0x40e51f64cde8b1f2);
diff --git a/lib/compiler_rt/divxf3_test.zig b/lib/compiler_rt/divxf3_test.zig
index 0aec97b54d07d72c549a5b59f0cfd753807b7507..cb897a1014022d50e8cb93043749b033b56af55d 100644
--- a/lib/compiler_rt/divxf3_test.zig
+++ b/lib/compiler_rt/divxf3_test.zig
@@ -4,6 +4,10 @@ const testing = std.testing;
const __divxf3 = @import("divxf3.zig").__divxf3;
+const nanRep: u80 = @as(u80, @bitCast(math.nan(f80)));
+const infRep: u80 = @as(u80, @bitCast(math.inf(f80)));
+const negInfRep: u80 = @as(u80, @bitCast(-math.inf(f80)));
+
fn compareResult(result: f80, expected: u80) bool {
const rep: u80 = @bitCast(result);
@@ -39,14 +43,19 @@ fn test__divxf3(a: f80, b: f80) !void {
}
test "divxf3" {
- // NaN / any = NaN
- try expect__divxf3_result(math.nan(f80), 0x1.23456789abcdefp+5, 0x7fffC000000000000000);
- // inf / any(except inf and nan) = inf
- try expect__divxf3_result(math.inf(f80), 0x1.23456789abcdefp+5, 0x7fff8000000000000000);
- // inf / inf = nan
- try expect__divxf3_result(math.inf(f80), math.inf(f80), 0x7fffC000000000000000);
- // inf / nan = nan
- try expect__divxf3_result(math.inf(f80), math.nan(f80), 0x7fffC000000000000000);
+ try expect__divxf3_result(math.nan(f80), 0x1.23456789abcdefp+5, nanRep);
+ try expect__divxf3_result(0x1.23456789abcdefp+5, math.nan(f80), nanRep);
+ try expect__divxf3_result(math.inf(f80), 0x1.23456789abcdefp+5, infRep);
+ try expect__divxf3_result(-math.inf(f80), 0x1.23456789abcdefp+5, negInfRep);
+ try expect__divxf3_result(0x1.23456789abcdefp+5, math.inf(f80), 0x0);
+ try expect__divxf3_result(0x1.23456789abcdefp+5, -math.inf(f80), 0x80000000000000000000);
+ try expect__divxf3_result(math.inf(f80), math.inf(f80), nanRep);
+ try expect__divxf3_result(0.0, 0.0, nanRep);
+ try expect__divxf3_result(-0.0, 0.0, nanRep);
+ try expect__divxf3_result(0.0, 1.0, 0x0);
+ try expect__divxf3_result(-0.0, 1.0, 0x80000000000000000000);
+ try expect__divxf3_result(1.0, 0.0, infRep);
+ try expect__divxf3_result(1.0, -0.0, negInfRep);
try test__divxf3(0x1.a23b45362464523375893ab4cdefp+5, 0x1.eedcbaba3a94546558237654321fp-1);
try test__divxf3(0x1.a2b34c56d745382f9abf2c3dfeffp-50, 0x1.ed2c3ba15935332532287654321fp-9);
diff --git a/lib/compiler_rt/fixdfti.zig b/lib/compiler_rt/fixdfti.zig
index 4717fd7b59f1b17854dfc742b73bfd506c1522fd..ff7434d63da148afc20b22bbfb54d6c1bdd17822 100644
--- a/lib/compiler_rt/fixdfti.zig
+++ b/lib/compiler_rt/fixdfti.zig
@@ -3,19 +3,9 @@ const intFromFloat = @import("./int_from_float.zig").intFromFloat;
const symbol = @import("../compiler_rt.zig").symbol;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__fixdfti_windows_x86_64, "__fixdfti");
- } else {
- symbol(&__fixdfti, "__fixdfti");
- }
+ symbol(&__fixdfti, "__fixdfti");
}
pub fn __fixdfti(a: f64) callconv(.c) i128 {
return intFromFloat(i128, a);
}
-
-const v2u64 = @Vector(2, u64);
-
-fn __fixdfti_windows_x86_64(a: f64) callconv(.c) v2u64 {
- return @bitCast(intFromFloat(i128, a));
-}
diff --git a/lib/compiler_rt/fixsfti.zig b/lib/compiler_rt/fixsfti.zig
index 0980012a453eba643ea0af0206d8256bab481990..121eff084d58a00726ed140a0d4f4cacafdce87b 100644
--- a/lib/compiler_rt/fixsfti.zig
+++ b/lib/compiler_rt/fixsfti.zig
@@ -4,19 +4,9 @@ const symbol = compiler_rt.symbol;
const intFromFloat = @import("./int_from_float.zig").intFromFloat;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__fixsfti_windows_x86_64, "__fixsfti");
- } else {
- symbol(&__fixsfti, "__fixsfti");
- }
+ symbol(&__fixsfti, "__fixsfti");
}
pub fn __fixsfti(a: f32) callconv(.c) i128 {
return intFromFloat(i128, a);
}
-
-const v2u64 = @Vector(2, u64);
-
-fn __fixsfti_windows_x86_64(a: f32) callconv(.c) v2u64 {
- return @bitCast(intFromFloat(i128, a));
-}
diff --git a/lib/compiler_rt/fixtfti.zig b/lib/compiler_rt/fixtfti.zig
index cb642d61664a2780003a78cc0293f80657b516a5..0aac298ca2c4d0fa3f8d7fd02cf1290f98929c2b 100644
--- a/lib/compiler_rt/fixtfti.zig
+++ b/lib/compiler_rt/fixtfti.zig
@@ -3,21 +3,11 @@ const intFromFloat = @import("./int_from_float.zig").intFromFloat;
const symbol = @import("../compiler_rt.zig").symbol;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__fixtfti_windows_x86_64, "__fixtfti");
- } else {
- if (compiler_rt.want_ppc_abi)
- symbol(&__fixtfti, "__fixkfti");
- symbol(&__fixtfti, "__fixtfti");
- }
+ if (compiler_rt.want_ppc_abi)
+ symbol(&__fixtfti, "__fixkfti");
+ symbol(&__fixtfti, "__fixtfti");
}
pub fn __fixtfti(a: f128) callconv(.c) i128 {
return intFromFloat(i128, a);
}
-
-const v2u64 = @Vector(2, u64);
-
-fn __fixtfti_windows_x86_64(a: f128) callconv(.c) v2u64 {
- return @bitCast(intFromFloat(i128, a));
-}
diff --git a/lib/compiler_rt/fixunsdfti.zig b/lib/compiler_rt/fixunsdfti.zig
index 95d15ac3138eab9596b375c50814521c4aac5416..1a634baaf5a6da399abaebb3e236ea5c02005ead 100644
--- a/lib/compiler_rt/fixunsdfti.zig
+++ b/lib/compiler_rt/fixunsdfti.zig
@@ -3,19 +3,9 @@ const symbol = @import("../compiler_rt.zig").symbol;
const intFromFloat = @import("./int_from_float.zig").intFromFloat;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__fixunsdfti_windows_x86_64, "__fixunsdfti");
- } else {
- symbol(&__fixunsdfti, "__fixunsdfti");
- }
+ symbol(&__fixunsdfti, "__fixunsdfti");
}
pub fn __fixunsdfti(a: f64) callconv(.c) u128 {
return intFromFloat(u128, a);
}
-
-const v2u64 = @Vector(2, u64);
-
-fn __fixunsdfti_windows_x86_64(a: f64) callconv(.c) v2u64 {
- return @bitCast(intFromFloat(u128, a));
-}
diff --git a/lib/compiler_rt/fixunshfti.zig b/lib/compiler_rt/fixunshfti.zig
index a090027196937f25b649dcd6d8e3d589e7cd4083..3dc7a5f99390d05606bb09298651e1d4482e3ab6 100644
--- a/lib/compiler_rt/fixunshfti.zig
+++ b/lib/compiler_rt/fixunshfti.zig
@@ -3,19 +3,9 @@ const intFromFloat = @import("./int_from_float.zig").intFromFloat;
const symbol = @import("../compiler_rt.zig").symbol;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__fixunshfti_windows_x86_64, "__fixunshfti");
- } else {
- symbol(&__fixunshfti, "__fixunshfti");
- }
+ symbol(&__fixunshfti, "__fixunshfti");
}
pub fn __fixunshfti(a: f16) callconv(.c) u128 {
return intFromFloat(u128, a);
}
-
-const v2u64 = @Vector(2, u64);
-
-fn __fixunshfti_windows_x86_64(a: f16) callconv(.c) v2u64 {
- return @bitCast(intFromFloat(u128, a));
-}
diff --git a/lib/compiler_rt/fixunssfti.zig b/lib/compiler_rt/fixunssfti.zig
index da46f43d5bc111b53ee317a70a0456d3ea554853..6824afcde4b518642189696a47c0983047dd47c3 100644
--- a/lib/compiler_rt/fixunssfti.zig
+++ b/lib/compiler_rt/fixunssfti.zig
@@ -4,19 +4,9 @@ const intFromFloat = @import("./int_from_float.zig").intFromFloat;
const symbol = @import("../compiler_rt.zig").symbol;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__fixunssfti_windows_x86_64, "__fixunssfti");
- } else {
- symbol(&__fixunssfti, "__fixunssfti");
- }
+ symbol(&__fixunssfti, "__fixunssfti");
}
pub fn __fixunssfti(a: f32) callconv(.c) u128 {
return intFromFloat(u128, a);
}
-
-const v2u64 = @Vector(2, u64);
-
-fn __fixunssfti_windows_x86_64(a: f32) callconv(.c) v2u64 {
- return @bitCast(intFromFloat(u128, a));
-}
diff --git a/lib/compiler_rt/fixunstfti.zig b/lib/compiler_rt/fixunstfti.zig
index 81c2a160957c20492c3781353a4042807d7ed0af..78c6b1e8f7b90aa5d90a957920e949bb0aa2cbc0 100644
--- a/lib/compiler_rt/fixunstfti.zig
+++ b/lib/compiler_rt/fixunstfti.zig
@@ -4,21 +4,11 @@ const symbol = compiler_rt.symbol;
const intFromFloat = @import("./int_from_float.zig").intFromFloat;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__fixunstfti_windows_x86_64, "__fixunstfti");
- } else {
- if (compiler_rt.want_ppc_abi)
- symbol(&__fixunstfti, "__fixunskfti");
- symbol(&__fixunstfti, "__fixunstfti");
- }
+ if (compiler_rt.want_ppc_abi)
+ symbol(&__fixunstfti, "__fixunskfti");
+ symbol(&__fixunstfti, "__fixunstfti");
}
pub fn __fixunstfti(a: f128) callconv(.c) u128 {
return intFromFloat(u128, a);
}
-
-const v2u64 = @Vector(2, u64);
-
-fn __fixunstfti_windows_x86_64(a: f128) callconv(.c) v2u64 {
- return @bitCast(intFromFloat(u128, a));
-}
diff --git a/lib/compiler_rt/fixunsxfti.zig b/lib/compiler_rt/fixunsxfti.zig
index 24296dd416c85377442b95e1dcdea92ed27a96e7..064c1352c9045870c1a984850f71c86fcf6e8e61 100644
--- a/lib/compiler_rt/fixunsxfti.zig
+++ b/lib/compiler_rt/fixunsxfti.zig
@@ -4,19 +4,9 @@ const symbol = compiler_rt.symbol;
const intFromFloat = @import("./int_from_float.zig").intFromFloat;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__fixunsxfti_windows_x86_64, "__fixunsxfti");
- } else {
- symbol(&__fixunsxfti, "__fixunsxfti");
- }
+ symbol(&__fixunsxfti, "__fixunsxfti");
}
pub fn __fixunsxfti(a: f80) callconv(.c) u128 {
return intFromFloat(u128, a);
}
-
-const v2u64 = @Vector(2, u64);
-
-fn __fixunsxfti_windows_x86_64(a: f80) callconv(.c) v2u64 {
- return @bitCast(intFromFloat(u128, a));
-}
diff --git a/lib/compiler_rt/float_from_int.zig b/lib/compiler_rt/float_from_int.zig
index d275e181799b4de5ef87a12933beca8e355af935..548d027accbb674e1ecbaeb77ef01a5491e256bc 100644
--- a/lib/compiler_rt/float_from_int.zig
+++ b/lib/compiler_rt/float_from_int.zig
@@ -64,10 +64,21 @@ inline fn limb(limbs: []const u32, index: usize) u32 {
pub inline fn floatFromBigInt(comptime T: type, comptime signedness: std.builtin.Signedness, x: []const u32) T {
switch (x.len) {
0 => return 0,
- inline 1...4 => |limbs_len| return @floatFromInt(@as(
- @Int(signedness, 32 * limbs_len),
- @bitCast(x[0..limbs_len].*),
- )),
+ inline 1...4 => |limbs_len| {
+ const low_to_high: [limbs_len]u32 = switch (@import("builtin").cpu.arch.endian()) {
+ .little => x[0..limbs_len].*,
+ .big => switch (limbs_len) {
+ 1 => .{x[0]},
+ 2 => .{ x[1], x[0] },
+ 3 => .{ x[2], x[1], x[0] },
+ 4 => .{ x[3], x[2], x[1], x[0] },
+ else => comptime unreachable,
+ },
+ };
+ const I = @Int(signedness, 32 * limbs_len);
+ const int: I = @bitCast(low_to_high);
+ return @floatFromInt(int);
+ },
else => {},
}
diff --git a/lib/compiler_rt/floattidf.zig b/lib/compiler_rt/floattidf.zig
index 5fd6b4c0f68782935fb6b90713228dabfab7d928..02298705324edcd49b36f69a64c0c78873ecb57b 100644
--- a/lib/compiler_rt/floattidf.zig
+++ b/lib/compiler_rt/floattidf.zig
@@ -3,17 +3,9 @@ const symbol = @import("../compiler_rt.zig").symbol;
const floatFromInt = @import("./float_from_int.zig").floatFromInt;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__floattidf_windows_x86_64, "__floattidf");
- } else {
- symbol(&__floattidf, "__floattidf");
- }
+ symbol(&__floattidf, "__floattidf");
}
pub fn __floattidf(a: i128) callconv(.c) f64 {
return floatFromInt(f64, a);
}
-
-fn __floattidf_windows_x86_64(a: @Vector(2, u64)) callconv(.c) f64 {
- return floatFromInt(f64, @as(i128, @bitCast(a)));
-}
diff --git a/lib/compiler_rt/floattihf.zig b/lib/compiler_rt/floattihf.zig
index 643849f48e25ca2735ab813dd152f3b93015fcbf..a751e3142c5b273819199105a6848c0280aee3c5 100644
--- a/lib/compiler_rt/floattihf.zig
+++ b/lib/compiler_rt/floattihf.zig
@@ -4,17 +4,9 @@ const symbol = compiler_rt.symbol;
const floatFromInt = @import("./float_from_int.zig").floatFromInt;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__floattihf_windows_x86_64, "__floattihf");
- } else {
- symbol(&__floattihf, "__floattihf");
- }
+ symbol(&__floattihf, "__floattihf");
}
pub fn __floattihf(a: i128) callconv(.c) f16 {
return floatFromInt(f16, a);
}
-
-fn __floattihf_windows_x86_64(a: @Vector(2, u64)) callconv(.c) f16 {
- return floatFromInt(f16, @as(i128, @bitCast(a)));
-}
diff --git a/lib/compiler_rt/floattisf.zig b/lib/compiler_rt/floattisf.zig
index 8926105d2df059bccfdf34bebfcff4277c988504..72af61c6b6805d9bd03e6d215dd300fe7589c21f 100644
--- a/lib/compiler_rt/floattisf.zig
+++ b/lib/compiler_rt/floattisf.zig
@@ -3,17 +3,9 @@ const floatFromInt = @import("./float_from_int.zig").floatFromInt;
const symbol = @import("../compiler_rt.zig").symbol;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__floattisf_windows_x86_64, "__floattisf");
- } else {
- symbol(&__floattisf, "__floattisf");
- }
+ symbol(&__floattisf, "__floattisf");
}
pub fn __floattisf(a: i128) callconv(.c) f32 {
return floatFromInt(f32, a);
}
-
-fn __floattisf_windows_x86_64(a: @Vector(2, u64)) callconv(.c) f32 {
- return floatFromInt(f32, @as(i128, @bitCast(a)));
-}
diff --git a/lib/compiler_rt/floattitf.zig b/lib/compiler_rt/floattitf.zig
index f8e6ca80e61d65f4c765b94aade334ccd13d1ed1..3e49a68fd56912ebe7573346b6b8aea6b98b91ba 100644
--- a/lib/compiler_rt/floattitf.zig
+++ b/lib/compiler_rt/floattitf.zig
@@ -3,19 +3,11 @@ const symbol = @import("../compiler_rt.zig").symbol;
const floatFromInt = @import("./float_from_int.zig").floatFromInt;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__floattitf_windows_x86_64, "__floattitf");
- } else {
- if (compiler_rt.want_ppc_abi)
- symbol(&__floattitf, "__floattikf");
- symbol(&__floattitf, "__floattitf");
- }
+ if (compiler_rt.want_ppc_abi)
+ symbol(&__floattitf, "__floattikf");
+ symbol(&__floattitf, "__floattitf");
}
pub fn __floattitf(a: i128) callconv(.c) f128 {
return floatFromInt(f128, a);
}
-
-fn __floattitf_windows_x86_64(a: @Vector(2, u64)) callconv(.c) f128 {
- return floatFromInt(f128, @as(i128, @bitCast(a)));
-}
diff --git a/lib/compiler_rt/floattixf.zig b/lib/compiler_rt/floattixf.zig
index b69b8f9845fa858e5a05133aa4b69a5c11342ca3..be05180795aef517800c15d01c928bab4f7f19a0 100644
--- a/lib/compiler_rt/floattixf.zig
+++ b/lib/compiler_rt/floattixf.zig
@@ -4,17 +4,9 @@ const symbol = compiler_rt.symbol;
const floatFromInt = @import("./float_from_int.zig").floatFromInt;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__floattixf_windows_x86_64, "__floattixf");
- } else {
- symbol(&__floattixf, "__floattixf");
- }
+ symbol(&__floattixf, "__floattixf");
}
pub fn __floattixf(a: i128) callconv(.c) f80 {
return floatFromInt(f80, a);
}
-
-fn __floattixf_windows_x86_64(a: @Vector(2, u64)) callconv(.c) f80 {
- return floatFromInt(f80, @as(i128, @bitCast(a)));
-}
diff --git a/lib/compiler_rt/floatuntidf.zig b/lib/compiler_rt/floatuntidf.zig
index 7e08a66b97c4f18a85ec386e4fc8eda16bb972ab..b770457bc4992a5bd6237d832e2ca4c0cbed11e0 100644
--- a/lib/compiler_rt/floatuntidf.zig
+++ b/lib/compiler_rt/floatuntidf.zig
@@ -3,17 +3,9 @@ const floatFromInt = @import("./float_from_int.zig").floatFromInt;
const symbol = @import("../compiler_rt.zig").symbol;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__floatuntidf_windows_x86_64, "__floatuntidf");
- } else {
- symbol(&__floatuntidf, "__floatuntidf");
- }
+ symbol(&__floatuntidf, "__floatuntidf");
}
pub fn __floatuntidf(a: u128) callconv(.c) f64 {
return floatFromInt(f64, a);
}
-
-fn __floatuntidf_windows_x86_64(a: @Vector(2, u64)) callconv(.c) f64 {
- return floatFromInt(f64, @as(u128, @bitCast(a)));
-}
diff --git a/lib/compiler_rt/floatuntihf.zig b/lib/compiler_rt/floatuntihf.zig
index 5c50f39eaad5be332c32eb5618e8ff8011f660b1..5b4373cb7c496b0acf1a2fe6ef988872b30e8780 100644
--- a/lib/compiler_rt/floatuntihf.zig
+++ b/lib/compiler_rt/floatuntihf.zig
@@ -3,17 +3,9 @@ const symbol = @import("../compiler_rt.zig").symbol;
const floatFromInt = @import("./float_from_int.zig").floatFromInt;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__floatuntihf_windows_x86_64, "__floatuntihf");
- } else {
- symbol(&__floatuntihf, "__floatuntihf");
- }
+ symbol(&__floatuntihf, "__floatuntihf");
}
pub fn __floatuntihf(a: u128) callconv(.c) f16 {
return floatFromInt(f16, a);
}
-
-fn __floatuntihf_windows_x86_64(a: @Vector(2, u64)) callconv(.c) f16 {
- return floatFromInt(f16, @as(u128, @bitCast(a)));
-}
diff --git a/lib/compiler_rt/floatuntisf.zig b/lib/compiler_rt/floatuntisf.zig
index 5a15f7c19d9f6906bb1a485d7101976f2297ac40..de9a021476edecfcc26761133c0645d799c677da 100644
--- a/lib/compiler_rt/floatuntisf.zig
+++ b/lib/compiler_rt/floatuntisf.zig
@@ -4,17 +4,9 @@ const symbol = compiler_rt.symbol;
const floatFromInt = @import("./float_from_int.zig").floatFromInt;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__floatuntisf_windows_x86_64, "__floatuntisf");
- } else {
- symbol(&__floatuntisf, "__floatuntisf");
- }
+ symbol(&__floatuntisf, "__floatuntisf");
}
pub fn __floatuntisf(a: u128) callconv(.c) f32 {
return floatFromInt(f32, a);
}
-
-fn __floatuntisf_windows_x86_64(a: @Vector(2, u64)) callconv(.c) f32 {
- return floatFromInt(f32, @as(u128, @bitCast(a)));
-}
diff --git a/lib/compiler_rt/floatuntitf.zig b/lib/compiler_rt/floatuntitf.zig
index 6df02c5bef9a6d43c54a82e207446d049a0b84e8..47cd65cc3ff4460d937e0ccd7acabb2455ae704a 100644
--- a/lib/compiler_rt/floatuntitf.zig
+++ b/lib/compiler_rt/floatuntitf.zig
@@ -3,19 +3,11 @@ const floatFromInt = @import("./float_from_int.zig").floatFromInt;
const symbol = @import("../compiler_rt.zig").symbol;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__floatuntitf_windows_x86_64, "__floatuntitf");
- } else {
- if (compiler_rt.want_ppc_abi)
- symbol(&__floatuntitf, "__floatuntikf");
- symbol(&__floatuntitf, "__floatuntitf");
- }
+ if (compiler_rt.want_ppc_abi)
+ symbol(&__floatuntitf, "__floatuntikf");
+ symbol(&__floatuntitf, "__floatuntitf");
}
pub fn __floatuntitf(a: u128) callconv(.c) f128 {
return floatFromInt(f128, a);
}
-
-fn __floatuntitf_windows_x86_64(a: @Vector(2, u64)) callconv(.c) f128 {
- return floatFromInt(f128, @as(u128, @bitCast(a)));
-}
diff --git a/lib/compiler_rt/floatuntixf.zig b/lib/compiler_rt/floatuntixf.zig
index 27e668109fdc4eaf3315dea7e129aa70393782c7..41fb45b3a3a1b8e213c03a4ef5e847feb8d31211 100644
--- a/lib/compiler_rt/floatuntixf.zig
+++ b/lib/compiler_rt/floatuntixf.zig
@@ -4,17 +4,9 @@ const symbol = compiler_rt.symbol;
const floatFromInt = @import("./float_from_int.zig").floatFromInt;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__floatuntixf_windows_x86_64, "__floatuntixf");
- } else {
- symbol(&__floatuntixf, "__floatuntixf");
- }
+ symbol(&__floatuntixf, "__floatuntixf");
}
pub fn __floatuntixf(a: u128) callconv(.c) f80 {
return floatFromInt(f80, a);
}
-
-fn __floatuntixf_windows_x86_64(a: @Vector(2, u64)) callconv(.c) f80 {
- return floatFromInt(f80, @as(u128, @bitCast(a)));
-}
diff --git a/lib/compiler_rt/int_from_float.zig b/lib/compiler_rt/int_from_float.zig
index 494ac6cdc392001e356f713bee733c73b19069e1..5445e7fb7c6d36111d89112350b5bfc9ced375c8 100644
--- a/lib/compiler_rt/int_from_float.zig
+++ b/lib/compiler_rt/int_from_float.zig
@@ -6,32 +6,16 @@ const compiler_rt = @import("../compiler_rt.zig");
const symbol = compiler_rt.symbol;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__fixxfti_windows_x86_64, "__fixxfti");
- } else {
- symbol(&__fixxfti, "__fixxfti");
- }
-
+ symbol(&__fixxfti, "__fixxfti");
symbol(&__fixhfsi, "__fixhfsi");
symbol(&__fixhfdi, "__fixhfdi");
-
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__fixhfti_windows_x86_64, "__fixhfti");
- } else {
- symbol(&__fixhfti, "__fixhfti");
- }
+ symbol(&__fixhfti, "__fixhfti");
}
-const v2u64 = @Vector(2, u64);
-
pub fn __fixhfti(a: f16) callconv(.c) i128 {
return intFromFloat(i128, a);
}
-fn __fixhfti_windows_x86_64(a: f16) callconv(.c) v2u64 {
- return @bitCast(intFromFloat(i128, a));
-}
-
fn __fixhfdi(a: f16) callconv(.c) i64 {
return intFromFloat(i64, a);
}
@@ -44,10 +28,6 @@ pub fn __fixxfti(a: f80) callconv(.c) i128 {
return intFromFloat(i128, a);
}
-fn __fixxfti_windows_x86_64(a: f80) callconv(.c) v2u64 {
- return @bitCast(intFromFloat(i128, a));
-}
-
pub inline fn intFromFloat(comptime I: type, a: anytype) I {
const F = @TypeOf(a);
const float_bits = @typeInfo(F).float.bits;
@@ -100,10 +80,18 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul
switch (result.len) {
0 => return,
inline 1...4 => |limbs_len| {
- result[0..limbs_len].* = @bitCast(@as(
- @Int(signedness, 32 * limbs_len),
- @intFromFloat(a),
- ));
+ const I = @Int(signedness, 32 * limbs_len);
+ const low_to_high: [limbs_len]u32 = @bitCast(@as(I, @intFromFloat(a)));
+ result[0..limbs_len].* = switch (@import("builtin").cpu.arch.endian()) {
+ .little => low_to_high,
+ .big => switch (limbs_len) {
+ 1 => .{low_to_high[0]},
+ 2 => .{ low_to_high[1], low_to_high[0] },
+ 3 => .{ low_to_high[2], low_to_high[1], low_to_high[0] },
+ 4 => .{ low_to_high[3], low_to_high[2], low_to_high[1], low_to_high[0] },
+ else => comptime unreachable,
+ },
+ };
return;
},
else => {},
diff --git a/lib/compiler_rt/limb64.zig b/lib/compiler_rt/limb64.zig
index e21e2f21fdc99ee34dc04c49d922db821fd22385..56e4bfc817373e3ba1e90c3525f83ee6a99fd995 100644
--- a/lib/compiler_rt/limb64.zig
+++ b/lib/compiler_rt/limb64.zig
@@ -75,7 +75,17 @@ fn asLimbs(v: anytype) Limbs(@TypeOf(v)) {
const int_info = @typeInfo(T).int;
const limb_cnt = comptime limbCount(int_info.bits);
const ET = @Int(int_info.signedness, limb_cnt * 64);
- return @bitCast(@as(ET, v));
+ const low_to_high: Limbs(T) = @bitCast(@as(ET, v));
+ switch (endian) {
+ .little => return low_to_high,
+ .big => {
+ var swapped: Limbs(T) = undefined;
+ for (low_to_high, 0..) |x, i| {
+ swapped[limb_cnt - i - 1] = x;
+ }
+ return swapped;
+ },
+ }
}
fn limbWrap(limb: u64, is_signed: bool, bits: u16) u64 {
@@ -944,11 +954,7 @@ inline fn add3(x: *[3]u64, start: usize, v0: u64) void {
fn mulwide(a: u64, b: u64) [2]u64 {
const muldXi = @import("mulXi3.zig").muldXi;
- const limbs: [2]u64 = @bitCast(muldXi(u64, a, b));
- return switch (endian) {
- .little => limbs,
- .big => .{ limbs[1], limbs[0] },
- };
+ return @bitCast(muldXi(u64, a, b));
}
fn __mulo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) bool {
diff --git a/lib/compiler_rt/mulXi3.zig b/lib/compiler_rt/mulXi3.zig
index 9fce9754f3a748e82e55728e5e18195970e53b52..5766a070fdd9bef9da49d03890a8fa65a004cda8 100644
--- a/lib/compiler_rt/mulXi3.zig
+++ b/lib/compiler_rt/mulXi3.zig
@@ -12,11 +12,7 @@ comptime {
} else {
symbol(&__muldi3, "__muldi3");
}
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__multi3_windows_x86_64, "__multi3");
- } else {
- symbol(&__multi3, "__multi3");
- }
+ symbol(&__multi3, "__multi3");
}
pub fn __mulsi3(a: i32, b: i32) callconv(.c) i32 {
@@ -89,12 +85,6 @@ pub fn __multi3(a: i128, b: i128) callconv(.c) i128 {
return mulX(i128, a, b);
}
-const v2u64 = @Vector(2, u64);
-
-fn __multi3_windows_x86_64(a: v2u64, b: v2u64) callconv(.c) v2u64 {
- return @bitCast(mulX(i128, @as(i128, @bitCast(a)), @as(i128, @bitCast(b))));
-}
-
test {
_ = @import("mulXi3_test.zig");
}
diff --git a/lib/compiler_rt/udivmod.zig b/lib/compiler_rt/udivmod.zig
index fdb338c21ac012c786f2fba1c54f9dfc119f0c88..01b7ebe96753983c8bba0b722e846baaee1b1a75 100644
--- a/lib/compiler_rt/udivmod.zig
+++ b/lib/compiler_rt/udivmod.zig
@@ -8,40 +8,21 @@ const symbol = compiler_rt.symbol;
const HalveInt = compiler_rt.HalveInt;
comptime {
- if (compiler_rt.want_windows_v2u64_abi) {
- symbol(&__umodti3_windows_x86_64, "__umodti3");
- symbol(&__modti3_windows_x86_64, "__modti3");
- symbol(&__udivti3_windows_x86_64, "__udivti3");
- symbol(&__divti3_windows_x86_64, "__divti3");
- symbol(&__udivmodti4_windows_x86_64, "__udivmodti4");
- } else {
- symbol(&__umodti3, "__umodti3");
- symbol(&__modti3, "__modti3");
- symbol(&__udivti3, "__udivti3");
- symbol(&__divti3, "__divti3");
- symbol(&__udivmodti4, "__udivmodti4");
- }
+ symbol(&__umodti3, "__umodti3");
+ symbol(&__modti3, "__modti3");
+ symbol(&__udivti3, "__udivti3");
+ symbol(&__divti3, "__divti3");
+ symbol(&__udivmodti4, "__udivmodti4");
}
-const v128 = @Vector(2, u64);
-const v2u64 = @Vector(2, u64);
-
pub fn __udivmodti4(a: u128, b: u128, maybe_rem: ?*u128) callconv(.c) u128 {
return udivmod(u128, a, b, maybe_rem);
}
-fn __udivmodti4_windows_x86_64(a: v2u64, b: v2u64, maybe_rem: ?*u128) callconv(.c) v2u64 {
- return @bitCast(udivmod(u128, @bitCast(a), @bitCast(b), maybe_rem));
-}
-
pub fn __divti3(a: i128, b: i128) callconv(.c) i128 {
return div(a, b);
}
-fn __divti3_windows_x86_64(a: v128, b: v128) callconv(.c) v128 {
- return @bitCast(div(@bitCast(a), @bitCast(b)));
-}
-
inline fn div(a: i128, b: i128) i128 {
const s_a = a >> (128 - 1);
const s_b = b >> (128 - 1);
@@ -58,18 +39,10 @@ pub fn __udivti3(a: u128, b: u128) callconv(.c) u128 {
return udivmod(u128, a, b, null);
}
-fn __udivti3_windows_x86_64(a: v2u64, b: v2u64) callconv(.c) v2u64 {
- return @bitCast(udivmod(u128, @bitCast(a), @bitCast(b), null));
-}
-
pub fn __modti3(a: i128, b: i128) callconv(.c) i128 {
return mod(a, b);
}
-fn __modti3_windows_x86_64(a: v2u64, b: v2u64) callconv(.c) v2u64 {
- return @bitCast(mod(@as(i128, @bitCast(a)), @as(i128, @bitCast(b))));
-}
-
inline fn mod(a: i128, b: i128) i128 {
const s_a = a >> (128 - 1); // s = a < 0 ? -1 : 0
const s_b = b >> (128 - 1); // s = b < 0 ? -1 : 0
@@ -88,18 +61,6 @@ pub fn __umodti3(a: u128, b: u128) callconv(.c) u128 {
return r;
}
-fn __umodti3_windows_x86_64(a: v2u64, b: v2u64) callconv(.c) v2u64 {
- var r: u128 = undefined;
- _ = udivmod(u128, @bitCast(a), @bitCast(b), &r);
- return @bitCast(r);
-}
-
-const lo = switch (builtin.cpu.arch.endian()) {
- .big => 1,
- .little => 0,
-};
-const hi = 1 - lo;
-
// Let _u1 and _u0 be the high and low limbs of U respectively.
// Returns U / v_ and sets r = U % v_.
fn divwide_generic(comptime T: type, _u1: T, _u0: T, v_: T, r: *T) T {
@@ -191,22 +152,22 @@ pub fn udivmod(comptime T: type, a_: T, b_: T, maybe_rem: ?*T) T {
return 0;
}
- const a: [2]HalfT = @bitCast(a_);
- const b: [2]HalfT = @bitCast(b_);
+ const a: [2]HalfT = @bitCast(a_); // [0] is low bits, [1] is high bits
+ const b: [2]HalfT = @bitCast(b_); // [0] is low bits, [1] is high bits
var q: [2]HalfT = undefined;
var r: [2]HalfT = undefined;
// When the divisor fits in 64 bits, we can use an optimized path
- if (b[hi] == 0) {
- r[hi] = 0;
- if (a[hi] < b[lo]) {
+ if (b[1] == 0) {
+ r[1] = 0;
+ if (a[1] < b[0]) {
// The result fits in 64 bits
- q[hi] = 0;
- q[lo] = divwide(HalfT, a[hi], a[lo], b[lo], &r[lo]);
+ q[1] = 0;
+ q[0] = divwide(HalfT, a[1], a[0], b[0], &r[0]);
} else {
// First, divide with the high part to get the remainder. After that a_hi < b_lo.
- q[hi] = a[hi] / b[lo];
- q[lo] = divwide(HalfT, a[hi] % b[lo], a[lo], b[lo], &r[lo]);
+ q[1] = a[1] / b[0];
+ q[0] = divwide(HalfT, a[1] % b[0], a[0], b[0], &r[0]);
}
if (maybe_rem) |rem| {
rem.* = @bitCast(r);
@@ -214,21 +175,21 @@ pub fn udivmod(comptime T: type, a_: T, b_: T, maybe_rem: ?*T) T {
return @bitCast(q);
}
- // Large-divisor case: b[hi] != 0, so the quotient fits in one HalfT word.
+ // Large-divisor case: b[1] != 0, so the quotient fits in one HalfT word.
//
// Trial quotient via divwide (Knuth Vol 2, Section 4.3.1):
// Normalize the divisor so its high half has the MSB set, then use divwide
// on the top bits to get a trial quotient that is at most 1 too large.
// This replaces the O(shift) bit-by-bit loop with O(1) operations.
- const s: Log2Int(HalfT) = @intCast(@clz(b[hi]));
+ const s: Log2Int(HalfT) = @intCast(@clz(b[1]));
if (s == 0) {
- // b[hi] already has its MSB set, so b >= 2^(T_bits - 1). Since a >= b
+ // b[1] already has its MSB set, so b >= 2^(T_bits - 1). Since a >= b
// (we passed the b_ > a_ check), a >= 2^(T_bits - 1) too, meaning
- // a[hi] also has its MSB set. Therefore a / b < 2, and the quotient
+ // a[1] also has its MSB set. Therefore a / b < 2, and the quotient
// is exactly 1.
q = @bitCast(@as(T, 0));
- q[lo] = 1;
+ q[0] = 1;
if (maybe_rem) |rem| {
rem.* = a_ - b_;
}
@@ -240,12 +201,12 @@ pub fn udivmod(comptime T: type, a_: T, b_: T, maybe_rem: ?*T) T {
std.math.IntFittingRange(0, half_bits),
@intCast(s),
));
- const bn_hi: HalfT = (b[hi] << s) | (b[lo] >> sr);
+ const bn_hi: HalfT = (b[1] << s) | (b[0] >> sr);
// Trial numerator: the top (half_bits + s) bits of (a << s), as [a2:a1].
// a2 < bn_hi is guaranteed since a2 < 2^s and bn_hi >= 2^(half_bits - 1).
- const a2: HalfT = a[hi] >> sr;
- const a1: HalfT = (a[hi] << s) | (a[lo] >> sr);
+ const a2: HalfT = a[1] >> sr;
+ const a1: HalfT = (a[1] << s) | (a[0] >> sr);
// Trial quotient via divwide: q_hat = floor([a2:a1] / bn_hi).
// By Knuth's theorem (normalized divisor), q <= q_hat <= q + 1.
@@ -256,42 +217,42 @@ pub fn udivmod(comptime T: type, a_: T, b_: T, maybe_rem: ?*T) T {
// Compute the product using HalfT * HalfT -> T widening multiplications,
// which are native single-instruction ops when HalfT fits in a register
// (e.g. u64 * u64 -> u128 via mulq on x86_64, mul on aarch64).
- // product = q_hat * [b[hi]:b[lo]] = [p_top : p_mid : p_lo] (3 half-words)
- const prod_lo: T = @as(T, q_hat) * @as(T, b[lo]);
- const prod_hi: T = @as(T, q_hat) * @as(T, b[hi]);
+ // product = q_hat * [b[1]:b[0]] = [p_top : p_mid : p_lo] (3 half-words)
+ const prod_lo: T = @as(T, q_hat) * @as(T, b[0]);
+ const prod_hi: T = @as(T, q_hat) * @as(T, b[1]);
const prod_lo_parts: [2]HalfT = @bitCast(prod_lo);
const prod_hi_parts: [2]HalfT = @bitCast(prod_hi);
- const mid_add = @addWithOverflow(prod_hi_parts[lo], prod_lo_parts[hi]);
+ const mid_add = @addWithOverflow(prod_hi_parts[0], prod_lo_parts[1]);
var p_mid: HalfT = mid_add[0];
- const p_top: HalfT = prod_hi_parts[hi] +% @as(HalfT, mid_add[1]);
- var p_lo: HalfT = prod_lo_parts[lo];
+ const p_top: HalfT = prod_hi_parts[1] +% @as(HalfT, mid_add[1]);
+ var p_lo: HalfT = prod_lo_parts[0];
// If product > a, decrement q_hat (at most once, guaranteed by Knuth).
- if (p_top > 0 or p_mid > a[hi] or (p_mid == a[hi] and p_lo > a[lo])) {
+ if (p_top > 0 or p_mid > a[1] or (p_mid == a[1] and p_lo > a[0])) {
q_hat -= 1;
// Subtract b from the product for correct remainder computation.
// After correction, (q_hat * b) fits in T bits, so borrows into
// p_top cancel it to zero -- we only need [p_mid:p_lo].
- const sub_lo = @subWithOverflow(p_lo, b[lo]);
+ const sub_lo = @subWithOverflow(p_lo, b[0]);
p_lo = sub_lo[0];
- const sub_mid = @subWithOverflow(p_mid, b[hi]);
+ const sub_mid = @subWithOverflow(p_mid, b[1]);
const sub_mid2 = @subWithOverflow(sub_mid[0], @as(HalfT, sub_lo[1]));
p_mid = sub_mid2[0];
}
q = @bitCast(@as(T, 0));
- q[lo] = q_hat;
+ q[0] = q_hat;
if (maybe_rem) |rem| {
- // remainder = a - q_hat * b = [a[hi]:a[lo]] - [p_mid:p_lo]
+ // remainder = a - q_hat * b = [a[1]:a[0]] - [p_mid:p_lo]
// This subtraction is non-negative since q_hat <= true quotient.
- const rem_lo = @subWithOverflow(a[lo], p_lo);
- r[lo] = rem_lo[0];
- const rem_hi = @subWithOverflow(a[hi], p_mid);
+ const rem_lo = @subWithOverflow(a[0], p_lo);
+ r[0] = rem_lo[0];
+ const rem_hi = @subWithOverflow(a[1], p_mid);
const rem_hi2 = @subWithOverflow(rem_hi[0], @as(HalfT, rem_lo[1]));
- r[hi] = rem_hi2[0];
+ r[1] = rem_hi2[0];
rem.* = @bitCast(r);
}
return @bitCast(q);
diff --git a/lib/docs/wasm/Walk.zig b/lib/docs/wasm/Walk.zig
index f0601e6438f80ce8951146fcbb3024bd8f7cee0b..2d5a45d72f739abb1d763bea3d6804b3ee53859d 100644
--- a/lib/docs/wasm/Walk.zig
+++ b/lib/docs/wasm/Walk.zig
@@ -10,9 +10,9 @@ const Oom = error{OutOfMemory};
pub const Decl = @import("Decl.zig");
-pub var files: std.StringArrayHashMapUnmanaged(File) = .empty;
+pub var files: std.array_hash_map.String(File) = .empty;
pub var decls: std.ArrayList(Decl) = .empty;
-pub var modules: std.StringArrayHashMapUnmanaged(File.Index) = .empty;
+pub var modules: std.array_hash_map.String(File.Index) = .empty;
file: File.Index,
@@ -42,17 +42,17 @@ pub const Category = union(enum(u8)) {
pub const File = struct {
ast: Ast,
/// Maps identifiers to the declarations they point to.
- ident_decls: std.AutoArrayHashMapUnmanaged(Ast.TokenIndex, Ast.Node.Index) = .empty,
+ ident_decls: std.array_hash_map.Auto(Ast.TokenIndex, Ast.Node.Index) = .empty,
/// Maps field access identifiers to the containing field access node.
- token_parents: std.AutoArrayHashMapUnmanaged(Ast.TokenIndex, Ast.Node.Index) = .empty,
+ token_parents: std.array_hash_map.Auto(Ast.TokenIndex, Ast.Node.Index) = .empty,
/// Maps declarations to their global index.
- node_decls: std.AutoArrayHashMapUnmanaged(Ast.Node.Index, Decl.Index) = .empty,
+ node_decls: std.array_hash_map.Auto(Ast.Node.Index, Decl.Index) = .empty,
/// Maps function declarations to doctests.
- doctests: std.AutoArrayHashMapUnmanaged(Ast.Node.Index, Ast.Node.Index) = .empty,
+ doctests: std.array_hash_map.Auto(Ast.Node.Index, Ast.Node.Index) = .empty,
/// root node => its namespace scope
/// struct/union/enum/opaque decl node => its namespace scope
/// local var decl node => its local variable scope
- scopes: std.AutoArrayHashMapUnmanaged(Ast.Node.Index, *Scope) = .empty,
+ scopes: std.array_hash_map.Auto(Ast.Node.Index, *Scope) = .empty,
pub fn lookup_token(file: *File, token: Ast.TokenIndex) Decl.Index {
const decl_node = file.ident_decls.get(token) orelse return .none;
@@ -465,8 +465,8 @@ pub const Scope = struct {
const Namespace = struct {
base: Scope = .{ .tag = .namespace },
parent: *Scope,
- names: std.StringArrayHashMapUnmanaged(Ast.Node.Index) = .empty,
- doctests: std.StringArrayHashMapUnmanaged(Ast.Node.Index) = .empty,
+ names: std.array_hash_map.String(Ast.Node.Index) = .empty,
+ doctests: std.array_hash_map.String(Ast.Node.Index) = .empty,
decl_index: Decl.Index,
};
diff --git a/lib/docs/wasm/main.zig b/lib/docs/wasm/main.zig
index bee3e4acbcc370261f3b137d40584ea2ad2f8065..d73f2a68160ff2db197067d8cc39e40e4998a824 100644
--- a/lib/docs/wasm/main.zig
+++ b/lib/docs/wasm/main.zig
@@ -264,7 +264,7 @@ const ErrorIdentifier = packed struct(u64) {
};
var string_result: ArrayList(u8) = .empty;
-var error_set_result: std.StringArrayHashMapUnmanaged(ErrorIdentifier) = .empty;
+var error_set_result: std.array_hash_map.String(ErrorIdentifier) = .empty;
export fn decl_error_set(decl_index: Decl.Index) Slice(ErrorIdentifier) {
return Slice(ErrorIdentifier).init(decl_error_set_fallible(decl_index) catch @panic("OOM"));
@@ -305,7 +305,7 @@ fn sort_error_set_result() void {
fn addErrorsFromDecl(
decl_index: Decl.Index,
- out: *std.StringArrayHashMapUnmanaged(ErrorIdentifier),
+ out: *std.array_hash_map.String(ErrorIdentifier),
) Oom!void {
switch (decl_index.get().categorize()) {
.error_set => |node| try addErrorsFromExpr(decl_index, out, node),
@@ -316,7 +316,7 @@ fn addErrorsFromDecl(
fn addErrorsFromExpr(
decl_index: Decl.Index,
- out: *std.StringArrayHashMapUnmanaged(ErrorIdentifier),
+ out: *std.array_hash_map.String(ErrorIdentifier),
node: Ast.Node.Index,
) Oom!void {
const decl = decl_index.get();
@@ -343,7 +343,7 @@ fn addErrorsFromExpr(
fn addErrorsFromNode(
decl_index: Decl.Index,
- out: *std.StringArrayHashMapUnmanaged(ErrorIdentifier),
+ out: *std.array_hash_map.String(ErrorIdentifier),
node: Ast.Node.Index,
) Oom!void {
const decl = decl_index.get();
diff --git a/lib/fuzzer.zig b/lib/fuzzer.zig
index 37189a2b635f0a8c8774ee3d88d670e01bc37b90..acb23b66c58777bc2a6738081e23fcb52ee3c1d9 100644
--- a/lib/fuzzer.zig
+++ b/lib/fuzzer.zig
@@ -340,7 +340,7 @@ const Fuzzer = struct {
quality_buf: []Input.Best,
input_buf: []Input.Best.Map,
},
- seen_uids: std.ArrayHashMapUnmanaged(Uid, struct {
+ seen_uids: std.array_hash_map.Custom(Uid, struct {
slices: union {
ints: std.ArrayList([]u64),
bytes: std.ArrayList(Input.Data.Bytes),
@@ -505,7 +505,7 @@ const Fuzzer = struct {
}
};
- pub const UidSlices = std.ArrayHashMapUnmanaged(Uid, struct {
+ pub const UidSlices = std.array_hash_map.Custom(Uid, struct {
base: u32,
len: u32,
}, Uid.hashmap_ctx, false);
@@ -584,7 +584,7 @@ const Fuzzer = struct {
};
pub const Builder = struct {
- uid_slices: std.ArrayHashMapUnmanaged(Uid, union {
+ uid_slices: std.array_hash_map.Custom(Uid, union {
ints: std.MultiArrayList(struct {
value: u64,
order_i: u32,
diff --git a/lib/libc/include/aarch64-linux-any/asm/kvm.h b/lib/libc/include/aarch64-linux-any/asm/kvm.h
index 8b5e526846d26113ae86a97811cc1b335f8cb86e..720b270b1cabfdc3e9ce02547648d37091b8d0da 100644
--- a/lib/libc/include/aarch64-linux-any/asm/kvm.h
+++ b/lib/libc/include/aarch64-linux-any/asm/kvm.h
@@ -416,6 +416,7 @@ enum {
#define KVM_DEV_ARM_ITS_RESTORE_TABLES 2
#define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3
#define KVM_DEV_ARM_ITS_CTRL_RESET 4
+#define KVM_DEV_ARM_VGIC_USERSPACE_PPIS 5
/* Device Control API on vcpu fd */
#define KVM_ARM_VCPU_PMU_V3_CTRL 0
diff --git a/lib/libc/include/any-linux-any/drm/amdgpu_drm.h b/lib/libc/include/any-linux-any/drm/amdgpu_drm.h
index fd93842e5816e8687c3dbe5281777a31fc0bdf6d..011f02b4c51e25f3667c8495baa497c6fd79e725 100644
--- a/lib/libc/include/any-linux-any/drm/amdgpu_drm.h
+++ b/lib/libc/include/any-linux-any/drm/amdgpu_drm.h
@@ -479,7 +479,9 @@ struct drm_amdgpu_userq_signal {
* @num_syncobj_handles: A count that represents the number of syncobj handles in
* @syncobj_handles.
*/
- __u64 num_syncobj_handles;
+ __u16 num_syncobj_handles;
+ __u16 pad0;
+ __u32 pad1;
/**
* @bo_read_handles: The list of BO handles that the submitted user queue job
* is using for read only. This will update BO fences in the kernel.
@@ -563,7 +565,8 @@ struct drm_amdgpu_userq_wait {
* @num_syncobj_handles: A count that represents the number of syncobj handles in
* @syncobj_handles.
*/
- __u32 num_syncobj_handles;
+ __u16 num_syncobj_handles;
+ __u16 pad0;
/**
* @num_bo_read_handles: A count that represents the number of read BO handles in
* @bo_read_handles.
diff --git a/lib/libc/include/any-linux-any/drm/amdxdna_accel.h b/lib/libc/include/any-linux-any/drm/amdxdna_accel.h
index 0f74bcb537d2e81406992b682c533cc6cec0708f..ce26bcbdba8215abebecb5f8188a767eb7184dbf 100644
--- a/lib/libc/include/any-linux-any/drm/amdxdna_accel.h
+++ b/lib/libc/include/any-linux-any/drm/amdxdna_accel.h
@@ -156,10 +156,11 @@ struct amdxdna_drm_config_hwctx {
enum amdxdna_bo_type {
AMDXDNA_BO_INVALID = 0,
- AMDXDNA_BO_SHMEM,
- AMDXDNA_BO_DEV_HEAP,
- AMDXDNA_BO_DEV,
- AMDXDNA_BO_CMD,
+ AMDXDNA_BO_SHMEM = 1, /* Be compatible with legacy application code. */
+ AMDXDNA_BO_SHARE = 1,
+ AMDXDNA_BO_DEV_HEAP = 2,
+ AMDXDNA_BO_DEV = 3,
+ AMDXDNA_BO_CMD = 4,
};
/**
@@ -353,7 +354,8 @@ struct amdxdna_drm_query_clock_metadata {
};
enum amdxdna_sensor_type {
- AMDXDNA_SENSOR_TYPE_POWER
+ AMDXDNA_SENSOR_TYPE_POWER,
+ AMDXDNA_SENSOR_TYPE_COLUMN_UTILIZATION
};
/**
@@ -589,8 +591,37 @@ struct amdxdna_async_error {
__u64 ex_err_code;
};
+/**
+ * struct amdxdna_drm_bo_usage - all types of BO usage
+ * BOs managed by XRT/SHIM/driver is counted as internal.
+ * Others are counted as external which are managed by applications.
+ *
+ * Among all types of BOs:
+ * AMDXDNA_BO_DEV_HEAP - is counted for internal.
+ * AMDXDNA_BO_SHARE - is counted for external.
+ * AMDXDNA_BO_CMD - is counted for internal.
+ * AMDXDNA_BO_DEV - is counted by heap_usage only, not internal
+ * or external. It does not add to the total memory
+ * footprint since its mem comes from heap which is
+ * already counted as internal.
+ */
+struct amdxdna_drm_bo_usage {
+ /** @pid: The ID of the process to query from. */
+ __s64 pid;
+ /** @total_usage: Total BO size used by process. */
+ __u64 total_usage;
+ /** @internal_usage: Total internal BO size used by process. */
+ __u64 internal_usage;
+ /** @heap_usage: Total device BO size used by process. */
+ __u64 heap_usage;
+};
+
+/*
+ * Supported params in struct amdxdna_drm_get_array
+ */
#define DRM_AMDXDNA_HW_CONTEXT_ALL 0
#define DRM_AMDXDNA_HW_LAST_ASYNC_ERR 2
+#define DRM_AMDXDNA_BO_USAGE 6
/**
* struct amdxdna_drm_get_array - Get information array.
@@ -603,6 +634,12 @@ struct amdxdna_drm_get_array {
*
* %DRM_AMDXDNA_HW_CONTEXT_ALL:
* Returns all created hardware contexts.
+ *
+ * %DRM_AMDXDNA_HW_LAST_ASYNC_ERR:
+ * Returns last async error.
+ *
+ * %DRM_AMDXDNA_BO_USAGE:
+ * Returns usage of heap/internal/external BOs.
*/
__u32 param;
/**
diff --git a/lib/libc/include/any-linux-any/drm/drm_fourcc.h b/lib/libc/include/any-linux-any/drm/drm_fourcc.h
index 498ee6226f5f01245b8c423ba709767c4e0c6308..a39442f53e57d837aa815e29c593b7470dbbfd86 100644
--- a/lib/libc/include/any-linux-any/drm/drm_fourcc.h
+++ b/lib/libc/include/any-linux-any/drm/drm_fourcc.h
@@ -1422,6 +1422,22 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier)
#define DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED \
DRM_FORMAT_MOD_ARM_CODE(DRM_FORMAT_MOD_ARM_TYPE_MISC, 1ULL)
+/*
+ * ARM 64k interleaved modifier
+ *
+ * This is used by ARM Mali v10+ GPUs. With this modifier, the plane is divided
+ * into 64k byte 1:1 or 2:1 -sided tiles. The 64k tiles are laid out linearly.
+ * Each 64k tile is divided into blocks of 16x16 texel blocks, which are
+ * themselves laid out linearly within a 64k tile. Then within each 16x16
+ * block, texel blocks are laid out according to U order, similar to
+ * 16X16_BLOCK_U_INTERLEAVED.
+ *
+ * Note that unlike 16X16_BLOCK_U_INTERLEAVED, the layout does not change
+ * depending on whether a format is compressed or not.
+ */
+#define DRM_FORMAT_MOD_ARM_INTERLEAVED_64K \
+ DRM_FORMAT_MOD_ARM_CODE(DRM_FORMAT_MOD_ARM_TYPE_MISC, 2ULL)
+
/*
* Allwinner tiled modifier
*
diff --git a/lib/libc/include/any-linux-any/drm/drm_mode.h b/lib/libc/include/any-linux-any/drm/drm_mode.h
index b9d7342bd5a3d8930cbfded47618a9c0539dccb4..bffc2f8987f61ea57ef9e3832fe835faa973d296 100644
--- a/lib/libc/include/any-linux-any/drm/drm_mode.h
+++ b/lib/libc/include/any-linux-any/drm/drm_mode.h
@@ -27,6 +27,9 @@
#ifndef _DRM_MODE_H
#define _DRM_MODE_H
+#include
+#include
+
#include "drm.h"
#if defined(__cplusplus)
@@ -166,6 +169,10 @@ extern "C" {
#define DRM_MODE_LINK_STATUS_GOOD 0
#define DRM_MODE_LINK_STATUS_BAD 1
+/* Panel type property */
+#define DRM_MODE_PANEL_TYPE_UNKNOWN 0
+#define DRM_MODE_PANEL_TYPE_OLED 1
+
/*
* DRM_MODE_ROTATE_
*
@@ -1545,6 +1552,83 @@ struct drm_mode_closefb {
__u32 pad;
};
+/*
+ * Put 16-bit ARGB values into a standard 64-bit representation that can be
+ * used for ioctl parameters, inter-driver communication, etc.
+ *
+ * If the component values being provided contain less than 16 bits of
+ * precision, use a conversion ratio to get a better color approximation.
+ * The ratio is computed as (2^16 - 1) / (2^bpc - 1), where bpc and 16 are
+ * the input and output precision, respectively.
+ * Also note bpc must be greater than 0.
+ */
+#define __DRM_ARGB64_PREP(c, shift) \
+ (((__u64)(c) & __GENMASK(15, 0)) << (shift))
+
+#define __DRM_ARGB64_PREP_BPC(c, shift, bpc) \
+({ \
+ __u16 mask = __GENMASK((bpc) - 1, 0); \
+ __u16 conv = __KERNEL_DIV_ROUND_CLOSEST((mask & (c)) * \
+ __GENMASK(15, 0), mask);\
+ __DRM_ARGB64_PREP(conv, shift); \
+})
+
+#define DRM_ARGB64_PREP(alpha, red, green, blue) \
+( \
+ __DRM_ARGB64_PREP(alpha, 48) | \
+ __DRM_ARGB64_PREP(red, 32) | \
+ __DRM_ARGB64_PREP(green, 16) | \
+ __DRM_ARGB64_PREP(blue, 0) \
+)
+
+#define DRM_ARGB64_PREP_BPC(alpha, red, green, blue, bpc) \
+({ \
+ __typeof__(bpc) __bpc = bpc; \
+ __DRM_ARGB64_PREP_BPC(alpha, 48, __bpc) | \
+ __DRM_ARGB64_PREP_BPC(red, 32, __bpc) | \
+ __DRM_ARGB64_PREP_BPC(green, 16, __bpc) | \
+ __DRM_ARGB64_PREP_BPC(blue, 0, __bpc); \
+})
+
+/*
+ * Extract the specified color component from a standard 64-bit ARGB value.
+ *
+ * If the requested precision is less than 16 bits, make use of a conversion
+ * ratio calculated as (2^bpc - 1) / (2^16 - 1), where bpc and 16 are the
+ * output and input precision, respectively.
+ *
+ * If speed is more important than accuracy, use DRM_ARGB64_GET*_BPCS()
+ * instead of DRM_ARGB64_GET*_BPC() in order to replace the expensive
+ * division with a simple bit right-shift operation.
+ */
+#define __DRM_ARGB64_GET(c, shift) \
+ ((__u16)(((__u64)(c) >> (shift)) & __GENMASK(15, 0)))
+
+#define __DRM_ARGB64_GET_BPC(c, shift, bpc) \
+({ \
+ __u16 comp = __DRM_ARGB64_GET(c, shift); \
+ __KERNEL_DIV_ROUND_CLOSEST(comp * __GENMASK((bpc) - 1, 0), \
+ __GENMASK(15, 0)); \
+})
+
+#define __DRM_ARGB64_GET_BPCS(c, shift, bpc) \
+ (__DRM_ARGB64_GET(c, shift) >> (16 - (bpc)))
+
+#define DRM_ARGB64_GETA(c) __DRM_ARGB64_GET(c, 48)
+#define DRM_ARGB64_GETR(c) __DRM_ARGB64_GET(c, 32)
+#define DRM_ARGB64_GETG(c) __DRM_ARGB64_GET(c, 16)
+#define DRM_ARGB64_GETB(c) __DRM_ARGB64_GET(c, 0)
+
+#define DRM_ARGB64_GETA_BPC(c, bpc) __DRM_ARGB64_GET_BPC(c, 48, bpc)
+#define DRM_ARGB64_GETR_BPC(c, bpc) __DRM_ARGB64_GET_BPC(c, 32, bpc)
+#define DRM_ARGB64_GETG_BPC(c, bpc) __DRM_ARGB64_GET_BPC(c, 16, bpc)
+#define DRM_ARGB64_GETB_BPC(c, bpc) __DRM_ARGB64_GET_BPC(c, 0, bpc)
+
+#define DRM_ARGB64_GETA_BPCS(c, bpc) __DRM_ARGB64_GET_BPCS(c, 48, bpc)
+#define DRM_ARGB64_GETR_BPCS(c, bpc) __DRM_ARGB64_GET_BPCS(c, 32, bpc)
+#define DRM_ARGB64_GETG_BPCS(c, bpc) __DRM_ARGB64_GET_BPCS(c, 16, bpc)
+#define DRM_ARGB64_GETB_BPCS(c, bpc) __DRM_ARGB64_GET_BPCS(c, 0, bpc)
+
#if defined(__cplusplus)
}
#endif
diff --git a/lib/libc/include/any-linux-any/drm/drm_ras.h b/lib/libc/include/any-linux-any/drm/drm_ras.h
new file mode 100644
index 0000000000000000000000000000000000000000..bae74e86fe040f275d7838c322c678fe3464ac62
--- /dev/null
+++ b/lib/libc/include/any-linux-any/drm/drm_ras.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/drm_ras.yaml */
+/* YNL-GEN uapi header */
+/* To regenerate run: tools/net/ynl/ynl-regen.sh */
+
+#ifndef _LINUX_DRM_RAS_H
+#define _LINUX_DRM_RAS_H
+
+#define DRM_RAS_FAMILY_NAME "drm-ras"
+#define DRM_RAS_FAMILY_VERSION 1
+
+/*
+ * Type of the node. Currently, only error-counter nodes are supported, which
+ * expose reliability counters for a hardware/software component.
+ */
+enum drm_ras_node_type {
+ DRM_RAS_NODE_TYPE_ERROR_COUNTER = 1,
+};
+
+enum {
+ DRM_RAS_A_NODE_ATTRS_NODE_ID = 1,
+ DRM_RAS_A_NODE_ATTRS_DEVICE_NAME,
+ DRM_RAS_A_NODE_ATTRS_NODE_NAME,
+ DRM_RAS_A_NODE_ATTRS_NODE_TYPE,
+
+ __DRM_RAS_A_NODE_ATTRS_MAX,
+ DRM_RAS_A_NODE_ATTRS_MAX = (__DRM_RAS_A_NODE_ATTRS_MAX - 1)
+};
+
+enum {
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID = 1,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_NAME,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_VALUE,
+
+ __DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX = (__DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX - 1)
+};
+
+enum {
+ DRM_RAS_CMD_LIST_NODES = 1,
+ DRM_RAS_CMD_GET_ERROR_COUNTER,
+
+ __DRM_RAS_CMD_MAX,
+ DRM_RAS_CMD_MAX = (__DRM_RAS_CMD_MAX - 1)
+};
+
+#endif /* _LINUX_DRM_RAS_H */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/drm/msm_drm.h b/lib/libc/include/any-linux-any/drm/msm_drm.h
index af4445b6184ba9cca7d53332708272daa566c51b..708a24f4a0484e5ee6d66092c6eee97eb7bb73a1 100644
--- a/lib/libc/include/any-linux-any/drm/msm_drm.h
+++ b/lib/libc/include/any-linux-any/drm/msm_drm.h
@@ -117,6 +117,7 @@ struct drm_msm_timespec {
* ioctl will throw -EPIPE.
*/
#define MSM_PARAM_EN_VM_BIND 0x16 /* WO, once */
+#define MSM_PARAM_AQE 0x17 /* RO */
/* For backwards compat. The original support for preemption was based on
* a single ring per priority level so # of priority levels equals the #
diff --git a/lib/libc/include/any-linux-any/drm/nouveau_drm.h b/lib/libc/include/any-linux-any/drm/nouveau_drm.h
index ba589a1197c2377a243414ce0b31508d2c72a1da..e40db8acf32e808a955a1f76f44e8ffa102fc3be 100644
--- a/lib/libc/include/any-linux-any/drm/nouveau_drm.h
+++ b/lib/libc/include/any-linux-any/drm/nouveau_drm.h
@@ -432,6 +432,69 @@ struct drm_nouveau_exec {
__u64 push_ptr;
};
+struct drm_nouveau_get_zcull_info {
+ /**
+ * @width_align_pixels: required alignment for region widths, in pixels
+ * (typically #TPC's * 16).
+ */
+ __u32 width_align_pixels;
+ /**
+ * @height_align_pixels: required alignment for region heights, in
+ * pixels (typically 32).
+ */
+ __u32 height_align_pixels;
+ /**
+ * @pixel_squares_by_aliquots: the pixel area covered by an aliquot
+ * (typically #Zcull_banks * 16 * 16).
+ */
+ __u32 pixel_squares_by_aliquots;
+ /**
+ * @aliquot_total: the total aliquot pool available in hardware
+ */
+ __u32 aliquot_total;
+ /**
+ * @zcull_region_byte_multiplier: the size of an aliquot in bytes, which
+ * is used for save/restore operations on a region
+ */
+ __u32 zcull_region_byte_multiplier;
+ /**
+ * @zcull_region_header_size: the region header size in bytes, which is
+ * used for save/restore operations on a region
+ */
+ __u32 zcull_region_header_size;
+ /**
+ * @zcull_subregion_header_size: the subregion header size in bytes,
+ * which is used for save/restore operations on a region
+ */
+ __u32 zcull_subregion_header_size;
+ /**
+ * @subregion_count: the total number of subregions the hardware
+ * supports
+ */
+ __u32 subregion_count;
+ /**
+ * @subregion_width_align_pixels: required alignment for subregion
+ * widths, in pixels (typically #TPC's * 16).
+ */
+ __u32 subregion_width_align_pixels;
+ /**
+ * @subregion_height_align_pixels: required alignment for subregion
+ * heights, in pixels
+ */
+ __u32 subregion_height_align_pixels;
+
+ /**
+ * @ctxsw_size: the size, in bytes, of a zcull context switching region.
+ * Will be zero if the kernel does not support zcull context switching.
+ */
+ __u32 ctxsw_size;
+ /**
+ * @ctxsw_align: the alignment, in bytes, of a zcull context switching
+ * region
+ */
+ __u32 ctxsw_align;
+};
+
#define DRM_NOUVEAU_GETPARAM 0x00
#define DRM_NOUVEAU_SETPARAM 0x01 /* deprecated */
#define DRM_NOUVEAU_CHANNEL_ALLOC 0x02
@@ -445,6 +508,7 @@ struct drm_nouveau_exec {
#define DRM_NOUVEAU_VM_INIT 0x10
#define DRM_NOUVEAU_VM_BIND 0x11
#define DRM_NOUVEAU_EXEC 0x12
+#define DRM_NOUVEAU_GET_ZCULL_INFO 0x13
#define DRM_NOUVEAU_GEM_NEW 0x40
#define DRM_NOUVEAU_GEM_PUSHBUF 0x41
#define DRM_NOUVEAU_GEM_CPU_PREP 0x42
@@ -513,6 +577,8 @@ struct drm_nouveau_svm_bind {
#define DRM_IOCTL_NOUVEAU_VM_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_VM_INIT, struct drm_nouveau_vm_init)
#define DRM_IOCTL_NOUVEAU_VM_BIND DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_VM_BIND, struct drm_nouveau_vm_bind)
#define DRM_IOCTL_NOUVEAU_EXEC DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_EXEC, struct drm_nouveau_exec)
+
+#define DRM_IOCTL_NOUVEAU_GET_ZCULL_INFO DRM_IOR (DRM_COMMAND_BASE + DRM_NOUVEAU_GET_ZCULL_INFO, struct drm_nouveau_get_zcull_info)
#if defined(__cplusplus)
}
#endif
diff --git a/lib/libc/include/any-linux-any/drm/panthor_drm.h b/lib/libc/include/any-linux-any/drm/panthor_drm.h
index ea2c927003bf70d363d7c05ae2be35193900df49..33b14b9f025e29b8ae79b4f1906a94606f01cb67 100644
--- a/lib/libc/include/any-linux-any/drm/panthor_drm.h
+++ b/lib/libc/include/any-linux-any/drm/panthor_drm.h
@@ -409,6 +409,38 @@ struct drm_panthor_csif_info {
__u32 pad;
};
+/**
+ * enum drm_panthor_timestamp_info_flags - drm_panthor_timestamp_info.flags
+ */
+enum drm_panthor_timestamp_info_flags {
+ /** @DRM_PANTHOR_TIMESTAMP_GPU: Query GPU time. */
+ DRM_PANTHOR_TIMESTAMP_GPU = 1 << 0,
+
+ /** @DRM_PANTHOR_TIMESTAMP_CPU_NONE: Don't query CPU time. */
+ DRM_PANTHOR_TIMESTAMP_CPU_NONE = 0 << 1,
+
+ /** @DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC: Query CPU time using CLOCK_MONOTONIC. */
+ DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC = 1 << 1,
+
+ /** @DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC_RAW: Query CPU time using CLOCK_MONOTONIC_RAW. */
+ DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC_RAW = 2 << 1,
+
+ /** @DRM_PANTHOR_TIMESTAMP_CPU_TYPE_MASK: Space reserved for CPU clock type. */
+ DRM_PANTHOR_TIMESTAMP_CPU_TYPE_MASK = 7 << 1,
+
+ /** @DRM_PANTHOR_TIMESTAMP_GPU_OFFSET: Query GPU offset. */
+ DRM_PANTHOR_TIMESTAMP_GPU_OFFSET = 1 << 4,
+
+ /** @DRM_PANTHOR_TIMESTAMP_GPU_CYCLE_COUNT: Query GPU cycle count. */
+ DRM_PANTHOR_TIMESTAMP_GPU_CYCLE_COUNT = 1 << 5,
+
+ /** @DRM_PANTHOR_TIMESTAMP_FREQ: Query timestamp frequency. */
+ DRM_PANTHOR_TIMESTAMP_FREQ = 1 << 6,
+
+ /** @DRM_PANTHOR_TIMESTAMP_DURATION: Return duration of time query. */
+ DRM_PANTHOR_TIMESTAMP_DURATION = 1 << 7,
+};
+
/**
* struct drm_panthor_timestamp_info - Timestamp information
*
@@ -421,11 +453,38 @@ struct drm_panthor_timestamp_info {
*/
__u64 timestamp_frequency;
- /** @current_timestamp: The current timestamp. */
+ /** @current_timestamp: The current GPU timestamp. */
__u64 current_timestamp;
- /** @timestamp_offset: The offset of the timestamp timer. */
+ /** @timestamp_offset: The offset of the GPU timestamp timer. */
__u64 timestamp_offset;
+
+ /**
+ * @flags: Bitmask of drm_panthor_timestamp_info_flags.
+ *
+ * If set to 0, then it is interpreted as:
+ * DRM_PANTHOR_TIMESTAMP_GPU |
+ * DRM_PANTHOR_TIMESTAMP_GPU_OFFSET |
+ * DRM_PANTHOR_TIMESTAMP_FREQ
+ *
+ * Note: these flags are exclusive to each other (only one can be used):
+ * - DRM_PANTHOR_TIMESTAMP_CPU_NONE
+ * - DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC
+ * - DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC_RAW
+ */
+ __u32 flags;
+
+ /** @duration_nsec: Duration of time query. */
+ __u32 duration_nsec;
+
+ /** @cycle_count: Value of GPU_CYCLE_COUNT. */
+ __u64 cycle_count;
+
+ /** @cpu_timestamp_sec: Seconds part of CPU timestamp. */
+ __u64 cpu_timestamp_sec;
+
+ /** @cpu_timestamp_nsec: Nanseconds part of CPU timestamp. */
+ __u64 cpu_timestamp_nsec;
};
/**
diff --git a/lib/libc/include/any-linux-any/drm/xe_drm.h b/lib/libc/include/any-linux-any/drm/xe_drm.h
index 249bb0a26ed4c319d0dd810d236c8fafc5871c95..2225db07af5efce2c29957e84ace52f1c7c5aca0 100644
--- a/lib/libc/include/any-linux-any/drm/xe_drm.h
+++ b/lib/libc/include/any-linux-any/drm/xe_drm.h
@@ -83,6 +83,7 @@ extern "C" {
* - &DRM_IOCTL_XE_OBSERVATION
* - &DRM_IOCTL_XE_MADVISE
* - &DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS
+ * - &DRM_IOCTL_XE_VM_GET_PROPERTY
*/
/*
@@ -107,6 +108,7 @@ extern "C" {
#define DRM_XE_MADVISE 0x0c
#define DRM_XE_VM_QUERY_MEM_RANGE_ATTRS 0x0d
#define DRM_XE_EXEC_QUEUE_SET_PROPERTY 0x0e
+#define DRM_XE_VM_GET_PROPERTY 0x0f
/* Must be kept compact -- no holes */
@@ -125,6 +127,7 @@ extern "C" {
#define DRM_IOCTL_XE_MADVISE DRM_IOW(DRM_COMMAND_BASE + DRM_XE_MADVISE, struct drm_xe_madvise)
#define DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_VM_QUERY_MEM_RANGE_ATTRS, struct drm_xe_vm_query_mem_range_attr)
#define DRM_IOCTL_XE_EXEC_QUEUE_SET_PROPERTY DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC_QUEUE_SET_PROPERTY, struct drm_xe_exec_queue_set_property)
+#define DRM_IOCTL_XE_VM_GET_PROPERTY DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_VM_GET_PROPERTY, struct drm_xe_vm_get_property)
/**
* DOC: Xe IOCTL Extensions
@@ -335,10 +338,6 @@ struct drm_xe_mem_region {
__u64 total_size;
/**
* @used: Estimate of the memory used in bytes for this region.
- *
- * Requires CAP_PERFMON or CAP_SYS_ADMIN to get reliable
- * accounting. Without this the value here will always equal
- * zero.
*/
__u64 used;
/**
@@ -363,9 +362,7 @@ struct drm_xe_mem_region {
* @cpu_visible_used: Estimate of CPU visible memory used, in
* bytes.
*
- * Requires CAP_PERFMON or CAP_SYS_ADMIN to get reliable
- * accounting. Without this the value here will always equal
- * zero. Note this is only currently tracked for
+ * Note this is only currently tracked for
* DRM_XE_MEM_REGION_CLASS_VRAM regions (for other types the value
* here will always be zero).
*/
@@ -412,6 +409,9 @@ struct drm_xe_query_mem_regions {
* - %DRM_XE_QUERY_CONFIG_FLAG_HAS_NO_COMPRESSION_HINT - Flag is set if the
* device supports the userspace hint %DRM_XE_GEM_CREATE_FLAG_NO_COMPRESSION.
* This is exposed only on Xe2+.
+ * - %DRM_XE_QUERY_CONFIG_FLAG_HAS_DISABLE_STATE_CACHE_PERF_FIX - Flag is set
+ * if a queue can be creaed with
+ * %DRM_XE_EXEC_QUEUE_SET_DISABLE_STATE_CACHE_PERF_FIX
* - %DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT - Minimal memory alignment
* required by this device, typically SZ_4K or SZ_64K
* - %DRM_XE_QUERY_CONFIG_VA_BITS - Maximum bits of a virtual address
@@ -431,6 +431,8 @@ struct drm_xe_query_config {
#define DRM_XE_QUERY_CONFIG_FLAG_HAS_LOW_LATENCY (1 << 1)
#define DRM_XE_QUERY_CONFIG_FLAG_HAS_CPU_ADDR_MIRROR (1 << 2)
#define DRM_XE_QUERY_CONFIG_FLAG_HAS_NO_COMPRESSION_HINT (1 << 3)
+ #define DRM_XE_QUERY_CONFIG_FLAG_HAS_DISABLE_STATE_CACHE_PERF_FIX (1 << 4)
+ #define DRM_XE_QUERY_CONFIG_FLAG_HAS_PURGING_SUPPORT (1 << 5)
#define DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT 2
#define DRM_XE_QUERY_CONFIG_VA_BITS 3
#define DRM_XE_QUERY_CONFIG_MAX_EXEC_QUEUE_PRIORITY 4
@@ -975,6 +977,11 @@ struct drm_xe_gem_mmap_offset {
* demand when accessed, and also allows per-VM overcommit of memory.
* The xe driver internally uses recoverable pagefaults to implement
* this.
+ * - %DRM_XE_VM_CREATE_FLAG_NO_VM_OVERCOMMIT - Requires also
+ * DRM_XE_VM_CREATE_FLAG_FAULT_MODE. This disallows per-VM overcommit
+ * but only during a &DRM_IOCTL_XE_VM_BIND operation with the
+ * %DRM_XE_VM_BIND_FLAG_IMMEDIATE flag set. This may be useful for
+ * user-space naively probing the amount of available memory.
*/
struct drm_xe_vm_create {
/** @extensions: Pointer to the first extension struct, if any */
@@ -983,6 +990,7 @@ struct drm_xe_vm_create {
#define DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE (1 << 0)
#define DRM_XE_VM_CREATE_FLAG_LR_MODE (1 << 1)
#define DRM_XE_VM_CREATE_FLAG_FAULT_MODE (1 << 2)
+#define DRM_XE_VM_CREATE_FLAG_NO_VM_OVERCOMMIT (1 << 3)
/** @flags: Flags */
__u32 flags;
@@ -1053,6 +1061,13 @@ struct drm_xe_vm_destroy {
* not invoke autoreset. Neither will stack variables going out of scope.
* Therefore it's recommended to always explicitly reset the madvises when
* freeing the memory backing a region used in a &DRM_IOCTL_XE_MADVISE call.
+ * - %DRM_XE_VM_BIND_FLAG_DECOMPRESS - Request on-device decompression for a MAP.
+ * When set on a MAP bind operation, request the driver schedule an on-device
+ * in-place decompression (via the migrate/resolve path) for the GPU mapping
+ * created by this bind. Only valid for DRM_XE_VM_BIND_OP_MAP; usage on
+ * other ops is rejected. The bind's pat_index must select the device's
+ * "no-compression" PAT. Only meaningful for VRAM-backed BOs on devices that
+ * support Flat CCS and the required HW generation XE2+.
*
* The @prefetch_mem_region_instance for %DRM_XE_VM_BIND_OP_PREFETCH can also be:
* - %DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC, which ensures prefetching occurs in
@@ -1103,7 +1118,9 @@ struct drm_xe_vm_bind_op {
* incoherent GT access is possible.
*
* Note: For userptr and externally imported dma-buf the kernel expects
- * either 1WAY or 2WAY for the @pat_index.
+ * either 1WAY or 2WAY for the @pat_index. Starting from NVL-P, for
+ * userptr, svm, madvise and externally imported dma-buf the kernel expects
+ * either 2WAY or 1WAY and XA @pat_index.
*
* For DRM_XE_VM_BIND_FLAG_NULL bindings there are no KMD restrictions
* on the @pat_index. For such mappings there is no actual memory being
@@ -1160,6 +1177,7 @@ struct drm_xe_vm_bind_op {
#define DRM_XE_VM_BIND_FLAG_CHECK_PXP (1 << 4)
#define DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR (1 << 5)
#define DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET (1 << 6)
+#define DRM_XE_VM_BIND_FLAG_DECOMPRESS (1 << 7)
/** @flags: Bind flags */
__u32 flags;
@@ -1249,6 +1267,89 @@ struct drm_xe_vm_bind {
__u64 reserved[2];
};
+/** struct xe_vm_fault - Describes faults for %DRM_XE_VM_GET_PROPERTY_FAULTS */
+struct xe_vm_fault {
+ /** @address: Canonical address of the fault */
+ __u64 address;
+ /** @address_precision: Precision of faulted address */
+ __u32 address_precision;
+ /** @access_type: Type of address access that resulted in fault */
+#define FAULT_ACCESS_TYPE_READ 0
+#define FAULT_ACCESS_TYPE_WRITE 1
+#define FAULT_ACCESS_TYPE_ATOMIC 2
+ __u8 access_type;
+ /** @fault_type: Type of fault reported */
+#define FAULT_TYPE_NOT_PRESENT 0
+#define FAULT_TYPE_WRITE_ACCESS 1
+#define FAULT_TYPE_ATOMIC_ACCESS 2
+ __u8 fault_type;
+ /** @fault_level: fault level of the fault */
+#define FAULT_LEVEL_PTE 0
+#define FAULT_LEVEL_PDE 1
+#define FAULT_LEVEL_PDP 2
+#define FAULT_LEVEL_PML4 3
+#define FAULT_LEVEL_PML5 4
+ __u8 fault_level;
+ /** @pad: MBZ */
+ __u8 pad;
+ /** @reserved: MBZ */
+ __u64 reserved[4];
+};
+
+/**
+ * struct drm_xe_vm_get_property - Input of &DRM_IOCTL_XE_VM_GET_PROPERTY
+ *
+ * The user provides a VM and a property to query among DRM_XE_VM_GET_PROPERTY_*,
+ * and sets the values in the vm_id and property members, respectively. This
+ * determines both the VM to get the property of, as well as the property to
+ * report.
+ *
+ * If size is set to 0, the driver fills it with the required size for the
+ * requested property. The user is expected here to allocate memory for the
+ * property structure and to provide a pointer to the allocated memory using the
+ * data member. For some properties, this may be zero, in which case, the
+ * value of the property will be saved to the value member and size will remain
+ * zero on return.
+ *
+ * If size is not zero, then the IOCTL will attempt to copy the requested
+ * property into the data member.
+ *
+ * The IOCTL will return -ENOENT if the VM could not be identified from the
+ * provided VM ID, or -EINVAL if the IOCTL fails for any other reason, such as
+ * providing an invalid size for the given property or if the property data
+ * could not be copied to the memory allocated to the data member.
+ *
+ * The property member can be:
+ * - %DRM_XE_VM_GET_PROPERTY_FAULTS
+ */
+struct drm_xe_vm_get_property {
+ /** @extensions: Pointer to the first extension struct, if any */
+ __u64 extensions;
+
+ /** @vm_id: The ID of the VM to query the properties of */
+ __u32 vm_id;
+
+#define DRM_XE_VM_GET_PROPERTY_FAULTS 0
+ /** @property: property to get */
+ __u32 property;
+
+ /** @size: Size to allocate for @data */
+ __u32 size;
+
+ /** @pad: MBZ */
+ __u32 pad;
+
+ union {
+ /** @data: Pointer to user-defined array of flexible size and type */
+ __u64 data;
+ /** @value: Return value for scalar queries */
+ __u64 value;
+ };
+
+ /** @reserved: MBZ */
+ __u64 reserved[3];
+};
+
/**
* struct drm_xe_exec_queue_create - Input of &DRM_IOCTL_XE_EXEC_QUEUE_CREATE
*
@@ -1285,6 +1386,9 @@ struct drm_xe_vm_bind {
* - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY - Set the queue
* priority within the multi-queue group. Current valid priority values are 0–2
* (default is 1), with higher values indicating higher priority.
+ * - %DRM_XE_EXEC_QUEUE_SET_DISABLE_STATE_CACHE_PERF_FIX - Set the queue to
+ * enable render color cache keying on BTP+BTI instead of just BTI
+ * (only valid for render queues).
*
* The example below shows how to use @drm_xe_exec_queue_create to create
* a simple exec_queue (no parallel submission) of class
@@ -1329,6 +1433,7 @@ struct drm_xe_exec_queue_create {
#define DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP 4
#define DRM_XE_MULTI_GROUP_CREATE (1ull << 63)
#define DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY 5
+#define DRM_XE_EXEC_QUEUE_SET_DISABLE_STATE_CACHE_PERF_FIX 6
/** @extensions: Pointer to the first extension struct, if any */
__u64 extensions;
@@ -2067,6 +2172,7 @@ struct drm_xe_query_eu_stall {
* - DRM_XE_MEM_RANGE_ATTR_PREFERRED_LOC: Set preferred memory location.
* - DRM_XE_MEM_RANGE_ATTR_ATOMIC: Set atomic access policy.
* - DRM_XE_MEM_RANGE_ATTR_PAT: Set page attribute table index.
+ * - DRM_XE_VMA_ATTR_PURGEABLE_STATE: Set purgeable state for BOs.
*
* Example:
*
@@ -2099,6 +2205,7 @@ struct drm_xe_madvise {
#define DRM_XE_MEM_RANGE_ATTR_PREFERRED_LOC 0
#define DRM_XE_MEM_RANGE_ATTR_ATOMIC 1
#define DRM_XE_MEM_RANGE_ATTR_PAT 2
+#define DRM_XE_VMA_ATTR_PURGEABLE_STATE 3
/** @type: type of attribute */
__u32 type;
@@ -2189,6 +2296,72 @@ struct drm_xe_madvise {
/** @pat_index.reserved: Reserved */
__u64 reserved;
} pat_index;
+
+ /**
+ * @purge_state_val: Purgeable state configuration
+ *
+ * Used when @type == DRM_XE_VMA_ATTR_PURGEABLE_STATE.
+ *
+ * Configures the purgeable state of buffer objects in the specified
+ * virtual address range. This allows applications to hint to the kernel
+ * about bo's usage patterns for better memory management.
+ *
+ * By default all VMAs are in WILLNEED state.
+ *
+ * Supported values for @purge_state_val.val:
+ * - DRM_XE_VMA_PURGEABLE_STATE_WILLNEED (0): Marks BO as needed.
+ * If the BO was previously purged, the kernel sets the __u32 at
+ * @retained_ptr to 0 (backing store lost) so the application knows
+ * it must recreate the BO.
+ *
+ * - DRM_XE_VMA_PURGEABLE_STATE_DONTNEED (1): Marks BO as not currently
+ * needed. Kernel may purge it under memory pressure to reclaim memory.
+ * Only applies to non-shared BOs. The kernel sets the __u32 at
+ * @retained_ptr to 1 if the backing store still exists (not yet purged),
+ * or 0 if it was already purged.
+ *
+ * Important: Once marked as DONTNEED, touching the BO's memory
+ * is undefined behavior. It may succeed temporarily (before the
+ * kernel purges the backing store) but will suddenly fail once
+ * the BO transitions to PURGED state.
+ *
+ * To transition back: use WILLNEED and check @retained_ptr —
+ * if 0, backing store was lost and the BO must be recreated.
+ *
+ * The following operations are blocked in DONTNEED state to
+ * prevent the BO from being re-mapped after madvise:
+ * - New mmap() calls: Fail with -EBUSY
+ * - VM_BIND operations: Fail with -EBUSY
+ * - New dma-buf exports: Fail with -EBUSY
+ * - CPU page faults (existing mmap): Fail with SIGBUS
+ * - GPU page faults (fault-mode VMs): Fail with -EACCES
+ */
+ struct {
+#define DRM_XE_VMA_PURGEABLE_STATE_WILLNEED 0
+#define DRM_XE_VMA_PURGEABLE_STATE_DONTNEED 1
+ /** @purge_state_val.val: value for DRM_XE_VMA_ATTR_PURGEABLE_STATE */
+ __u32 val;
+
+ /** @purge_state_val.pad: MBZ */
+ __u32 pad;
+ /**
+ * @purge_state_val.retained_ptr: Pointer to a __u32 output
+ * field for backing store status.
+ *
+ * Userspace must initialize the __u32 value at this address
+ * to 0 before the ioctl. Kernel writes a __u32 after the
+ * operation:
+ * - 1 if backing store exists (not purged)
+ * - 0 if backing store was purged
+ *
+ * If userspace fails to initialize to 0, ioctl returns -EINVAL.
+ * This ensures a safe default (0 = assume purged) if kernel
+ * cannot write the result.
+ *
+ * Similar to i915's drm_i915_gem_madvise.retained field.
+ */
+ __u64 retained_ptr;
+ } purge_state_val;
};
/** @reserved: Reserved */
@@ -2357,6 +2530,85 @@ struct drm_xe_exec_queue_set_property {
__u64 reserved[2];
};
+/**
+ * DOC: Xe DRM RAS
+ *
+ * The enums and strings defined below map to the attributes of the DRM RAS Netlink Interface.
+ * Refer to Documentation/netlink/specs/drm_ras.yaml for complete interface specification.
+ *
+ * Node Registration
+ * =================
+ *
+ * The driver registers DRM RAS nodes for each error severity level.
+ * enum drm_xe_ras_error_severity defines the node-id, while DRM_XE_RAS_ERROR_SEVERITY_NAMES maps
+ * node-id to node-name.
+ *
+ * Error Classification
+ * ====================
+ *
+ * Each node contains a list of error counters. Each error is identified by a error-id and
+ * an error-name. enum drm_xe_ras_error_component defines the error-id, while
+ * DRM_XE_RAS_ERROR_COMPONENT_NAMES maps error-id to error-name.
+ *
+ * User Interface
+ * ==============
+ *
+ * To retrieve error values of a error counter, userspace applications should
+ * follow the below steps:
+ *
+ * 1. Use command LIST_NODES to enumerate all available nodes
+ * 2. Select node by node-id or node-name
+ * 3. Use command GET_ERROR_COUNTERS to list errors of specific node
+ * 4. Query specific error values using either error-id or error-name
+ *
+ * .. code-block:: C
+ *
+ * // Lookup tables for ID-to-name resolution
+ * static const char *nodes[] = DRM_XE_RAS_ERROR_SEVERITY_NAMES;
+ * static const char *errors[] = DRM_XE_RAS_ERROR_COMPONENT_NAMES;
+ *
+ */
+
+/**
+ * enum drm_xe_ras_error_severity - DRM RAS error severity.
+ */
+enum drm_xe_ras_error_severity {
+ /** @DRM_XE_RAS_ERR_SEV_CORRECTABLE: Correctable Error */
+ DRM_XE_RAS_ERR_SEV_CORRECTABLE = 0,
+ /** @DRM_XE_RAS_ERR_SEV_UNCORRECTABLE: Uncorrectable Error */
+ DRM_XE_RAS_ERR_SEV_UNCORRECTABLE,
+ /** @DRM_XE_RAS_ERR_SEV_MAX: Max severity */
+ DRM_XE_RAS_ERR_SEV_MAX /* non-ABI */
+};
+
+/**
+ * enum drm_xe_ras_error_component - DRM RAS error component.
+ */
+enum drm_xe_ras_error_component {
+ /** @DRM_XE_RAS_ERR_COMP_CORE_COMPUTE: Core Compute Error */
+ DRM_XE_RAS_ERR_COMP_CORE_COMPUTE = 1,
+ /** @DRM_XE_RAS_ERR_COMP_SOC_INTERNAL: SoC Internal Error */
+ DRM_XE_RAS_ERR_COMP_SOC_INTERNAL,
+ /** @DRM_XE_RAS_ERR_COMP_MAX: Max Error */
+ DRM_XE_RAS_ERR_COMP_MAX /* non-ABI */
+};
+
+/*
+ * Error severity to name mapping.
+ */
+#define DRM_XE_RAS_ERROR_SEVERITY_NAMES { \
+ [DRM_XE_RAS_ERR_SEV_CORRECTABLE] = "correctable-errors", \
+ [DRM_XE_RAS_ERR_SEV_UNCORRECTABLE] = "uncorrectable-errors", \
+}
+
+/*
+ * Error component to name mapping.
+ */
+#define DRM_XE_RAS_ERROR_COMPONENT_NAMES { \
+ [DRM_XE_RAS_ERR_COMP_CORE_COMPUTE] = "core-compute", \
+ [DRM_XE_RAS_ERR_COMP_SOC_INTERNAL] = "soc-internal" \
+}
+
#if defined(__cplusplus)
}
#endif
diff --git a/lib/libc/include/any-linux-any/fwctl/bnxt.h b/lib/libc/include/any-linux-any/fwctl/bnxt.h
new file mode 100644
index 0000000000000000000000000000000000000000..ef8f733bc42b79530ecbd31863775836e2274a91
--- /dev/null
+++ b/lib/libc/include/any-linux-any/fwctl/bnxt.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2026, Broadcom Inc
+ */
+
+#ifndef _FWCTL_BNXT_H_
+#define _FWCTL_BNXT_H_
+
+#include
+
+enum fwctl_bnxt_commands {
+ FWCTL_BNXT_INLINE_COMMANDS = 0,
+ FWCTL_BNXT_QUERY_COMMANDS,
+ FWCTL_BNXT_SEND_COMMANDS,
+};
+
+/**
+ * struct fwctl_info_bnxt - ioctl(FWCTL_INFO) out_device_data
+ * @uctx_caps: The command capabilities driver accepts.
+ *
+ * Return basic information about the FW interface available.
+ */
+struct fwctl_info_bnxt {
+ __u32 uctx_caps;
+};
+#endif
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/fwctl/fwctl.h b/lib/libc/include/any-linux-any/fwctl/fwctl.h
index 511c656d93c4ab14c71a33ce4ca488fe6114b93a..83b9dcaf764ffa31846b84f459a604bb319b20ef 100644
--- a/lib/libc/include/any-linux-any/fwctl/fwctl.h
+++ b/lib/libc/include/any-linux-any/fwctl/fwctl.h
@@ -44,6 +44,7 @@ enum fwctl_device_type {
FWCTL_DEVICE_TYPE_ERROR = 0,
FWCTL_DEVICE_TYPE_MLX5 = 1,
FWCTL_DEVICE_TYPE_CXL = 2,
+ FWCTL_DEVICE_TYPE_BNXT = 3,
FWCTL_DEVICE_TYPE_PDS = 4,
};
diff --git a/lib/libc/include/any-linux-any/linux/audit.h b/lib/libc/include/any-linux-any/linux/audit.h
index fd93ab126e39a896dd7216fb7e70e401ab2aa81b..a57548c3771444f3aaf5cbc5217672536677c4ce 100644
--- a/lib/libc/include/any-linux-any/linux/audit.h
+++ b/lib/libc/include/any-linux-any/linux/audit.h
@@ -350,7 +350,7 @@ enum {
#define AUDIT_STATUS_ENABLED 0x0001
#define AUDIT_STATUS_FAILURE 0x0002
#define AUDIT_STATUS_PID 0x0004
-#define AUDIT_STATUS_RATE_LIMIT 0x0008
+#define AUDIT_STATUS_RATE_LIMIT 0x0008
#define AUDIT_STATUS_BACKLOG_LIMIT 0x0010
#define AUDIT_STATUS_BACKLOG_WAIT_TIME 0x0020
#define AUDIT_STATUS_LOST 0x0040
@@ -386,8 +386,8 @@ enum {
* These bits disambiguate different calling conventions that share an
* ELF machine type, bitness, and endianness
*/
-#define __AUDIT_ARCH_CONVENTION_MASK 0x30000000
-#define __AUDIT_ARCH_CONVENTION_MIPS64_N32 0x20000000
+#define __AUDIT_ARCH_CONVENTION_MASK 0x30000000
+#define __AUDIT_ARCH_CONVENTION_MIPS64_N32 0x20000000
/* distinguish syscall tables */
#define __AUDIT_ARCH_64BIT 0x80000000
@@ -508,7 +508,7 @@ struct audit_tty_status {
__u32 log_passwd; /* 1 = enabled, 0 = disabled */
};
-#define AUDIT_UID_UNSET (unsigned int)-1
+#define AUDIT_UID_UNSET ((unsigned int)-1)
#define AUDIT_SID_UNSET ((unsigned int)-1)
/* audit_rule_data supports filter rules with both integer and string
diff --git a/lib/libc/include/any-linux-any/linux/baycom.h b/lib/libc/include/any-linux-any/linux/baycom.h
deleted file mode 100644
index 92426d5bdfddcc21c01c482dae84fb81af701bca..0000000000000000000000000000000000000000
--- a/lib/libc/include/any-linux-any/linux/baycom.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * The Linux BAYCOM driver for the Baycom serial 1200 baud modem
- * and the parallel 9600 baud modem
- * (C) 1997-1998 by Thomas Sailer, HB9JNX/AE4WA
- */
-
-#ifndef _BAYCOM_H
-#define _BAYCOM_H
-
-/* -------------------------------------------------------------------- */
-/*
- * structs for the IOCTL commands
- */
-
-struct baycom_debug_data {
- unsigned long debug1;
- unsigned long debug2;
- long debug3;
-};
-
-struct baycom_ioctl {
- int cmd;
- union {
- struct baycom_debug_data dbg;
- } data;
-};
-
-/* -------------------------------------------------------------------- */
-
-/*
- * ioctl values change for baycom
- */
-#define BAYCOMCTL_GETDEBUG 0x92
-
-/* -------------------------------------------------------------------- */
-
-#endif /* _BAYCOM_H */
-
-/* --------------------------------------------------------------------- */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/bpf.h b/lib/libc/include/any-linux-any/linux/bpf.h
index 5fc9addc4643c9d8e16e279672a526fb672b6392..c36772f0a62bee8c198862c5b1890effbc686da6 100644
--- a/lib/libc/include/any-linux-any/linux/bpf.h
+++ b/lib/libc/include/any-linux-any/linux/bpf.h
@@ -4645,7 +4645,9 @@ union bpf_attr {
* Description
* Discard reserved ring buffer sample, pointed to by *data*.
* If **BPF_RB_NO_WAKEUP** is specified in *flags*, no notification
- * of new data availability is sent.
+ * of new data availability is sent. Discarded records remain in
+ * the ring buffer until consumed by user space, so a later submit
+ * using adaptive wakeup might not wake up the consumer.
* If **BPF_RB_FORCE_WAKEUP** is specified in *flags*, notification
* of new data availability is sent unconditionally.
* If **0** is specified in *flags*, an adaptive notification
diff --git a/lib/libc/include/any-linux-any/linux/bsg.h b/lib/libc/include/any-linux-any/linux/bsg.h
index b3a21ce6f70328108672a4ac28b57fbce298e9cf..b0242153fccc95010ab982ed6a93c6e59c93c98a 100644
--- a/lib/libc/include/any-linux-any/linux/bsg.h
+++ b/lib/libc/include/any-linux-any/linux/bsg.h
@@ -63,5 +63,73 @@ struct sg_io_v4 {
__u32 padding;
};
+struct bsg_uring_cmd {
+ __u64 request; /* [i], [*i] command descriptor address */
+ __u32 request_len; /* [i] command descriptor length in bytes */
+ __u32 protocol; /* [i] protocol type (BSG_PROTOCOL_*) */
+ __u32 subprotocol; /* [i] subprotocol type (BSG_SUB_PROTOCOL_*) */
+ __u32 max_response_len; /* [i] response buffer size in bytes */
+
+ __u64 response; /* [i], [*o] response data address */
+ __u64 dout_xferp; /* [i], [*i] */
+ __u32 dout_xfer_len; /* [i] bytes to be transferred to device */
+ __u32 dout_iovec_count; /* [i] 0 -> "flat" dout transfer else
+ * dout_xferp points to array of iovec
+ */
+ __u64 din_xferp; /* [i], [*o] */
+ __u32 din_xfer_len; /* [i] bytes to be transferred from device */
+ __u32 din_iovec_count; /* [i] 0 -> "flat" din transfer */
+
+ __u32 timeout_ms; /* [i] timeout in milliseconds */
+ __u8 reserved[12]; /* reserved for future extension */
+};
+
+
+
+/*
+ * SCSI BSG io_uring completion (res2, 64-bit)
+ *
+ * When using BSG_PROTOCOL_SCSI + BSG_SUB_PROTOCOL_SCSI_CMD with
+ * IORING_OP_URING_CMD, the completion queue entry (CQE) contains:
+ * - result: errno (0 on success)
+ * - res2: packed SCSI status
+ *
+ * res2 bit layout:
+ * [0..7] device_status (SCSI status byte, e.g. CHECK_CONDITION)
+ * [8..15] driver_status (e.g. DRIVER_SENSE when sense data is valid)
+ * [16..23] host_status (e.g. DID_OK, DID_TIME_OUT)
+ * [24..31] sense_len_wr (bytes of sense data written to response buffer)
+ * [32..63] resid_len (residual transfer length)
+ */
+static __inline__ __u8 bsg_scsi_res2_device_status(__u64 res2)
+{
+ return res2 & 0xff;
+}
+static __inline__ __u8 bsg_scsi_res2_driver_status(__u64 res2)
+{
+ return res2 >> 8;
+}
+static __inline__ __u8 bsg_scsi_res2_host_status(__u64 res2)
+{
+ return res2 >> 16;
+}
+static __inline__ __u8 bsg_scsi_res2_sense_len(__u64 res2)
+{
+ return res2 >> 24;
+}
+static __inline__ __u32 bsg_scsi_res2_resid_len(__u64 res2)
+{
+ return res2 >> 32;
+}
+static __inline__ __u64 bsg_scsi_res2_build(__u8 device_status, __u8 driver_status,
+ __u8 host_status, __u8 sense_len_wr,
+ __u32 resid_len)
+{
+ return ((__u64)(__u32)(resid_len) << 32) |
+ ((__u64)sense_len_wr << 24) |
+ ((__u64)host_status << 16) |
+ ((__u64)driver_status << 8) |
+ (__u64)device_status;
+}
#endif /* BSG_H */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/btf.h b/lib/libc/include/any-linux-any/linux/btf.h
index 3a42631355748aeb0573ca00a012839731c8ceaa..0f2ef31bf519f56e229fdc48dc70e98d4167b485 100644
--- a/lib/libc/include/any-linux-any/linux/btf.h
+++ b/lib/libc/include/any-linux-any/linux/btf.h
@@ -8,6 +8,16 @@
#define BTF_MAGIC 0xeB9F
#define BTF_VERSION 1
+/*
+ * BTF layout section consists of a struct btf_layout for each known
+ * kind at BTF encoding time.
+ */
+struct btf_layout {
+ __u8 info_sz; /* size of singular element after btf_type */
+ __u8 elem_sz; /* size of each of btf_vlen(t) elements */
+ __u16 flags; /* currently unused */
+};
+
struct btf_header {
__u16 magic;
__u8 version;
@@ -19,6 +29,8 @@ struct btf_header {
__u32 type_len; /* length of type section */
__u32 str_off; /* offset of string section */
__u32 str_len; /* length of string section */
+ __u32 layout_off; /* offset of layout section */
+ __u32 layout_len; /* length of layout section */
};
/* Max # of type identifier */
diff --git a/lib/libc/include/any-linux-any/linux/btrfs_tree.h b/lib/libc/include/any-linux-any/linux/btrfs_tree.h
index 4dac10eb3d38d82ff7846e402608b909f3c2327a..1eec392e1d5344c64b98dd6e466c21d56701c081 100644
--- a/lib/libc/include/any-linux-any/linux/btrfs_tree.h
+++ b/lib/libc/include/any-linux-any/linux/btrfs_tree.h
@@ -1241,7 +1241,8 @@ struct btrfs_free_space_info {
__le32 flags;
} __attribute__ ((__packed__));
-#define BTRFS_FREE_SPACE_USING_BITMAPS (1ULL << 0)
+#define BTRFS_FREE_SPACE_USING_BITMAPS (1UL << 0)
+#define BTRFS_FREE_SPACE_FLAGS_MASK (BTRFS_FREE_SPACE_USING_BITMAPS)
#define BTRFS_QGROUP_LEVEL_SHIFT 48
static __inline__ __u16 btrfs_qgroup_level(__u64 qgroupid)
diff --git a/lib/libc/include/any-linux-any/linux/caif/caif_socket.h b/lib/libc/include/any-linux-any/linux/caif/caif_socket.h
deleted file mode 100644
index a4761dadee8be6da41f36419afd7cf729e24a0b8..0000000000000000000000000000000000000000
--- a/lib/libc/include/any-linux-any/linux/caif/caif_socket.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* linux/caif_socket.h
- * CAIF Definitions for CAIF socket and network layer
- * Copyright (C) ST-Ericsson AB 2010
- * Author: Sjur Brendeland
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#ifndef _LINUX_CAIF_SOCKET_H
-#define _LINUX_CAIF_SOCKET_H
-
-#include
-#include
-
-/**
- * enum caif_link_selector - Physical Link Selection.
- * @CAIF_LINK_HIGH_BANDW: Physical interface for high-bandwidth
- * traffic.
- * @CAIF_LINK_LOW_LATENCY: Physical interface for low-latency
- * traffic.
- *
- * CAIF Link Layers can register their link properties.
- * This enum is used for choosing between CAIF Link Layers when
- * setting up CAIF Channels when multiple CAIF Link Layers exists.
- */
-enum caif_link_selector {
- CAIF_LINK_HIGH_BANDW,
- CAIF_LINK_LOW_LATENCY
-};
-
-/**
- * enum caif_channel_priority - CAIF channel priorities.
- *
- * @CAIF_PRIO_MIN: Min priority for a channel.
- * @CAIF_PRIO_LOW: Low-priority channel.
- * @CAIF_PRIO_NORMAL: Normal/default priority level.
- * @CAIF_PRIO_HIGH: High priority level
- * @CAIF_PRIO_MAX: Max priority for channel
- *
- * Priority can be set on CAIF Channels in order to
- * prioritize between traffic on different CAIF Channels.
- * These priority levels are recommended, but the priority value
- * is not restricted to the values defined in this enum, any value
- * between CAIF_PRIO_MIN and CAIF_PRIO_MAX could be used.
- */
-enum caif_channel_priority {
- CAIF_PRIO_MIN = 0x01,
- CAIF_PRIO_LOW = 0x04,
- CAIF_PRIO_NORMAL = 0x0f,
- CAIF_PRIO_HIGH = 0x14,
- CAIF_PRIO_MAX = 0x1F
-};
-
-/**
- * enum caif_protocol_type - CAIF Channel type.
- * @CAIFPROTO_AT: Classic AT channel.
- * @CAIFPROTO_DATAGRAM: Datagram channel.
- * @CAIFPROTO_DATAGRAM_LOOP: Datagram loopback channel, used for testing.
- * @CAIFPROTO_UTIL: Utility (Psock) channel.
- * @CAIFPROTO_RFM: Remote File Manager
- * @CAIFPROTO_DEBUG: Debug link
- *
- * This enum defines the CAIF Channel type to be used. This defines
- * the service to connect to on the modem.
- */
-enum caif_protocol_type {
- CAIFPROTO_AT,
- CAIFPROTO_DATAGRAM,
- CAIFPROTO_DATAGRAM_LOOP,
- CAIFPROTO_UTIL,
- CAIFPROTO_RFM,
- CAIFPROTO_DEBUG,
- _CAIFPROTO_MAX
-};
-#define CAIFPROTO_MAX _CAIFPROTO_MAX
-
-/**
- * enum caif_at_type - AT Service Endpoint
- * @CAIF_ATTYPE_PLAIN: Connects to a plain vanilla AT channel.
- */
-enum caif_at_type {
- CAIF_ATTYPE_PLAIN = 2
-};
- /**
- * enum caif_debug_type - Content selection for debug connection
- * @CAIF_DEBUG_TRACE_INTERACTIVE: Connection will contain
- * both trace and interactive debug.
- * @CAIF_DEBUG_TRACE: Connection contains trace only.
- * @CAIF_DEBUG_INTERACTIVE: Connection to interactive debug.
- */
-enum caif_debug_type {
- CAIF_DEBUG_TRACE_INTERACTIVE = 0,
- CAIF_DEBUG_TRACE,
- CAIF_DEBUG_INTERACTIVE,
-};
-
-/**
- * enum caif_debug_service - Debug Service Endpoint
- * @CAIF_RADIO_DEBUG_SERVICE: Debug service on the Radio sub-system
- * @CAIF_APP_DEBUG_SERVICE: Debug for the applications sub-system
- */
-enum caif_debug_service {
- CAIF_RADIO_DEBUG_SERVICE = 1,
- CAIF_APP_DEBUG_SERVICE
-};
-
-/**
- * struct sockaddr_caif - the sockaddr structure for CAIF sockets.
- * @family: Address family number, must be AF_CAIF.
- * @u: Union of address data 'switched' by family.
- * :
- * @u.at: Applies when family = CAIFPROTO_AT.
- *
- * @u.at.type: Type of AT link to set up (enum caif_at_type).
- *
- * @u.util: Applies when family = CAIFPROTO_UTIL
- *
- * @u.util.service: Utility service name.
- *
- * @u.dgm: Applies when family = CAIFPROTO_DATAGRAM
- *
- * @u.dgm.connection_id: Datagram connection id.
- *
- * @u.dgm.nsapi: NSAPI of the PDP-Context.
- *
- * @u.rfm: Applies when family = CAIFPROTO_RFM
- *
- * @u.rfm.connection_id: Connection ID for RFM.
- *
- * @u.rfm.volume: Volume to mount.
- *
- * @u.dbg: Applies when family = CAIFPROTO_DEBUG.
- *
- * @u.dbg.type: Type of debug connection to set up
- * (caif_debug_type).
- *
- * @u.dbg.service: Service sub-system to connect (caif_debug_service
- * Description:
- * This structure holds the connect parameters used for setting up a
- * CAIF Channel. It defines the service to connect to on the modem.
- */
-struct sockaddr_caif {
- __kernel_sa_family_t family;
- union {
- struct {
- __u8 type; /* type: enum caif_at_type */
- } at; /* CAIFPROTO_AT */
- struct {
- char service[16];
- } util; /* CAIFPROTO_UTIL */
- union {
- __u32 connection_id;
- __u8 nsapi;
- } dgm; /* CAIFPROTO_DATAGRAM(_LOOP)*/
- struct {
- __u32 connection_id;
- char volume[16];
- } rfm; /* CAIFPROTO_RFM */
- struct {
- __u8 type; /* type:enum caif_debug_type */
- __u8 service; /* service:caif_debug_service */
- } dbg; /* CAIFPROTO_DEBUG */
- } u;
-};
-
-/**
- * enum caif_socket_opts - CAIF option values for getsockopt and setsockopt.
- *
- * @CAIFSO_LINK_SELECT: Selector used if multiple CAIF Link layers are
- * available. Either a high bandwidth
- * link can be selected (CAIF_LINK_HIGH_BANDW) or
- * a low latency link (CAIF_LINK_LOW_LATENCY).
- * This option is of type __u32.
- * Alternatively SO_BINDTODEVICE can be used.
- *
- * @CAIFSO_REQ_PARAM: Used to set the request parameters for a
- * utility channel. (maximum 256 bytes). This
- * option must be set before connecting.
- *
- * @CAIFSO_RSP_PARAM: Gets the response parameters for a utility
- * channel. (maximum 256 bytes). This option
- * is valid after a successful connect.
- *
- *
- * This enum defines the CAIF Socket options to be used on a socket
- * of type PF_CAIF.
- *
- */
-enum caif_socket_opts {
- CAIFSO_LINK_SELECT = 127,
- CAIFSO_REQ_PARAM = 128,
- CAIFSO_RSP_PARAM = 129,
-};
-
-#endif /* _LINUX_CAIF_SOCKET_H */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/caif/if_caif.h b/lib/libc/include/any-linux-any/linux/caif/if_caif.h
deleted file mode 100644
index f69dfe6534b3c94f048c6de9c452ba5d8a684028..0000000000000000000000000000000000000000
--- a/lib/libc/include/any-linux-any/linux/caif/if_caif.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * Copyright (C) ST-Ericsson AB 2010
- * Author: Sjur Brendeland
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#ifndef IF_CAIF_H_
-#define IF_CAIF_H_
-#include
-#include
-#include
-
-/**
- * enum ifla_caif - CAIF NetlinkRT parameters.
- * @IFLA_CAIF_IPV4_CONNID: Connection ID for IPv4 PDP Context.
- * The type of attribute is NLA_U32.
- * @IFLA_CAIF_IPV6_CONNID: Connection ID for IPv6 PDP Context.
- * The type of attribute is NLA_U32.
- * @IFLA_CAIF_LOOPBACK: If different from zero, device is doing loopback
- * The type of attribute is NLA_U8.
- *
- * When using RT Netlink to create, destroy or configure a CAIF IP interface,
- * enum ifla_caif is used to specify the configuration attributes.
- */
-enum ifla_caif {
- __IFLA_CAIF_UNSPEC,
- IFLA_CAIF_IPV4_CONNID,
- IFLA_CAIF_IPV6_CONNID,
- IFLA_CAIF_LOOPBACK,
- __IFLA_CAIF_MAX
-};
-#define IFLA_CAIF_MAX (__IFLA_CAIF_MAX-1)
-
-#endif /*IF_CAIF_H_*/
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/capi.h b/lib/libc/include/any-linux-any/linux/capi.h
deleted file mode 100644
index d2ee971fe4eefb38625cebe7ea084c50fa459188..0000000000000000000000000000000000000000
--- a/lib/libc/include/any-linux-any/linux/capi.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* $Id: capi.h,v 1.4.6.1 2001/09/23 22:25:05 kai Exp $
- *
- * CAPI 2.0 Interface for Linux
- *
- * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#ifndef __LINUX_CAPI_H__
-#define __LINUX_CAPI_H__
-
-#include
-#include
-#include
-
-/*
- * CAPI_REGISTER
- */
-
-typedef struct capi_register_params { /* CAPI_REGISTER */
- __u32 level3cnt; /* No. of simulatneous user data connections */
- __u32 datablkcnt; /* No. of buffered data messages */
- __u32 datablklen; /* Size of buffered data messages */
-} capi_register_params;
-
-#define CAPI_REGISTER _IOW('C',0x01,struct capi_register_params)
-
-/*
- * CAPI_GET_MANUFACTURER
- */
-
-#define CAPI_MANUFACTURER_LEN 64
-
-#define CAPI_GET_MANUFACTURER _IOWR('C',0x06,int) /* broken: wanted size 64 (CAPI_MANUFACTURER_LEN) */
-
-/*
- * CAPI_GET_VERSION
- */
-
-typedef struct capi_version {
- __u32 majorversion;
- __u32 minorversion;
- __u32 majormanuversion;
- __u32 minormanuversion;
-} capi_version;
-
-#define CAPI_GET_VERSION _IOWR('C',0x07,struct capi_version)
-
-/*
- * CAPI_GET_SERIAL
- */
-
-#define CAPI_SERIAL_LEN 8
-#define CAPI_GET_SERIAL _IOWR('C',0x08,int) /* broken: wanted size 8 (CAPI_SERIAL_LEN) */
-
-/*
- * CAPI_GET_PROFILE
- */
-
-typedef struct capi_profile {
- __u16 ncontroller; /* number of installed controller */
- __u16 nbchannel; /* number of B-Channels */
- __u32 goptions; /* global options */
- __u32 support1; /* B1 protocols support */
- __u32 support2; /* B2 protocols support */
- __u32 support3; /* B3 protocols support */
- __u32 reserved[6]; /* reserved */
- __u32 manu[5]; /* manufacturer specific information */
-} capi_profile;
-
-#define CAPI_GET_PROFILE _IOWR('C',0x09,struct capi_profile)
-
-typedef struct capi_manufacturer_cmd {
- unsigned long cmd;
- void *data;
-} capi_manufacturer_cmd;
-
-/*
- * CAPI_MANUFACTURER_CMD
- */
-
-#define CAPI_MANUFACTURER_CMD _IOWR('C',0x20, struct capi_manufacturer_cmd)
-
-/*
- * CAPI_GET_ERRCODE
- * capi errcode is set, * if read, write, or ioctl returns EIO,
- * ioctl returns errcode directly, and in arg, if != 0
- */
-
-#define CAPI_GET_ERRCODE _IOR('C',0x21, __u16)
-
-/*
- * CAPI_INSTALLED
- */
-#define CAPI_INSTALLED _IOR('C',0x22, __u16)
-
-
-/*
- * member contr is input for
- * CAPI_GET_MANUFACTURER, CAPI_GET_VERSION, CAPI_GET_SERIAL
- * and CAPI_GET_PROFILE
- */
-typedef union capi_ioctl_struct {
- __u32 contr;
- capi_register_params rparams;
- __u8 manufacturer[CAPI_MANUFACTURER_LEN];
- capi_version version;
- __u8 serial[CAPI_SERIAL_LEN];
- capi_profile profile;
- capi_manufacturer_cmd cmd;
- __u16 errcode;
-} capi_ioctl_struct;
-
-/*
- * Middleware extension
- */
-
-#define CAPIFLAG_HIGHJACKING 0x0001
-
-#define CAPI_GET_FLAGS _IOR('C',0x23, unsigned)
-#define CAPI_SET_FLAGS _IOR('C',0x24, unsigned)
-#define CAPI_CLR_FLAGS _IOR('C',0x25, unsigned)
-
-#define CAPI_NCCI_OPENCOUNT _IOR('C',0x26, unsigned)
-
-#define CAPI_NCCI_GETUNIT _IOR('C',0x27, unsigned)
-
-#endif /* __LINUX_CAPI_H__ */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/const.h b/lib/libc/include/any-linux-any/linux/const.h
index 5d2ccb6eb51c137550d84391252bd92e814f1757..2cf4a3dd42c200ca696bf7c9666cc032263bce2f 100644
--- a/lib/libc/include/any-linux-any/linux/const.h
+++ b/lib/libc/include/any-linux-any/linux/const.h
@@ -50,4 +50,22 @@
#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+/*
+ * Divide positive or negative dividend by positive or negative divisor
+ * and round to closest integer. Result is undefined for negative
+ * divisors if the dividend variable type is unsigned and for negative
+ * dividends if the divisor variable type is unsigned.
+ */
+#define __KERNEL_DIV_ROUND_CLOSEST(x, divisor) \
+({ \
+ __typeof__(x) __x = x; \
+ __typeof__(divisor) __d = divisor; \
+ \
+ (((__typeof__(x))-1) > 0 || \
+ ((__typeof__(divisor))-1) > 0 || \
+ (((__x) > 0) == ((__d) > 0))) ? \
+ (((__x) + ((__d) / 2)) / (__d)) : \
+ (((__x) - ((__d) / 2)) / (__d)); \
+})
+
#endif /* _LINUX_CONST_H */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/devlink.h b/lib/libc/include/any-linux-any/linux/devlink.h
index 621e00d943e7ee9fc136586c2a80af2bdaed77f1..72613412e4b8056bc00cc49da4cbdc321f7048a6 100644
--- a/lib/libc/include/any-linux-any/linux/devlink.h
+++ b/lib/libc/include/any-linux-any/linux/devlink.h
@@ -19,6 +19,8 @@
#define DEVLINK_GENL_VERSION 0x1
#define DEVLINK_GENL_MCGRP_CONFIG_NAME "config"
+#define DEVLINK_INDEX_BUS_NAME "devlink_index"
+
enum devlink_command {
/* don't change the order or add anything between, this is ABI! */
DEVLINK_CMD_UNSPEC,
@@ -642,6 +644,9 @@ enum devlink_attr {
DEVLINK_ATTR_PARAM_VALUE_DEFAULT, /* dynamic */
DEVLINK_ATTR_PARAM_RESET_DEFAULT, /* flag */
+ DEVLINK_ATTR_INDEX, /* uint */
+ DEVLINK_ATTR_RESOURCE_SCOPE_MASK, /* u32 */
+
/* Add new attributes above here, update the spec in
* Documentation/netlink/specs/devlink.yaml and re-generate
* net/devlink/netlink_gen.c.
@@ -700,6 +705,16 @@ enum devlink_resource_unit {
DEVLINK_RESOURCE_UNIT_ENTRY,
};
+enum devlink_resource_scope {
+ DEVLINK_RESOURCE_SCOPE_DEV_BIT,
+ DEVLINK_RESOURCE_SCOPE_PORT_BIT,
+};
+
+#define DEVLINK_RESOURCE_SCOPE_DEV \
+ _BITUL(DEVLINK_RESOURCE_SCOPE_DEV_BIT)
+#define DEVLINK_RESOURCE_SCOPE_PORT \
+ _BITUL(DEVLINK_RESOURCE_SCOPE_PORT_BIT)
+
enum devlink_port_fn_attr_cap {
DEVLINK_PORT_FN_ATTR_CAP_ROCE_BIT,
DEVLINK_PORT_FN_ATTR_CAP_MIGRATABLE_BIT,
diff --git a/lib/libc/include/any-linux-any/linux/dpll.h b/lib/libc/include/any-linux-any/linux/dpll.h
index 99ad96d532fcda4a25e013a575d2812a113125c3..68a160b367fceb0d62605fd713305bd8f5a2702d 100644
--- a/lib/libc/include/any-linux-any/linux/dpll.h
+++ b/lib/libc/include/any-linux-any/linux/dpll.h
@@ -191,7 +191,8 @@ enum dpll_pin_capabilities {
DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE = 4,
};
-#define DPLL_PHASE_OFFSET_DIVIDER 1000
+#define DPLL_PHASE_OFFSET_DIVIDER 1000
+#define DPLL_PIN_MEASURED_FREQUENCY_DIVIDER 1000
/**
* enum dpll_feature_state - Allow control (enable/disable) and status checking
@@ -218,6 +219,7 @@ enum dpll_a {
DPLL_A_CLOCK_QUALITY_LEVEL,
DPLL_A_PHASE_OFFSET_MONITOR,
DPLL_A_PHASE_OFFSET_AVG_FACTOR,
+ DPLL_A_FREQUENCY_MONITOR,
__DPLL_A_MAX,
DPLL_A_MAX = (__DPLL_A_MAX - 1)
@@ -254,6 +256,7 @@ enum dpll_a_pin {
DPLL_A_PIN_REFERENCE_SYNC,
DPLL_A_PIN_PHASE_ADJUST_GRAN,
DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT,
+ DPLL_A_PIN_MEASURED_FREQUENCY,
__DPLL_A_PIN_MAX,
DPLL_A_PIN_MAX = (__DPLL_A_PIN_MAX - 1)
diff --git a/lib/libc/include/any-linux-any/linux/ethtool.h b/lib/libc/include/any-linux-any/linux/ethtool.h
index 399bf5ccf81a7b679474ea45034e01839e355337..78cccfe2680509b9e555e87ce64f21ec69e5a62b 100644
--- a/lib/libc/include/any-linux-any/linux/ethtool.h
+++ b/lib/libc/include/any-linux-any/linux/ethtool.h
@@ -225,7 +225,7 @@ enum tunable_id {
ETHTOOL_ID_UNSPEC,
ETHTOOL_RX_COPYBREAK,
ETHTOOL_TX_COPYBREAK,
- ETHTOOL_PFC_PREVENTION_TOUT, /* timeout in msecs */
+ ETHTOOL_PFC_PREVENTION_TOUT, /* both pause and pfc, see man ethtool */
ETHTOOL_TX_COPYBREAK_BUF_SIZE,
/*
* Add your fresh new tunable attribute above and remember to update
diff --git a/lib/libc/include/any-linux-any/linux/ethtool_netlink_generated.h b/lib/libc/include/any-linux-any/linux/ethtool_netlink_generated.h
index 2ab973732a9c37896dd3bf3602870aee7569cc6c..61fa282ac825e6dd97a0880d9f2c535709518642 100644
--- a/lib/libc/include/any-linux-any/linux/ethtool_netlink_generated.h
+++ b/lib/libc/include/any-linux-any/linux/ethtool_netlink_generated.h
@@ -371,6 +371,8 @@ enum {
ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS,
ETHTOOL_A_COALESCE_RX_PROFILE,
ETHTOOL_A_COALESCE_TX_PROFILE,
+ ETHTOOL_A_COALESCE_RX_CQE_FRAMES,
+ ETHTOOL_A_COALESCE_RX_CQE_NSECS,
__ETHTOOL_A_COALESCE_CNT,
ETHTOOL_A_COALESCE_MAX = (__ETHTOOL_A_COALESCE_CNT - 1)
@@ -381,6 +383,7 @@ enum {
ETHTOOL_A_PAUSE_STAT_PAD,
ETHTOOL_A_PAUSE_STAT_TX_FRAMES,
ETHTOOL_A_PAUSE_STAT_RX_FRAMES,
+ ETHTOOL_A_PAUSE_STAT_TX_PAUSE_STORM_EVENTS,
__ETHTOOL_A_PAUSE_STAT_CNT,
ETHTOOL_A_PAUSE_STAT_MAX = (__ETHTOOL_A_PAUSE_STAT_CNT - 1)
diff --git a/lib/libc/include/any-linux-any/linux/fs.h b/lib/libc/include/any-linux-any/linux/fs.h
index 5548e4a1c57e1b3b732a95e3e22ad2b98f9d8799..5df9a3189e5f442b4ea38bbf4b1aa2ef349f644c 100644
--- a/lib/libc/include/any-linux-any/linux/fs.h
+++ b/lib/libc/include/any-linux-any/linux/fs.h
@@ -653,4 +653,16 @@ struct procmap_query {
__u64 build_id_addr; /* in */
};
+/*
+ * Shutdown the filesystem.
+ */
+#define FS_IOC_SHUTDOWN _IOR('X', 125, __u32)
+
+/*
+ * Flags for FS_IOC_SHUTDOWN
+ */
+#define FS_SHUTDOWN_FLAGS_DEFAULT 0x0
+#define FS_SHUTDOWN_FLAGS_LOGFLUSH 0x1 /* flush log but not data*/
+#define FS_SHUTDOWN_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */
+
#endif /* _LINUX_FS_H */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/hdlcdrv.h b/lib/libc/include/any-linux-any/linux/hdlcdrv.h
deleted file mode 100644
index fa22437bc7a8e148acc3f0e1ab1f1f5c19cc508a..0000000000000000000000000000000000000000
--- a/lib/libc/include/any-linux-any/linux/hdlcdrv.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * hdlcdrv.h -- HDLC packet radio network driver.
- * The Linux soundcard driver for 1200 baud and 9600 baud packet radio
- * (C) 1996-1998 by Thomas Sailer, HB9JNX/AE4WA
- */
-
-#ifndef _HDLCDRV_H
-#define _HDLCDRV_H
-
-/* -------------------------------------------------------------------- */
-/*
- * structs for the IOCTL commands
- */
-
-struct hdlcdrv_params {
- int iobase;
- int irq;
- int dma;
- int dma2;
- int seriobase;
- int pariobase;
- int midiiobase;
-};
-
-struct hdlcdrv_channel_params {
- int tx_delay; /* the transmitter keyup delay in 10ms units */
- int tx_tail; /* the transmitter keyoff delay in 10ms units */
- int slottime; /* the slottime in 10ms; usually 10 = 100ms */
- int ppersist; /* the p-persistence 0..255 */
- int fulldup; /* some driver do not support full duplex, setting */
- /* this just makes them send even if DCD is on */
-};
-
-struct hdlcdrv_old_channel_state {
- int ptt;
- int dcd;
- int ptt_keyed;
-};
-
-struct hdlcdrv_channel_state {
- int ptt;
- int dcd;
- int ptt_keyed;
- unsigned long tx_packets;
- unsigned long tx_errors;
- unsigned long rx_packets;
- unsigned long rx_errors;
-};
-
-struct hdlcdrv_ioctl {
- int cmd;
- union {
- struct hdlcdrv_params mp;
- struct hdlcdrv_channel_params cp;
- struct hdlcdrv_channel_state cs;
- struct hdlcdrv_old_channel_state ocs;
- unsigned int calibrate;
- unsigned char bits;
- char modename[128];
- char drivername[32];
- } data;
-};
-
-/* -------------------------------------------------------------------- */
-
-/*
- * ioctl values
- */
-#define HDLCDRVCTL_GETMODEMPAR 0
-#define HDLCDRVCTL_SETMODEMPAR 1
-#define HDLCDRVCTL_MODEMPARMASK 2 /* not handled by hdlcdrv */
-#define HDLCDRVCTL_GETCHANNELPAR 10
-#define HDLCDRVCTL_SETCHANNELPAR 11
-#define HDLCDRVCTL_OLDGETSTAT 20
-#define HDLCDRVCTL_CALIBRATE 21
-#define HDLCDRVCTL_GETSTAT 22
-
-/*
- * these are mainly for debugging purposes
- */
-#define HDLCDRVCTL_GETSAMPLES 30
-#define HDLCDRVCTL_GETBITS 31
-
-/*
- * not handled by hdlcdrv, but by its depending drivers
- */
-#define HDLCDRVCTL_GETMODE 40
-#define HDLCDRVCTL_SETMODE 41
-#define HDLCDRVCTL_MODELIST 42
-#define HDLCDRVCTL_DRIVERNAME 43
-
-/*
- * mask of needed modem parameters, returned by HDLCDRVCTL_MODEMPARMASK
- */
-#define HDLCDRV_PARMASK_IOBASE (1<<0)
-#define HDLCDRV_PARMASK_IRQ (1<<1)
-#define HDLCDRV_PARMASK_DMA (1<<2)
-#define HDLCDRV_PARMASK_DMA2 (1<<3)
-#define HDLCDRV_PARMASK_SERIOBASE (1<<4)
-#define HDLCDRV_PARMASK_PARIOBASE (1<<5)
-#define HDLCDRV_PARMASK_MIDIIOBASE (1<<6)
-
-/* -------------------------------------------------------------------- */
-
-
-/* -------------------------------------------------------------------- */
-
-#endif /* _HDLCDRV_H */
-
-/* -------------------------------------------------------------------- */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/if_link.h b/lib/libc/include/any-linux-any/linux/if_link.h
index 991d8cf537390a65b80b6bf07db17b2233f6d678..6116c2f5b90f9017be90cc33a973beb23c93ad90 100644
--- a/lib/libc/include/any-linux-any/linux/if_link.h
+++ b/lib/libc/include/any-linux-any/linux/if_link.h
@@ -742,6 +742,11 @@ enum in6_addr_gen_mode {
* @IFLA_BR_FDB_MAX_LEARNED
* Set the number of max dynamically learned FDB entries for the current
* bridge.
+ *
+ * @IFLA_BR_STP_MODE
+ * Set the STP mode for the bridge, which controls how the bridge
+ * selects between userspace and kernel STP. The valid values are
+ * documented below in the ``BR_STP_MODE_*`` constants.
*/
enum {
IFLA_BR_UNSPEC,
@@ -794,11 +799,45 @@ enum {
IFLA_BR_MCAST_QUERIER_STATE,
IFLA_BR_FDB_N_LEARNED,
IFLA_BR_FDB_MAX_LEARNED,
+ IFLA_BR_STP_MODE,
__IFLA_BR_MAX,
};
#define IFLA_BR_MAX (__IFLA_BR_MAX - 1)
+/**
+ * DOC: Bridge STP mode values
+ *
+ * @BR_STP_MODE_AUTO
+ * Default. The kernel invokes the ``/sbin/bridge-stp`` helper to hand
+ * the bridge to a userspace STP daemon (e.g. mstpd). Only attempted in
+ * the initial network namespace; in other namespaces this falls back to
+ * kernel STP.
+ *
+ * @BR_STP_MODE_USER
+ * Directly enable userspace STP (``BR_USER_STP``) without invoking the
+ * ``/sbin/bridge-stp`` helper. Works in any network namespace.
+ * Userspace is responsible for ensuring an STP daemon manages the
+ * bridge.
+ *
+ * @BR_STP_MODE_KERNEL
+ * Directly enable kernel STP (``BR_KERNEL_STP``) without invoking the
+ * helper.
+ *
+ * The mode controls how the bridge selects between userspace and kernel
+ * STP when STP is enabled via ``IFLA_BR_STP_STATE``. It can only be
+ * changed while STP is disabled (``IFLA_BR_STP_STATE`` == 0), returns
+ * ``-EBUSY`` otherwise. The default value is ``BR_STP_MODE_AUTO``.
+ */
+enum br_stp_mode {
+ BR_STP_MODE_AUTO,
+ BR_STP_MODE_USER,
+ BR_STP_MODE_KERNEL,
+ __BR_STP_MODE_MAX
+};
+
+#define BR_STP_MODE_MAX (__BR_STP_MODE_MAX - 1)
+
struct ifla_bridge_id {
__u8 prio[2];
__u8 addr[6]; /* ETH_ALEN */
@@ -1294,6 +1333,11 @@ enum netkit_mode {
NETKIT_L3,
};
+enum netkit_pairing {
+ NETKIT_DEVICE_PAIR,
+ NETKIT_DEVICE_SINGLE,
+};
+
/* NETKIT_SCRUB_NONE leaves clearing skb->{mark,priority} up to
* the BPF program if attached. This also means the latter can
* consume the two fields if they were populated earlier.
@@ -1318,6 +1362,7 @@ enum {
IFLA_NETKIT_PEER_SCRUB,
IFLA_NETKIT_HEADROOM,
IFLA_NETKIT_TAILROOM,
+ IFLA_NETKIT_PAIRING,
__IFLA_NETKIT_MAX,
};
#define IFLA_NETKIT_MAX (__IFLA_NETKIT_MAX - 1)
@@ -1566,6 +1611,8 @@ enum {
IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE,
IFLA_BOND_SLAVE_PRIO,
IFLA_BOND_SLAVE_ACTOR_PORT_PRIO,
+ IFLA_BOND_SLAVE_AD_CHURN_ACTOR_STATE,
+ IFLA_BOND_SLAVE_AD_CHURN_PARTNER_STATE,
__IFLA_BOND_SLAVE_MAX,
};
diff --git a/lib/libc/include/any-linux-any/linux/if_pppox.h b/lib/libc/include/any-linux-any/linux/if_pppox.h
index a3988ac76cc21adbf1be70969ba4c09e676677ca..94537cbd51b7292ceed1349851d11c9e89d0b8b3 100644
--- a/lib/libc/include/any-linux-any/linux/if_pppox.h
+++ b/lib/libc/include/any-linux-any/linux/if_pppox.h
@@ -103,16 +103,6 @@ struct sockaddr_pppol2tpv3in6 {
struct pppol2tpv3in6_addr pppol2tp;
} __attribute__((packed));
-/*********************************************************************
- *
- * ioctl interface for defining forwarding of connections
- *
- ********************************************************************/
-
-#define PPPOEIOCSFWD _IOW(0xB1 ,0, size_t)
-#define PPPOEIOCDFWD _IO(0xB1 ,1)
-/*#define PPPOEIOCGFWD _IOWR(0xB1,2, size_t)*/
-
/* Codes to identify message types */
#define PADI_CODE 0x09
#define PADO_CODE 0x07
diff --git a/lib/libc/include/any-linux-any/linux/inet_diag.h b/lib/libc/include/any-linux-any/linux/inet_diag.h
index 375684de5bf06327601e240e6b8001df16cbd83c..219a35785fa93279a6a63d5d6c3fce21e3d13c46 100644
--- a/lib/libc/include/any-linux-any/linux/inet_diag.h
+++ b/lib/libc/include/any-linux-any/linux/inet_diag.h
@@ -129,6 +129,15 @@ struct inet_diag_msg {
__u32 idiag_inode;
};
+enum {
+ IDIAG_TIMER_OFF,
+ IDIAG_TIMER_ON,
+ IDIAG_TIMER_KEEPALIVE,
+ IDIAG_TIMER_TIMEWAIT,
+ IDIAG_TIMER_PROBE0,
+ IDIAG_TIMER_DELACK,
+};
+
/* Extensions */
enum {
diff --git a/lib/libc/include/any-linux-any/linux/io_uring.h b/lib/libc/include/any-linux-any/linux/io_uring.h
index 7616a1ccf344b16fe577c356c11cdb0b84794418..1526ababbaf5482c82a28167f49a723c4c4178ec 100644
--- a/lib/libc/include/any-linux-any/linux/io_uring.h
+++ b/lib/libc/include/any-linux-any/linux/io_uring.h
@@ -10,6 +10,8 @@
#include
#include
+#include
+
/*
* this file is shared with liburing and that has to autodetect
* if linux/time_types.h is available or not, it can
@@ -341,6 +343,10 @@ enum io_uring_op {
/*
* sqe->timeout_flags
+ *
+ * IORING_TIMEOUT_IMMEDIATE_ARG: If set, sqe->addr stores the timeout
+ * value in nanoseconds instead of
+ * pointing to a timespec.
*/
#define IORING_TIMEOUT_ABS (1U << 0)
#define IORING_TIMEOUT_UPDATE (1U << 1)
@@ -349,6 +355,7 @@ enum io_uring_op {
#define IORING_LINK_TIMEOUT_UPDATE (1U << 4)
#define IORING_TIMEOUT_ETIME_SUCCESS (1U << 5)
#define IORING_TIMEOUT_MULTISHOT (1U << 6)
+#define IORING_TIMEOUT_IMMEDIATE_ARG (1U << 7)
#define IORING_TIMEOUT_CLOCK_MASK (IORING_TIMEOUT_BOOTTIME | IORING_TIMEOUT_REALTIME)
#define IORING_TIMEOUT_UPDATE_MASK (IORING_TIMEOUT_UPDATE | IORING_LINK_TIMEOUT_UPDATE)
/*
@@ -898,7 +905,8 @@ struct io_uring_buf_reg {
__u32 ring_entries;
__u16 bgid;
__u16 flags;
- __u64 resv[3];
+ __u32 min_left;
+ __u32 resv[5];
};
/* argument for IORING_REGISTER_PBUF_STATUS */
@@ -1050,100 +1058,6 @@ struct io_timespec {
__u64 tv_nsec;
};
-/* Zero copy receive refill queue entry */
-struct io_uring_zcrx_rqe {
- __u64 off;
- __u32 len;
- __u32 __pad;
-};
-
-struct io_uring_zcrx_cqe {
- __u64 off;
- __u64 __pad;
-};
-
-/* The bit from which area id is encoded into offsets */
-#define IORING_ZCRX_AREA_SHIFT 48
-#define IORING_ZCRX_AREA_MASK (~(((__u64)1 << IORING_ZCRX_AREA_SHIFT) - 1))
-
-struct io_uring_zcrx_offsets {
- __u32 head;
- __u32 tail;
- __u32 rqes;
- __u32 __resv2;
- __u64 __resv[2];
-};
-
-enum io_uring_zcrx_area_flags {
- IORING_ZCRX_AREA_DMABUF = 1,
-};
-
-struct io_uring_zcrx_area_reg {
- __u64 addr;
- __u64 len;
- __u64 rq_area_token;
- __u32 flags;
- __u32 dmabuf_fd;
- __u64 __resv2[2];
-};
-
-enum zcrx_reg_flags {
- ZCRX_REG_IMPORT = 1,
-};
-
-enum zcrx_features {
- /*
- * The user can ask for the desired rx page size by passing the
- * value in struct io_uring_zcrx_ifq_reg::rx_buf_len.
- */
- ZCRX_FEATURE_RX_PAGE_SIZE = 1 << 0,
-};
-
-/*
- * Argument for IORING_REGISTER_ZCRX_IFQ
- */
-struct io_uring_zcrx_ifq_reg {
- __u32 if_idx;
- __u32 if_rxq;
- __u32 rq_entries;
- __u32 flags;
-
- __u64 area_ptr; /* pointer to struct io_uring_zcrx_area_reg */
- __u64 region_ptr; /* struct io_uring_region_desc * */
-
- struct io_uring_zcrx_offsets offsets;
- __u32 zcrx_id;
- __u32 rx_buf_len;
- __u64 __resv[3];
-};
-
-enum zcrx_ctrl_op {
- ZCRX_CTRL_FLUSH_RQ,
- ZCRX_CTRL_EXPORT,
-
- __ZCRX_CTRL_LAST,
-};
-
-struct zcrx_ctrl_flush_rq {
- __u64 __resv[6];
-};
-
-struct zcrx_ctrl_export {
- __u32 zcrx_fd;
- __u32 __resv1[11];
-};
-
-struct zcrx_ctrl {
- __u32 zcrx_id;
- __u32 op; /* see enum zcrx_ctrl_op */
- __u64 __resv[2];
-
- union {
- struct zcrx_ctrl_export zc_export;
- struct zcrx_ctrl_flush_rq zc_flush;
- };
-};
-
#ifdef __cplusplus
}
#endif
diff --git a/lib/libc/include/any-linux-any/linux/io_uring/zcrx.h b/lib/libc/include/any-linux-any/linux/io_uring/zcrx.h
new file mode 100644
index 0000000000000000000000000000000000000000..a42e55fd3100f8ea71ce40eb7fb05e2f775806c7
--- /dev/null
+++ b/lib/libc/include/any-linux-any/linux/io_uring/zcrx.h
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR MIT */
+/*
+ * Header file for the io_uring zerocopy receive (zcrx) interface.
+ *
+ * Copyright (C) 2026 Pavel Begunkov
+ * Copyright (C) 2026 David Wei
+ * Copyright (C) Meta Platforms, Inc.
+ */
+#ifndef LINUX_IO_ZCRX_H
+#define LINUX_IO_ZCRX_H
+
+#include
+
+/* Zero copy receive refill queue entry */
+struct io_uring_zcrx_rqe {
+ __u64 off;
+ __u32 len;
+ __u32 __pad;
+};
+
+struct io_uring_zcrx_cqe {
+ __u64 off;
+ __u64 __pad;
+};
+
+/* The bit from which area id is encoded into offsets */
+#define IORING_ZCRX_AREA_SHIFT 48
+#define IORING_ZCRX_AREA_MASK (~(((__u64)1 << IORING_ZCRX_AREA_SHIFT) - 1))
+
+struct io_uring_zcrx_offsets {
+ __u32 head;
+ __u32 tail;
+ __u32 rqes;
+ __u32 __resv2;
+ __u64 __resv[2];
+};
+
+enum io_uring_zcrx_area_flags {
+ IORING_ZCRX_AREA_DMABUF = 1,
+};
+
+struct io_uring_zcrx_area_reg {
+ __u64 addr;
+ __u64 len;
+ __u64 rq_area_token;
+ __u32 flags;
+ __u32 dmabuf_fd;
+ __u64 __resv2[2];
+};
+
+enum zcrx_reg_flags {
+ ZCRX_REG_IMPORT = 1,
+
+ /*
+ * Register a zcrx instance without a net device. All data will be
+ * copied. The refill queue entries might not be automatically
+ * consumed and need to be flushed, see ZCRX_CTRL_FLUSH_RQ.
+ */
+ ZCRX_REG_NODEV = 2,
+};
+
+enum zcrx_features {
+ /*
+ * The user can ask for the desired rx page size by passing the
+ * value in struct io_uring_zcrx_ifq_reg::rx_buf_len.
+ */
+ ZCRX_FEATURE_RX_PAGE_SIZE = 1 << 0,
+};
+
+/*
+ * Argument for IORING_REGISTER_ZCRX_IFQ
+ */
+struct io_uring_zcrx_ifq_reg {
+ __u32 if_idx;
+ __u32 if_rxq;
+ __u32 rq_entries;
+ __u32 flags;
+
+ __u64 area_ptr; /* pointer to struct io_uring_zcrx_area_reg */
+ __u64 region_ptr; /* struct io_uring_region_desc * */
+
+ struct io_uring_zcrx_offsets offsets;
+ __u32 zcrx_id;
+ __u32 rx_buf_len;
+ __u64 __resv[3];
+};
+
+enum zcrx_ctrl_op {
+ ZCRX_CTRL_FLUSH_RQ,
+ ZCRX_CTRL_EXPORT,
+
+ __ZCRX_CTRL_LAST,
+};
+
+struct zcrx_ctrl_flush_rq {
+ __u64 __resv[6];
+};
+
+struct zcrx_ctrl_export {
+ __u32 zcrx_fd;
+ __u32 __resv1[11];
+};
+
+struct zcrx_ctrl {
+ __u32 zcrx_id;
+ __u32 op; /* see enum zcrx_ctrl_op */
+ __u64 __resv[2];
+
+ union {
+ struct zcrx_ctrl_export zc_export;
+ struct zcrx_ctrl_flush_rq zc_flush;
+ };
+};
+
+#endif /* LINUX_IO_ZCRX_H */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/iommufd.h b/lib/libc/include/any-linux-any/linux/iommufd.h
index 8489beb6a06c9d4a82c9a57f91510983d7aa1c92..d8d8e4fba370b7dc479219a7d07319d21aafc733 100644
--- a/lib/libc/include/any-linux-any/linux/iommufd.h
+++ b/lib/libc/include/any-linux-any/linux/iommufd.h
@@ -695,11 +695,15 @@ enum iommu_hw_info_type {
* @IOMMU_HW_CAP_PCI_PASID_PRIV: Privileged Mode Supported, user ignores it
* when the struct
* iommu_hw_info::out_max_pasid_log2 is zero.
+ * @IOMMU_HW_CAP_PCI_ATS_NOT_SUPPORTED: ATS is not supported or cannot be used
+ * on this device (absence implies ATS
+ * may be enabled)
*/
enum iommufd_hw_capabilities {
IOMMU_HW_CAP_DIRTY_TRACKING = 1 << 0,
IOMMU_HW_CAP_PCI_PASID_EXEC = 1 << 1,
IOMMU_HW_CAP_PCI_PASID_PRIV = 1 << 2,
+ IOMMU_HW_CAP_PCI_ATS_NOT_SUPPORTED = 1 << 3,
};
/**
@@ -1052,6 +1056,11 @@ struct iommu_fault_alloc {
enum iommu_viommu_type {
IOMMU_VIOMMU_TYPE_DEFAULT = 0,
IOMMU_VIOMMU_TYPE_ARM_SMMUV3 = 1,
+ /*
+ * TEGRA241_CMDQV requirements (otherwise, VCMDQs will not work)
+ * - Kernel will allocate a VINTF (HYP_OWN=0) to back this VIOMMU. So,
+ * VMM must wire the HYP_OWN bit to 0 in guest VINTF_CONFIG register
+ */
IOMMU_VIOMMU_TYPE_TEGRA241_CMDQV = 2,
};
diff --git a/lib/libc/include/any-linux-any/linux/isdn/capicmd.h b/lib/libc/include/any-linux-any/linux/isdn/capicmd.h
deleted file mode 100644
index c81d27dabf125516352e36bdde5e861e090ba50d..0000000000000000000000000000000000000000
--- a/lib/libc/include/any-linux-any/linux/isdn/capicmd.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* $Id: capicmd.h,v 1.2.6.2 2001/09/23 22:24:33 kai Exp $
- *
- * CAPI 2.0 Interface for Linux
- *
- * Copyright 1997 by Carsten Paeth
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#ifndef __CAPICMD_H__
-#define __CAPICMD_H__
-
-#define CAPI_MSG_BASELEN 8
-#define CAPI_DATA_B3_REQ_LEN (CAPI_MSG_BASELEN+4+4+2+2+2)
-#define CAPI_DATA_B3_RESP_LEN (CAPI_MSG_BASELEN+4+2)
-#define CAPI_DISCONNECT_B3_RESP_LEN (CAPI_MSG_BASELEN+4)
-
-/*----- CAPI commands -----*/
-#define CAPI_ALERT 0x01
-#define CAPI_CONNECT 0x02
-#define CAPI_CONNECT_ACTIVE 0x03
-#define CAPI_CONNECT_B3_ACTIVE 0x83
-#define CAPI_CONNECT_B3 0x82
-#define CAPI_CONNECT_B3_T90_ACTIVE 0x88
-#define CAPI_DATA_B3 0x86
-#define CAPI_DISCONNECT_B3 0x84
-#define CAPI_DISCONNECT 0x04
-#define CAPI_FACILITY 0x80
-#define CAPI_INFO 0x08
-#define CAPI_LISTEN 0x05
-#define CAPI_MANUFACTURER 0xff
-#define CAPI_RESET_B3 0x87
-#define CAPI_SELECT_B_PROTOCOL 0x41
-
-/*----- CAPI subcommands -----*/
-
-#define CAPI_REQ 0x80
-#define CAPI_CONF 0x81
-#define CAPI_IND 0x82
-#define CAPI_RESP 0x83
-
-/*----- CAPI combined commands -----*/
-
-#define CAPICMD(cmd,subcmd) (((cmd)<<8)|(subcmd))
-
-#define CAPI_DISCONNECT_REQ CAPICMD(CAPI_DISCONNECT,CAPI_REQ)
-#define CAPI_DISCONNECT_CONF CAPICMD(CAPI_DISCONNECT,CAPI_CONF)
-#define CAPI_DISCONNECT_IND CAPICMD(CAPI_DISCONNECT,CAPI_IND)
-#define CAPI_DISCONNECT_RESP CAPICMD(CAPI_DISCONNECT,CAPI_RESP)
-
-#define CAPI_ALERT_REQ CAPICMD(CAPI_ALERT,CAPI_REQ)
-#define CAPI_ALERT_CONF CAPICMD(CAPI_ALERT,CAPI_CONF)
-
-#define CAPI_CONNECT_REQ CAPICMD(CAPI_CONNECT,CAPI_REQ)
-#define CAPI_CONNECT_CONF CAPICMD(CAPI_CONNECT,CAPI_CONF)
-#define CAPI_CONNECT_IND CAPICMD(CAPI_CONNECT,CAPI_IND)
-#define CAPI_CONNECT_RESP CAPICMD(CAPI_CONNECT,CAPI_RESP)
-
-#define CAPI_CONNECT_ACTIVE_REQ CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_REQ)
-#define CAPI_CONNECT_ACTIVE_CONF CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_CONF)
-#define CAPI_CONNECT_ACTIVE_IND CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_IND)
-#define CAPI_CONNECT_ACTIVE_RESP CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_RESP)
-
-#define CAPI_SELECT_B_PROTOCOL_REQ CAPICMD(CAPI_SELECT_B_PROTOCOL,CAPI_REQ)
-#define CAPI_SELECT_B_PROTOCOL_CONF CAPICMD(CAPI_SELECT_B_PROTOCOL,CAPI_CONF)
-
-#define CAPI_CONNECT_B3_ACTIVE_REQ CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_REQ)
-#define CAPI_CONNECT_B3_ACTIVE_CONF CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_CONF)
-#define CAPI_CONNECT_B3_ACTIVE_IND CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_IND)
-#define CAPI_CONNECT_B3_ACTIVE_RESP CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_RESP)
-
-#define CAPI_CONNECT_B3_REQ CAPICMD(CAPI_CONNECT_B3,CAPI_REQ)
-#define CAPI_CONNECT_B3_CONF CAPICMD(CAPI_CONNECT_B3,CAPI_CONF)
-#define CAPI_CONNECT_B3_IND CAPICMD(CAPI_CONNECT_B3,CAPI_IND)
-#define CAPI_CONNECT_B3_RESP CAPICMD(CAPI_CONNECT_B3,CAPI_RESP)
-
-
-#define CAPI_CONNECT_B3_T90_ACTIVE_IND CAPICMD(CAPI_CONNECT_B3_T90_ACTIVE,CAPI_IND)
-#define CAPI_CONNECT_B3_T90_ACTIVE_RESP CAPICMD(CAPI_CONNECT_B3_T90_ACTIVE,CAPI_RESP)
-
-#define CAPI_DATA_B3_REQ CAPICMD(CAPI_DATA_B3,CAPI_REQ)
-#define CAPI_DATA_B3_CONF CAPICMD(CAPI_DATA_B3,CAPI_CONF)
-#define CAPI_DATA_B3_IND CAPICMD(CAPI_DATA_B3,CAPI_IND)
-#define CAPI_DATA_B3_RESP CAPICMD(CAPI_DATA_B3,CAPI_RESP)
-
-#define CAPI_DISCONNECT_B3_REQ CAPICMD(CAPI_DISCONNECT_B3,CAPI_REQ)
-#define CAPI_DISCONNECT_B3_CONF CAPICMD(CAPI_DISCONNECT_B3,CAPI_CONF)
-#define CAPI_DISCONNECT_B3_IND CAPICMD(CAPI_DISCONNECT_B3,CAPI_IND)
-#define CAPI_DISCONNECT_B3_RESP CAPICMD(CAPI_DISCONNECT_B3,CAPI_RESP)
-
-#define CAPI_RESET_B3_REQ CAPICMD(CAPI_RESET_B3,CAPI_REQ)
-#define CAPI_RESET_B3_CONF CAPICMD(CAPI_RESET_B3,CAPI_CONF)
-#define CAPI_RESET_B3_IND CAPICMD(CAPI_RESET_B3,CAPI_IND)
-#define CAPI_RESET_B3_RESP CAPICMD(CAPI_RESET_B3,CAPI_RESP)
-
-#define CAPI_LISTEN_REQ CAPICMD(CAPI_LISTEN,CAPI_REQ)
-#define CAPI_LISTEN_CONF CAPICMD(CAPI_LISTEN,CAPI_CONF)
-
-#define CAPI_MANUFACTURER_REQ CAPICMD(CAPI_MANUFACTURER,CAPI_REQ)
-#define CAPI_MANUFACTURER_CONF CAPICMD(CAPI_MANUFACTURER,CAPI_CONF)
-#define CAPI_MANUFACTURER_IND CAPICMD(CAPI_MANUFACTURER,CAPI_IND)
-#define CAPI_MANUFACTURER_RESP CAPICMD(CAPI_MANUFACTURER,CAPI_RESP)
-
-#define CAPI_FACILITY_REQ CAPICMD(CAPI_FACILITY,CAPI_REQ)
-#define CAPI_FACILITY_CONF CAPICMD(CAPI_FACILITY,CAPI_CONF)
-#define CAPI_FACILITY_IND CAPICMD(CAPI_FACILITY,CAPI_IND)
-#define CAPI_FACILITY_RESP CAPICMD(CAPI_FACILITY,CAPI_RESP)
-
-#define CAPI_INFO_REQ CAPICMD(CAPI_INFO,CAPI_REQ)
-#define CAPI_INFO_CONF CAPICMD(CAPI_INFO,CAPI_CONF)
-#define CAPI_INFO_IND CAPICMD(CAPI_INFO,CAPI_IND)
-#define CAPI_INFO_RESP CAPICMD(CAPI_INFO,CAPI_RESP)
-
-#endif /* __CAPICMD_H__ */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/kernelcapi.h b/lib/libc/include/any-linux-any/linux/kernelcapi.h
deleted file mode 100644
index 042a0083d78d724fedec907b7ef79cc8370ef695..0000000000000000000000000000000000000000
--- a/lib/libc/include/any-linux-any/linux/kernelcapi.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * $Id: kernelcapi.h,v 1.8.6.2 2001/02/07 11:31:31 kai Exp $
- *
- * Kernel CAPI 2.0 Interface for Linux
- *
- * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
- *
- */
-
-#ifndef __KERNELCAPI_H__
-#define __KERNELCAPI_H__
-
-#define CAPI_MAXAPPL 240 /* maximum number of applications */
-#define CAPI_MAXCONTR 32 /* maximum number of controller */
-#define CAPI_MAXDATAWINDOW 8
-
-
-typedef struct kcapi_flagdef {
- int contr;
- int flag;
-} kcapi_flagdef;
-
-typedef struct kcapi_carddef {
- char driver[32];
- unsigned int port;
- unsigned irq;
- unsigned int membase;
- int cardnr;
-} kcapi_carddef;
-
-/* new ioctls >= 10 */
-#define KCAPI_CMD_TRACE 10
-#define KCAPI_CMD_ADDCARD 11 /* OBSOLETE */
-
-/*
- * flag > 2 => trace also data
- * flag & 1 => show trace
- */
-#define KCAPI_TRACE_OFF 0
-#define KCAPI_TRACE_SHORT_NO_DATA 1
-#define KCAPI_TRACE_FULL_NO_DATA 2
-#define KCAPI_TRACE_SHORT 3
-#define KCAPI_TRACE_FULL 4
-
-
-
-#endif /* __KERNELCAPI_H__ */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/keyboard.h b/lib/libc/include/any-linux-any/linux/keyboard.h
index 7c073b866ae51b3ab677c8395799bc2952f3f585..4328b04be8606cd2babdf04b3ecf59d2fa51c0a6 100644
--- a/lib/libc/include/any-linux-any/linux/keyboard.h
+++ b/lib/libc/include/any-linux-any/linux/keyboard.h
@@ -41,6 +41,7 @@
#define KT_SLOCK 12
#define KT_DEAD2 13
#define KT_BRL 14
+#define KT_CSI 15 /* CSI sequences with modifier support */
#define K(t,v) (((t)<<8)|(v))
#define KTYP(x) ((x) >> 8)
@@ -461,5 +462,33 @@
#define NR_BRL 11
+/* KT_CSI keys: value is the CSI parameter number for ESC [ ~ */
+#define K_CSI_HOME K(KT_CSI, 1) /* ESC [ 1 ~ */
+#define K_CSI_INSERT K(KT_CSI, 2) /* ESC [ 2 ~ */
+#define K_CSI_DELETE K(KT_CSI, 3) /* ESC [ 3 ~ */
+#define K_CSI_END K(KT_CSI, 4) /* ESC [ 4 ~ */
+#define K_CSI_PGUP K(KT_CSI, 5) /* ESC [ 5 ~ */
+#define K_CSI_PGDN K(KT_CSI, 6) /* ESC [ 6 ~ */
+#define K_CSI_F1 K(KT_CSI, 11) /* ESC [ 11 ~ */
+#define K_CSI_F2 K(KT_CSI, 12) /* ESC [ 12 ~ */
+#define K_CSI_F3 K(KT_CSI, 13) /* ESC [ 13 ~ */
+#define K_CSI_F4 K(KT_CSI, 14) /* ESC [ 14 ~ */
+#define K_CSI_F5 K(KT_CSI, 15) /* ESC [ 15 ~ */
+#define K_CSI_F6 K(KT_CSI, 17) /* ESC [ 17 ~ */
+#define K_CSI_F7 K(KT_CSI, 18) /* ESC [ 18 ~ */
+#define K_CSI_F8 K(KT_CSI, 19) /* ESC [ 19 ~ */
+#define K_CSI_F9 K(KT_CSI, 20) /* ESC [ 20 ~ */
+#define K_CSI_F10 K(KT_CSI, 21) /* ESC [ 21 ~ */
+#define K_CSI_F11 K(KT_CSI, 23) /* ESC [ 23 ~ */
+#define K_CSI_F12 K(KT_CSI, 24) /* ESC [ 24 ~ */
+#define K_CSI_F13 K(KT_CSI, 25) /* ESC [ 25 ~ */
+#define K_CSI_F14 K(KT_CSI, 26) /* ESC [ 26 ~ */
+#define K_CSI_F15 K(KT_CSI, 28) /* ESC [ 28 ~ */
+#define K_CSI_F16 K(KT_CSI, 29) /* ESC [ 29 ~ */
+#define K_CSI_F17 K(KT_CSI, 31) /* ESC [ 31 ~ */
+#define K_CSI_F18 K(KT_CSI, 32) /* ESC [ 32 ~ */
+#define K_CSI_F19 K(KT_CSI, 33) /* ESC [ 33 ~ */
+#define K_CSI_F20 K(KT_CSI, 34) /* ESC [ 34 ~ */
+
#define MAX_DIACR 256
#endif /* __LINUX_KEYBOARD_H */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/kvm.h b/lib/libc/include/any-linux-any/linux/kvm.h
index b7e6426d60eddfa931413cf1128892352650ef55..420a3fe8b1c774bc9d2c67f29b0b3f12fab31c2c 100644
--- a/lib/libc/include/any-linux-any/linux/kvm.h
+++ b/lib/libc/include/any-linux-any/linux/kvm.h
@@ -693,6 +693,11 @@ struct kvm_enable_cap {
#define KVM_VM_TYPE_ARM_IPA_SIZE_MASK 0xffULL
#define KVM_VM_TYPE_ARM_IPA_SIZE(x) \
((x) & KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
+
+#define KVM_VM_TYPE_ARM_PROTECTED (1UL << 31)
+#define KVM_VM_TYPE_ARM_MASK (KVM_VM_TYPE_ARM_IPA_SIZE_MASK | \
+ KVM_VM_TYPE_ARM_PROTECTED)
+
/*
* ioctls for /dev/kvm fds:
*/
@@ -979,6 +984,7 @@ struct kvm_enable_cap {
#define KVM_CAP_ARM_SEA_TO_USER 245
#define KVM_CAP_S390_USER_OPEREXEC 246
#define KVM_CAP_S390_KEYOP 247
+#define KVM_CAP_S390_VSIE_ESAMODE 248
struct kvm_irq_routing_irqchip {
__u32 irqchip;
@@ -1214,6 +1220,10 @@ enum kvm_device_type {
#define KVM_DEV_TYPE_LOONGARCH_EIOINTC KVM_DEV_TYPE_LOONGARCH_EIOINTC
KVM_DEV_TYPE_LOONGARCH_PCHPIC,
#define KVM_DEV_TYPE_LOONGARCH_PCHPIC KVM_DEV_TYPE_LOONGARCH_PCHPIC
+ KVM_DEV_TYPE_LOONGARCH_DMSINTC,
+#define KVM_DEV_TYPE_LOONGARCH_DMSINTC KVM_DEV_TYPE_LOONGARCH_DMSINTC
+ KVM_DEV_TYPE_ARM_VGIC_V5,
+#define KVM_DEV_TYPE_ARM_VGIC_V5 KVM_DEV_TYPE_ARM_VGIC_V5
KVM_DEV_TYPE_MAX,
diff --git a/lib/libc/include/any-linux-any/linux/landlock.h b/lib/libc/include/any-linux-any/linux/landlock.h
index e9c183f4c6882061abde48ca40d1ade1dfca10c1..42ee46819bb6b003527219b52dd54f6c13bf99d1 100644
--- a/lib/libc/include/any-linux-any/linux/landlock.h
+++ b/lib/libc/include/any-linux-any/linux/landlock.h
@@ -116,7 +116,9 @@ struct landlock_ruleset_attr {
* ``LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF``, this flag only affects
* future nested domains, not the one being created. It can also be used
* with a @ruleset_fd value of -1 to mute subdomain logs without creating a
- * domain.
+ * domain. When combined with %LANDLOCK_RESTRICT_SELF_TSYNC and a
+ * @ruleset_fd value of -1, this configuration is propagated to all threads
+ * of the current process.
*
* The following flag supports policy enforcement in multithreaded processes:
*
@@ -248,6 +250,26 @@ struct landlock_net_port_attr {
*
* This access right is available since the fifth version of the Landlock
* ABI.
+ * - %LANDLOCK_ACCESS_FS_RESOLVE_UNIX: Look up pathname UNIX domain sockets
+ * (:manpage:`unix(7)`). On UNIX domain sockets, this restricts both calls to
+ * :manpage:`connect(2)` as well as calls to :manpage:`sendmsg(2)` with an
+ * explicit recipient address.
+ *
+ * This access right only applies to connections to UNIX server sockets which
+ * were created outside of the newly created Landlock domain (e.g. from within
+ * a parent domain or from an unrestricted process). Newly created UNIX
+ * servers within the same Landlock domain continue to be accessible. In this
+ * regard, %LANDLOCK_ACCESS_FS_RESOLVE_UNIX has the same semantics as the
+ * ``LANDLOCK_SCOPE_*`` flags.
+ *
+ * If a resolve attempt is denied, the operation returns an ``EACCES`` error,
+ * in line with other filesystem access rights (but different to denials for
+ * abstract UNIX domain sockets).
+ *
+ * This access right is available since the ninth version of the Landlock ABI.
+ *
+ * The rationale for this design is described in
+ * :ref:`Documentation/security/landlock.rst `.
*
* Whether an opened file can be truncated with :manpage:`ftruncate(2)` or used
* with `ioctl(2)` is determined during :manpage:`open(2)`, in the same way as
@@ -333,6 +355,7 @@ struct landlock_net_port_attr {
#define LANDLOCK_ACCESS_FS_REFER (1ULL << 13)
#define LANDLOCK_ACCESS_FS_TRUNCATE (1ULL << 14)
#define LANDLOCK_ACCESS_FS_IOCTL_DEV (1ULL << 15)
+#define LANDLOCK_ACCESS_FS_RESOLVE_UNIX (1ULL << 16)
/* clang-format on */
/**
diff --git a/lib/libc/include/any-linux-any/linux/map_benchmark.h b/lib/libc/include/any-linux-any/linux/map_benchmark.h
index 1689166dc56bf2b26d7d98e108fd2bf53b7eccb3..42e033de3c065125653bd98e252f3c8c07e694a1 100644
--- a/lib/libc/include/any-linux-any/linux/map_benchmark.h
+++ b/lib/libc/include/any-linux-any/linux/map_benchmark.h
@@ -17,6 +17,12 @@
#define DMA_MAP_TO_DEVICE 1
#define DMA_MAP_FROM_DEVICE 2
+enum {
+ DMA_MAP_BENCH_SINGLE_MODE,
+ DMA_MAP_BENCH_SG_MODE,
+ DMA_MAP_BENCH_MODE_MAX
+};
+
struct map_benchmark {
__u64 avg_map_100ns; /* average map latency in 100ns */
__u64 map_stddev; /* standard deviation of map latency */
@@ -28,8 +34,11 @@ struct map_benchmark {
__u32 dma_bits; /* DMA addressing capability */
__u32 dma_dir; /* DMA data direction */
__u32 dma_trans_ns; /* time for DMA transmission in ns */
- __u32 granule; /* how many PAGE_SIZE will do map/unmap once a time */
- __u8 expansion[76]; /* For future use */
+ __u32 granule; /* - SINGLE_MODE: number of pages mapped/unmapped per operation
+ * - SG_MODE: number of scatterlist entries (each maps one page)
+ */
+ __u8 map_mode; /* the mode of dma map */
+ __u8 expansion[75]; /* For future use */
};
#endif /* _DMA_BENCHMARK_H */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/mii.h b/lib/libc/include/any-linux-any/linux/mii.h
index e8e001d058cf49d55e524483a02f2e5780a4460a..a43e06f027a30ea67f1daa29e3b4f01c7c3b7467 100644
--- a/lib/libc/include/any-linux-any/linux/mii.h
+++ b/lib/libc/include/any-linux-any/linux/mii.h
@@ -82,7 +82,8 @@
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */
#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */
-#define ADVERTISE_RESV 0x1000 /* Unused... */
+#define ADVERTISE_XNP 0x1000 /* Extended Next Page */
+#define ADVERTISE_RESV ADVERTISE_XNP /* Used to be reserved */
#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
diff --git a/lib/libc/include/any-linux-any/linux/module_signature.h b/lib/libc/include/any-linux-any/linux/module_signature.h
new file mode 100644
index 0000000000000000000000000000000000000000..f781c9e651e79918ad411e2929720391c8d4f11a
--- /dev/null
+++ b/lib/libc/include/any-linux-any/linux/module_signature.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * Module signature handling.
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+
+#ifndef _LINUX_MODULE_SIGNATURE_H
+#define _LINUX_MODULE_SIGNATURE_H
+
+#include
+
+/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */
+#define MODULE_SIGNATURE_MARKER "~Module signature appended~\n"
+
+enum module_signature_type {
+ MODULE_SIGNATURE_TYPE_PKCS7 = 2, /* Signature in PKCS#7 message */
+};
+
+/*
+ * Module signature information block.
+ *
+ * The constituents of the signature section are, in order:
+ *
+ * - Signer's name
+ * - Key identifier
+ * - Signature data
+ * - Information block
+ */
+struct module_signature {
+ __u8 algo; /* Public-key crypto algorithm [0] */
+ __u8 hash; /* Digest algorithm [0] */
+ __u8 id_type; /* Key identifier type [enum module_signature_type] */
+ __u8 signer_len; /* Length of signer's name [0] */
+ __u8 key_id_len; /* Length of key identifier [0] */
+ __u8 __pad[3];
+ __be32 sig_len; /* Length of signature data */
+};
+
+#endif /* _LINUX_MODULE_SIGNATURE_H */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/mount.h b/lib/libc/include/any-linux-any/linux/mount.h
index 85793fab9df1e8941f9ecf224ae39adc1e216b85..f4648d2538f3b3e2378ffbfcfb9bab321c51a54d 100644
--- a/lib/libc/include/any-linux-any/linux/mount.h
+++ b/lib/libc/include/any-linux-any/linux/mount.h
@@ -110,6 +110,7 @@ enum fsconfig_command {
* fsmount() flags.
*/
#define FSMOUNT_CLOEXEC 0x00000001
+#define FSMOUNT_NAMESPACE 0x00000002 /* Create the mount in a new mount namespace */
/*
* Mount attributes.
diff --git a/lib/libc/include/any-linux-any/linux/mshv.h b/lib/libc/include/any-linux-any/linux/mshv.h
index f01c0c84b31a0a038edcffb148f8d93ba84d9cdc..af91e8bda9ddd465cfab659b05642c1889510878 100644
--- a/lib/libc/include/any-linux-any/linux/mshv.h
+++ b/lib/libc/include/any-linux-any/linux/mshv.h
@@ -357,7 +357,7 @@ struct mshv_vtl_sint_post_msg {
struct mshv_vtl_ram_disposition {
__u64 start_pfn;
- __u64 last_pfn;
+ __u64 last_pfn; /* last_pfn is excluded from the range [start_pfn, last_pfn) */
};
struct mshv_vtl_set_poll_file {
diff --git a/lib/libc/include/any-linux-any/linux/netdev.h b/lib/libc/include/any-linux-any/linux/netdev.h
index d48296f17fb3882dacc8a8eaa16f8d29b3efa8c3..bad43a494eacc89a407c29c89b3cf81de88037ed 100644
--- a/lib/libc/include/any-linux-any/linux/netdev.h
+++ b/lib/libc/include/any-linux-any/linux/netdev.h
@@ -160,6 +160,7 @@ enum {
NETDEV_A_QUEUE_DMABUF,
NETDEV_A_QUEUE_IO_URING,
NETDEV_A_QUEUE_XSK,
+ NETDEV_A_QUEUE_LEASE,
__NETDEV_A_QUEUE_MAX,
NETDEV_A_QUEUE_MAX = (__NETDEV_A_QUEUE_MAX - 1)
@@ -202,6 +203,15 @@ enum {
NETDEV_A_QSTATS_MAX = (__NETDEV_A_QSTATS_MAX - 1)
};
+enum {
+ NETDEV_A_LEASE_IFINDEX = 1,
+ NETDEV_A_LEASE_QUEUE,
+ NETDEV_A_LEASE_NETNS_ID,
+
+ __NETDEV_A_LEASE_MAX,
+ NETDEV_A_LEASE_MAX = (__NETDEV_A_LEASE_MAX - 1)
+};
+
enum {
NETDEV_A_DMABUF_IFINDEX = 1,
NETDEV_A_DMABUF_QUEUES,
@@ -228,6 +238,7 @@ enum {
NETDEV_CMD_BIND_RX,
NETDEV_CMD_NAPI_SET,
NETDEV_CMD_BIND_TX,
+ NETDEV_CMD_QUEUE_CREATE,
__NETDEV_CMD_MAX,
NETDEV_CMD_MAX = (__NETDEV_CMD_MAX - 1)
diff --git a/lib/libc/include/any-linux-any/linux/netfilter/nf_tables.h b/lib/libc/include/any-linux-any/linux/netfilter/nf_tables.h
index 4f481f87ecaf7ee34363e0d4d50de2ad2194718f..adbd4f65077b5da7024848cd68ce9db6698818b0 100644
--- a/lib/libc/include/any-linux-any/linux/netfilter/nf_tables.h
+++ b/lib/libc/include/any-linux-any/linux/netfilter/nf_tables.h
@@ -46,6 +46,7 @@ enum nft_registers {
};
#define NFT_REG_MAX (__NFT_REG_MAX - 1)
+
#define NFT_REG_SIZE 16
#define NFT_REG32_SIZE 4
#define NFT_REG32_COUNT (NFT_REG32_15 - NFT_REG32_00 + 1)
@@ -884,7 +885,7 @@ enum nft_exthdr_flags {
* @NFT_EXTHDR_OP_TCPOPT: match against tcp options
* @NFT_EXTHDR_OP_IPV4: match against ipv4 options
* @NFT_EXTHDR_OP_SCTP: match against sctp chunks
- * @NFT_EXTHDR_OP_DCCP: match against dccp otions
+ * @NFT_EXTHDR_OP_DCCP: match against dccp options
*/
enum nft_exthdr_op {
NFT_EXTHDR_OP_IPV6,
diff --git a/lib/libc/include/any-linux-any/linux/netrom.h b/lib/libc/include/any-linux-any/linux/netrom.h
deleted file mode 100644
index c80c1466418215e31af99614da7d2d7d4c6fce25..0000000000000000000000000000000000000000
--- a/lib/libc/include/any-linux-any/linux/netrom.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * These are the public elements of the Linux kernel NET/ROM implementation.
- * For kernel AX.25 see the file ax25.h. This file requires ax25.h for the
- * definition of the ax25_address structure.
- */
-
-#ifndef NETROM_KERNEL_H
-#define NETROM_KERNEL_H
-
-#include
-
-#define NETROM_MTU 236
-
-#define NETROM_T1 1
-#define NETROM_T2 2
-#define NETROM_N2 3
-#define NETROM_T4 6
-#define NETROM_IDLE 7
-
-#define SIOCNRDECOBS (SIOCPROTOPRIVATE+2)
-
-struct nr_route_struct {
-#define NETROM_NEIGH 0
-#define NETROM_NODE 1
- int type;
- ax25_address callsign;
- char device[16];
- unsigned int quality;
- char mnemonic[7];
- ax25_address neighbour;
- unsigned int obs_count;
- unsigned int ndigis;
- ax25_address digipeaters[AX25_MAX_DIGIS];
-};
-
-#endif
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/nfc.h b/lib/libc/include/any-linux-any/linux/nfc.h
index 13adaefeb82d697b872b7c498eb72583ce5a975a..bb2f6749a6fb2263784602d23abb0a418f3d8e64 100644
--- a/lib/libc/include/any-linux-any/linux/nfc.h
+++ b/lib/libc/include/any-linux-any/linux/nfc.h
@@ -55,7 +55,7 @@
* (it sends %NFC_ATTR_DEVICE_INDEX)
* @NFC_EVENT_TM_ACTIVATED: event emitted when the adapter is activated in
* target mode.
- * @NFC_EVENT_DEVICE_DEACTIVATED: event emitted when the adapter is deactivated
+ * @NFC_EVENT_TM_DEACTIVATED: event emitted when the adapter is deactivated
* from target mode.
* @NFC_CMD_LLC_GET_PARAMS: request LTO, RW, and MIUX parameters for a device
* @NFC_CMD_LLC_SET_PARAMS: set one or more of LTO, RW, and MIUX parameters for
@@ -156,7 +156,7 @@ enum nfc_commands {
* @NFC_ATTR_SE_INDEX: Secure element index
* @NFC_ATTR_SE_TYPE: Secure element type (UICC or EMBEDDED)
* @NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS: Firmware download operation status
- * @NFC_ATTR_APDU: Secure element APDU
+ * @NFC_ATTR_SE_APDU: Secure element APDU
* @NFC_ATTR_TARGET_ISO15693_DSFID: ISO 15693 Data Storage Format Identifier
* @NFC_ATTR_TARGET_ISO15693_UID: ISO 15693 Unique Identifier
* @NFC_ATTR_SE_PARAMS: Parameters data from an evt_transaction
@@ -291,7 +291,7 @@ struct sockaddr_nfc_llcp {
#define NFC_HEADER_SIZE 1
-/**
+/*
* Pseudo-header info for raw socket packets
* First byte is the adapter index
* Second byte contains flags
diff --git a/lib/libc/include/any-linux-any/linux/nfsd/export.h b/lib/libc/include/any-linux-any/linux/nfsd/export.h
index babed2e348bbbbd5ffbdbd3e073d1874662d4f86..10b5d0c86b2d7993a0ff2ddcf4813cf9ed3770d3 100644
--- a/lib/libc/include/any-linux-any/linux/nfsd/export.h
+++ b/lib/libc/include/any-linux-any/linux/nfsd/export.h
@@ -34,7 +34,7 @@
#define NFSEXP_GATHERED_WRITES 0x0020
#define NFSEXP_NOREADDIRPLUS 0x0040
#define NFSEXP_SECURITY_LABEL 0x0080
-/* 0x100 currently unused */
+#define NFSEXP_SIGN_FH 0x0100
#define NFSEXP_NOHIDE 0x0200
#define NFSEXP_NOSUBTREECHECK 0x0400
#define NFSEXP_NOAUTHNLM 0x0800 /* Don't authenticate NLM requests - just trust */
@@ -55,7 +55,7 @@
#define NFSEXP_PNFS 0x20000
/* All flags that we claim to support. (Note we don't support NOACL.) */
-#define NFSEXP_ALLFLAGS 0x3FEFF
+#define NFSEXP_ALLFLAGS 0x3FFFF
/* The flags that may vary depending on security flavor: */
#define NFSEXP_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
diff --git a/lib/libc/include/any-linux-any/linux/nfsd_netlink.h b/lib/libc/include/any-linux-any/linux/nfsd_netlink.h
index f1a633bce26c7103c8fcb65f181cd7f9190c4fb1..bb104b4490ee434efc637dba2319feb4f6bd1281 100644
--- a/lib/libc/include/any-linux-any/linux/nfsd_netlink.h
+++ b/lib/libc/include/any-linux-any/linux/nfsd_netlink.h
@@ -36,6 +36,7 @@ enum {
NFSD_A_SERVER_LEASETIME,
NFSD_A_SERVER_SCOPE,
NFSD_A_SERVER_MIN_THREADS,
+ NFSD_A_SERVER_FH_KEY,
__NFSD_A_SERVER_MAX,
NFSD_A_SERVER_MAX = (__NFSD_A_SERVER_MAX - 1)
diff --git a/lib/libc/include/any-linux-any/linux/nl80211.h b/lib/libc/include/any-linux-any/linux/nl80211.h
index 53af5a957a78d76ad7d78de8e07983f1793863ed..903c2127dd42807a29eaa4e95c2e084c833fa33f 100644
--- a/lib/libc/include/any-linux-any/linux/nl80211.h
+++ b/lib/libc/include/any-linux-any/linux/nl80211.h
@@ -906,8 +906,9 @@
* @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP
* (or GO) interface (i.e. hostapd) to ask for unexpected frames to
* implement sending deauth to stations that send unexpected class 3
- * frames. Also used as the event sent by the kernel when such a frame
- * is received.
+ * frames. For NAN_DATA interfaces, this is used to report frames from
+ * unknown peers (A2 not assigned to any active NDP).
+ * Also used as the event sent by the kernel when such a frame is received.
* For the event, the %NL80211_ATTR_MAC attribute carries the TA and
* other attributes like the interface index are present.
* If used as the command it must have an interface index and you can
@@ -1361,6 +1362,59 @@
* user space that the NAN new cluster has been joined. The cluster ID is
* indicated by %NL80211_ATTR_MAC.
*
+ * @NL80211_CMD_INCUMBENT_SIGNAL_DETECT: Once any incumbent signal is detected
+ * on the operating channel in 6 GHz band, userspace is notified with the
+ * signal interference bitmap using
+ * %NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP. The current channel
+ * definition is also sent.
+ *
+ * @NL80211_CMD_NAN_SET_LOCAL_SCHED: Set the local NAN schedule. NAN must be
+ * operational (%NL80211_CMD_START_NAN was executed). Must contain
+ * %NL80211_ATTR_NAN_TIME_SLOTS and %NL80211_ATTR_NAN_AVAIL_BLOB, but
+ * %NL80211_ATTR_NAN_CHANNEL is optional (for example in case of a channel
+ * removal, that channel won't be provided).
+ * If %NL80211_ATTR_NAN_SCHED_DEFERRED is set, the command is a request
+ * from the device to perform an announced schedule update. See
+ * %NL80211_ATTR_NAN_SCHED_DEFERRED for more details.
+ * If not set, the schedule should be applied immediately.
+ * @NL80211_CMD_NAN_SCHED_UPDATE_DONE: Event sent to user space to notify that
+ * a deferred local NAN schedule update (requested with
+ * %NL80211_CMD_NAN_SET_LOCAL_SCHED and %NL80211_ATTR_NAN_SCHED_DEFERRED)
+ * has been completed. The presence of %NL80211_ATTR_NAN_SCHED_UPDATE_SUCCESS
+ * indicates that the update was successful.
+ * @NL80211_CMD_NAN_SET_PEER_SCHED: Set the peer NAN schedule. NAN
+ * must be operational (%NL80211_CMD_START_NAN was executed).
+ * Required attributes: %NL80211_ATTR_MAC (peer NMI address) and
+ * %NL80211_ATTR_NAN_COMMITTED_DW.
+ * Optionally, the full schedule can be provided by including all of:
+ * %NL80211_ATTR_NAN_SEQ_ID, %NL80211_ATTR_NAN_CHANNEL (one or more), and
+ * %NL80211_ATTR_NAN_PEER_MAPS (see &enum nl80211_nan_peer_map_attrs).
+ * If any of these three optional attributes is provided, all three must
+ * be provided.
+ * Each peer channel must be compatible with at least one local channel
+ * set by %NL80211_CMD_SET_LOCAL_NAN_SCHED. Different maps must not
+ * contain compatible channels.
+ * For single-radio devices (n_radio <= 1), different maps must not
+ * schedule the same time slot, as the device cannot operate on multiple
+ * channels simultaneously.
+ * When updating an existing peer schedule, the full new schedule must be
+ * provided - partial updates are not supported. The new schedule will
+ * completely replace the previous one.
+ * The peer schedule is automatically removed when the NMI station is
+ * removed.
+ * @NL80211_CMD_NAN_ULW_UPDATE: Notification from the driver to user space
+ * with the updated ULW blob of the device. User space can use this blob
+ * to attach to frames sent to peers. This notification contains
+ * %NL80211_ATTR_NAN_ULW with the ULW blob.
+ * @NL80211_CMD_NAN_CHANNEL_EVAC: Notification to indicate that a NAN
+ * channel has been evacuated due to resource conflicts with other
+ * interfaces. This can happen when another interface sharing the channel
+ * resource with NAN needs to move to a different channel (e.g., channel
+ * switch or link switch on a BSS interface).
+ * The notification contains %NL80211_ATTR_NAN_CHANNEL attribute
+ * identifying the evacuated channel.
+ * User space may reconfigure the local schedule in response to this
+ * notification.
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -1624,6 +1678,18 @@ enum nl80211_commands {
NL80211_CMD_NAN_NEXT_DW_NOTIFICATION,
NL80211_CMD_NAN_CLUSTER_JOINED,
+ NL80211_CMD_INCUMBENT_SIGNAL_DETECT,
+
+ NL80211_CMD_NAN_SET_LOCAL_SCHED,
+
+ NL80211_CMD_NAN_SCHED_UPDATE_DONE,
+
+ NL80211_CMD_NAN_SET_PEER_SCHED,
+
+ NL80211_CMD_NAN_ULW_UPDATE,
+
+ NL80211_CMD_NAN_CHANNEL_EVAC,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -2651,7 +2717,8 @@ enum nl80211_commands {
* a flow is assigned on each round of the DRR scheduler.
* @NL80211_ATTR_HE_CAPABILITY: HE Capability information element (from
* association request when used with NL80211_CMD_NEW_STATION). Can be set
- * only if %NL80211_STA_FLAG_WME is set.
+ * only if %NL80211_STA_FLAG_WME is set (except for NAN, which uses WME
+ * anyway).
*
* @NL80211_ATTR_FTM_RESPONDER: nested attribute which user-space can include
* in %NL80211_CMD_START_AP or %NL80211_CMD_SET_BEACON for fine timing
@@ -2983,6 +3050,95 @@ enum nl80211_commands {
* @NL80211_ATTR_DISABLE_UHR: Force UHR capable interfaces to disable
* this feature during association. This is a flag attribute.
* Currently only supported in mac80211 drivers.
+ * @NL80211_ATTR_NAN_CHANNEL: This is a nested attribute. There can be multiple
+ * attributes of this type, each one represents a channel definition and
+ * consists of top-level attributes like %NL80211_ATTR_WIPHY_FREQ.
+ * When used with %NL80211_CMD_NAN_SET_LOCAL_SCHED, it specifies
+ * the channel definitions on which the radio needs to operate during
+ * specific time slots. All of the channel definitions should be mutually
+ * incompatible. With this command, %NL80211_ATTR_NAN_CHANNEL_ENTRY and
+ * %NL80211_ATTR_NAN_RX_NSS are mandatory.
+ * When used with %NL80211_CMD_NAN_SET_PEER_SCHED, it configures the
+ * peer NAN channels. In that case, the channel definitions can be
+ * compatible to each other, or even identical just with different RX NSS.
+ * With this command, %NL80211_ATTR_NAN_CHANNEL_ENTRY and
+ * %NL80211_ATTR_NAN_RX_NSS are mandatory.
+ * The number of channels should fit the current configuration of channels
+ * and the possible interface combinations.
+ * If an existing NAN channel is changed but the chandef isn't, the
+ * channel entry must also remain unchanged.
+ * When used with %NL80211_CMD_NAN_CHANNEL_EVAC, this identifies the
+ * channels that were evacuated.
+ * @NL80211_ATTR_NAN_CHANNEL_ENTRY: a byte array of 6 bytes. contains the
+ * Channel Entry as defined in Wi-Fi Aware (TM) 4.0 specification Table
+ * 100 (Channel Entry format for the NAN Availability attribute).
+ * @NL80211_ATTR_NAN_RX_NSS: (u8) RX NSS used for a NAN channel. This is
+ * used with %NL80211_ATTR_NAN_CHANNEL when configuring NAN channels with
+ * %NL80211_CMD_NAN_SET_LOCAL_SCHED or %NL80211_CMD_NAN_SET_PEER_SCHED.
+ * @NL80211_ATTR_NAN_TIME_SLOTS: an array of u8 values and 32 cells. each value
+ * maps a time slot to the chandef on which the radio should operate on in
+ * that time. %NL80211_NAN_SCHED_NOT_AVAIL_SLOT indicates unscheduled.
+ * The chandef is represented using its index, where the index is the
+ * sequential number of the %NL80211_ATTR_NAN_CHANNEL attribute within all
+ * the attributes of this type.
+ * Each slots spans over 16TUs, hence the entire schedule spans over
+ * 512TUs. Other slot durations and periods are currently not supported.
+ * @NL80211_ATTR_NAN_AVAIL_BLOB: (Binary) The NAN Availability attribute blob,
+ * including the attribute header, as defined in Wi-Fi Aware (TM) 4.0
+ * specification Table 93 (NAN Availability attribute format). Required with
+ * %NL80211_CMD_NAN_SET_LOCAL_SCHED to provide the raw NAN Availability
+ * attribute. Used by the device to publish Schedule Update NAFs.
+ * @NL80211_ATTR_NAN_SCHED_DEFERRED: Flag attribute used with
+ * %NL80211_CMD_NAN_SET_LOCAL_SCHED. When present, the command is a
+ * request from the device to perform an announced schedule update. This
+ * means that it needs to send the updated NAN availability to the peers,
+ * and do the actual switch on the right time (i.e. at the end of the slot
+ * after the slot in which the updated NAN Availability was sent). Since
+ * the slots management is done in the device, the update to the peers
+ * needs to be sent by the device, so it knows the actual switch time.
+ * If the flag is not set, the schedule should be applied immediately.
+ * When this flag is set, the total number of NAN channels from both the
+ * old and new schedules must not exceed the allowed number of local NAN
+ * channels, because with deferred scheduling the old channels cannot be
+ * removed before adding the new ones to free up space.
+ * @NL80211_ATTR_NAN_SCHED_UPDATE_SUCCESS: flag attribute used with
+ * %NL80211_CMD_NAN_SCHED_UPDATE_DONE to indicate that the deferred
+ * schedule update completed successfully. If this flag is not present,
+ * the update failed.
+ * @NL80211_ATTR_NAN_NMI_MAC: The address of the NMI station to which this NDI
+ * station belongs. Used with %NL80211_CMD_NEW_STATION when adding an NDI
+ * station.
+ * @NL80211_ATTR_NAN_ULW: (Binary) The initial ULW(s) as published by the
+ * peer, as defined in the Wi-Fi Aware (TM) 4.0 specification Table 109
+ * (Unaligned Schedule attribute format). Used to configure the device
+ * with the initial ULW(s) of a peer, before the device starts tracking it.
+ * @NL80211_ATTR_NAN_COMMITTED_DW: (u16) The committed DW as published by the
+ * peer, as defined in the Wi-Fi Aware (TM) 4.0 specification Table 80
+ * (Committed DW Information field format).
+ * @NL80211_ATTR_NAN_SEQ_ID: (u8) The sequence ID of the peer schedule that
+ * %NL80211_CMD_NAN_SET_PEER_SCHED defines. The device follows the
+ * sequence ID in the frames to identify newer schedules. Once a schedule
+ * with a higher sequence ID is received, the device may stop communicating
+ * with that peer until a new peer schedule with a matching sequence ID is
+ * received.
+ * @NL80211_ATTR_NAN_MAX_CHAN_SWITCH_TIME: (u16) The maximum channel switch
+ * time, in microseconds.
+ * @NL80211_ATTR_NAN_PEER_MAPS: Nested array of peer schedule maps.
+ * Used with %NL80211_CMD_NAN_SET_PEER_SCHED. Contains up to 2 entries,
+ * each containing nested attributes from &enum nl80211_nan_peer_map_attrs.
+ *
+ * @NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP: u32 attribute specifying
+ * the signal interference bitmap detected on the operating bandwidth for
+ * %NL80211_CMD_INCUMBENT_SIGNAL_DETECT. Each bit represents a 20 MHz
+ * segment, lowest bit corresponds to the lowest 20 MHz segment, in the
+ * operating bandwidth where the interference is detected. Punctured
+ * sub-channels are included in the bitmap structure; however, since
+ * interference detection is not performed on these sub-channels, their
+ * corresponding bits are consistently set to zero.
+ *
+ * @NL80211_ATTR_UHR_OPERATION: Full UHR Operation element, as it appears in
+ * association response etc., since it's abridged in the beacon. Used
+ * for START_AP etc.
*
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
@@ -3557,6 +3713,26 @@ enum nl80211_attrs {
NL80211_ATTR_UHR_CAPABILITY,
NL80211_ATTR_DISABLE_UHR,
+ NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP,
+
+ NL80211_ATTR_UHR_OPERATION,
+
+ NL80211_ATTR_NAN_CHANNEL,
+ NL80211_ATTR_NAN_CHANNEL_ENTRY,
+ NL80211_ATTR_NAN_TIME_SLOTS,
+ NL80211_ATTR_NAN_RX_NSS,
+ NL80211_ATTR_NAN_AVAIL_BLOB,
+ NL80211_ATTR_NAN_SCHED_DEFERRED,
+ NL80211_ATTR_NAN_SCHED_UPDATE_SUCCESS,
+
+ NL80211_ATTR_NAN_NMI_MAC,
+
+ NL80211_ATTR_NAN_ULW,
+ NL80211_ATTR_NAN_COMMITTED_DW,
+ NL80211_ATTR_NAN_SEQ_ID,
+ NL80211_ATTR_NAN_MAX_CHAN_SWITCH_TIME,
+ NL80211_ATTR_NAN_PEER_MAPS,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -3650,6 +3826,9 @@ enum nl80211_attrs {
* @NL80211_IFTYPE_OCB: Outside Context of a BSS
* This mode corresponds to the MIB variable dot11OCBActivated=true
* @NL80211_IFTYPE_NAN: NAN device interface type (not a netdev)
+ * @NL80211_IFTYPE_NAN_DATA: NAN data interface type (netdev); NAN data
+ * interfaces can only be brought up (IFF_UP) when a NAN interface
+ * already exists and NAN has been started (using %NL80211_CMD_START_NAN).
* @NL80211_IFTYPE_MAX: highest interface type number currently defined
* @NUM_NL80211_IFTYPES: number of defined interface types
*
@@ -3671,6 +3850,7 @@ enum nl80211_iftype {
NL80211_IFTYPE_P2P_DEVICE,
NL80211_IFTYPE_OCB,
NL80211_IFTYPE_NAN,
+ NL80211_IFTYPE_NAN_DATA,
/* keep last */
NUM_NL80211_IFTYPES,
@@ -4359,6 +4539,46 @@ enum nl80211_band_attr {
#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA
+/**
+ * enum nl80211_nan_phy_cap_attr - NAN PHY capabilities attributes
+ * @__NL80211_NAN_PHY_CAP_ATTR_INVALID: attribute number 0 is reserved
+ * @NL80211_NAN_PHY_CAP_ATTR_HT_MCS_SET: 16-byte attribute containing HT MCS set
+ * @NL80211_NAN_PHY_CAP_ATTR_HT_CAPA: HT capabilities (u16)
+ * @NL80211_NAN_PHY_CAP_ATTR_HT_AMPDU_FACTOR: HT A-MPDU factor (u8)
+ * @NL80211_NAN_PHY_CAP_ATTR_HT_AMPDU_DENSITY: HT A-MPDU density (u8)
+ * @NL80211_NAN_PHY_CAP_ATTR_VHT_MCS_SET: 8-byte attribute containing VHT MCS set
+ * @NL80211_NAN_PHY_CAP_ATTR_VHT_CAPA: VHT capabilities (u32)
+ * @NL80211_NAN_PHY_CAP_ATTR_HE_MAC: HE MAC capabilities
+ * @NL80211_NAN_PHY_CAP_ATTR_HE_PHY: HE PHY capabilities
+ * @NL80211_NAN_PHY_CAP_ATTR_HE_MCS_SET: HE supported NSS/MCS combinations
+ * @NL80211_NAN_PHY_CAP_ATTR_HE_PPE: HE PPE thresholds
+ * @NL80211_NAN_PHY_CAP_ATTR_MAX: highest NAN PHY cap attribute number
+ * @__NL80211_NAN_PHY_CAP_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_nan_phy_cap_attr {
+ __NL80211_NAN_PHY_CAP_ATTR_INVALID,
+
+ /* HT capabilities */
+ NL80211_NAN_PHY_CAP_ATTR_HT_MCS_SET,
+ NL80211_NAN_PHY_CAP_ATTR_HT_CAPA,
+ NL80211_NAN_PHY_CAP_ATTR_HT_AMPDU_FACTOR,
+ NL80211_NAN_PHY_CAP_ATTR_HT_AMPDU_DENSITY,
+
+ /* VHT capabilities */
+ NL80211_NAN_PHY_CAP_ATTR_VHT_MCS_SET,
+ NL80211_NAN_PHY_CAP_ATTR_VHT_CAPA,
+
+ /* HE capabilities */
+ NL80211_NAN_PHY_CAP_ATTR_HE_MAC,
+ NL80211_NAN_PHY_CAP_ATTR_HE_PHY,
+ NL80211_NAN_PHY_CAP_ATTR_HE_MCS_SET,
+ NL80211_NAN_PHY_CAP_ATTR_HE_PPE,
+
+ /* keep last */
+ __NL80211_NAN_PHY_CAP_ATTR_AFTER_LAST,
+ NL80211_NAN_PHY_CAP_ATTR_MAX = __NL80211_NAN_PHY_CAP_ATTR_AFTER_LAST - 1
+};
+
/**
* enum nl80211_wmm_rule - regulatory wmm rule
*
@@ -4480,6 +4700,10 @@ enum nl80211_wmm_rule {
* as a non-primary subchannel. Only applicable to S1G channels.
* @NL80211_FREQUENCY_ATTR_NO_UHR: UHR operation is not allowed on this channel
* in current regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_CAC_START_TIME: Channel Availability Check (CAC)
+ * start time (CLOCK_BOOTTIME, nanoseconds). Only present when CAC is
+ * currently in progress on this channel.
+ * @NL80211_FREQUENCY_ATTR_PAD: attribute used for padding for 64-bit alignment
* @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
* currently defined
* @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
@@ -4530,6 +4754,8 @@ enum nl80211_frequency_attr {
NL80211_FREQUENCY_ATTR_NO_16MHZ,
NL80211_FREQUENCY_ATTR_S1G_NO_PRIMARY,
NL80211_FREQUENCY_ATTR_NO_UHR,
+ NL80211_FREQUENCY_ATTR_CAC_START_TIME,
+ NL80211_FREQUENCY_ATTR_PAD,
/* keep last */
__NL80211_FREQUENCY_ATTR_AFTER_LAST,
@@ -5466,6 +5692,8 @@ enum nl80211_bss_status {
* @NL80211_AUTHTYPE_FILS_SK_PFS: Fast Initial Link Setup shared key with PFS
* @NL80211_AUTHTYPE_FILS_PK: Fast Initial Link Setup public key
* @NL80211_AUTHTYPE_EPPKE: Enhanced Privacy Protection Key Exchange
+ * @NL80211_AUTHTYPE_IEEE8021X: IEEE 802.1X authentication utilizing
+ * Authentication frames
* @__NL80211_AUTHTYPE_NUM: internal
* @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
* @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
@@ -5482,6 +5710,7 @@ enum nl80211_auth_type {
NL80211_AUTHTYPE_FILS_SK_PFS,
NL80211_AUTHTYPE_FILS_PK,
NL80211_AUTHTYPE_EPPKE,
+ NL80211_AUTHTYPE_IEEE8021X,
/* keep last */
__NL80211_AUTHTYPE_NUM,
@@ -6795,6 +7024,11 @@ enum nl80211_feature_flags {
* frames in both non‑AP STA and AP mode as specified in
* "IEEE P802.11bi/D3.0, 12.16.6".
*
+ * @NL80211_EXT_FEATURE_IEEE8021X_AUTH: Driver supports IEEE 802.1X
+ * authentication utilizing Authentication frames with user space SME
+ * (NL80211_CMD_AUTHENTICATE) in non-AP STA mode, as specified in
+ * "IEEE P802.11bi/D4.0, 12.16.5".
+ *
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
*/
@@ -6873,6 +7107,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_BEACON_RATE_EHT,
NL80211_EXT_FEATURE_EPPKE,
NL80211_EXT_FEATURE_ASSOC_FRAME_ENCRYPTION,
+ NL80211_EXT_FEATURE_IEEE8021X_AUTH,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
@@ -8517,6 +8752,8 @@ enum nl80211_s1g_short_beacon_attrs {
* @NL80211_NAN_CAPA_CAPABILITIES: u8 attribute containing the
* capabilities of the device as defined in Wi-Fi Aware (TM)
* specification Table 79 (Capabilities field).
+ * @NL80211_NAN_CAPA_PHY: nested attribute containing band-agnostic
+ * capabilities for NAN data path. See &enum nl80211_nan_phy_cap_attr.
* @__NL80211_NAN_CAPABILITIES_LAST: Internal
* @NL80211_NAN_CAPABILITIES_MAX: Highest NAN capability attribute.
*/
@@ -8529,9 +8766,38 @@ enum nl80211_nan_capabilities {
NL80211_NAN_CAPA_NUM_ANTENNAS,
NL80211_NAN_CAPA_MAX_CHANNEL_SWITCH_TIME,
NL80211_NAN_CAPA_CAPABILITIES,
+ NL80211_NAN_CAPA_PHY,
/* keep last */
__NL80211_NAN_CAPABILITIES_LAST,
NL80211_NAN_CAPABILITIES_MAX = __NL80211_NAN_CAPABILITIES_LAST - 1,
};
+/**
+ * enum nl80211_nan_peer_map_attrs - NAN peer schedule map attributes
+ *
+ * Nested attributes used within %NL80211_ATTR_NAN_PEER_MAPS to define
+ * individual peer schedule maps.
+ *
+ * @__NL80211_NAN_PEER_MAP_ATTR_INVALID: Invalid
+ * @NL80211_NAN_PEER_MAP_ATTR_MAP_ID: (u8) The map ID for this schedule map.
+ * @NL80211_NAN_PEER_MAP_ATTR_TIME_SLOTS: An array of u8 values with 32 cells.
+ * Each value maps a time slot to a channel index within the schedule's
+ * channel list (%NL80211_ATTR_NAN_CHANNEL attributes).
+ * %NL80211_NAN_SCHED_NOT_AVAIL_SLOT indicates unscheduled.
+ * @__NL80211_NAN_PEER_MAP_ATTR_LAST: Internal
+ * @NL80211_NAN_PEER_MAP_ATTR_MAX: Highest peer map attribute
+ */
+enum nl80211_nan_peer_map_attrs {
+ __NL80211_NAN_PEER_MAP_ATTR_INVALID,
+
+ NL80211_NAN_PEER_MAP_ATTR_MAP_ID,
+ NL80211_NAN_PEER_MAP_ATTR_TIME_SLOTS,
+
+ /* keep last */
+ __NL80211_NAN_PEER_MAP_ATTR_LAST,
+ NL80211_NAN_PEER_MAP_ATTR_MAX = __NL80211_NAN_PEER_MAP_ATTR_LAST - 1,
+};
+
+#define NL80211_NAN_SCHED_NOT_AVAIL_SLOT 0xff
+
#endif /* __LINUX_NL80211_H */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/openvswitch.h b/lib/libc/include/any-linux-any/linux/openvswitch.h
index 730ff8bb46cec0b8163113b05bb3f59622417fa5..2754f46325a6bddf30bc1776c8ec621d3e47f0a9 100644
--- a/lib/libc/include/any-linux-any/linux/openvswitch.h
+++ b/lib/libc/include/any-linux-any/linux/openvswitch.h
@@ -70,12 +70,15 @@ enum ovs_datapath_cmd {
* set on the datapath port (for OVS_ACTION_ATTR_MISS). Only valid on
* %OVS_DP_CMD_NEW requests. A value of zero indicates that upcalls should
* not be sent.
+ * @OVS_DP_ATTR_MASKS_CACHE_SIZE: Number of the entries in the flow table
+ * masks cache.
* @OVS_DP_ATTR_PER_CPU_PIDS: Per-cpu array of PIDs for upcalls when
* OVS_DP_F_DISPATCH_UPCALL_PER_CPU feature is set.
* @OVS_DP_ATTR_STATS: Statistics about packets that have passed through the
* datapath. Always present in notifications.
* @OVS_DP_ATTR_MEGAFLOW_STATS: Statistics about mega flow masks usage for the
* datapath. Always present in notifications.
+ * @OVS_DP_ATTR_USER_FEATURES: OVS_DP_F_* flags.
* @OVS_DP_ATTR_IFINDEX: Interface index for a new datapath netdev. Only
* valid for %OVS_DP_CMD_NEW requests.
*
@@ -83,18 +86,23 @@ enum ovs_datapath_cmd {
* payload for %OVS_DP_* commands.
*/
enum ovs_datapath_attr {
+ /* private: */
OVS_DP_ATTR_UNSPEC,
+ /* public: */
OVS_DP_ATTR_NAME, /* name of dp_ifindex netdev */
OVS_DP_ATTR_UPCALL_PID, /* Netlink PID to receive upcalls */
OVS_DP_ATTR_STATS, /* struct ovs_dp_stats */
OVS_DP_ATTR_MEGAFLOW_STATS, /* struct ovs_dp_megaflow_stats */
OVS_DP_ATTR_USER_FEATURES, /* OVS_DP_F_* */
+ /* private: */
OVS_DP_ATTR_PAD,
+ /* public: */
OVS_DP_ATTR_MASKS_CACHE_SIZE,
OVS_DP_ATTR_PER_CPU_PIDS, /* Netlink PIDS to receive upcalls in
* per-cpu dispatch mode
*/
OVS_DP_ATTR_IFINDEX,
+ /* private: */
__OVS_DP_ATTR_MAX
};
@@ -181,6 +189,7 @@ enum ovs_packet_cmd {
* %OVS_USERSPACE_ATTR_EGRESS_TUN_PORT attribute, which is sent only if the
* output port is actually a tunnel port. Contains the output tunnel key
* extracted from the packet as nested %OVS_TUNNEL_KEY_ATTR_* attributes.
+ * @OVS_PACKET_ATTR_PROBE: Packet operation is a feature probe.
* @OVS_PACKET_ATTR_MRU: Present for an %OVS_PACKET_CMD_ACTION and
* @OVS_PACKET_ATTR_LEN: Packet size before truncation.
* %OVS_PACKET_ATTR_USERSPACE action specify the Maximum received fragment
@@ -196,21 +205,26 @@ enum ovs_packet_cmd {
* payload for %OVS_PACKET_* commands.
*/
enum ovs_packet_attr {
+ /* private: */
OVS_PACKET_ATTR_UNSPEC,
+ /* public: */
OVS_PACKET_ATTR_PACKET, /* Packet data. */
OVS_PACKET_ATTR_KEY, /* Nested OVS_KEY_ATTR_* attributes. */
OVS_PACKET_ATTR_ACTIONS, /* Nested OVS_ACTION_ATTR_* attributes. */
OVS_PACKET_ATTR_USERDATA, /* OVS_ACTION_ATTR_USERSPACE arg. */
OVS_PACKET_ATTR_EGRESS_TUN_KEY, /* Nested OVS_TUNNEL_KEY_ATTR_*
attributes. */
+ /* private: */
OVS_PACKET_ATTR_UNUSED1,
OVS_PACKET_ATTR_UNUSED2,
+ /* public: */
OVS_PACKET_ATTR_PROBE, /* Packet operation is a feature probe,
error logging should be suppressed. */
OVS_PACKET_ATTR_MRU, /* Maximum received IP fragment size. */
OVS_PACKET_ATTR_LEN, /* Packet size before truncation. */
OVS_PACKET_ATTR_HASH, /* Packet hash. */
OVS_PACKET_ATTR_UPCALL_PID, /* u32 Netlink PID. */
+ /* private: */
__OVS_PACKET_ATTR_MAX
};
@@ -257,6 +271,11 @@ enum ovs_vport_type {
* upcalls should not be sent.
* @OVS_VPORT_ATTR_STATS: A &struct ovs_vport_stats giving statistics for
* packets sent or received through the vport.
+ * @OVS_VPORT_ATTR_IFINDEX: Provides the ifindex of a vport, or sets the desired
+ * ifindex while creating a new vport with type %OVS_VPORT_TYPE_INTERNAL.
+ * @OVS_VPORT_ATTR_NETNSID: Provides the netns id of the vport if it's not local.
+ * @OVS_VPORT_ATTR_UPCALL_STATS: Provides upcall statistics for a vport.
+ * Contains nested %OVS_VPORT_UPCALL_ATTR_* attributes.
*
* These attributes follow the &struct ovs_header within the Generic Netlink
* payload for %OVS_VPORT_* commands.
@@ -272,7 +291,9 @@ enum ovs_vport_type {
* ovs_header plus %OVS_VPORT_ATTR_PORT_NO determine the vport.
*/
enum ovs_vport_attr {
+ /* private: */
OVS_VPORT_ATTR_UNSPEC,
+ /* public: */
OVS_VPORT_ATTR_PORT_NO, /* u32 port number within datapath */
OVS_VPORT_ATTR_TYPE, /* u32 OVS_VPORT_TYPE_* constant. */
OVS_VPORT_ATTR_NAME, /* string name, up to IFNAMSIZ bytes long */
@@ -280,23 +301,27 @@ enum ovs_vport_attr {
OVS_VPORT_ATTR_UPCALL_PID, /* array of u32 Netlink socket PIDs for */
/* receiving upcalls */
OVS_VPORT_ATTR_STATS, /* struct ovs_vport_stats */
+ /* private: */
OVS_VPORT_ATTR_PAD,
+ /* public: */
OVS_VPORT_ATTR_IFINDEX,
OVS_VPORT_ATTR_NETNSID,
OVS_VPORT_ATTR_UPCALL_STATS,
+ /* private: */
__OVS_VPORT_ATTR_MAX
};
#define OVS_VPORT_ATTR_MAX (__OVS_VPORT_ATTR_MAX - 1)
/**
- * enum ovs_vport_upcall_attr - attributes for %OVS_VPORT_UPCALL* commands
- * @OVS_VPORT_UPCALL_SUCCESS: 64-bit upcall success packets.
- * @OVS_VPORT_UPCALL_FAIL: 64-bit upcall fail packets.
+ * enum ovs_vport_upcall_attr - attributes for %OVS_VPORT_ATTR_UPCALL_STATS
+ * @OVS_VPORT_UPCALL_ATTR_SUCCESS: 64-bit upcall success packets.
+ * @OVS_VPORT_UPCALL_ATTR_FAIL: 64-bit upcall fail packets.
*/
enum ovs_vport_upcall_attr {
OVS_VPORT_UPCALL_ATTR_SUCCESS,
OVS_VPORT_UPCALL_ATTR_FAIL,
+ /* private: */
__OVS_VPORT_UPCALL_ATTR_MAX
};
@@ -431,6 +456,7 @@ enum ovs_frag_type {
OVS_FRAG_TYPE_NONE,
OVS_FRAG_TYPE_FIRST,
OVS_FRAG_TYPE_LATER,
+ /* private: */
__OVS_FRAG_TYPE_MAX
};
@@ -604,6 +630,8 @@ struct ovs_nsh_key_md1 {
* a wildcarded match. Omitting attribute is treated as wildcarding all
* corresponding fields. Optional for all requests. If not present,
* all flow key bits are exact match bits.
+ * @OVS_FLOW_ATTR_PROBE: Flow operation is a feature probe, error logging
+ * should be suppressed.
* @OVS_FLOW_ATTR_UFID: A value between 1-16 octets specifying a unique
* identifier for the flow. Causes the flow to be indexed by this value rather
* than the value of the %OVS_FLOW_ATTR_KEY attribute. Optional for all
@@ -617,7 +645,9 @@ struct ovs_nsh_key_md1 {
* payload for %OVS_FLOW_* commands.
*/
enum ovs_flow_attr {
+ /* private: */
OVS_FLOW_ATTR_UNSPEC,
+ /* public: */
OVS_FLOW_ATTR_KEY, /* Sequence of OVS_KEY_ATTR_* attributes. */
OVS_FLOW_ATTR_ACTIONS, /* Nested OVS_ACTION_ATTR_* attributes. */
OVS_FLOW_ATTR_STATS, /* struct ovs_flow_stats. */
@@ -629,13 +659,14 @@ enum ovs_flow_attr {
* logging should be suppressed. */
OVS_FLOW_ATTR_UFID, /* Variable length unique flow identifier. */
OVS_FLOW_ATTR_UFID_FLAGS,/* u32 of OVS_UFID_F_*. */
+ /* private: */
OVS_FLOW_ATTR_PAD,
__OVS_FLOW_ATTR_MAX
};
#define OVS_FLOW_ATTR_MAX (__OVS_FLOW_ATTR_MAX - 1)
-/**
+/*
* Omit attributes for notifications.
*
* If a datapath request contains an %OVS_UFID_F_OMIT_* flag, then the datapath
@@ -653,17 +684,23 @@ enum ovs_flow_attr {
* fractions of packets.
* @OVS_SAMPLE_ATTR_ACTIONS: Set of actions to execute in sampling event.
* Actions are passed as nested attributes.
+ * @OVS_SAMPLE_ATTR_ARG: For in-kernel use, passing &struct sample_arg
+ * derived from other attributes.
*
* Executes the specified actions with the given probability on a per-packet
* basis. Nested actions will be able to access the probability value of the
* parent @OVS_ACTION_ATTR_SAMPLE.
*/
enum ovs_sample_attr {
+ /* private: */
OVS_SAMPLE_ATTR_UNSPEC,
+ /* public: */
OVS_SAMPLE_ATTR_PROBABILITY, /* u32 number */
OVS_SAMPLE_ATTR_ACTIONS, /* Nested OVS_ACTION_ATTR_* attributes. */
+ /* private: */
__OVS_SAMPLE_ATTR_MAX,
+ /* public: */
};
#define OVS_SAMPLE_ATTR_MAX (__OVS_SAMPLE_ATTR_MAX - 1)
@@ -680,12 +717,15 @@ enum ovs_sample_attr {
* @OVS_USERSPACE_ATTR_ACTIONS: If present, send actions with upcall.
*/
enum ovs_userspace_attr {
+ /* private: */
OVS_USERSPACE_ATTR_UNSPEC,
+ /* public: */
OVS_USERSPACE_ATTR_PID, /* u32 Netlink PID to receive upcalls. */
OVS_USERSPACE_ATTR_USERDATA, /* Optional user-specified cookie. */
OVS_USERSPACE_ATTR_EGRESS_TUN_PORT, /* Optional, u32 output port
* to get tunnel info. */
OVS_USERSPACE_ATTR_ACTIONS, /* Optional flag to get actions. */
+ /* private: */
__OVS_USERSPACE_ATTR_MAX
};
@@ -806,7 +846,9 @@ struct ovs_action_hash {
* @OVS_CT_ATTR_TIMEOUT: Variable length string defining conntrack timeout.
*/
enum ovs_ct_attr {
+ /* private: */
OVS_CT_ATTR_UNSPEC,
+ /* public: */
OVS_CT_ATTR_COMMIT, /* No argument, commits connection. */
OVS_CT_ATTR_ZONE, /* u16 zone id. */
OVS_CT_ATTR_MARK, /* mark to associate with this connection. */
@@ -818,6 +860,7 @@ enum ovs_ct_attr {
OVS_CT_ATTR_EVENTMASK, /* u32 mask of IPCT_* events. */
OVS_CT_ATTR_TIMEOUT, /* Associate timeout with this connection for
* fine-grain timeout tuning. */
+ /* private: */
__OVS_CT_ATTR_MAX
};
@@ -846,7 +889,9 @@ enum ovs_ct_attr {
* @OVS_NAT_ATTR_PROTO_RANDOM: Flag for fully randomized L4 port mapping
*/
enum ovs_nat_attr {
+ /* private: */
OVS_NAT_ATTR_UNSPEC,
+ /* public: */
OVS_NAT_ATTR_SRC,
OVS_NAT_ATTR_DST,
OVS_NAT_ATTR_IP_MIN,
@@ -856,38 +901,44 @@ enum ovs_nat_attr {
OVS_NAT_ATTR_PERSISTENT,
OVS_NAT_ATTR_PROTO_HASH,
OVS_NAT_ATTR_PROTO_RANDOM,
+ /* private: */
__OVS_NAT_ATTR_MAX,
};
#define OVS_NAT_ATTR_MAX (__OVS_NAT_ATTR_MAX - 1)
-/*
+/**
* struct ovs_action_push_eth - %OVS_ACTION_ATTR_PUSH_ETH action argument.
* @addresses: Source and destination MAC addresses.
- * @eth_type: Ethernet type
*/
struct ovs_action_push_eth {
struct ovs_key_ethernet addresses;
};
-/*
+/**
* enum ovs_check_pkt_len_attr - Attributes for %OVS_ACTION_ATTR_CHECK_PKT_LEN.
*
* @OVS_CHECK_PKT_LEN_ATTR_PKT_LEN: u16 Packet length to check for.
* @OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER: Nested OVS_ACTION_ATTR_*
* actions to apply if the packer length is greater than the specified
* length in the attr - OVS_CHECK_PKT_LEN_ATTR_PKT_LEN.
- * @OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL - Nested OVS_ACTION_ATTR_*
+ * @OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL: Nested OVS_ACTION_ATTR_*
* actions to apply if the packer length is lesser or equal to the specified
* length in the attr - OVS_CHECK_PKT_LEN_ATTR_PKT_LEN.
+ * @OVS_CHECK_PKT_LEN_ATTR_ARG: For in-kernel use, passing &struct
+ * check_pkt_len_arg derived from other attributes.
*/
enum ovs_check_pkt_len_attr {
+ /* private: */
OVS_CHECK_PKT_LEN_ATTR_UNSPEC,
+ /* public: */
OVS_CHECK_PKT_LEN_ATTR_PKT_LEN,
OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER,
OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL,
+ /* private: */
__OVS_CHECK_PKT_LEN_ATTR_MAX,
+ /* public: */
};
#define OVS_CHECK_PKT_LEN_ATTR_MAX (__OVS_CHECK_PKT_LEN_ATTR_MAX - 1)
@@ -940,6 +991,9 @@ enum ovs_psample_attr {
* from the packet.
* @OVS_ACTION_ATTR_SAMPLE: Probabilitically executes actions, as specified in
* the nested %OVS_SAMPLE_ATTR_* attributes.
+ * @OVS_ACTION_ATTR_RECIRC: Recirculate the clone of the packet through the
+ * datapath with the new id (u32 recirc_id).
+ * @OVS_ACTION_ATTR_HASH: Compute the packet hash, using &struct ovs_action_hash.
* @OVS_ACTION_ATTR_PUSH_MPLS: Push a new MPLS label stack entry onto the
* top of the packets MPLS label stack. Set the ethertype of the
* encapsulating frame to either %ETH_P_MPLS_UC or %ETH_P_MPLS_MC to
@@ -969,6 +1023,8 @@ enum ovs_psample_attr {
* start of the packet or at the start of the l3 header depending on the value
* of l3 tunnel flag in the tun_flags field of OVS_ACTION_ATTR_ADD_MPLS
* argument.
+ * @OVS_ACTION_ATTR_DEC_TTL: Decrement TTL or hop limit of the packet. Execute
+ * nested %OVS_DEC_TTL_ATTR_* actions if the value is less or equal to 1.
* @OVS_ACTION_ATTR_DROP: Explicit drop action.
* @OVS_ACTION_ATTR_PSAMPLE: Send a sample of the packet to external observers
* via psample.
@@ -982,7 +1038,9 @@ enum ovs_psample_attr {
*/
enum ovs_action_attr {
+ /* private: */
OVS_ACTION_ATTR_UNSPEC,
+ /* public: */
OVS_ACTION_ATTR_OUTPUT, /* u32 port number. */
OVS_ACTION_ATTR_USERSPACE, /* Nested OVS_USERSPACE_ATTR_*. */
OVS_ACTION_ATTR_SET, /* One nested OVS_KEY_ATTR_*. */
@@ -1012,9 +1070,11 @@ enum ovs_action_attr {
OVS_ACTION_ATTR_DROP, /* u32 error code. */
OVS_ACTION_ATTR_PSAMPLE, /* Nested OVS_PSAMPLE_ATTR_*. */
+ /* private: */
__OVS_ACTION_ATTR_MAX, /* Nothing past this will be accepted
* from userspace. */
+ /* public: */
};
#define OVS_ACTION_ATTR_MAX (__OVS_ACTION_ATTR_MAX - 1)
diff --git a/lib/libc/include/any-linux-any/linux/ovpn.h b/lib/libc/include/any-linux-any/linux/ovpn.h
index 5c3959fcb6d7db810868d5c892a750f7536c151d..89c97f903ca84bd3d295d56ae1a7dbbbaaa11692 100644
--- a/lib/libc/include/any-linux-any/linux/ovpn.h
+++ b/lib/libc/include/any-linux-any/linux/ovpn.h
@@ -55,6 +55,7 @@ enum {
OVPN_A_PEER_LINK_TX_BYTES,
OVPN_A_PEER_LINK_RX_PACKETS,
OVPN_A_PEER_LINK_TX_PACKETS,
+ OVPN_A_PEER_TX_ID,
__OVPN_A_PEER_MAX,
OVPN_A_PEER_MAX = (__OVPN_A_PEER_MAX - 1)
@@ -100,6 +101,7 @@ enum {
OVPN_CMD_KEY_SWAP,
OVPN_CMD_KEY_SWAP_NTF,
OVPN_CMD_KEY_DEL,
+ OVPN_CMD_PEER_FLOAT_NTF,
__OVPN_CMD_MAX,
OVPN_CMD_MAX = (__OVPN_CMD_MAX - 1)
diff --git a/lib/libc/include/any-linux-any/linux/pidfd.h b/lib/libc/include/any-linux-any/linux/pidfd.h
index b6b447e819543c8829d8dfc37aa6b63674dc4703..7bf8a8cf339b87a34c1a219a06258fe2b60c5dee 100644
--- a/lib/libc/include/any-linux-any/linux/pidfd.h
+++ b/lib/libc/include/any-linux-any/linux/pidfd.h
@@ -24,10 +24,12 @@
#define PIDFD_INFO_COREDUMP (1UL << 4) /* Only returned if requested. */
#define PIDFD_INFO_SUPPORTED_MASK (1UL << 5) /* Want/got supported mask flags */
#define PIDFD_INFO_COREDUMP_SIGNAL (1UL << 6) /* Always returned if PIDFD_INFO_COREDUMP is requested. */
+#define PIDFD_INFO_COREDUMP_CODE (1UL << 7) /* Always returned if PIDFD_INFO_COREDUMP is requested. */
#define PIDFD_INFO_SIZE_VER0 64 /* sizeof first published struct */
#define PIDFD_INFO_SIZE_VER1 72 /* sizeof second published struct */
#define PIDFD_INFO_SIZE_VER2 80 /* sizeof third published struct */
+#define PIDFD_INFO_SIZE_VER3 88 /* sizeof fourth published struct */
/*
* Values for @coredump_mask in pidfd_info.
@@ -94,6 +96,8 @@ struct pidfd_info {
struct /* coredump info */ {
__u32 coredump_mask;
__u32 coredump_signal;
+ __u32 coredump_code;
+ __u32 coredump_pad; /* align supported_mask to 8 bytes */
};
__u64 supported_mask; /* Mask flags that this kernel supports */
};
diff --git a/lib/libc/include/any-linux-any/linux/psp-sev.h b/lib/libc/include/any-linux-any/linux/psp-sev.h
index ba30f4cd48a256788db8016bbb51b88a607f9d98..5f69905a2ede55d0ab2815f940035b99953f367a 100644
--- a/lib/libc/include/any-linux-any/linux/psp-sev.h
+++ b/lib/libc/include/any-linux-any/linux/psp-sev.h
@@ -277,7 +277,7 @@ struct sev_user_data_snp_wrapped_vlek_hashstick {
* struct sev_issue_cmd - SEV ioctl parameters
*
* @cmd: SEV commands to execute
- * @opaque: pointer to the command structure
+ * @data: pointer to the command structure
* @error: SEV FW return code on failure
*/
struct sev_issue_cmd {
diff --git a/lib/libc/include/any-linux-any/linux/rose.h b/lib/libc/include/any-linux-any/linux/rose.h
deleted file mode 100644
index 5dcdc842e3f315a9c63697e72e6608d1b4156390..0000000000000000000000000000000000000000
--- a/lib/libc/include/any-linux-any/linux/rose.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * These are the public elements of the Linux kernel Rose implementation.
- * For kernel AX.25 see the file ax25.h. This file requires ax25.h for the
- * definition of the ax25_address structure.
- */
-
-#ifndef ROSE_KERNEL_H
-#define ROSE_KERNEL_H
-
-#include
-#include
-
-#define ROSE_MTU 251
-
-#define ROSE_MAX_DIGIS 6
-
-#define ROSE_DEFER 1
-#define ROSE_T1 2
-#define ROSE_T2 3
-#define ROSE_T3 4
-#define ROSE_IDLE 5
-#define ROSE_QBITINCL 6
-#define ROSE_HOLDBACK 7
-
-#define SIOCRSGCAUSE (SIOCPROTOPRIVATE+0)
-#define SIOCRSSCAUSE (SIOCPROTOPRIVATE+1)
-#define SIOCRSL2CALL (SIOCPROTOPRIVATE+2)
-#define SIOCRSSL2CALL (SIOCPROTOPRIVATE+2)
-#define SIOCRSACCEPT (SIOCPROTOPRIVATE+3)
-#define SIOCRSCLRRT (SIOCPROTOPRIVATE+4)
-#define SIOCRSGL2CALL (SIOCPROTOPRIVATE+5)
-#define SIOCRSGFACILITIES (SIOCPROTOPRIVATE+6)
-
-#define ROSE_DTE_ORIGINATED 0x00
-#define ROSE_NUMBER_BUSY 0x01
-#define ROSE_INVALID_FACILITY 0x03
-#define ROSE_NETWORK_CONGESTION 0x05
-#define ROSE_OUT_OF_ORDER 0x09
-#define ROSE_ACCESS_BARRED 0x0B
-#define ROSE_NOT_OBTAINABLE 0x0D
-#define ROSE_REMOTE_PROCEDURE 0x11
-#define ROSE_LOCAL_PROCEDURE 0x13
-#define ROSE_SHIP_ABSENT 0x39
-
-typedef struct {
- char rose_addr[5];
-} rose_address;
-
-struct sockaddr_rose {
- __kernel_sa_family_t srose_family;
- rose_address srose_addr;
- ax25_address srose_call;
- int srose_ndigis;
- ax25_address srose_digi;
-};
-
-struct full_sockaddr_rose {
- __kernel_sa_family_t srose_family;
- rose_address srose_addr;
- ax25_address srose_call;
- unsigned int srose_ndigis;
- ax25_address srose_digis[ROSE_MAX_DIGIS];
-};
-
-struct rose_route_struct {
- rose_address address;
- unsigned short mask;
- ax25_address neighbour;
- char device[16];
- unsigned char ndigis;
- ax25_address digipeaters[AX25_MAX_DIGIS];
-};
-
-struct rose_cause_struct {
- unsigned char cause;
- unsigned char diagnostic;
-};
-
-struct rose_facilities_struct {
- rose_address source_addr, dest_addr;
- ax25_address source_call, dest_call;
- unsigned char source_ndigis, dest_ndigis;
- ax25_address source_digis[ROSE_MAX_DIGIS];
- ax25_address dest_digis[ROSE_MAX_DIGIS];
- unsigned int rand;
- rose_address fail_addr;
- ax25_address fail_call;
-};
-
-#endif
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/rseq.h b/lib/libc/include/any-linux-any/linux/rseq.h
index b84d319db3f09c895b91aa44586ed2ba22bc6aac..072890252ed6cdd503e69c25b38f3e0c3ca08940 100644
--- a/lib/libc/include/any-linux-any/linux/rseq.h
+++ b/lib/libc/include/any-linux-any/linux/rseq.h
@@ -28,7 +28,7 @@ enum rseq_cs_flags_bit {
RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT = 0,
RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT = 1,
RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT = 2,
- /* (3) Intentional gap to put new bits into a separate byte */
+ /* (3) Intentional gap to keep new bits separate */
/* User read only feature flags */
RSEQ_CS_FLAG_SLICE_EXT_AVAILABLE_BIT = 4,
@@ -161,6 +161,9 @@ struct rseq {
* - RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT
* - RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL
* - RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE
+ *
+ * It is now used for feature status advertisement by the kernel.
+ * See: enum rseq_cs_flags_bit for further information.
*/
__u32 flags;
diff --git a/lib/libc/include/any-linux-any/linux/scc.h b/lib/libc/include/any-linux-any/linux/scc.h
deleted file mode 100644
index b629398387a65b29dfeb395ad8dc0baf7f92a7fa..0000000000000000000000000000000000000000
--- a/lib/libc/include/any-linux-any/linux/scc.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* $Id: scc.h,v 1.29 1997/04/02 14:56:45 jreuter Exp jreuter $ */
-
-#ifndef _SCC_H
-#define _SCC_H
-
-#include
-
-/* selection of hardware types */
-
-#define PA0HZP 0x00 /* hardware type for PA0HZP SCC card and compatible */
-#define EAGLE 0x01 /* hardware type for EAGLE card */
-#define PC100 0x02 /* hardware type for PC100 card */
-#define PRIMUS 0x04 /* hardware type for PRIMUS-PC (DG9BL) card */
-#define DRSI 0x08 /* hardware type for DRSI PC*Packet card */
-#define BAYCOM 0x10 /* hardware type for BayCom (U)SCC */
-
-/* DEV ioctl() commands */
-
-enum SCC_ioctl_cmds {
- SIOCSCCRESERVED = SIOCDEVPRIVATE,
- SIOCSCCCFG,
- SIOCSCCINI,
- SIOCSCCCHANINI,
- SIOCSCCSMEM,
- SIOCSCCGKISS,
- SIOCSCCSKISS,
- SIOCSCCGSTAT,
- SIOCSCCCAL
-};
-
-/* Device parameter control (from WAMPES) */
-
-enum L1_params {
- PARAM_DATA,
- PARAM_TXDELAY,
- PARAM_PERSIST,
- PARAM_SLOTTIME,
- PARAM_TXTAIL,
- PARAM_FULLDUP,
- PARAM_SOFTDCD, /* was: PARAM_HW */
- PARAM_MUTE, /* ??? */
- PARAM_DTR,
- PARAM_RTS,
- PARAM_SPEED,
- PARAM_ENDDELAY, /* ??? */
- PARAM_GROUP,
- PARAM_IDLE,
- PARAM_MIN,
- PARAM_MAXKEY,
- PARAM_WAIT,
- PARAM_MAXDEFER,
- PARAM_TX,
- PARAM_HWEVENT = 31,
- PARAM_RETURN = 255 /* reset kiss mode */
-};
-
-/* fulldup parameter */
-
-enum FULLDUP_modes {
- KISS_DUPLEX_HALF, /* normal CSMA operation */
- KISS_DUPLEX_FULL, /* fullduplex, key down trx after transmission */
- KISS_DUPLEX_LINK, /* fullduplex, key down trx after 'idletime' sec */
- KISS_DUPLEX_OPTIMA /* fullduplex, let the protocol layer control the hw */
-};
-
-/* misc. parameters */
-
-#define TIMER_OFF 65535U /* to switch off timers */
-#define NO_SUCH_PARAM 65534U /* param not implemented */
-
-/* HWEVENT parameter */
-
-enum HWEVENT_opts {
- HWEV_DCD_ON,
- HWEV_DCD_OFF,
- HWEV_ALL_SENT
-};
-
-/* channel grouping */
-
-#define RXGROUP 0100 /* if set, only tx when all channels clear */
-#define TXGROUP 0200 /* if set, don't transmit simultaneously */
-
-/* Tx/Rx clock sources */
-
-enum CLOCK_sources {
- CLK_DPLL, /* normal halfduplex operation */
- CLK_EXTERNAL, /* external clocking (G3RUH/DF9IC modems) */
- CLK_DIVIDER, /* Rx = DPLL, Tx = divider (fullduplex with */
- /* modems without clock regeneration */
- CLK_BRG /* experimental fullduplex mode with DPLL/BRG for */
- /* MODEMs without clock recovery */
-};
-
-/* Tx state */
-
-enum TX_state {
- TXS_IDLE, /* Transmitter off, no data pending */
- TXS_BUSY, /* waiting for permission to send / tailtime */
- TXS_ACTIVE, /* Transmitter on, sending data */
- TXS_NEWFRAME, /* reset CRC and send (next) frame */
- TXS_IDLE2, /* Transmitter on, no data pending */
- TXS_WAIT, /* Waiting for Mintime to expire */
- TXS_TIMEOUT /* We had a transmission timeout */
-};
-
-typedef unsigned long io_port; /* type definition for an 'io port address' */
-
-/* SCC statistical information */
-
-struct scc_stat {
- long rxints; /* Receiver interrupts */
- long txints; /* Transmitter interrupts */
- long exints; /* External/status interrupts */
- long spints; /* Special receiver interrupts */
-
- long txframes; /* Packets sent */
- long rxframes; /* Number of Frames Actually Received */
- long rxerrs; /* CRC Errors */
- long txerrs; /* KISS errors */
-
- unsigned int nospace; /* "Out of buffers" */
- unsigned int rx_over; /* Receiver Overruns */
- unsigned int tx_under; /* Transmitter Underruns */
-
- unsigned int tx_state; /* Transmitter state */
- int tx_queued; /* tx frames enqueued */
-
- unsigned int maxqueue; /* allocated tx_buffers */
- unsigned int bufsize; /* used buffersize */
-};
-
-struct scc_modem {
- long speed; /* Line speed, bps */
- char clocksrc; /* 0 = DPLL, 1 = external, 2 = divider */
- char nrz; /* NRZ instead of NRZI */
-};
-
-struct scc_kiss_cmd {
- int command; /* one of the KISS-Commands defined above */
- unsigned param; /* KISS-Param */
-};
-
-struct scc_hw_config {
- io_port data_a; /* data port channel A */
- io_port ctrl_a; /* control port channel A */
- io_port data_b; /* data port channel B */
- io_port ctrl_b; /* control port channel B */
- io_port vector_latch; /* INTACK-Latch (#) */
- io_port special; /* special function port */
-
- int irq; /* irq */
- long clock; /* clock */
- char option; /* command for function port */
-
- char brand; /* hardware type */
- char escc; /* use ext. features of a 8580/85180/85280 */
-};
-
-/* (#) only one INTACK latch allowed. */
-
-
-struct scc_mem_config {
- unsigned int dummy;
- unsigned int bufsize;
-};
-
-struct scc_calibrate {
- unsigned int time;
- unsigned char pattern;
-};
-
-#endif /* _SCC_H */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/sched.h b/lib/libc/include/any-linux-any/linux/sched.h
index 82995e5dd0f4d230ceec49453d51b74c34539ead..e88d5440602d1bbae51351dd276981339e8e4acf 100644
--- a/lib/libc/include/any-linux-any/linux/sched.h
+++ b/lib/libc/include/any-linux-any/linux/sched.h
@@ -34,8 +34,12 @@
#define CLONE_IO 0x80000000 /* Clone io context */
/* Flags for the clone3() syscall. */
-#define CLONE_CLEAR_SIGHAND 0x100000000ULL /* Clear any signal handler and reset to SIG_DFL. */
-#define CLONE_INTO_CGROUP 0x200000000ULL /* Clone into a specific cgroup given the right permissions. */
+#define CLONE_CLEAR_SIGHAND (1ULL << 32) /* Clear any signal handler and reset to SIG_DFL. */
+#define CLONE_INTO_CGROUP (1ULL << 33) /* Clone into a specific cgroup given the right permissions. */
+#define CLONE_AUTOREAP (1ULL << 34) /* Auto-reap child on exit. */
+#define CLONE_NNP (1ULL << 35) /* Set no_new_privs on child. */
+#define CLONE_PIDFD_AUTOKILL (1ULL << 36) /* Kill child when clone pidfd closes. */
+#define CLONE_EMPTY_MNTNS (1ULL << 37) /* Create an empty mount namespace. */
/*
* cloning flags intersect with CSIGNAL so can be used with unshare and clone3
@@ -43,6 +47,12 @@
*/
#define CLONE_NEWTIME 0x00000080 /* New time namespace */
+/*
+ * unshare flags share the bit space with clone flags but only apply to the
+ * unshare syscall:
+ */
+#define UNSHARE_EMPTY_MNTNS 0x00100000 /* Unshare an empty mount namespace. */
+
#ifndef __ASSEMBLY__
/**
* struct clone_args - arguments for the clone3 syscall
@@ -146,4 +156,7 @@ struct clone_args {
SCHED_FLAG_KEEP_ALL | \
SCHED_FLAG_UTIL_CLAMP)
+/* Only for sched_getattr() own flag param, if task is SCHED_DEADLINE */
+#define SCHED_GETATTR_FLAG_DL_DYNAMIC 0x01
+
#endif /* _LINUX_SCHED_H */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/sed-opal.h b/lib/libc/include/any-linux-any/linux/sed-opal.h
index 733afdf08dca56cb5596fd9ff1eef1366dce6c11..4774427e7b7c3a0839fb1c6bfca6abbf9a2c0881 100644
--- a/lib/libc/include/any-linux-any/linux/sed-opal.h
+++ b/lib/libc/include/any-linux-any/linux/sed-opal.h
@@ -74,6 +74,19 @@ struct opal_lr_act {
__u8 align[2]; /* Align to 8 byte boundary */
};
+struct opal_lr_react {
+ struct opal_key key;
+ struct opal_key new_admin_key; /* Set new Admin1 PIN if key_len is > 0 */
+ __u8 num_lrs; /*
+ * Configure selected ranges (from lr[]) in SUM.
+ * If num_lrs > 0 the 'entire_table' must be 0
+ */
+ __u8 lr[OPAL_MAX_LRS];
+ __u8 range_policy; /* Set RangeStartRangeLengthPolicy parameter */
+ __u8 entire_table; /* Set all locking objects in SUM */
+ __u8 align[4]; /* Align to 8 byte boundary */
+};
+
struct opal_session_info {
__u32 sum;
__u32 who;
@@ -98,6 +111,18 @@ struct opal_lr_status {
__u8 align[4];
};
+struct opal_sum_ranges {
+ /*
+ * Initiate Admin1 session if key_len > 0,
+ * use Anybody session otherwise.
+ */
+ struct opal_key key;
+ __u8 num_lrs;
+ __u8 lr[OPAL_MAX_LRS];
+ __u8 range_policy;
+ __u8 align[5]; /* Align to 8 byte boundary */
+};
+
struct opal_lock_unlock {
struct opal_session_info session;
__u32 l_state;
@@ -216,5 +241,10 @@ struct opal_revert_lsp {
#define IOC_OPAL_DISCOVERY _IOW('p', 239, struct opal_discovery)
#define IOC_OPAL_REVERT_LSP _IOW('p', 240, struct opal_revert_lsp)
#define IOC_OPAL_SET_SID_PW _IOW('p', 241, struct opal_new_pw)
+#define IOC_OPAL_REACTIVATE_LSP _IOW('p', 242, struct opal_lr_react)
+#define IOC_OPAL_LR_SET_START_LEN _IOW('p', 243, struct opal_user_lr_setup)
+#define IOC_OPAL_ENABLE_DISABLE_LR _IOW('p', 244, struct opal_user_lr_setup)
+#define IOC_OPAL_GET_SUM_STATUS _IOW('p', 245, struct opal_sum_ranges)
+#define IOC_OPAL_STACK_RESET _IO('p', 246)
#endif /* _SED_OPAL_H */
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/seg6_iptunnel.h b/lib/libc/include/any-linux-any/linux/seg6_iptunnel.h
index 4361e5c5a1bbfa4244f22cc85932ca719d6390bf..19d538851169c5b73c0830909cbd114958b1b521 100644
--- a/lib/libc/include/any-linux-any/linux/seg6_iptunnel.h
+++ b/lib/libc/include/any-linux-any/linux/seg6_iptunnel.h
@@ -20,6 +20,7 @@
enum {
SEG6_IPTUNNEL_UNSPEC,
SEG6_IPTUNNEL_SRH,
+ SEG6_IPTUNNEL_SRC, /* struct in6_addr */
__SEG6_IPTUNNEL_MAX,
};
#define SEG6_IPTUNNEL_MAX (__SEG6_IPTUNNEL_MAX - 1)
diff --git a/lib/libc/include/any-linux-any/linux/tee.h b/lib/libc/include/any-linux-any/linux/tee.h
index 4f8d7d97a77a2749fb910e0620e0bca74a92d805..0d64a060b18a76630cf37d18a43a634eef7da9aa 100644
--- a/lib/libc/include/any-linux-any/linux/tee.h
+++ b/lib/libc/include/any-linux-any/linux/tee.h
@@ -470,6 +470,7 @@ struct tee_ioctl_object_invoke_arg {
__u32 op;
__u32 ret;
__u32 num_params;
+ __u32 :32;
/* num_params tells the actual number of element in params */
struct tee_ioctl_param params[];
};
diff --git a/lib/libc/include/any-linux-any/linux/trace_mmap.h b/lib/libc/include/any-linux-any/linux/trace_mmap.h
index fb720ddd3b650afc9bd42f2092408c00ffa38222..27e098d364b2c548d19fd24e917e6d6863b1fdf1 100644
--- a/lib/libc/include/any-linux-any/linux/trace_mmap.h
+++ b/lib/libc/include/any-linux-any/linux/trace_mmap.h
@@ -10,6 +10,7 @@
* @meta_struct_len: Size of this structure.
* @subbuf_size: Size of each sub-buffer.
* @nr_subbufs: Number of subbfs in the ring-buffer, including the reader.
+ * @reader: The reader composite info structure
* @reader.lost_events: Number of events lost at the time of the reader swap.
* @reader.id: subbuf ID of the current reader. ID range [0 : @nr_subbufs - 1]
* @reader.read: Number of bytes read on the reader subbuf.
@@ -17,8 +18,8 @@
* @entries: Number of entries in the ring-buffer.
* @overrun: Number of entries lost in the ring-buffer.
* @read: Number of entries that have been read.
- * @Reserved1: Internal use only.
- * @Reserved2: Internal use only.
+ * @pages_lost: Number of pages overwritten by the writer.
+ * @pages_touched: Number of pages written by the writer.
*/
struct trace_buffer_meta {
__u32 meta_page_size;
@@ -39,8 +40,8 @@ struct trace_buffer_meta {
__u64 overrun;
__u64 read;
- __u64 Reserved1;
- __u64 Reserved2;
+ __u64 pages_lost;
+ __u64 pages_touched;
};
#define TRACE_MMAP_IOCTL_GET_READER _IO('R', 0x20)
diff --git a/lib/libc/include/any-linux-any/linux/ublk_cmd.h b/lib/libc/include/any-linux-any/linux/ublk_cmd.h
index a8a5dff94e9f8722ce8a1d69cf4df91403087b22..7aee5d9b127619e9a20978f3850b6fd00c8c2045 100644
--- a/lib/libc/include/any-linux-any/linux/ublk_cmd.h
+++ b/lib/libc/include/any-linux-any/linux/ublk_cmd.h
@@ -57,6 +57,45 @@
_IOWR('u', 0x16, struct ublksrv_ctrl_cmd)
#define UBLK_U_CMD_TRY_STOP_DEV \
_IOWR('u', 0x17, struct ublksrv_ctrl_cmd)
+/*
+ * Register a shared memory buffer for zero-copy I/O.
+ * Input: ctrl_cmd.addr points to struct ublk_shmem_buf_reg (buffer VA + size)
+ * ctrl_cmd.len = sizeof(struct ublk_shmem_buf_reg)
+ * Result: >= 0 is the assigned buffer index, < 0 is error
+ *
+ * The kernel pins pages from the calling process's address space
+ * and inserts PFN ranges into a per-device maple tree. When a block
+ * request's pages match registered pages, the driver sets
+ * UBLK_IO_F_SHMEM_ZC and encodes the buffer index + offset in addr,
+ * allowing the server to access the data via its own mapping of the
+ * same shared memory — true zero copy.
+ *
+ * The memory can be backed by memfd, hugetlbfs, or any GUP-compatible
+ * shared mapping. Queue freeze is handled internally.
+ *
+ * The buffer VA and size are passed via a user buffer (not __inline__ in
+ * ctrl_cmd) so that unprivileged devices can prepend the device path
+ * to ctrl_cmd.addr without corrupting the VA.
+ */
+#define UBLK_U_CMD_REG_BUF \
+ _IOWR('u', 0x18, struct ublksrv_ctrl_cmd)
+/*
+ * Unregister a shared memory buffer.
+ * Input: ctrl_cmd.data[0] = buffer index
+ */
+#define UBLK_U_CMD_UNREG_BUF \
+ _IOWR('u', 0x19, struct ublksrv_ctrl_cmd)
+
+/* Parameter buffer for UBLK_U_CMD_REG_BUF, pointed to by ctrl_cmd.addr */
+struct ublk_shmem_buf_reg {
+ __u64 addr; /* userspace virtual address of shared memory */
+ __u64 len; /* buffer size in bytes, page-aligned, default max 4GB */
+ __u32 flags;
+ __u32 reserved;
+};
+
+/* Pin pages without FOLL_WRITE; usable with write-sealed memfd */
+#define UBLK_SHMEM_BUF_READ_ONLY (1U << 0)
/*
* 64bits are enough now, and it should be easy to extend in case of
* running out of feature flags
@@ -370,6 +409,14 @@
/* Disable automatic partition scanning when device is started */
#define UBLK_F_NO_AUTO_PART_SCAN (1ULL << 18)
+/*
+ * Enable shared memory zero copy. When enabled, the server can register
+ * shared memory buffers via UBLK_U_CMD_REG_BUF. If a block request's
+ * pages match a registered buffer, UBLK_IO_F_SHMEM_ZC is set and addr
+ * encodes the buffer index + offset instead of a userspace buffer address.
+ */
+#define UBLK_F_SHMEM_ZC (1ULL << 19)
+
/* device state */
#define UBLK_S_DEV_DEAD 0
#define UBLK_S_DEV_LIVE 1
@@ -469,6 +516,12 @@ struct ublksrv_ctrl_dev_info {
#define UBLK_IO_F_NEED_REG_BUF (1U << 17)
/* Request has an integrity data buffer */
#define UBLK_IO_F_INTEGRITY (1UL << 18)
+/*
+ * I/O buffer is in a registered shared memory buffer. When set, the addr
+ * field in ublksrv_io_desc encodes buffer index and byte offset instead
+ * of a userspace virtual address.
+ */
+#define UBLK_IO_F_SHMEM_ZC (1U << 19)
/*
* io cmd is described by this structure, and stored in share memory, indexed
@@ -743,4 +796,31 @@ struct ublk_params {
struct ublk_param_integrity integrity;
};
+/*
+ * Shared memory zero-copy addr encoding for UBLK_IO_F_SHMEM_ZC.
+ *
+ * When UBLK_IO_F_SHMEM_ZC is set, ublksrv_io_desc.addr is encoded as:
+ * bits [0:31] = byte offset within the buffer (up to 4GB)
+ * bits [32:47] = buffer index (up to 65536)
+ * bits [48:63] = reserved (must be zero)
+ */
+#define UBLK_SHMEM_ZC_OFF_MASK 0xffffffffULL
+#define UBLK_SHMEM_ZC_IDX_OFF 32
+#define UBLK_SHMEM_ZC_IDX_MASK 0xffffULL
+
+static __inline__ __u64 ublk_shmem_zc_addr(__u16 index, __u32 offset)
+{
+ return ((__u64)index << UBLK_SHMEM_ZC_IDX_OFF) | offset;
+}
+
+static __inline__ __u16 ublk_shmem_zc_index(__u64 addr)
+{
+ return (addr >> UBLK_SHMEM_ZC_IDX_OFF) & UBLK_SHMEM_ZC_IDX_MASK;
+}
+
+static __inline__ __u32 ublk_shmem_zc_offset(__u64 addr)
+{
+ return (__u32)(addr & UBLK_SHMEM_ZC_OFF_MASK);
+}
+
#endif
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/udp.h b/lib/libc/include/any-linux-any/linux/udp.h
index f101b125180675b639d0d25d540ca99ee19df8a6..c63c35eb84cfbff6ca7928000c3e8bff2a3addec 100644
--- a/lib/libc/include/any-linux-any/linux/udp.h
+++ b/lib/libc/include/any-linux-any/linux/udp.h
@@ -29,6 +29,8 @@ struct udphdr {
/* UDP socket options */
#define UDP_CORK 1 /* Never send partially complete segments */
+/* Deprecated, reserved for UDPLITE_SEND_CSCOV 10 */
+/* Deprecated, reserved for UDPLITE_RECV_CSCOV 11 */
#define UDP_ENCAP 100 /* Set the socket to accept encapsulated packets */
#define UDP_NO_CHECK6_TX 101 /* Disable sending checksum for UDP6X */
#define UDP_NO_CHECK6_RX 102 /* Disable accepting checksum for UDP6 */
diff --git a/lib/libc/include/any-linux-any/linux/um_timetravel.h b/lib/libc/include/any-linux-any/linux/um_timetravel.h
index f7e7a05844665250a965d9e7ad966e9c40e0b3f8..7d6119490ca5a7a191dd695be866ef47b6c99161 100644
--- a/lib/libc/include/any-linux-any/linux/um_timetravel.h
+++ b/lib/libc/include/any-linux-any/linux/um_timetravel.h
@@ -56,6 +56,9 @@ enum um_timetravel_shared_mem_fds {
* in the control message
*/
UM_TIMETRAVEL_SHARED_LOGFD,
+ /**
+ * @UM_TIMETRAVEL_SHARED_MAX_FDS: number of fds listed here
+ */
UM_TIMETRAVEL_SHARED_MAX_FDS,
};
@@ -242,6 +245,7 @@ union um_timetravel_schedshm_client {
__u64 req_time;
__u64 name;
};
+ /* private: */
char reserve[128]; /* reserved for future usage */
};
@@ -264,7 +268,7 @@ union um_timetravel_schedshm_client {
* is made by any client. Clients also must update this value when they
* insert/update an own request into the shared memory while not running
* themselves, and the new request is before than the current value.
- * current_time: Current time, can only be set by the client in running state
+ * @current_time: Current time, can only be set by the client in running state
* (indicated by @running_id), though that client may only run until @free_until,
* so it must remain smaller than @free_until.
* @running_id: The current client in state running, set before a client is
diff --git a/lib/libc/include/any-linux-any/linux/usb/ch9.h b/lib/libc/include/any-linux-any/linux/usb/ch9.h
index bfd55b636e238097c146610fdfd4cff4f1ab9ec6..1554e43dd9622f49a10b3004e434bf8c7c31be18 100644
--- a/lib/libc/include/any-linux-any/linux/usb/ch9.h
+++ b/lib/libc/include/any-linux-any/linux/usb/ch9.h
@@ -102,6 +102,8 @@
#define USB_REQ_LOOPBACK_DATA_WRITE 0x15
#define USB_REQ_LOOPBACK_DATA_READ 0x16
#define USB_REQ_SET_INTERFACE_DS 0x17
+#define USB_REQ_AUTH_IN 0x18
+#define USB_REQ_AUTH_OUT 0x19
/* specific requests for USB Power Delivery */
#define USB_REQ_GET_PARTNER_PDO 20
@@ -121,15 +123,17 @@
* are at most sixteen features of each type.) Hubs may also support a
* new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend.
*/
-#define USB_DEVICE_SELF_POWERED 0 /* (read only) */
-#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */
-#define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */
-#define USB_DEVICE_BATTERY 2 /* (wireless) */
-#define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */
-#define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/
-#define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */
-#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */
-#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */
+#define USB_DEVICE_SELF_POWERED 0 /* (read only) */
+#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */
+#define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */
+#define USB_DEVICE_BATTERY 2 /* (wireless) */
+#define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */
+#define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/
+#define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */
+#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */
+#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */
+
+#define USB_DEVICE_BULK_MAX_PACKET_UPDATE 8 /* (eUSB2v2) bump maxpacket to 1024 */
/*
* Test Mode Selectors
@@ -1147,6 +1151,17 @@ struct usb_ptm_cap_descriptor {
/*-------------------------------------------------------------------------*/
+struct usb_authentication_capability_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType; /* set to USB_DT_DEVICE_CAPABILITY */
+ __u8 bmAttributes;
+
+ __u8 bcdProtocolVersion;
+ __u8 bcdCapability;
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------*/
+
/* USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with
* each endpoint descriptor for a wireless device
*/
diff --git a/lib/libc/include/any-linux-any/linux/version.h b/lib/libc/include/any-linux-any/linux/version.h
index 00d7d509bb5698f58c7847ae0a751cb2627381e2..94b0184204d7238ddd4a9e7ee445358fd4672097 100644
--- a/lib/libc/include/any-linux-any/linux/version.h
+++ b/lib/libc/include/any-linux-any/linux/version.h
@@ -1,5 +1,5 @@
-#define LINUX_VERSION_CODE 458752
+#define LINUX_VERSION_CODE 459008
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
#define LINUX_VERSION_MAJOR 7
-#define LINUX_VERSION_PATCHLEVEL 0
+#define LINUX_VERSION_PATCHLEVEL 1
#define LINUX_VERSION_SUBLEVEL 0
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/linux/vfio.h b/lib/libc/include/any-linux-any/linux/vfio.h
index 2e2dcfc6fbe30ef94fc77c16572c508c5ba267c5..6733e6f96bbc0a29ec2d42e550e9f13c4b9bf008 100644
--- a/lib/libc/include/any-linux-any/linux/vfio.h
+++ b/lib/libc/include/any-linux-any/linux/vfio.h
@@ -141,7 +141,7 @@ struct vfio_info_cap_header {
*
* Retrieve information about the group. Fills in provided
* struct vfio_group_info. Caller sets argsz.
- * Return: 0 on succes, -errno on failure.
+ * Return: 0 on success, -errno on failure.
* Availability: Always
*/
struct vfio_group_status {
@@ -1266,6 +1266,19 @@ enum vfio_device_mig_state {
* The initial_bytes field indicates the amount of initial precopy
* data available from the device. This field should have a non-zero initial
* value and decrease as migration data is read from the device.
+ * The presence of the VFIO_PRECOPY_INFO_REINIT output flag indicates
+ * that new initial data is present on the stream.
+ * The new initial data may result, for example, from device reconfiguration
+ * during migration that requires additional initialization data.
+ * In that case initial_bytes may report a non-zero value irrespective of
+ * any previously reported values, which progresses towards zero as precopy
+ * data is read from the data stream. dirty_bytes is also reset
+ * to zero and represents the state change of the device relative to the new
+ * initial_bytes.
+ * VFIO_PRECOPY_INFO_REINIT can be reported only after userspace opts in to
+ * VFIO_DEVICE_FEATURE_MIG_PRECOPY_INFOv2. Without this opt-in, the flags field
+ * of struct vfio_precopy_info is reserved for bug-compatibility reasons.
+ *
* It is recommended to leave PRE_COPY for STOP_COPY only after this field
* reaches zero. Leaving PRE_COPY earlier might make things slower.
*
@@ -1301,6 +1314,7 @@ enum vfio_device_mig_state {
struct vfio_precopy_info {
__u32 argsz;
__u32 flags;
+#define VFIO_PRECOPY_INFO_REINIT (1 << 0) /* output - new initial data is present */
__aligned_u64 initial_bytes;
__aligned_u64 dirty_bytes;
};
@@ -1510,6 +1524,16 @@ struct vfio_device_feature_dma_buf {
struct vfio_region_dma_range dma_ranges[] __counted_by(nr_ranges);
};
+/*
+ * Enables the migration precopy_info_v2 behaviour.
+ *
+ * VFIO_DEVICE_FEATURE_MIG_PRECOPY_INFOv2.
+ *
+ * On SET, enables the v2 pre_copy_info behaviour, where the
+ * vfio_precopy_info.flags is a valid output field.
+ */
+#define VFIO_DEVICE_FEATURE_MIG_PRECOPY_INFOv2 12
+
/* -------- API for Type1 VFIO IOMMU -------- */
/**
diff --git a/lib/libc/include/any-linux-any/rdma/bnxt_re-abi.h b/lib/libc/include/any-linux-any/rdma/bnxt_re-abi.h
index 8dda9fba76c4abef5e5667fb7301f1702bf05798..d04bff1136963c6be8f2b733c11a9697d3b81f0f 100644
--- a/lib/libc/include/any-linux-any/rdma/bnxt_re-abi.h
+++ b/lib/libc/include/any-linux-any/rdma/bnxt_re-abi.h
@@ -102,12 +102,17 @@ struct bnxt_re_pd_resp {
struct bnxt_re_cq_req {
__aligned_u64 cq_va;
__aligned_u64 cq_handle;
+ __aligned_u64 comp_mask;
};
-enum bnxt_re_cq_mask {
+enum bnxt_re_resp_cq_mask {
BNXT_RE_CQ_TOGGLE_PAGE_SUPPORT = 0x1,
};
+enum bnxt_re_req_cq_mask {
+ BNXT_RE_CQ_FIXED_NUM_CQE_ENABLE = 0x1,
+};
+
struct bnxt_re_cq_resp {
__u32 cqid;
__u32 tail;
@@ -163,6 +168,8 @@ enum bnxt_re_objects {
BNXT_RE_OBJECT_ALLOC_PAGE = (1U << UVERBS_ID_NS_SHIFT),
BNXT_RE_OBJECT_NOTIFY_DRV,
BNXT_RE_OBJECT_GET_TOGGLE_MEM,
+ BNXT_RE_OBJECT_DBR,
+ BNXT_RE_OBJECT_DEFAULT_DBR,
};
enum bnxt_re_alloc_page_type {
@@ -231,4 +238,31 @@ struct bnxt_re_packet_pacing_caps {
struct bnxt_re_query_device_ex_resp {
struct bnxt_re_packet_pacing_caps packet_pacing_caps;
};
+
+struct bnxt_re_db_region {
+ __u32 dpi;
+ __u32 reserved;
+ __aligned_u64 umdbr;
+};
+
+enum bnxt_re_obj_dbr_alloc_attrs {
+ BNXT_RE_ALLOC_DBR_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+ BNXT_RE_ALLOC_DBR_ATTR,
+ BNXT_RE_ALLOC_DBR_OFFSET,
+};
+
+enum bnxt_re_obj_dbr_free_attrs {
+ BNXT_RE_FREE_DBR_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+};
+
+enum bnxt_re_obj_default_dbr_attrs {
+ BNXT_RE_DEFAULT_DBR_ATTR = (1U << UVERBS_ID_NS_SHIFT),
+};
+
+enum bnxt_re_obj_dpi_methods {
+ BNXT_RE_METHOD_DBR_ALLOC = (1U << UVERBS_ID_NS_SHIFT),
+ BNXT_RE_METHOD_DBR_FREE,
+ BNXT_RE_METHOD_GET_DEFAULT_DBR,
+};
+
#endif /* __BNXT_RE_UVERBS_ABI_H__*/
\ No newline at end of file
diff --git a/lib/libc/include/any-linux-any/rdma/efa-abi.h b/lib/libc/include/any-linux-any/rdma/efa-abi.h
index 35553184b7fed0735c2eda73954a206000406e92..6d2ab8a6efc1e002bc0cb78201011583a9babc71 100644
--- a/lib/libc/include/any-linux-any/rdma/efa-abi.h
+++ b/lib/libc/include/any-linux-any/rdma/efa-abi.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) */
/*
- * Copyright 2018-2025 Amazon.com, Inc. or its affiliates. All rights reserved.
+ * Copyright 2018-2026 Amazon.com, Inc. or its affiliates. All rights reserved.
*/
#ifndef EFA_ABI_USER_H
@@ -22,12 +22,12 @@
*/
enum {
- EFA_ALLOC_UCONTEXT_CMD_COMP_TX_BATCH = 1 << 0,
- EFA_ALLOC_UCONTEXT_CMD_COMP_MIN_SQ_WR = 1 << 1,
+ EFA_ALLOC_UCONTEXT_CMD_SUPP_CAPS_TX_BATCH = 1 << 0,
+ EFA_ALLOC_UCONTEXT_CMD_SUPP_CAPS_MIN_SQ_WR = 1 << 1,
};
struct efa_ibv_alloc_ucontext_cmd {
- __u32 comp_mask;
+ __u32 supported_caps;
__u8 reserved_20[4];
};
@@ -44,7 +44,8 @@ struct efa_ibv_alloc_ucontext_resp {
__u32 max_llq_size; /* bytes */
__u16 max_tx_batch; /* units of 64 bytes */
__u16 min_sq_wr;
- __u8 reserved_a0[4];
+ __u16 inline_buf_size_ex;
+ __u8 reserved_b0[2];
};
struct efa_ibv_alloc_pd_resp {
diff --git a/lib/libc/include/any-linux-any/rdma/ib_user_ioctl_verbs.h b/lib/libc/include/any-linux-any/rdma/ib_user_ioctl_verbs.h
index 087df334051c1fd445ef1db9e4fc0f454d1f0158..8559ecbb749dee64f37301aa87e182a79961d2ac 100644
--- a/lib/libc/include/any-linux-any/rdma/ib_user_ioctl_verbs.h
+++ b/lib/libc/include/any-linux-any/rdma/ib_user_ioctl_verbs.h
@@ -46,6 +46,7 @@
enum ib_uverbs_core_support {
IB_UVERBS_CORE_SUPPORT_OPTIONAL_MR_ACCESS = 1 << 0,
+ IB_UVERBS_CORE_SUPPORT_ROBUST_UDATA = 1 << 1,
};
enum ib_uverbs_access_flags {
diff --git a/lib/libc/include/any-linux-any/rdma/mlx5_user_ioctl_cmds.h b/lib/libc/include/any-linux-any/rdma/mlx5_user_ioctl_cmds.h
index b6bf89d8e61e9985d4cd88ec3d04e34c13f11d04..fdd63256f66e4d09e23f910e36e25760953b94e6 100644
--- a/lib/libc/include/any-linux-any/rdma/mlx5_user_ioctl_cmds.h
+++ b/lib/libc/include/any-linux-any/rdma/mlx5_user_ioctl_cmds.h
@@ -139,6 +139,7 @@ enum mlx5_ib_var_alloc_attrs {
MLX5_IB_ATTR_VAR_OBJ_ALLOC_MMAP_OFFSET,
MLX5_IB_ATTR_VAR_OBJ_ALLOC_MMAP_LENGTH,
MLX5_IB_ATTR_VAR_OBJ_ALLOC_PAGE_ID,
+ MLX5_IB_ATTR_VAR_OBJ_ALLOC_FLAGS,
};
enum mlx5_ib_var_obj_destroy_attrs {
diff --git a/lib/libc/include/any-linux-any/rdma/mlx5_user_ioctl_verbs.h b/lib/libc/include/any-linux-any/rdma/mlx5_user_ioctl_verbs.h
index 9cdf7447e3109739d0749919f160f63787218e98..789d33f8e7e9bcffaea299bc18d0523f1d69c01b 100644
--- a/lib/libc/include/any-linux-any/rdma/mlx5_user_ioctl_verbs.h
+++ b/lib/libc/include/any-linux-any/rdma/mlx5_user_ioctl_verbs.h
@@ -100,6 +100,10 @@ enum mlx5_ib_uapi_query_port_flags {
MLX5_IB_UAPI_QUERY_PORT_ESW_OWNER_VHCA_ID = 1 << 5,
};
+enum mlx5_ib_uapi_var_alloc_flags {
+ MLX5_IB_UAPI_VAR_ALLOC_FLAG_TLP = 1 << 0,
+};
+
struct mlx5_ib_uapi_reg {
__u32 value;
__u32 mask;
diff --git a/lib/libc/include/any-linux-any/rdma/rdma_netlink.h b/lib/libc/include/any-linux-any/rdma/rdma_netlink.h
index 869200781e8204039008ba985e761c8d1d9be9b5..0c5336f6c9b081b8832270d2ff6c2ecbfd3d639d 100644
--- a/lib/libc/include/any-linux-any/rdma/rdma_netlink.h
+++ b/lib/libc/include/any-linux-any/rdma/rdma_netlink.h
@@ -308,6 +308,10 @@ enum rdma_nldev_command {
RDMA_NLDEV_CMD_MONITOR,
+ RDMA_NLDEV_CMD_FRMR_POOLS_GET, /* can dump */
+
+ RDMA_NLDEV_CMD_FRMR_POOLS_SET,
+
RDMA_NLDEV_NUM_OPS
};
@@ -582,6 +586,24 @@ enum rdma_nldev_attr {
RDMA_NLDEV_SYS_ATTR_MONITOR_MODE, /* u8 */
RDMA_NLDEV_ATTR_STAT_OPCOUNTER_ENABLED, /* u8 */
+
+ /*
+ * FRMR Pools attributes
+ */
+ RDMA_NLDEV_ATTR_FRMR_POOLS, /* nested table */
+ RDMA_NLDEV_ATTR_FRMR_POOL_ENTRY, /* nested table */
+ RDMA_NLDEV_ATTR_FRMR_POOL_KEY, /* nested table */
+ RDMA_NLDEV_ATTR_FRMR_POOL_KEY_ATS, /* u8 */
+ RDMA_NLDEV_ATTR_FRMR_POOL_KEY_ACCESS_FLAGS, /* u32 */
+ RDMA_NLDEV_ATTR_FRMR_POOL_KEY_VENDOR_KEY, /* u64 */
+ RDMA_NLDEV_ATTR_FRMR_POOL_KEY_NUM_DMA_BLOCKS, /* u64 */
+ RDMA_NLDEV_ATTR_FRMR_POOL_QUEUE_HANDLES, /* u32 */
+ RDMA_NLDEV_ATTR_FRMR_POOL_MAX_IN_USE, /* u64 */
+ RDMA_NLDEV_ATTR_FRMR_POOL_IN_USE, /* u64 */
+ RDMA_NLDEV_ATTR_FRMR_POOLS_AGING_PERIOD, /* u32 */
+ RDMA_NLDEV_ATTR_FRMR_POOL_PINNED_HANDLES, /* u32 */
+ RDMA_NLDEV_ATTR_FRMR_POOL_KEY_KERNEL_VENDOR_KEY, /* u64 */
+
/*
* Always the end
*/
diff --git a/lib/libc/include/any-linux-any/scsi/fc/fc_els.h b/lib/libc/include/any-linux-any/scsi/fc/fc_els.h
index 5220bc05d555ca0a732033006cb7645aa564f41b..68d3472d896d88f196001f83a3d2a3c7da3c2ed4 100644
--- a/lib/libc/include/any-linux-any/scsi/fc/fc_els.h
+++ b/lib/libc/include/any-linux-any/scsi/fc/fc_els.h
@@ -1026,7 +1026,7 @@ struct fc_fn_li_desc {
*/
__be32 event_count; /* minimum number of event
* occurrences during the event
- * threshold to caause the LI event
+ * threshold to cause the LI event
*/
__be32 pname_count; /* number of portname_list elements */
__be64 pname_list[]; /* list of N_Port_Names accessible
diff --git a/lib/libc/include/hexagon-linux-any/asm/sigcontext.h b/lib/libc/include/hexagon-linux-any/asm/sigcontext.h
index 7064daf5a5bc7916d2325a1cf1e201c0e37e7850..ff1dd437caf8098d68c557c315c2bc1048d73174 100644
--- a/lib/libc/include/hexagon-linux-any/asm/sigcontext.h
+++ b/lib/libc/include/hexagon-linux-any/asm/sigcontext.h
@@ -29,6 +29,6 @@
*/
struct sigcontext {
struct user_regs_struct sc_regs;
-} __aligned(8);
+} __attribute__((aligned(8)));
#endif
\ No newline at end of file
diff --git a/lib/libc/include/loongarch-linux-any/asm/hwcap.h b/lib/libc/include/loongarch-linux-any/asm/hwcap.h
index 9201ebbf041c18921f5a657385cab7594001b5fc..3f1a3d5b9784ce183b6977c5422f5c4cdd68b8ab 100644
--- a/lib/libc/include/loongarch-linux-any/asm/hwcap.h
+++ b/lib/libc/include/loongarch-linux-any/asm/hwcap.h
@@ -19,5 +19,6 @@
#define HWCAP_LOONGARCH_PTW (1 << 13)
#define HWCAP_LOONGARCH_LSPW (1 << 14)
#define HWCAP_LOONGARCH_SCQ (1 << 15)
+#define HWCAP_LOONGARCH_LAM_BH (1 << 16)
#endif /* _ASM_HWCAP_H */
\ No newline at end of file
diff --git a/lib/libc/include/loongarch-linux-any/asm/kvm.h b/lib/libc/include/loongarch-linux-any/asm/kvm.h
index 069fc9f13f26a6222cbc8ca440468efa6ea9c764..91d26cfcb481e0aad31cc7f1fb36e4853bb10811 100644
--- a/lib/libc/include/loongarch-linux-any/asm/kvm.h
+++ b/lib/libc/include/loongarch-linux-any/asm/kvm.h
@@ -155,4 +155,8 @@ struct kvm_iocsr_entry {
#define KVM_DEV_LOONGARCH_PCH_PIC_GRP_CTRL 0x40000006
#define KVM_DEV_LOONGARCH_PCH_PIC_CTRL_INIT 0
+#define KVM_DEV_LOONGARCH_DMSINTC_GRP_CTRL 0x40000007
+#define KVM_DEV_LOONGARCH_DMSINTC_MSG_ADDR_BASE 0x0
+#define KVM_DEV_LOONGARCH_DMSINTC_MSG_ADDR_SIZE 0x1
+
#endif /* __UAPI_ASM_LOONGARCH_KVM_H */
\ No newline at end of file
diff --git a/lib/libc/include/m68k-linux-any/asm/ucontext.h b/lib/libc/include/m68k-linux-any/asm/ucontext.h
new file mode 100644
index 0000000000000000000000000000000000000000..ce57d5cfd90482e8e6e901d7cee792581bca4c08
--- /dev/null
+++ b/lib/libc/include/m68k-linux-any/asm/ucontext.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _M68K_UCONTEXT_H
+#define _M68K_UCONTEXT_H
+
+#include
+#include
+
+typedef int greg_t;
+#define NGREG 18
+typedef greg_t gregset_t[NGREG];
+
+typedef struct fpregset {
+ int f_fpcntl[3];
+ int f_fpregs[8*3];
+} fpregset_t;
+
+struct mcontext {
+ int version;
+ gregset_t gregs;
+ fpregset_t fpregs;
+};
+
+#define MCONTEXT_VERSION 2
+
+struct ucontext {
+ unsigned long uc_flags;
+ struct ucontext *uc_link;
+ stack_t uc_stack;
+ struct mcontext uc_mcontext;
+ unsigned long uc_filler[80];
+ sigset_t uc_sigmask; /* mask last for extensibility */
+};
+
+#endif
\ No newline at end of file
diff --git a/lib/libc/include/riscv-linux-any/asm/kvm.h b/lib/libc/include/riscv-linux-any/asm/kvm.h
index 99f9a958941b5acbd836def26f95f2c86eca186a..293195b123236ebf4b01987a0172bc3f0732bf37 100644
--- a/lib/libc/include/riscv-linux-any/asm/kvm.h
+++ b/lib/libc/include/riscv-linux-any/asm/kvm.h
@@ -110,6 +110,10 @@ struct kvm_riscv_timer {
__u64 state;
};
+/* Possible states for kvm_riscv_timer */
+#define KVM_RISCV_TIMER_STATE_OFF 0
+#define KVM_RISCV_TIMER_STATE_ON 1
+
/*
* ISA extension IDs specific to KVM. This is not the same as the host ISA
* extension IDs as that is internal to the host and should not be exposed
@@ -238,10 +242,6 @@ struct kvm_riscv_sbi_fwft {
struct kvm_riscv_sbi_fwft_feature pointer_masking;
};
-/* Possible states for kvm_riscv_timer */
-#define KVM_RISCV_TIMER_STATE_OFF 0
-#define KVM_RISCV_TIMER_STATE_ON 1
-
/* If you need to interpret the index values, here is the key: */
#define KVM_REG_RISCV_TYPE_MASK 0x00000000FF000000
#define KVM_REG_RISCV_TYPE_SHIFT 24
diff --git a/lib/libc/include/riscv-linux-any/asm/setup.h b/lib/libc/include/riscv-linux-any/asm/setup.h
index 1094751b59fb571a1c24db0f162af1abd15a65d2..9f043d39ecbe9ef57204eaaaf2868e6d5870348c 100644
--- a/lib/libc/include/riscv-linux-any/asm/setup.h
+++ b/lib/libc/include/riscv-linux-any/asm/setup.h
@@ -3,6 +3,6 @@
#ifndef _ASM_RISCV_SETUP_H
#define _ASM_RISCV_SETUP_H
-#define COMMAND_LINE_SIZE 1024
+#define COMMAND_LINE_SIZE 2048
#endif /* _ASM_RISCV_SETUP_H */
\ No newline at end of file
diff --git a/lib/libc/mingw/math/lroundl.c b/lib/libc/mingw/math/lroundl.c
deleted file mode 100644
index b4584a896d3e0190c88049a9bebfeb26c48916ed..0000000000000000000000000000000000000000
--- a/lib/libc/mingw/math/lroundl.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is part of the mingw-w64 runtime package.
- * No warranty is given; refer to the file DISCLAIMER.PD within this package.
- */
-#include
-#include
-#include
-
-long
-lroundl (long double x)
-{
- long double res;
-
- if (x >= 0.0L)
- {
- res = ceill (x);
- if (res - x > 0.5L)
- res -= 1.0;
- }
- else
- {
- res = ceill (-x);
- if (res + x > 0.5L)
- res -= 1.0L;
- res = -res;
- }
- if (!isfinite (res)
- || res > (long double)LONG_MAX
- || res < (long double)LONG_MIN)
- {
- errno = ERANGE;
- /* Undefined behaviour, so we could return anything. */
- /* return res > 0.0L ? LONG_MAX : LONG_MIN; */
- }
- return (long) res;
-}
diff --git a/lib/libc/musl/src/internal/floatscan.c b/lib/libc/musl/src/internal/floatscan.c
index 8c0828fcb39e6e0e742309913eef1aa955e582e5..b15366b685e9757d56b3c41d5caf7a69c4682d35 100644
--- a/lib/libc/musl/src/internal/floatscan.c
+++ b/lib/libc/musl/src/internal/floatscan.c
@@ -347,7 +347,7 @@ static long double hexfloat(FILE *f, int bits, int emin, int sign, int pok)
else d = c-'0';
if (dc<8) {
x = x*16 + d;
- } else if (dc < LDBL_MANT_DIG/4+1) {
+ } else if (dc < (LDBL_MANT_DIG+3)/4+1) {
y += d*(scale/=16);
} else if (d && !gottail) {
y += 0.5*scale;
diff --git a/lib/libc/musl/src/math/aarch64/lround.c b/lib/libc/musl/src/math/aarch64/lround.c
deleted file mode 100644
index 85656c78d1c334a1618b2fa606670ae8e1038c5b..0000000000000000000000000000000000000000
--- a/lib/libc/musl/src/math/aarch64/lround.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include
-
-long lround(double x)
-{
- long n;
- __asm__ ("fcvtas %x0, %d1" : "=r"(n) : "w"(x));
- return n;
-}
diff --git a/lib/libc/musl/src/math/aarch64/lroundf.c b/lib/libc/musl/src/math/aarch64/lroundf.c
deleted file mode 100644
index 32e51f3cc3c738214bde60d0873532415cdd4acc..0000000000000000000000000000000000000000
--- a/lib/libc/musl/src/math/aarch64/lroundf.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include
-
-long lroundf(float x)
-{
- long n;
- __asm__ ("fcvtas %x0, %s1" : "=r"(n) : "w"(x));
- return n;
-}
diff --git a/lib/libc/musl/src/math/lround.c b/lib/libc/musl/src/math/lround.c
deleted file mode 100644
index b8b795470f1868d831e7c2893c7f3b7f019ddbdb..0000000000000000000000000000000000000000
--- a/lib/libc/musl/src/math/lround.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include
-
-long lround(double x)
-{
- return round(x);
-}
diff --git a/lib/libc/musl/src/math/lroundf.c b/lib/libc/musl/src/math/lroundf.c
deleted file mode 100644
index c4707e7db712cd545915efea603173e21efc709e..0000000000000000000000000000000000000000
--- a/lib/libc/musl/src/math/lroundf.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include
-
-long lroundf(float x)
-{
- return roundf(x);
-}
diff --git a/lib/libc/musl/src/math/lroundl.c b/lib/libc/musl/src/math/lroundl.c
deleted file mode 100644
index 094fdf6483842e90a9fac200394255d02bb8073d..0000000000000000000000000000000000000000
--- a/lib/libc/musl/src/math/lroundl.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include
-
-long lroundl(long double x)
-{
- return roundl(x);
-}
diff --git a/lib/libc/musl/src/math/powerpc64/lround.c b/lib/libc/musl/src/math/powerpc64/lround.c
deleted file mode 100644
index ee4d1143c33de9b15f09ba3d79b5704a4187d1a4..0000000000000000000000000000000000000000
--- a/lib/libc/musl/src/math/powerpc64/lround.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include
-
-#ifdef __VSX__
-
-long lround(double x)
-{
- long n;
- __asm__ (
- "xsrdpi %1, %1\n"
- "fctid %0, %1\n" : "=d"(n), "+d"(x));
- return n;
-}
-
-#else
-
-#include "../lround.c"
-
-#endif
diff --git a/lib/libc/musl/src/math/powerpc64/lroundf.c b/lib/libc/musl/src/math/powerpc64/lroundf.c
deleted file mode 100644
index 033094ffb2ccd645253b1a2b7338862af7455e54..0000000000000000000000000000000000000000
--- a/lib/libc/musl/src/math/powerpc64/lroundf.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include
-
-#ifdef __VSX__
-
-long lroundf(float x)
-{
- long n;
- __asm__ (
- "xsrdpi %1, %1\n"
- "fctid %0, %1\n" : "=d"(n), "+f"(x));
- return n;
-}
-
-#else
-
-#include "../lroundf.c"
-
-#endif
diff --git a/lib/libc/musl/src/thread/x32/clone.s b/lib/libc/musl/src/thread/x32/clone.s
index d713452676333d3e34ef9f004fcec4eebf2bcd6d..31e2ccabe61d5b9443cc08b9606ae26ca664bc5c 100644
--- a/lib/libc/musl/src/thread/x32/clone.s
+++ b/lib/libc/musl/src/thread/x32/clone.s
@@ -8,7 +8,7 @@ __clone:
mov %rdx,%rdi
mov %r8,%rdx
mov %r9,%r8
- mov 8(%rsp),%r10
+ mov 8(%rsp),%r10d
mov %r11,%r9
and $-16,%rsi
sub $8,%rsi
diff --git a/lib/libc/wasi/libc-top-half/musl/src/internal/floatscan.c b/lib/libc/wasi/libc-top-half/musl/src/internal/floatscan.c
index ec50fe0765046a04a8757bb7114f8ed530a6ed09..4cc6059f438e4368da315a13f12988f0ea1ec3f2 100644
--- a/lib/libc/wasi/libc-top-half/musl/src/internal/floatscan.c
+++ b/lib/libc/wasi/libc-top-half/musl/src/internal/floatscan.c
@@ -388,7 +388,7 @@ static long double hexfloat(FILE *f, int bits, int emin, int sign, int pok)
else d = c-'0';
if (dc<8) {
x = x*16 + d;
- } else if (dc < LDBL_MANT_DIG/4+1) {
+ } else if (dc < (LDBL_MANT_DIG+3)/4+1) {
y += d*(scale/=16);
} else if (d && !gottail) {
y += 0.5*scale;
diff --git a/lib/libcxx/include/__config b/lib/libcxx/include/__config
index de32af8f760e0f88f74b7ffa7554be2b7a9ae7f9..cc7a377334a83cbb34b8a997151b7e76b3810a9c 100644
--- a/lib/libcxx/include/__config
+++ b/lib/libcxx/include/__config
@@ -30,7 +30,7 @@
// _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM.
// Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 17.0.1 == 17.00.01), _LIBCPP_VERSION is
// defined to XXYYZZ.
-# define _LIBCPP_VERSION 220104
+# define _LIBCPP_VERSION 220108
# define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y
# define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y)
diff --git a/lib/libcxx/include/__tree b/lib/libcxx/include/__tree
index eb17f7d36936c819a89586da357c4957b57cb317..ddeb82f91b8ad587c15fa7d2af8b3bd3784379f8 100644
--- a/lib/libcxx/include/__tree
+++ b/lib/libcxx/include/__tree
@@ -2026,8 +2026,8 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(const_iterator __
template
template
_LIBCPP_HIDE_FROM_ABI _NodeHandle __tree<_Tp, _Compare, _Allocator>::__node_handle_extract(key_type const& __key) {
- iterator __it = find(__key);
- if (__it == end())
+ iterator __it = __lower_bound_multi(__key);
+ if (__it == end() || __value_comp_(__key, *__it))
return _NodeHandle();
return __node_handle_extract<_NodeHandle>(__it);
}
diff --git a/lib/libcxx/include/optional b/lib/libcxx/include/optional
index 12fbcdfa5c5d605ca01f0dedc64a0fc931b75176..4d85ac1e0ff5e800f9adf1e6aa8059b015e55713 100644
--- a/lib/libcxx/include/optional
+++ b/lib/libcxx/include/optional
@@ -828,6 +828,10 @@ private:
template
constexpr static bool __libcpp_opt_ref_ctor_deleted =
is_lvalue_reference_v<_Tp> && reference_constructs_from_temporary_v<_Tp, _Up>;
+
+ template
+ constexpr static bool __ref_ctor_enabled =
+ is_lvalue_reference_v<_Tp> && !reference_constructs_from_temporary_v<_Tp, _Up>;
# endif
// LWG2756: conditionally explicit conversion from _Up
@@ -935,7 +939,7 @@ public:
template ::template __enable_implicit<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v)
# if _LIBCPP_STD_VER >= 26
- noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, _Up&>)
+ noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, const _Up&>)
# endif
{
this->__construct_from(__v);
@@ -943,7 +947,7 @@ public:
template ::template __enable_explicit<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v)
# if _LIBCPP_STD_VER >= 26
- noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, _Up&>)
+ noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, const _Up&>)
# endif
{
this->__construct_from(__v);
@@ -981,25 +985,25 @@ public:
// optional(optional& rhs)
template
- requires(!__libcpp_opt_ref_ctor_deleted<_Up>) && (!is_same_v, optional<_Up>>) &&
- (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up&>
+ requires __ref_ctor_enabled<_Up&> && (!is_same_v, optional<_Up>>) && (!is_same_v<_Tp&, _Up>) &&
+ is_constructible_v<_Tp&, _Up&>
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up&, _Tp&>)
optional(optional<_Up>& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, _Up&>) {
this->__construct_from(__rhs);
}
template
- requires __libcpp_opt_ref_ctor_deleted<_Up> && (!is_same_v, optional<_Up>>) &&
+ requires __libcpp_opt_ref_ctor_deleted<_Up&> && (!is_same_v, optional<_Up>>) &&
(!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up&>
constexpr explicit optional(optional<_Up>& __rhs) noexcept = delete;
// optional(const optional&)
template ::template __enable_implicit<_Up>(), int> = 0>
- requires __libcpp_opt_ref_ctor_deleted<_Up>
+ requires __libcpp_opt_ref_ctor_deleted
optional(const optional<_Up>&) = delete;
template ::template __enable_explicit<_Up>(), int> = 0>
- requires __libcpp_opt_ref_ctor_deleted<_Up>
+ requires __libcpp_opt_ref_ctor_deleted
explicit optional(const optional<_Up>&) = delete;
// optional(optional&&)
@@ -1013,16 +1017,16 @@ public:
// optional(const optional&&)
template
- requires(!__libcpp_opt_ref_ctor_deleted<_Up>) && (!is_same_v, optional<_Up>>) &&
- (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up>
+ requires __ref_ctor_enabled && (!is_same_v, optional<_Up>>) &&
+ (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, const _Up>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!is_convertible_v)
optional(const optional<_Up>&& __v) noexcept(is_nothrow_constructible_v<_Tp&, const _Up>) {
this->__construct_from(std::move(__v));
}
template
- requires __libcpp_opt_ref_ctor_deleted<_Up> && (!is_same_v, optional<_Up>>) &&
- (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up>
+ requires __libcpp_opt_ref_ctor_deleted && (!is_same_v, optional<_Up>>) &&
+ (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, const _Up>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>&& __v) noexcept = delete;
# endif
diff --git a/lib/lldb/pretty_printers.py b/lib/lldb/pretty_printers.py
index 553c7672fb278e0b2b1e43f4565f02c4181ac049..222484e5b4ab55fe45e8ab03ddb85f894850bb51 100644
--- a/lib/lldb/pretty_printers.py
+++ b/lib/lldb/pretty_printers.py
@@ -707,7 +707,7 @@ def root_InternPool_Index_SummaryProvider(value, _=None):
return re.sub(
expr_path_re,
lambda matchobj: getattr(unwrapped.GetValueForExpressionPath(matchobj[1]), matchobj[2]).strip(matchobj[3] or ''),
- summary.summary.removeprefix('.').removeprefix('@"').removesuffix('"').replace(r'\"', '"'),
+ summary.value.removeprefix('.').removeprefix('@"').removesuffix('"').replace(r'\"', '"'),
)
class root_InternPool_Index_SynthProvider:
@@ -773,7 +773,7 @@ class root_InternPool_Index_Unwrapped_SynthProvider:
trailing_type = encoding_trailing.GetValueAsType()
trailing_bytes, trailing_data = bytearray(trailing_type.size), lldb.SBData()
def eval_config(config_name):
- expr = encoding_config.GetChildMemberWithName(config_name).summary.removeprefix('.').removeprefix('@"').removesuffix('"').replace(r'\"', '"')
+ expr = encoding_config.GetChildMemberWithName(config_name).value.removeprefix('.').removeprefix('@"').removesuffix('"').replace(r'\"', '"')
if 'payload.' in expr:
return self.payload.EvaluateExpression(expr.replace('payload.', '@this().'))
elif expr.startswith('trailing.'):
@@ -848,7 +848,8 @@ def root_InternPool_String_SummaryProvider(value, _=None):
if local_value is None:
wrapped = 0
local_value = locals_value.child[0]
- string = local_value.GetChildMemberWithName('shared').GetChildMemberWithName('strings').GetChildMemberWithName('view').GetChildMemberWithName('0').child[wrapped & (1 << tid_shift_32) - 1].address_of
+ shared = local_value.GetChildMemberWithName('shared')
+ string = shared.GetChildMemberWithName('string_bytes').GetChildMemberWithName('view').GetChildMemberWithName('0').child[shared.GetChildMemberWithName('strings').GetChildMemberWithName('view').GetChildMemberWithName('0').child[wrapped & (1 << tid_shift_32) - 1].unsigned].address_of
string.format = lldb.eFormatCString
return string.value
@@ -878,13 +879,13 @@ class root_InternPool_Nav_Index_SynthProvider:
wrapped = self.value.unsigned
if wrapped == (1 << 32) - 1: return
ip = self.value.CreateValueFromType(self.value.type).GetChildMemberWithName('debug_state').GetChildMemberWithName('intern_pool').GetNonSyntheticValue().GetChildMemberWithName('?')
- tid_shift_32 = ip.GetChildMemberWithName('tid_shift_32').unsigned
+ tid_shift_30 = ip.GetChildMemberWithName('tid_shift_30').unsigned
locals_value = ip.GetChildMemberWithName('locals').GetSyntheticValue()
- local_value = locals_value.child[wrapped >> tid_shift_32]
+ local_value = locals_value.child[wrapped >> tid_shift_30]
if local_value is None:
wrapped = 0
local_value = locals_value.child[0]
- self.nav = local_value.GetChildMemberWithName('shared').GetChildMemberWithName('navs').GetChildMemberWithName('view').child[wrapped & (1 << tid_shift_32) - 1]
+ self.nav = local_value.GetChildMemberWithName('shared').GetChildMemberWithName('navs').GetChildMemberWithName('view').child[wrapped & (1 << tid_shift_30) - 1]
def has_children(self): return False if self.nav is None else self.nav.GetNumChildren(1) > 0
def num_children(self): return 0 if self.nav is None else self.nav.GetNumChildren()
def get_child_index(self, name): return -1 if self.nav is None else self.nav.GetIndexOfChildWithName(name)
diff --git a/lib/std/Build.zig b/lib/std/Build.zig
index c5bf7d889dbae2ab9a7a8a4d00c2ec1ce74b09ec..a3bf69604e4ec7e68847e6caced7ed91fbbcf269 100644
--- a/lib/std/Build.zig
+++ b/lib/std/Build.zig
@@ -33,7 +33,7 @@ user_input_options: UserInputOptionsMap,
available_options_map: std.array_hash_map.String(AvailableOption) = .empty,
invalid_user_input: bool,
default_step: *Step,
-top_level_steps: std.StringArrayHashMapUnmanaged(*Step.TopLevel),
+top_level_steps: std.array_hash_map.String(*Step.TopLevel),
/// Path to the directory containing build.zig.
root: Cache.Path,
debug_log_scopes: []const []const u8 = &.{},
@@ -78,11 +78,11 @@ pub const Graph = struct {
io: Io,
/// Process lifetime.
arena: Allocator,
- system_integration_options: std.StringArrayHashMapUnmanaged(SystemLibraryMode) = .empty,
+ system_integration_options: std.array_hash_map.String(SystemLibraryMode) = .empty,
system_package_mode: bool = false,
zig_exe: []const u8,
environ_map: process.Environ.Map,
- needed_lazy_dependencies: std.StringArrayHashMapUnmanaged(void) = .empty,
+ needed_lazy_dependencies: std.array_hash_map.String(void) = .empty,
/// Information about the native target. Computed before build() is invoked.
host: ResolvedTarget,
dependency_cache: InitializedDepMap = .empty,
@@ -898,17 +898,7 @@ pub fn addRunArtifact(b: *Build, exe: *Step.Compile) *Step.Run {
const run_step = Step.Run.create(b, step_name);
run_step.producer = exe;
if (exe.kind == .@"test") {
- if (exe.exec_cmd_args) |exec_cmd_args| {
- for (exec_cmd_args) |cmd_arg| {
- if (cmd_arg) |arg| {
- run_step.addArg(arg);
- } else {
- run_step.addArtifactArg(exe);
- }
- }
- } else {
- run_step.addArtifactArg(exe);
- }
+ run_step.addArtifactArg(exe);
const test_server_mode: bool = s: {
if (exe.test_runner) |r| break :s r.mode == .server;
@@ -1836,10 +1826,14 @@ fn tryFindProgram(b: *Build, full_path: []const u8) ?[]const u8 {
if (b.graph.environ_map.get("PATHEXT")) |PATHEXT| {
var it = mem.tokenizeScalar(u8, PATHEXT, fs.path.delimiter);
+ const extended_path_buf = arena.alloc(u8, full_path.len + 1 + std.process.WindowsExtension.max_len) catch @panic("OOM");
+ @memcpy(extended_path_buf[0..full_path.len], full_path);
+
while (it.next()) |ext| {
if (!supportedWindowsProgramExtension(ext)) continue;
- const extended_path = try mem.concat(arena, &.{ full_path, ext });
+ @memcpy(extended_path_buf[full_path.len..][0..ext.len], ext);
+ const extended_path = extended_path_buf[0 .. full_path.len + ext.len];
if (Io.Dir.cwd().access(io, extended_path, .{ .execute = true })) |_| {
return extended_path;
@@ -2563,6 +2557,16 @@ pub const LazyPath = union(enum) {
return dupeInner(lazy_path, graph.arena);
}
+ /// Copies the slice of paths and all internal strings.
+ ///
+ /// The `graph` parameter is only used for the global arena allocator.
+ pub fn dupeList(lazy_paths: []const LazyPath, graph: *const Graph) []const LazyPath {
+ const arena = graph.arena;
+ const result = graph.alloc(LazyPath, lazy_paths.len);
+ for (result, lazy_paths) |*d, s| d.* = dupeInner(s, arena);
+ return result;
+ }
+
fn dupeInner(lazy_path: LazyPath, arena: Allocator) LazyPath {
return switch (lazy_path) {
.src_path => |sp| .{ .src_path = .{ .owner = sp.owner, .sub_path = sp.owner.dupePath(sp.sub_path) } },
@@ -2707,4 +2711,6 @@ pub fn systemIntegrationOption(
test {
_ = Cache;
_ = Step;
+ _ = Configuration;
+ _ = &findProgram;
}
diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig
index fe40251590f090d567744bcddd3451f62e52eac7..33c3148dd22080b5916100f4c3e210dabe38e14d 100644
--- a/lib/std/Build/Cache.zig
+++ b/lib/std/Build/Cache.zig
@@ -351,7 +351,7 @@ pub const Manifest = struct {
};
};
- pub const Files = std.ArrayHashMapUnmanaged(File, void, FilesContext, false);
+ pub const Files = std.array_hash_map.Custom(File, void, FilesContext, false);
pub const FilesContext = struct {
pub fn hash(fc: FilesContext, file: File) u32 {
diff --git a/lib/std/Build/Configuration.zig b/lib/std/Build/Configuration.zig
index d01ad0c89785c79c3d42d185cf371dd0bd7ec38f..12746e4498f76b745898559660dfb03c4722c233 100644
--- a/lib/std/Build/Configuration.zig
+++ b/lib/std/Build/Configuration.zig
@@ -1,10 +1,12 @@
const Configuration = @This();
const std = @import("../std.zig");
+const builtin = @import("builtin");
const Io = std.Io;
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
const max_u32 = std.math.maxInt(u32);
+const native_endian = builtin.target.cpu.arch.endian();
string_bytes: []u8,
steps: []Step,
@@ -569,6 +571,8 @@ pub const Step = extern struct {
flags2: Flags2,
args: Storage.LengthPrefixedList(Arg.Index),
cwd: Storage.FlagOptional(.flags, .cwd, LazyPath.Index),
+ preopen_names: Storage.LengthPrefixedList(String),
+ preopen_paths: Storage.LengthPrefixedList(LazyPath.Index),
captured_stdout: Storage.FlagOptional(.flags, .captured_stdout, CapturedStream),
captured_stderr: Storage.FlagOptional(.flags, .captured_stderr, CapturedStream),
file_inputs: Storage.LengthPrefixedList(LazyPath.Index),
@@ -583,6 +587,8 @@ pub const Step = extern struct {
expect_stderr_match: Storage.FlagLengthPrefixedList(.flags2, .expect_stderr_match, Bytes),
expect_stdout_match: Storage.FlagLengthPrefixedList(.flags2, .expect_stdout_match, Bytes),
expect_term_value: Storage.FlagOptional(.flags2, .expect_term, u32),
+ expect_stdout_snapshot: Storage.FlagOptional(.flags2, .expect_stdout_snapshot, LazyPath.Index),
+ expect_stderr_snapshot: Storage.FlagOptional(.flags2, .expect_stderr_snapshot, LazyPath.Index),
pub const CapturedStream = extern struct {
generated_file: GeneratedFileIndex,
@@ -608,7 +614,8 @@ pub const Step = extern struct {
producer: bool,
generated: bool,
dep_file: bool,
- _: u21 = 0,
+ make_absolute: bool,
+ _: u20 = 0,
};
pub const Tag = enum(u4) {
@@ -681,7 +688,9 @@ pub const Step = extern struct {
expect_stdout_match: bool,
expect_term: bool,
expect_term_status: ExpectTermStatus,
- _: u25 = 0,
+ expect_stdout_snapshot: bool,
+ expect_stderr_snapshot: bool,
+ _: u23 = 0,
};
};
@@ -695,7 +704,6 @@ pub const Step = extern struct {
root_name: String,
filters: Storage.FlagLengthPrefixedList(.flags, .filters_len, String),
- exec_cmd_args: Storage.FlagLengthPrefixedList(.flags, .exec_cmd_args_len, OptionalString),
installed_headers: Storage.FlagLengthPrefixedList(.flags, .installed_headers_len, Storage.Extended(InstalledHeader.Flags, InstalledHeader)),
force_undefined_symbols: Storage.FlagLengthPrefixedList(.flags, .force_undefined_symbols_len, String),
expect_errors: Storage.FlagUnion(.flags4, .expect_errors, ExpectErrors),
@@ -924,7 +932,6 @@ pub const Step = extern struct {
tag: Tag = .compile,
filters_len: bool,
- exec_cmd_args_len: bool,
installed_headers_len: bool,
force_undefined_symbols_len: bool,
@@ -951,6 +958,7 @@ pub const Step = extern struct {
force_load_objc: bool,
discard_local_symbols: bool,
mingw_unicode_entry_point: bool,
+ _: u1 = 0,
};
pub const Flags2 = packed struct(u32) {
@@ -1016,7 +1024,8 @@ pub const Step = extern struct {
generated_llvm_bc: bool,
generated_llvm_ir: bool,
generated_h: bool,
- _: u9 = 0,
+ incremental: DefaultingBool,
+ _: u7 = 0,
};
pub fn isDynamicLibrary(compile: *const Compile) bool {
@@ -2268,6 +2277,8 @@ pub const TargetQuery = struct {
gnux32,
eabi,
eabihf,
+ abin32,
+ x32,
ilp32,
android,
androideabi,
@@ -2301,6 +2312,8 @@ pub const TargetQuery = struct {
.gnux32 => .gnux32,
.eabi => .eabi,
.eabihf => .eabihf,
+ .abin32 => .abin32,
+ .x32 => .x32,
.ilp32 => .ilp32,
.android => .android,
.androideabi => .androideabi,
@@ -2334,6 +2347,8 @@ pub const TargetQuery = struct {
.gnux32 => .gnux32,
.eabi => .eabi,
.eabihf => .eabihf,
+ .abin32 => .abin32,
+ .x32 => .x32,
.ilp32 => .ilp32,
.android => .android,
.androideabi => .androideabi,
@@ -2581,6 +2596,8 @@ pub const TargetQuery = struct {
windows,
uefi,
@"3ds",
+ wiiu,
+ psx,
ps3,
ps4,
ps5,
@@ -2629,6 +2646,8 @@ pub const TargetQuery = struct {
.windows => .windows,
.uefi => .uefi,
.@"3ds" => .@"3ds",
+ .wiiu => .wiiu,
+ .psx => .psx,
.ps3 => .ps3,
.ps4 => .ps4,
.ps5 => .ps5,
@@ -2677,6 +2696,8 @@ pub const TargetQuery = struct {
.windows => .windows,
.uefi => .uefi,
.@"3ds" => .@"3ds",
+ .wiiu => .wiiu,
+ .psx => .psx,
.ps3 => .ps3,
.ps4 => .ps4,
.ps5 => .ps5,
@@ -3199,7 +3220,8 @@ pub const Storage = enum {
.@"extern" => {
const n = @divExact(@sizeOf(Field), @sizeOf(u32));
defer i.* += n;
- return @bitCast(buffer[i.*..][0..n].*);
+ const ptr: *align(@alignOf(u32)) const Field = @ptrCast(buffer[i.*..][0..n]);
+ return ptr.*;
},
},
else => comptime unreachable,
@@ -3365,7 +3387,8 @@ pub const Storage = enum {
},
.@"extern" => {
const n = @divExact(@sizeOf(Field), @sizeOf(u32));
- buffer[i..][0..n].* = @bitCast(value);
+ const ptr: *align(@alignOf(Field)) const [n]u32 = @ptrCast(&value);
+ buffer[i..][0..n].* = ptr.*;
return n;
},
},
@@ -3433,18 +3456,46 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
return result;
}
+/// Loads bits using native endianness when `value` spans multiple bytes.
+/// On big endian architectures, `bit_offset` uses MSb 0 bit numbering.
+/// On little endian architectures, `bit_offset` uses LSb 0 bit numbering.
+/// See `storeBits`.
pub fn loadBits(comptime Int: type, buffer: []const Int, bit_offset: usize, comptime Result: type) Result {
const index = bit_offset / @bitSizeOf(Int);
const small_bit_offset = bit_offset % @bitSizeOf(Int);
const ResultInt = @Int(.unsigned, @bitSizeOf(Result));
- const result: ResultInt = @truncate(buffer[index] >> @intCast(small_bit_offset));
- const available_bits = @bitSizeOf(Int) - small_bit_offset;
- if (available_bits >= @bitSizeOf(ResultInt)) return @bitCast(result);
- const missing_bits = @bitSizeOf(ResultInt) - available_bits;
- const upper: ResultInt = @truncate(buffer[index + 1] & ((@as(usize, 1) << @intCast(missing_bits)) - 1));
- return @bitCast(result | (upper << @intCast(available_bits)));
+ switch (native_endian) {
+ .little => {
+ const result: ResultInt = @truncate(buffer[index] >> @intCast(small_bit_offset));
+ const available_bits = @bitSizeOf(Int) - small_bit_offset;
+ if (available_bits >= @bitSizeOf(ResultInt)) return @bitCast(result);
+ const missing_bits = @bitSizeOf(ResultInt) - available_bits;
+ const upper: ResultInt = @truncate(buffer[index + 1] & ((@as(usize, 1) << @intCast(missing_bits)) - 1));
+ return @bitCast(result | (upper << @intCast(available_bits)));
+ },
+ .big => {
+ const available_bits = @bitSizeOf(Int) - small_bit_offset;
+ if (available_bits >= @bitSizeOf(ResultInt)) {
+ const shift = available_bits - @bitSizeOf(ResultInt);
+ const result: ResultInt = @truncate(buffer[index] >> @intCast(shift));
+ return @bitCast(result);
+ }
+ const mask = (@as(Int, 1) << @intCast(available_bits)) - 1;
+ const result: ResultInt = @intCast(buffer[index] & mask);
+ const missing_bits = @bitSizeOf(ResultInt) - available_bits;
+ const lower: ResultInt = @truncate(buffer[index + 1] >> @intCast(@bitSizeOf(Int) - missing_bits));
+ return @bitCast((result << @intCast(missing_bits)) | lower);
+ },
+ }
}
+/// Store bits using native endianness when `value` spans multiple bytes.
+/// On big endian architectures:
+/// - For a given value, the bits of an earlier byte are more significant than the bits of subsequent bytes.
+/// - `bit_offset` uses MSb 0 bit numbering.
+/// On little endian architectures:
+/// - For a given value, the bits of an earlier byte are less significant than the bits of subsequent bytes.
+/// - `bit_offset` uses LSb 0 bit numbering.
pub fn storeBits(comptime Int: type, buffer: []Int, bit_offset: usize, value: anytype) void {
const Value = @TypeOf(value);
const ValueInt = @Int(.unsigned, @bitSizeOf(Value));
@@ -3453,27 +3504,70 @@ pub fn storeBits(comptime Int: type, buffer: []Int, bit_offset: usize, value: an
const small_bit_offset = bit_offset % @bitSizeOf(Int);
const available_bits = @bitSizeOf(Int) - small_bit_offset;
if (available_bits >= @bitSizeOf(ValueInt)) {
- buffer[index] &= ~(((@as(Int, 1) << @intCast(@bitSizeOf(Value))) - 1) << @intCast(small_bit_offset));
- buffer[index] |= @as(Int, value_int) << @intCast(small_bit_offset);
+ const shift = switch (native_endian) {
+ .little => small_bit_offset,
+ .big => available_bits - @bitSizeOf(ValueInt),
+ };
+ buffer[index] &= ~(((@as(Int, 1) << @intCast(@bitSizeOf(Value))) - 1) << @intCast(shift));
+ buffer[index] |= @as(Int, value_int) << @intCast(shift);
} else {
const DoubleInt = @Int(.unsigned, @bitSizeOf(Int) * 2);
+ const shift = switch (native_endian) {
+ .little => small_bit_offset,
+ .big => @bitSizeOf(DoubleInt) - small_bit_offset - @bitSizeOf(ValueInt),
+ };
const ptr: *align(@alignOf(Int)) DoubleInt = @ptrCast(buffer[index..][0..2]);
- ptr.* &= ~(((@as(DoubleInt, 1) << @intCast(@bitSizeOf(Value))) - 1) << @intCast(small_bit_offset));
- ptr.* |= @as(DoubleInt, value_int) << @intCast(small_bit_offset);
+ ptr.* &= ~(((@as(DoubleInt, 1) << @intCast(@bitSizeOf(Value))) - 1) << @intCast(shift));
+ ptr.* |= @as(DoubleInt, value_int) << @intCast(shift);
}
}
test "loadBits and storeBits" {
- var buffer: [2]u32 = .{
- 0b01111111000000001111111100000000,
- 0b11111111000000001111111100000100,
+ var buffer: [2]u32 = switch (native_endian) {
+ .little => .{
+ //──┐ 0b100011 (end) ┌─┐ 0b100
+ 0b01111111000000001111111100000000,
+ // n <── bit offset 0 ┘
+ // ┌── 0b100011 (start)
+ 0b11111111000000001111111100000100,
+ },
+ .big => .{
+ // ┌─┐ 0b100 ┌── 0b100011 (start)
+ 0b11111110000000001111111100000100,
+ //└ bit offset 0 ──> n
+ //──┐ 0b100011 (end)
+ 0b01111111000000001111111100000000,
+ },
};
+
try std.testing.expectEqual(0b100, loadBits(u32, &buffer, 6, u3));
try std.testing.expectEqual(0b100011, loadBits(u32, &buffer, 29, u6));
+ storeBits(u32, &buffer, 0, @as(u1, 0b0));
storeBits(u32, &buffer, 6, @as(u3, 0b010));
- storeBits(u32, &buffer, 29, @as(u6, 0b010010));
+ storeBits(u32, &buffer, 29, @as(u6, 0b010110));
+ storeBits(u32, &buffer, 40, @as(u17, 0b01110110011111110));
+ try std.testing.expectEqual(0b0, loadBits(u32, &buffer, 0, u1));
try std.testing.expectEqual(0b010, loadBits(u32, &buffer, 6, u3));
- try std.testing.expectEqual(0b010010, loadBits(u32, &buffer, 29, u6));
+ try std.testing.expectEqual(0b010110, loadBits(u32, &buffer, 29, u6));
+ try std.testing.expectEqual(0b01110110011111110, loadBits(u32, &buffer, 40, u17));
+
+ // Test roundtripping of size/offset combinations
+ inline for (1..32) |value_size| {
+ for (0..64) |bit_offset| {
+ if (value_size + bit_offset > @bitSizeOf(@TypeOf(buffer))) continue;
+
+ buffer = .{ 0, 0 };
+
+ const Value = @Int(.unsigned, value_size);
+ const value: Value = @intCast((@as(u32, 1) << @intCast(@bitSizeOf(Value))) - 1);
+ storeBits(u32, &buffer, bit_offset, value);
+ std.testing.expectEqual(value, loadBits(u32, &buffer, bit_offset, Value)) catch |err| {
+ std.debug.print("value size: {} bit offset: {}\n", .{ value_size, bit_offset });
+ std.debug.print("buffer: {b:0>32} {b:0>32}\n", .{ buffer[0], buffer[1] });
+ return err;
+ };
+ }
+ }
}
diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig
index 35a07f1eb88b911f2a0303ee556de7de1bb43e93..f8996ccad050ea9b542a6f37b470a9c33ceb335d 100644
--- a/lib/std/Build/Module.zig
+++ b/lib/std/Build/Module.zig
@@ -12,7 +12,7 @@ root_source_file: ?LazyPath,
/// The modules that are mapped into this module's import table.
/// Use `addImport` rather than modifying this field directly in order to
/// maintain step dependency edges.
-import_table: std.StringArrayHashMapUnmanaged(*Module),
+import_table: std.array_hash_map.String(*Module),
resolved_target: ?std.Build.ResolvedTarget = null,
optimize: ?std.builtin.OptimizeMode = null,
@@ -22,7 +22,7 @@ c_macros: ArrayList([]const u8),
include_dirs: ArrayList(IncludeDir),
lib_paths: ArrayList(LazyPath),
rpaths: ArrayList(RPath),
-frameworks: std.StringArrayHashMapUnmanaged(LinkFrameworkOptions),
+frameworks: std.array_hash_map.String(LinkFrameworkOptions),
link_objects: ArrayList(LinkObject),
strip: ?bool,
@@ -146,13 +146,10 @@ pub const RcSourceFile = struct {
include_paths: []const LazyPath = &.{},
pub fn dupe(file: RcSourceFile, graph: *const std.Build.Graph) RcSourceFile {
- const arena = graph.arena;
- const include_paths = arena.alloc(LazyPath, file.include_paths.len) catch @panic("OOM");
- for (include_paths, file.include_paths) |*dest, lazy_path| dest.* = lazy_path.dupe(graph);
return .{
.file = file.file.dupe(graph),
.flags = graph.dupeStrings(file.flags),
- .include_paths = include_paths,
+ .include_paths = LazyPath.dupeList(file.include_paths, graph),
};
}
};
@@ -563,7 +560,7 @@ pub fn getGraph(root: *Module) Graph {
const arena = root.owner.graph.arena;
- var modules: std.AutoArrayHashMapUnmanaged(*std.Build.Module, []const u8) = .empty;
+ var modules: std.array_hash_map.Auto(*std.Build.Module, []const u8) = .empty;
var next_idx: usize = 0;
modules.putNoClobber(arena, root, "root") catch @panic("OOM");
diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig
index 5de789c8b2a7b762601c73a2b16a1598338e37c4..4fd3cc4b8098fdbc6ebd4571dfd395c5f6b0b195 100644
--- a/lib/std/Build/Step/Compile.zig
+++ b/lib/std/Build/Step/Compile.zig
@@ -51,7 +51,6 @@ shared_memory: bool = false,
global_base: ?u64 = null,
/// Set via options; intended to be read-only after that.
zig_lib_dir: ?LazyPath,
-exec_cmd_args: ?[]const ?[]const u8,
filters: []const []const u8,
test_runner: ?TestRunner,
wasi_exec_model: ?std.builtin.WasiExecModel = null,
@@ -187,7 +186,7 @@ entry: Entry = .default,
/// List of symbols forced as undefined in the symbol table
/// thus forcing their resolution by the linker.
/// Corresponds to `-u ` for ELF/MachO and `/include:` for COFF/PE.
-force_undefined_symbols: std.StringArrayHashMapUnmanaged(void),
+force_undefined_symbols: std.array_hash_map.String(void),
/// Overrides the default stack size
stack_size: ?u64 = null,
@@ -234,6 +233,12 @@ is_linking_libcpp: bool = false,
/// builtin fuzzer, see the `fuzz` flag in `Module`.
sanitize_coverage_trace_pc_guard: ?bool = null,
+/// Enable or disable incremental compilation.
+///
+/// Incremental compilation reduces compile time by mutating an existing build artifact. Non-
+/// incremental compilation is slower but preserves previous build artifacts.
+incremental: ?bool = null,
+
emit_directory: Configuration.OptionalGeneratedFileIndex = .none,
generated_docs: Configuration.OptionalGeneratedFileIndex = .none,
generated_asm: Configuration.OptionalGeneratedFileIndex = .none,
@@ -413,7 +418,6 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
.out_filename = out_filename,
.installed_headers = .empty,
.zig_lib_dir = null,
- .exec_cmd_args = null,
.filters = options.filters,
.test_runner = null, // set below
.rdynamic = false,
@@ -730,17 +734,6 @@ pub fn getEmittedLlvmBc(compile: *Compile) LazyPath {
return compile.getEmittedFileGeneric(&compile.generated_llvm_bc);
}
-pub fn setExecCmd(compile: *Compile, args: []const ?[]const u8) void {
- const graph = compile.step.owner.graph;
- const arena = graph.arena;
- assert(compile.kind == .@"test");
- const duped_args = arena.alloc(?[]const u8, args.len) catch @panic("OOM");
- for (args, 0..) |arg, i| {
- duped_args[i] = if (arg) |a| graph.dupeString(a) else null;
- }
- compile.exec_cmd_args = duped_args;
-}
-
pub fn rootModuleTarget(c: *Compile) std.Target {
// The root module is always given a target, so we know this to be non-null.
return c.root_module.resolved_target.?.result;
@@ -753,7 +746,7 @@ pub fn rootModuleTarget(c: *Compile) std.Target {
pub fn getCompileDependencies(start: *Compile, chase_dynamic: bool) []const *Compile {
const arena = start.step.owner.graph.arena;
- var compiles: std.AutoArrayHashMapUnmanaged(*Compile, void) = .empty;
+ var compiles: std.array_hash_map.Auto(*Compile, void) = .empty;
var next_idx: usize = 0;
compiles.putNoClobber(arena, start, {}) catch @panic("OOM");
diff --git a/lib/std/Build/Step/Fmt.zig b/lib/std/Build/Step/Fmt.zig
index 294afdb9af1c23b1500598afe3f1c4bbc68080a7..4052e21bd08c0c43e66f4e1bae94991f5fcc6b00 100644
--- a/lib/std/Build/Step/Fmt.zig
+++ b/lib/std/Build/Step/Fmt.zig
@@ -34,8 +34,8 @@ pub fn create(owner: *std.Build, options: Options) *Fmt {
.name = if (options.check) "zig fmt --check" else "zig fmt",
.owner = owner,
}),
- .paths = options.paths,
- .exclude_paths = options.exclude_paths,
+ .paths = LazyPath.dupeList(options.paths, graph),
+ .exclude_paths = LazyPath.dupeList(options.exclude_paths, graph),
.check = options.check,
};
diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig
index 4ace7803225ea6e14caf26bf6769bf4a061567a0..a0fc19f5dc8dc33d5f2ee870bd6210c0172d1bd4 100644
--- a/lib/std/Build/Step/Run.zig
+++ b/lib/std/Build/Step/Run.zig
@@ -26,6 +26,10 @@ cwd: ?Build.LazyPath,
/// Override this field to modify the environment, or use setEnvironmentVariable
environ_map: ?*EnvMap,
+/// Named files that will be provided to the parent process.
+/// See `std.process.Preopens`.
+preopens: std.array_hash_map.String(Build.LazyPath),
+
/// Controls the `NO_COLOR` and `CLICOLOR_FORCE` environment variables.
color: Color = .auto,
@@ -129,14 +133,16 @@ pub const StdIo = union(enum) {
expect_stdout_exact: []const u8,
expect_stdout_match: []const u8,
expect_term: process.Child.Term,
+ expect_stderr_snapshot: std.Build.LazyPath,
+ expect_stdout_snapshot: std.Build.LazyPath,
};
};
pub const Arg = union(enum) {
- artifact: PrefixedArtifact,
- lazy_path: PrefixedLazyPath,
+ artifact: DecoratedArtifact,
+ lazy_path: DecoratedLazyPath,
decorated_directory: DecoratedLazyPath,
- file_content: PrefixedLazyPath,
+ file_content: DecoratedFileContent,
bytes: []const u8,
output_file: *Output,
output_file_dep: *Output,
@@ -145,30 +151,38 @@ pub const Arg = union(enum) {
passthru,
};
-pub const PrefixedArtifact = struct {
+pub const DecoratedArtifact = struct {
prefix: []const u8,
+ suffix: []const u8,
artifact: *Step.Compile,
-};
-
-pub const PrefixedLazyPath = struct {
- prefix: []const u8,
- lazy_path: std.Build.LazyPath,
+ make_absolute: bool,
};
pub const DecoratedLazyPath = struct {
prefix: []const u8,
lazy_path: std.Build.LazyPath,
suffix: []const u8,
+ make_absolute: bool,
+};
+
+pub const DecoratedFileContent = struct {
+ prefix: []const u8,
+ lazy_path: std.Build.LazyPath,
+ suffix: []const u8,
};
pub const Output = struct {
generated_file: Configuration.GeneratedFileIndex,
prefix: []const u8,
basename: []const u8,
+ suffix: []const u8,
+ make_absolute: bool,
};
pub const CapturedStdIo = struct {
- output: Output,
+ generated_file: Configuration.GeneratedFileIndex,
+ prefix: []const u8,
+ basename: []const u8,
trim_whitespace: TrimWhitespace,
pub const Options = struct {
@@ -192,6 +206,7 @@ pub fn create(owner: *std.Build, name: []const u8) *Run {
.argv = .empty,
.cwd = null,
.environ_map = null,
+ .preopens = .empty,
.disable_zig_progress = false,
.stdio = .infer_from_args,
.stdin = .none,
@@ -219,17 +234,38 @@ pub fn enableTestRunnerMode(run: *Run) void {
run.test_runner_mode = true;
}
+pub const ArgOptions = struct {
+ prefix: []const u8 = "",
+ suffix: []const u8 = "",
+};
+
+pub const PathArgOptions = struct {
+ prefix: []const u8 = "",
+ suffix: []const u8 = "",
+ /// Makes the path absolute before passing it to the child process. Not supported by all hosts,
+ /// prefer accepting relative paths when possible.
+ make_absolute: bool = false,
+};
+
+/// Deprecated, use `addArtifactArg2`.
pub fn addArtifactArg(run: *Run, artifact: *Step.Compile) void {
- run.addPrefixedArtifactArg("", artifact);
+ run.addArtifactArg2(artifact, .{});
}
+/// Deprecated, use `addArtifactArg2`.
pub fn addPrefixedArtifactArg(run: *Run, prefix: []const u8, artifact: *Step.Compile) void {
+ run.addArtifactArg2(artifact, .{ .prefix = prefix });
+}
+
+pub fn addArtifactArg2(run: *Run, artifact: *Step.Compile, options: PathArgOptions) void {
const graph = run.step.owner.graph;
const arena = graph.arena;
- const prefixed_artifact: PrefixedArtifact = .{
- .prefix = graph.dupeString(prefix),
+ const prefixed_artifact: DecoratedArtifact = .{
+ .prefix = graph.dupeString(options.prefix),
.artifact = artifact,
+ .suffix = graph.dupeString(options.suffix),
+ .make_absolute = options.make_absolute,
};
run.argv.append(arena, .{ .artifact = prefixed_artifact }) catch @panic("OOM");
@@ -237,19 +273,18 @@ pub fn addPrefixedArtifactArg(run: *Run, prefix: []const u8, artifact: *Step.Com
bin_file.addStepDependencies(&run.step);
}
-/// Provides a file path as a command line argument to the command being run.
-///
-/// Returns a `std.Build.LazyPath` which can be used as inputs to other APIs
-/// throughout the build system.
-///
-/// `sub_path` is the name of the generated output file which may have zero or
-/// more path components.
-///
-/// Related:
-/// * `addPrefixedOutputFileArg` - same thing but prepends a string to the argument
-/// * `addFileArg` - for input files given to the child process
+/// Deprecated, use `addOutputFileArg2`.
pub fn addOutputFileArg(run: *Run, sub_path: []const u8) std.Build.LazyPath {
- return run.addPrefixedOutputFileArg("", sub_path);
+ return run.addOutputFileArg2(sub_path, .{});
+}
+
+/// Deprecated, use `addOutputFileArg2`.
+pub fn addPrefixedOutputFileArg(
+ run: *Run,
+ prefix: []const u8,
+ sub_path: []const u8,
+) std.Build.LazyPath {
+ return run.addOutputFileArg2(sub_path, .{ .prefix = prefix });
}
/// Provides a file path as a command line argument to the command being run.
@@ -264,16 +299,15 @@ pub fn addOutputFileArg(run: *Run, sub_path: []const u8) std.Build.LazyPath {
/// throughout the build system.
///
/// Related:
-/// * `addOutputFileArg` - same thing but without the prefix
/// * `addFileArg` - for input files given to the child process
-pub fn addPrefixedOutputFileArg(
+pub fn addOutputFileArg2(
run: *Run,
- prefix: []const u8,
/// The name of the generated output file which may have zero or more path
/// components.
///
/// Asserted to be non-empty.
sub_path: []const u8,
+ options: PathArgOptions,
) std.Build.LazyPath {
const b = run.step.owner;
const graph = b.graph;
@@ -282,9 +316,11 @@ pub fn addPrefixedOutputFileArg(
const output = graph.create(Output);
output.* = .{
- .prefix = graph.dupeString(prefix),
+ .prefix = graph.dupeString(options.prefix),
.basename = graph.dupeString(sub_path),
+ .suffix = graph.dupeString(options.suffix),
.generated_file = graph.addGeneratedFile(&run.step),
+ .make_absolute = options.make_absolute,
};
run.argv.append(arena, .{ .output_file = output }) catch @panic("OOM");
@@ -295,17 +331,14 @@ pub fn addPrefixedOutputFileArg(
return .{ .generated = .{ .index = output.generated_file } };
}
-/// Appends an input file to the command line arguments.
-///
-/// The child process will see a file path. Modifications to this file will be
-/// detected as a cache miss in subsequent builds, causing the child process to
-/// be re-executed.
-///
-/// Related:
-/// * `addPrefixedFileArg` - same thing but prepends a string to the argument
-/// * `addOutputFileArg` - for files generated by the child process
+/// See `addFileArg2`.
pub fn addFileArg(run: *Run, lp: std.Build.LazyPath) void {
- run.addPrefixedFileArg("", lp);
+ run.addFileArg2(lp, .{});
+}
+
+/// See `addFileArg2`.
+pub fn addPrefixedFileArg(run: *Run, prefix: []const u8, lp: std.Build.LazyPath) void {
+ run.addFileArg2(lp, .{ .prefix = prefix });
}
/// Appends an input file to the command line arguments prepended with a string.
@@ -318,36 +351,29 @@ pub fn addFileArg(run: *Run, lp: std.Build.LazyPath) void {
/// subsequent builds, causing the child process to be re-executed.
///
/// Related:
-/// * `addFileArg` - same thing but without the prefix
/// * `addOutputFileArg` - for files generated by the child process
-pub fn addPrefixedFileArg(run: *Run, prefix: []const u8, lp: std.Build.LazyPath) void {
+pub fn addFileArg2(run: *Run, lp: std.Build.LazyPath, options: PathArgOptions) void {
const graph = run.step.owner.graph;
const arena = graph.arena;
- const prefixed_file_source: PrefixedLazyPath = .{
- .prefix = graph.dupeString(prefix),
+ const prefixed_file_source: DecoratedLazyPath = .{
+ .prefix = graph.dupeString(options.prefix),
.lazy_path = lp.dupe(graph),
+ .suffix = graph.dupeString(options.suffix),
+ .make_absolute = options.make_absolute,
};
run.argv.append(arena, .{ .lazy_path = prefixed_file_source }) catch @panic("OOM");
lp.addStepDependencies(&run.step);
}
-/// Appends the content of an input file to the command line arguments.
-///
-/// The child process will see a single argument, even if the file contains whitespace.
-/// This means that the entire file content up to EOF is rendered as one contiguous
-/// string, including escape sequences. Notably, any (trailing) newlines will show up
-/// like this: "hello,\nfile world!\n"
-///
-/// Modifications to the source file will be detected as a cache miss in subsequent
-/// builds, causing the child process to be re-executed.
-///
-/// This function may not be used to supply the first argument of a `Run` step.
-///
-/// Related:
-/// * `addPrefixedFileContentArg` - same thing but prepends a string to the argument
+/// Deprecated, use `addFileContentArg2`.
pub fn addFileContentArg(run: *Run, lp: std.Build.LazyPath) void {
- run.addPrefixedFileContentArg("", lp);
+ return run.addFileContentArg2(lp, .{});
+}
+
+/// Deprecated, use `addFileContentArg2`.
+pub fn addPrefixedFileContentArg(run: *Run, prefix: []const u8, lp: std.Build.LazyPath) void {
+ return run.addFileContentArg2(lp, .{ .prefix = prefix });
}
/// Appends the content of an input file to the command line arguments prepended with a string.
@@ -368,7 +394,7 @@ pub fn addFileContentArg(run: *Run, lp: std.Build.LazyPath) void {
///
/// Related:
/// * `addFileContentArg` - same thing but without the prefix
-pub fn addPrefixedFileContentArg(run: *Run, prefix: []const u8, lp: std.Build.LazyPath) void {
+pub fn addFileContentArg2(run: *Run, lp: std.Build.LazyPath, options: ArgOptions) void {
const graph = run.step.owner.graph;
const arena = graph.arena;
@@ -379,24 +405,27 @@ pub fn addPrefixedFileContentArg(run: *Run, prefix: []const u8, lp: std.Build.La
@panic("'addFileContentArg'/'addPrefixedFileContentArg' cannot be first argument");
}
- const prefixed_file_source: PrefixedLazyPath = .{
- .prefix = graph.dupeString(prefix),
+ const file_content: DecoratedFileContent = .{
+ .prefix = graph.dupeString(options.prefix),
.lazy_path = lp.dupe(graph),
+ .suffix = graph.dupeString(options.suffix),
};
- run.argv.append(arena, .{ .file_content = prefixed_file_source }) catch @panic("OOM");
+ run.argv.append(arena, .{ .file_content = file_content }) catch @panic("OOM");
lp.addStepDependencies(&run.step);
}
-/// Provides a directory path as a command line argument to the command being run.
-///
-/// Returns a `std.Build.LazyPath` which can be used as inputs to other APIs
-/// throughout the build system.
-///
-/// Related:
-/// * `addPrefixedOutputDirectoryArg` - same thing but prepends a string to the argument
-/// * `addDirectoryArg` - for input directories given to the child process
+/// Deprecated, use `addOutputDirectoryArg2`.
pub fn addOutputDirectoryArg(run: *Run, basename: []const u8) std.Build.LazyPath {
- return run.addPrefixedOutputDirectoryArg("", basename);
+ return run.addOutputDirectoryArg2(basename, .{});
+}
+
+/// Deprecated, use `addOutputDirectoryArg2`.
+pub fn addPrefixedOutputDirectoryArg(
+ run: *Run,
+ prefix: []const u8,
+ basename: []const u8,
+) std.Build.LazyPath {
+ return run.addOutputDirectoryArg2(basename, .{ .prefix = prefix });
}
/// Provides a directory path as a command line argument to the command being run.
@@ -412,12 +441,11 @@ pub fn addOutputDirectoryArg(run: *Run, basename: []const u8) std.Build.LazyPath
/// throughout the build system.
///
/// Related:
-/// * `addOutputDirectoryArg` - same thing but without the prefix
/// * `addDirectoryArg` - for input directories given to the child process
-pub fn addPrefixedOutputDirectoryArg(
+pub fn addOutputDirectoryArg2(
run: *Run,
- prefix: []const u8,
basename: []const u8,
+ options: PathArgOptions,
) std.Build.LazyPath {
if (basename.len == 0) @panic("basename must not be empty");
const graph = run.step.owner.graph;
@@ -425,9 +453,11 @@ pub fn addPrefixedOutputDirectoryArg(
const output = arena.create(Output) catch @panic("OOM");
output.* = .{
- .prefix = graph.dupeString(prefix),
+ .prefix = graph.dupeString(options.prefix),
.basename = graph.dupeString(basename),
+ .suffix = graph.dupeString(options.suffix),
.generated_file = graph.addGeneratedFile(&run.step),
+ .make_absolute = options.make_absolute,
};
run.argv.append(arena, .{ .output_directory = output }) catch @panic("OOM");
@@ -438,56 +468,67 @@ pub fn addPrefixedOutputDirectoryArg(
return .{ .generated = .{ .index = output.generated_file } };
}
+/// Deprecated, use `addDirectoryArg2`.
pub fn addDirectoryArg(run: *Run, lazy_directory: std.Build.LazyPath) void {
- run.addDecoratedDirectoryArg("", lazy_directory, "");
+ run.addDirectoryArg2(lazy_directory, .{});
}
+/// Deprecated, use `addDirectoryArg2`.
pub fn addPrefixedDirectoryArg(run: *Run, prefix: []const u8, lazy_directory: std.Build.LazyPath) void {
- const graph = run.step.owner.graph;
- const arena = graph.arena;
- run.argv.append(arena, .{ .decorated_directory = .{
- .prefix = graph.dupeString(prefix),
- .lazy_path = lazy_directory.dupe(graph),
- .suffix = "",
- } }) catch @panic("OOM");
- lazy_directory.addStepDependencies(&run.step);
+ run.addDirectoryArg2(lazy_directory, .{ .prefix = prefix });
}
+/// Deprecated, use `addDirectoryArg2`.
pub fn addDecoratedDirectoryArg(
run: *Run,
prefix: []const u8,
lazy_directory: std.Build.LazyPath,
suffix: []const u8,
+) void {
+ run.addDirectoryArg2(lazy_directory, .{ .prefix = prefix, .suffix = suffix });
+}
+
+pub fn addDirectoryArg2(
+ run: *Run,
+ lazy_directory: std.Build.LazyPath,
+ options: PathArgOptions,
) void {
const graph = run.step.owner.graph;
const arena = graph.arena;
run.argv.append(arena, .{ .decorated_directory = .{
- .prefix = graph.dupeString(prefix),
+ .prefix = graph.dupeString(options.prefix),
.lazy_path = lazy_directory.dupe(graph),
- .suffix = graph.dupeString(suffix),
+ .suffix = graph.dupeString(options.suffix),
+ .make_absolute = options.make_absolute,
} }) catch @panic("OOM");
lazy_directory.addStepDependencies(&run.step);
}
+/// Deprecated, use `addDepFileOutputArg2`.
+pub fn addDepFileOutputArg(run: *Run, basename: []const u8) std.Build.LazyPath {
+ return run.addDepFileOutputArg2(basename, .{});
+}
+
+/// Deprecated, use `addDepFileOutputArg2`.
+pub fn addPrefixedDepFileOutputArg(run: *Run, prefix: []const u8, basename: []const u8) std.Build.LazyPath {
+ return run.addDepFileOutputArg2(basename, .{ .prefix = prefix });
+}
+
/// Add a path argument to a dep file (.d) for the child process to write its
/// discovered additional dependencies.
/// Only one dep file argument is allowed by instance.
-pub fn addDepFileOutputArg(run: *Run, basename: []const u8) std.Build.LazyPath {
- return run.addPrefixedDepFileOutputArg("", basename);
-}
-
-/// Add a prefixed path argument to a dep file (.d) for the child process to
-/// write its discovered additional dependencies.
-pub fn addPrefixedDepFileOutputArg(run: *Run, prefix: []const u8, basename: []const u8) std.Build.LazyPath {
+pub fn addDepFileOutputArg2(run: *Run, basename: []const u8, options: PathArgOptions) std.Build.LazyPath {
const b = run.step.owner;
const graph = b.graph;
const arena = graph.arena;
const dep_file = arena.create(Output) catch @panic("OOM");
dep_file.* = .{
- .prefix = graph.dupeString(prefix),
+ .prefix = graph.dupeString(options.prefix),
.basename = graph.dupeString(basename),
+ .suffix = graph.dupeString(options.suffix),
.generated_file = graph.addGeneratedFile(&run.step),
+ .make_absolute = options.make_absolute,
};
run.argv.append(arena, .{ .output_file_dep = dep_file }) catch @panic("OOM");
@@ -581,6 +622,17 @@ pub fn removeEnvironmentVariable(run: *Run, key: []const u8) void {
_ = run.getEnvMap().swapRemove(key);
}
+pub fn setPreopen(run: *Run, name: []const u8, resource: Build.LazyPath) void {
+ const graph = run.step.owner.graph;
+ const arena = graph.arena;
+ resource.addStepDependencies(&run.step);
+ run.preopens.put(
+ arena,
+ graph.dupeString(name),
+ resource.dupe(graph),
+ ) catch @panic("OOM");
+}
+
/// Adds a check for exact stderr match. Does not add any other checks.
pub fn expectStdErrEqual(run: *Run, bytes: []const u8) void {
const graph = run.step.owner.graph;
@@ -632,6 +684,13 @@ pub fn addCheck(run: *Run, new_check: StdIo.Check) void {
.check => |*checks| checks.append(b.allocator, new_check) catch @panic("OOM"),
else => @panic("illegal call to addCheck: conflicting helper method calls. Suggest to directly set stdio field of Run instead"),
}
+
+ switch (new_check) {
+ .expect_stderr_snapshot,
+ .expect_stdout_snapshot,
+ => |file| run.addFileInput(file),
+ else => {},
+ }
}
pub fn captureStdErr(run: *Run, options: CapturedStdIo.Options) std.Build.LazyPath {
@@ -642,19 +701,17 @@ pub fn captureStdErr(run: *Run, options: CapturedStdIo.Options) std.Build.LazyPa
const graph = b.graph;
const arena = graph.arena;
- if (run.captured_stderr) |captured| return .{ .generated = .{ .index = captured.output.generated_file } };
+ if (run.captured_stderr) |captured| return .{ .generated = .{ .index = captured.generated_file } };
const captured = arena.create(CapturedStdIo) catch @panic("OOM");
captured.* = .{
- .output = .{
- .prefix = "",
- .basename = if (options.basename) |basename| graph.dupeString(basename) else "stderr",
- .generated_file = graph.addGeneratedFile(&run.step),
- },
+ .prefix = "",
+ .basename = if (options.basename) |basename| graph.dupeString(basename) else "stderr",
+ .generated_file = graph.addGeneratedFile(&run.step),
.trim_whitespace = options.trim_whitespace,
};
run.captured_stderr = captured;
- return .{ .generated = .{ .index = captured.output.generated_file } };
+ return .{ .generated = .{ .index = captured.generated_file } };
}
pub fn captureStdOut(run: *Run, options: CapturedStdIo.Options) std.Build.LazyPath {
@@ -665,19 +722,17 @@ pub fn captureStdOut(run: *Run, options: CapturedStdIo.Options) std.Build.LazyPa
const graph = b.graph;
const arena = graph.arena;
- if (run.captured_stdout) |captured| return .{ .generated = .{ .index = captured.output.generated_file } };
+ if (run.captured_stdout) |captured| return .{ .generated = .{ .index = captured.generated_file } };
const captured = arena.create(CapturedStdIo) catch @panic("OOM");
captured.* = .{
- .output = .{
- .prefix = "",
- .basename = if (options.basename) |basename| graph.dupeString(basename) else "stdout",
- .generated_file = graph.addGeneratedFile(&run.step),
- },
+ .prefix = "",
+ .basename = if (options.basename) |basename| graph.dupeString(basename) else "stdout",
+ .generated_file = graph.addGeneratedFile(&run.step),
.trim_whitespace = options.trim_whitespace,
};
run.captured_stdout = captured;
- return .{ .generated = .{ .index = captured.output.generated_file } };
+ return .{ .generated = .{ .index = captured.generated_file } };
}
/// Adds an additional input files that, when modified, indicates that this Run
diff --git a/lib/std/DoublyLinkedList.zig b/lib/std/DoublyLinkedList.zig
index b7a5ed2e112cb926396261047becfebcc934f553..a792dc9b4ec291fc9be8a1841e180305cd45fa3d 100644
--- a/lib/std/DoublyLinkedList.zig
+++ b/lib/std/DoublyLinkedList.zig
@@ -127,20 +127,17 @@ pub fn remove(list: *DoublyLinkedList, node: *Node) void {
}
}
-/// Remove and return the last node in the list.
-///
-/// Returns:
-/// A pointer to the last node in the list.
-pub fn pop(list: *DoublyLinkedList) ?*Node {
+/// Remove and return a pointer to the last node in the list.
+pub fn popLast(list: *DoublyLinkedList) ?*Node {
const last = list.last orelse return null;
list.remove(last);
return last;
}
-/// Remove and return the first node in the list.
-///
-/// Returns:
-/// A pointer to the first node in the list.
+/// Deprecated in favor of `popLast`
+pub const pop = popLast;
+
+/// Remove and return a pointer to the first node in the list.
pub fn popFirst(list: *DoublyLinkedList) ?*Node {
const first = list.first orelse return null;
list.remove(first);
@@ -200,11 +197,14 @@ test "basics" {
}
_ = list.popFirst(); // {2, 3, 4, 5}
- _ = list.pop(); // {2, 3, 4}
+ _ = list.popLast(); // {2, 3, 4}
list.remove(&three.node); // {2, 4}
+ // peek first and last elements of the list
try testing.expect(@as(*L, @fieldParentPtr("node", list.first.?)).data == 2);
try testing.expect(@as(*L, @fieldParentPtr("node", list.last.?)).data == 4);
+
+ // list length
try testing.expect(list.len() == 2);
}
diff --git a/lib/std/Io/Dir.zig b/lib/std/Io/Dir.zig
index eda18e2579525f5299fda9a357bb89edb67adbd5..414e63c99cea565c4176dfa2dc0a327fe2ebec63 100644
--- a/lib/std/Io/Dir.zig
+++ b/lib/std/Io/Dir.zig
@@ -1116,6 +1116,10 @@ pub const RenamePreserveError = error{
///
/// On Windows, this error may be returned instead of PathAlreadyExists when
/// renaming a directory over an existing directory.
+ ///
+ /// On Darwin, this error may be returned when a component of either pathname
+ /// refers to a "dataless" directory that requires materialization, and the I/O
+ /// policy of the current thread or process disallows dataless directory materialization.
AccessDenied,
PathAlreadyExists,
/// Operating system or file system does not support atomic nonreplacing
diff --git a/lib/std/Io/Kqueue.zig b/lib/std/Io/Kqueue.zig
index 63fd846b72abecaf75f44487d6023385b486d345..45e49b0f0cadf89efee58186ac08d71f2739cfce 100644
--- a/lib/std/Io/Kqueue.zig
+++ b/lib/std/Io/Kqueue.zig
@@ -40,7 +40,7 @@ const Thread = struct {
steal_ready_search_index: u32,
/// For ensuring multiple fibers waiting on the same file descriptor and
/// filter use the same kevent.
- wait_queues: std.AutoArrayHashMapUnmanaged(WaitQueueKey, *Fiber),
+ wait_queues: std.array_hash_map.Auto(WaitQueueKey, *Fiber),
const WaitQueueKey = struct {
ident: usize,
diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig
index 90d74d4b3703bc8ed927c7d0ced77242fcc10f0f..d4b202e12d0fa9087716209c24215bc179d71c1a 100644
--- a/lib/std/Io/Threaded.zig
+++ b/lib/std/Io/Threaded.zig
@@ -218,6 +218,7 @@ pub const Environ = struct {
DEBUGINFOD_CACHE_PATH: ?[:0]const u8 = null,
XDG_CACHE_HOME: ?[:0]const u8 = null,
HOME: ?[:0]const u8 = null,
+ TERM: ?[:0]const u8 = null,
},
};
@@ -1562,7 +1563,7 @@ pub const splat_buffer_size = 64;
/// NtWaitForMultipleObjects accepts. We use this value also for poll() on
/// posix systems.
const poll_buffer_len = 64;
-pub const default_PATH = "/usr/local/bin:/bin/:/usr/bin";
+pub const default_PATH = "/usr/local/bin:/bin:/usr/bin";
/// There are multiple kernel bugs being worked around with retries.
const max_windows_kernel_bug_retries = 13;
@@ -7505,6 +7506,7 @@ fn dirRenamePreserve(
) Dir.RenamePreserveError!void {
const t: *Threaded = @ptrCast(@alignCast(userdata));
if (is_windows) return dirRenameWindowsInner(old_dir, old_sub_path, new_dir, new_sub_path, false);
+ if (is_darwin) return dirRenamePreserveDarwin(old_dir, old_sub_path, new_dir, new_sub_path);
if (native_os == .linux) return dirRenamePreserveLinux(old_dir, old_sub_path, new_dir, new_sub_path);
// Make a hard link then delete the original.
try dirHardLink(t, old_dir, old_sub_path, new_dir, new_sub_path, .{ .follow_symlinks = false });
@@ -7696,6 +7698,58 @@ fn dirRenamePosix(
return renameat(old_dir.handle, old_sub_path_posix, new_dir.handle, new_sub_path_posix);
}
+fn dirRenamePreserveDarwin(
+ old_dir: Dir,
+ old_sub_path: []const u8,
+ new_dir: Dir,
+ new_sub_path: []const u8,
+) Dir.RenamePreserveError!void {
+ var old_path_buffer: [posix.PATH_MAX]u8 = undefined;
+ var new_path_buffer: [posix.PATH_MAX]u8 = undefined;
+ const old_sub_path_posix = try pathToPosix(old_sub_path, &old_path_buffer);
+ const new_sub_path_posix = try pathToPosix(new_sub_path, &new_path_buffer);
+
+ const syscall: Syscall = try .start();
+ while (true) {
+ switch (posix.errno(std.c.renameatx_np(
+ old_dir.handle,
+ old_sub_path_posix,
+ new_dir.handle,
+ new_sub_path_posix,
+ .{ .EXCL = true },
+ ))) {
+ .SUCCESS => {
+ syscall.finish();
+ break;
+ },
+ .INTR => {
+ try syscall.checkCancel();
+ continue;
+ },
+ .INVAL => |err| return syscall.errnoBug(err),
+ .FAULT => |err| return syscall.errnoBug(err),
+ .BADF => |err| return syscall.errnoBug(err),
+ .ISDIR => |err| return syscall.errnoBug(err),
+ .NOTEMPTY => |err| return syscall.errnoBug(err),
+ .OPNOTSUPP => return syscall.fail(error.OperationUnsupported),
+ .IO => return syscall.fail(error.HardwareFailure),
+ .DEADLK => return syscall.fail(error.AccessDenied),
+ .ACCES => return syscall.fail(error.AccessDenied),
+ .DQUOT => return syscall.fail(error.DiskQuota),
+ .EXIST => return syscall.fail(error.PathAlreadyExists),
+ .LOOP => return syscall.fail(error.LinkQuotaExceeded),
+ .NAMETOOLONG => return syscall.fail(error.NameTooLong),
+ .NOENT => return syscall.fail(error.FileNotFound),
+ .NOSPC => return syscall.fail(error.NoSpaceLeft),
+ .NOTDIR => return syscall.fail(error.NotDir),
+ .PERM => return syscall.fail(error.PermissionDenied),
+ .ROFS => return syscall.fail(error.ReadOnlyFileSystem),
+ .XDEV => return syscall.fail(error.CrossDevice),
+ else => |err| return syscall.unexpectedErrno(err),
+ }
+ }
+}
+
fn dirRenamePreserveLinux(
old_dir: Dir,
old_sub_path: []const u8,
@@ -7783,49 +7837,6 @@ fn renameat(
};
}
-fn renameatPreserve(
- old_dir: posix.fd_t,
- old_sub_path: [*:0]const u8,
- new_dir: posix.fd_t,
- new_sub_path: [*:0]const u8,
-) Dir.RenameError!void {
- const syscall: Syscall = try .start();
- while (true) {
- switch (posix.errno(posix.system.renameat(old_dir, old_sub_path, new_dir, new_sub_path))) {
- .SUCCESS => return syscall.finish(),
- .INTR => {
- try syscall.checkCancel();
- continue;
- },
- else => |e| {
- syscall.finish();
- switch (e) {
- .ACCES => return error.AccessDenied,
- .PERM => return error.PermissionDenied,
- .BUSY => return error.FileBusy,
- .DQUOT => return error.DiskQuota,
- .FAULT => |err| return errnoBug(err),
- .INVAL => |err| return errnoBug(err),
- .ISDIR => return error.IsDir,
- .LOOP => return error.SymLinkLoop,
- .MLINK => return error.LinkQuotaExceeded,
- .NAMETOOLONG => return error.NameTooLong,
- .NOENT => return error.FileNotFound,
- .NOTDIR => return error.NotDir,
- .NOMEM => return error.SystemResources,
- .NOSPC => return error.NoSpaceLeft,
- .EXIST => return error.PathAlreadyExists,
- .NOTEMPTY => return error.PathAlreadyExists,
- .ROFS => return error.ReadOnlyFileSystem,
- .XDEV => return error.CrossDevice,
- .ILSEQ => return error.BadPathName,
- else => |err| return posix.unexpectedErrno(err),
- }
- },
- }
- }
-}
-
const dirSymLink = switch (native_os) {
.windows => dirSymLinkWindows,
.wasi => dirSymLinkWasi,
@@ -8165,31 +8176,16 @@ fn dirReadLinkWindows(dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLink
defer windows.CloseHandle(result_handle);
var reparse_buf: [windows.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 align(@alignOf(windows.REPARSE_DATA_BUFFER)) = undefined;
-
- syscall = try .start();
- while (true) switch (windows.ntdll.NtFsControlFile(
- result_handle,
- null, // event
- null, // APC routine
- null, // APC context
- &io_status_block,
- .GET_REPARSE_POINT,
- null, // input buffer
- 0, // input buffer length
- &reparse_buf,
- reparse_buf.len,
- )) {
- .SUCCESS => {
- syscall.finish();
- break;
- },
- .CANCELLED => {
- try syscall.checkCancel();
- continue;
- },
- .NOT_A_REPARSE_POINT => return syscall.fail(error.NotLink),
- else => |status| return syscall.unexpectedNtstatus(status),
- };
+ switch ((try deviceIoControl(&.{
+ .file = .{ .handle = result_handle, .flags = .{ .nonblocking = true } },
+ .code = .GET_REPARSE_POINT,
+ .out = &reparse_buf,
+ })).u.Status) {
+ .SUCCESS => {},
+ .CANCELLED => unreachable,
+ .NOT_A_REPARSE_POINT => return error.NotLink,
+ else => |status| return windows.unexpectedStatus(status),
+ }
const reparse_struct: *const windows.REPARSE_DATA_BUFFER = @ptrCast(@alignCast(&reparse_buf));
const IoReparseTagInt = @typeInfo(windows.IO_REPARSE_TAG).@"struct".backing_integer.?;
@@ -8790,9 +8786,8 @@ fn isTty(file: File) Io.Cancelable!bool {
fn fileEnableAnsiEscapeCodes(userdata: ?*anyopaque, file: File) File.EnableAnsiEscapeCodesError!void {
const t: *Threaded = @ptrCast(@alignCast(userdata));
- _ = t;
- if (!is_windows) return if (!try supportsAnsiEscapeCodes(file)) error.NotTerminalDevice;
+ if (!is_windows) return if (!try supportsAnsiEscapeCodes(t, file)) error.NotTerminalDevice;
// For Windows Terminal, VT Sequences processing is enabled by default.
const console: File = .{
@@ -8840,14 +8835,13 @@ fn fileEnableAnsiEscapeCodes(userdata: ?*anyopaque, file: File) File.EnableAnsiE
fn fileSupportsAnsiEscapeCodes(userdata: ?*anyopaque, file: File) Io.Cancelable!bool {
const t: *Threaded = @ptrCast(@alignCast(userdata));
- _ = t;
- return supportsAnsiEscapeCodes(file);
+ return supportsAnsiEscapeCodes(t, file);
}
-fn supportsAnsiEscapeCodes(file: File) Io.Cancelable!bool {
+fn supportsAnsiEscapeCodes(t: *Threaded, file: File) Io.Cancelable!bool {
if (is_windows) {
var get_console_mode = windows.CONSOLE.USER_IO.GET_MODE;
- switch ((try deviceIoControl(&.{
+ return switch ((try deviceIoControl(&.{
.file = .{
.handle = windows.peb().ProcessParameters.ConsoleHandle,
.flags = .{ .nonblocking = false },
@@ -8855,15 +8849,33 @@ fn supportsAnsiEscapeCodes(file: File) Io.Cancelable!bool {
.code = windows.IOCTL.CONDRV.ISSUE_USER_IO,
.in = @ptrCast(&get_console_mode.request(file, 0, .{}, 0, .{})),
})).u.Status) {
- .SUCCESS => if (get_console_mode.Data & windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING != 0)
- return true,
+ .SUCCESS => get_console_mode.Data & windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING != 0,
.CANCELLED => unreachable,
- .INVALID_HANDLE => return isCygwinPty(file),
- else => return false,
+ .INVALID_HANDLE => isCygwinPty(file),
+ else => false,
+ };
+ }
+
+ if (native_os == .wasi) {
+ // WASI sanitizes stdout when fd is a tty so ANSI escape codes
+ // will not be interpreted as actual cursor commands, and
+ // stderr is always sanitized.
+
+ return false;
+ }
+
+ if (try isTty(file)) {
+ if (file.handle == posix.STDOUT_FILENO or file.handle == posix.STDERR_FILENO) {
+ t.scanEnviron();
+ if (t.environ.string.TERM) |term| {
+ if (std.mem.eql(u8, term, "dumb")) {
+ return false;
+ }
+ }
}
- }
- if (try isTty(file)) return true;
+ return true;
+ }
return false;
}
@@ -10168,7 +10180,7 @@ fn fileSeekBy(userdata: ?*anyopaque, file: File, offset: i64) File.SeekError!voi
if (posix.SEEK == void) return error.Unseekable;
- if (native_os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) {
+ if (native_os == .linux and !builtin.link_libc and @sizeOf(posix.system.syscall_arg_t) == 4) {
var result: i64 = undefined;
const syscall: Syscall = try .start();
while (true) {
@@ -10280,7 +10292,7 @@ fn fileSeekTo(userdata: ?*anyopaque, file: File, offset: u64) File.SeekError!voi
}
fn posixSeekTo(fd: posix.fd_t, offset: u64) File.SeekError!void {
- if (native_os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) {
+ if (native_os == .linux and !builtin.link_libc and @sizeOf(posix.system.syscall_arg_t) == 4) {
const syscall: Syscall = try .start();
while (true) {
var result: i64 = undefined;
@@ -10892,6 +10904,7 @@ fn fileWriteStreaming(
.PIPE => return error.BrokenPipe,
.CONNRESET => |err| return errnoBug(err), // Not a socket handle.
.BUSY => return error.DeviceBusy,
+ .ACCES => return error.AccessDenied,
else => |err| return posix.unexpectedErrno(err),
}
},
@@ -13676,7 +13689,7 @@ fn netLookupFallible(
// Check for equal to "localhost(.)" or ends in ".localhost(.)"
const localhost = if (name[name.len - 1] == '.') "localhost." else "localhost";
if (std.mem.endsWith(u8, name, localhost) and
- (name.len == localhost.len or name[name.len - localhost.len] == '.'))
+ (name.len == localhost.len or name[name.len - localhost.len - 1] == '.'))
{
var results_buffer: [3]HostName.LookupResult = undefined;
var results_index: usize = 0;
@@ -14160,9 +14173,11 @@ fn addressUnixToPosix(a: *const net.UnixAddress, storage: *UnixAddress) posix.so
}
fn address4FromPosix(in: *const posix.sockaddr.in) net.Ip4Address {
+ // The network byte order address in `in.addr` is already the byte order we want.
+ const addr_bytes: *const [4]u8 = @ptrCast(&in.addr);
return .{
.port = std.mem.bigToNative(u16, in.port),
- .bytes = @bitCast(in.addr),
+ .bytes = addr_bytes.*,
};
}
@@ -14176,9 +14191,11 @@ fn address6FromPosix(in6: *const posix.sockaddr.in6) net.Ip6Address {
}
fn address4ToPosix(a: net.Ip4Address) posix.sockaddr.in {
+ // The byte order of `a.bytes` is already equivalent to a network byte order address.
+ const addr_raw: *align(1) const u32 = @ptrCast(&a.bytes);
return .{
.port = std.mem.nativeToBig(u16, a.port),
- .addr = @bitCast(a.bytes),
+ .addr = addr_raw.*,
};
}
diff --git a/lib/std/Io/Uring.zig b/lib/std/Io/Uring.zig
index 9184cd574153b4768c76347d4e246120827b4a26..e560500a755281510f64954d12040b1b6c5504b4 100644
--- a/lib/std/Io/Uring.zig
+++ b/lib/std/Io/Uring.zig
@@ -917,7 +917,7 @@ pub fn deinit(ev: *Evented) void {
const idle_stack_end_offset = std.mem.alignForward(
usize,
ev.threads.allocated.len * @sizeOf(Thread) + idle_stack_size,
- std.heap.page_size_max,
+ std.heap.pageSize(),
);
for (ev.threads.allocated[1..active_threads]) |*thread| thread.thread.join();
for (ev.threads.allocated[0..active_threads]) |*thread| thread.deinit(ev.backing_allocator);
diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig
index e4eb52d294ec7972b2059ada1fb9e15f313b3f6a..c5dd1f6bae8a7dce41a8ff26692e73fc43c65ba3 100644
--- a/lib/std/Io/Writer.zig
+++ b/lib/std/Io/Writer.zig
@@ -771,7 +771,7 @@ pub fn writeBytePreserve(w: *Writer, preserve: usize, byte: u8) Error!void {
w.end += 1;
return;
}
- try w.vtable.rebase(w, preserve, 1);
+ try w.vtable.rebase(w, preserve -| 1, 1);
w.buffer[w.end] = byte;
w.end += 1;
}
diff --git a/lib/std/Io/net.zig b/lib/std/Io/net.zig
index c704d8b9e924da4578e447f9d3e5be3ad9f42533..6611502cc157238167445e516cb5ea5b6a0af832 100644
--- a/lib/std/Io/net.zig
+++ b/lib/std/Io/net.zig
@@ -576,7 +576,7 @@ pub const Ip6Address = struct {
const name = text[text_i..];
if (name.len == 0) return .incomplete;
interface_name_text = name;
- text_i = @intCast(text.len);
+ text_i = std.math.cast(u8, text.len) orelse return .{ .overflow = text.len };
continue :state .end;
},
else => return .{ .invalid_byte = text_i },
@@ -592,11 +592,7 @@ pub const Ip6Address = struct {
if (remaining != 0) return .incomplete;
}
- // Workaround that can be removed when this proposal is
- // implemented https://github.com/ziglang/zig/issues/19755
- if ((comptime @import("builtin").cpu.arch.endian()) != .big) {
- for (&parts) |*part| part.* = @byteSwap(part.*);
- }
+ for (&parts) |*part| part.* = @byteSwap(part.*);
return .{ .success = .{
.bytes = @bitCast(parts),
diff --git a/lib/std/Io/net/test.zig b/lib/std/Io/net/test.zig
index 1565904c574a6e392593dc7ad4b3c85a9ac1fd0a..308dc1a32670e207e72511d0128b634972050e6a 100644
--- a/lib/std/Io/net/test.zig
+++ b/lib/std/Io/net/test.zig
@@ -92,6 +92,11 @@ test "invalid but parseable IPv6 scope ids" {
try testing.expectError(error.InterfaceNotFound, net.IpAddress.resolveIp6(io, "ff01::fb%123s45678901234", 0));
}
+test "oversized IPv6 scope id" {
+ const long_scope: [256]u8 = @splat('a');
+ try testing.expectError(error.ParseFailed, net.IpAddress.resolveIp6(testing.io, "ff01::fb%" ++ &long_scope, 0));
+}
+
test "parse and render IPv4 addresses" {
try testIp4ParseAndRender("0.0.0.0");
try testIp4ParseAndRender("255.255.255.255");
diff --git a/lib/std/Random/RomuTrio.zig b/lib/std/Random/RomuTrio.zig
index 5b7664d7f2b6cd7844020c1cd045a77955a0bc1f..9f005bf2f9fac8082eb4e71355dc90c73280d2b9 100644
--- a/lib/std/Random/RomuTrio.zig
+++ b/lib/std/Random/RomuTrio.zig
@@ -5,6 +5,7 @@
const std = @import("std");
const math = std.math;
const RomuTrio = @This();
+const builtin = @import("builtin");
x_state: u64,
y_state: u64,
@@ -33,7 +34,7 @@ fn next(self: *RomuTrio) u64 {
}
pub fn seedWithBuf(self: *RomuTrio, buf: [24]u8) void {
- const seed_buf = @as([3]u64, @bitCast(buf));
+ const seed_buf: [3]u64 = @bitCast(buf);
self.x_state = seed_buf[0];
self.y_state = seed_buf[1];
self.z_state = seed_buf[2];
@@ -121,7 +122,8 @@ test fill {
}
test "buf seeding test" {
- const buf0 = @as([24]u8, @bitCast([3]u64{ 16294208416658607535, 13964609475759908645, 4703697494102998476 }));
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ const buf0: [24]u8 = @bitCast([3]u64{ 16294208416658607535, 13964609475759908645, 4703697494102998476 });
const resulting_state = .{ .x = 16294208416658607535, .y = 13964609475759908645, .z = 4703697494102998476 };
var r = RomuTrio.init(0);
r.seedWithBuf(buf0);
diff --git a/lib/std/Random/Xoshiro256.zig b/lib/std/Random/Xoshiro256.zig
index fb65c2ba58e89b0bb50b22d1937ee8d359324e1c..6cb0583d982622b3f7df21b94368b03ddeb80c17 100644
--- a/lib/std/Random/Xoshiro256.zig
+++ b/lib/std/Random/Xoshiro256.zig
@@ -46,12 +46,12 @@ pub fn jump(self: *Xoshiro256) void {
while (table != 0) : (table >>= 1) {
if (@as(u1, @truncate(table)) != 0) {
- s ^= @as(u256, @bitCast(self.s));
+ s ^= @bitCast(self.s);
}
_ = self.next();
}
- self.s = @as([4]u64, @bitCast(s));
+ self.s = @bitCast(s);
}
pub fn seed(self: *Xoshiro256, init_s: u64) void {
diff --git a/lib/std/Target.zig b/lib/std/Target.zig
index fdeacdd719aaf0c02deec5e40c7c55b38dda0943..a75d23ca4d7530da5aaeda2c3f9c5a2056914391 100644
--- a/lib/std/Target.zig
+++ b/lib/std/Target.zig
@@ -49,7 +49,9 @@ pub const Os = struct {
uefi,
@"3ds",
+ wiiu,
+ psx,
ps3,
ps4,
ps5,
@@ -165,6 +167,7 @@ pub const Os = struct {
.plan9,
.serenity,
+ .psx,
.ps3,
.ps4,
.ps5,
@@ -196,6 +199,7 @@ pub const Os = struct {
.uefi,
.@"3ds",
+ .wiiu,
.psp,
.vita,
@@ -400,6 +404,7 @@ pub const Os = struct {
.plan9,
.serenity,
+ .psx,
.ps3,
.ps4,
.ps5,
@@ -453,7 +458,7 @@ pub const Os = struct {
break :blk default_min;
},
- .max = .{ .major = 7, .minor = 0, .patch = 9 },
+ .max = .{ .major = 7, .minor = 1, .patch = 9 },
},
.glibc = blk: {
// For 32-bit targets that traditionally used 32-bit time, we require
@@ -622,6 +627,13 @@ pub const Os = struct {
},
},
+ .wiiu => .{
+ .semver = .{
+ .min = .{ .major = 5, .minor = 5, .patch = 5 }, // Latest global release
+ .max = .{ .major = 5, .minor = 5, .patch = 6 }, // Latest US only release
+ },
+ },
+
.psp => .{
.semver = .{
// https://www.psdevwiki.com/psp/Official_Firmware_(OFW)#1.XX_Kernel
@@ -787,6 +799,8 @@ pub const Abi = enum {
gnux32,
eabi,
eabihf,
+ abin32,
+ x32,
ilp32,
android,
androideabi,
@@ -878,8 +892,12 @@ pub const Abi = enum {
=> .muslabi64,
// No musl support.
+ .alpha,
.arc,
.arceb,
+ .or1k,
+ .sparc,
+ .sparc64,
=> .gnu,
.csky,
=> .gnueabi,
@@ -933,6 +951,8 @@ pub const Abi = enum {
.windows => .gnu,
.uefi => .msvc,
.@"3ds" => .eabihf,
+ .wiiu => .eabihf,
+ .psx => .eabi,
.psp => .eabihf,
.vita => .eabihf,
.wasi, .emscripten => .musl,
@@ -1984,6 +2004,8 @@ pub const Cpu = struct {
.spirv_kernel,
.spirv_fragment,
.spirv_vertex,
+ .spirv_task,
+ .spirv_mesh,
=> &.{ .spirv32, .spirv64 },
.ez80_cet,
@@ -2080,6 +2102,7 @@ pub const Cpu = struct {
.m68k => &m68k.cpu.M68030,
.mips => &mips.cpu.mips32r2,
.mipsel => switch (os.tag) {
+ .psx => &mips.cpu.r3000a,
.psp => &mips.cpu.allegrex,
else => &mips.cpu.mips32r2,
},
@@ -2091,7 +2114,7 @@ pub const Cpu = struct {
.msp430 => &msp430.cpu.msp430,
.nvptx, .nvptx64 => &nvptx.cpu.sm_52,
.powerpc => switch (os.tag) {
- .openbsd => &powerpc.cpu.@"750",
+ .openbsd, .wiiu => &powerpc.cpu.@"750",
else => generic(arch),
},
.powerpc64 => switch (os.tag) {
@@ -2272,11 +2295,12 @@ pub fn requiresLibC(target: *const Target) bool {
.freestanding,
.fuchsia,
.managarm,
- .ps3,
.rtems,
.cuda,
.nvcl,
.amdhsa,
+ .psx,
+ .ps3,
.ps4,
.ps5,
.psp,
@@ -2296,6 +2320,7 @@ pub fn requiresLibC(target: *const Target) bool {
.other,
.@"3ds",
.tios,
+ .wiiu,
=> false,
};
}
@@ -2341,9 +2366,11 @@ pub fn supportsAddressSpace(
.lut => arch == .propeller and std.Target.propeller.featureSetHas(target.cpu.features, .p2),
.global, .local, .shared => is_gpu,
- .constant => is_gpu and (context == null or context == .constant),
+ .constant => (is_gpu and (context == null or context == .constant)) or
+ (is_spirv and (context == null or context == .constant or context == .pointer)),
.param => is_nvptx,
.input, .output, .uniform, .push_constant, .storage_buffer, .physical_storage_buffer => is_spirv,
+ .externref, .funcref => target.cpu.has(.wasm, .reference_types),
};
}
@@ -2440,6 +2467,7 @@ pub const DynamicLinker = struct {
.windows,
.@"3ds",
+ .wiiu,
.emscripten,
.wasi,
@@ -2453,6 +2481,7 @@ pub const DynamicLinker = struct {
.opengl,
.vulkan,
+ .psx,
.ps3,
.ps4,
.ps5,
@@ -2862,7 +2891,9 @@ pub const DynamicLinker = struct {
.windows,
.@"3ds",
+ .wiiu,
+ .psx,
.psp,
.vita,
@@ -2903,10 +2934,17 @@ pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 {
pub fn ptrBitWidth_arch_abi(cpu_arch: Cpu.Arch, abi: Abi) u16 {
switch (abi) {
- .gnux32, .muslx32, .gnuabin32, .muslabin32, .ilp32 => return 32,
- .gnuabi64, .muslabi64 => return 64,
+ .gnux32,
+ .muslx32,
+ .x32,
+ .gnuabin32,
+ .muslabin32,
+ .abin32,
+ .ilp32,
+ => return 32,
else => {},
}
+
return switch (cpu_arch) {
.avr,
.msp430,
@@ -2985,12 +3023,12 @@ pub fn ptrBitWidth(target: *const Target) u16 {
pub fn stackAlignment(target: *const Target) u16 {
// Overrides for when the stack alignment is not equal to the pointer width.
switch (target.cpu.arch) {
- .ez80,
- => return 1,
- .m68k,
- => return 2,
- .amdgcn,
- => return 4,
+ .ez80 => return 1,
+
+ .m68k => return 2,
+
+ .amdgcn => return 4,
+
.arm,
.armeb,
.hppa,
@@ -3001,6 +3039,7 @@ pub fn stackAlignment(target: *const Target) u16 {
.thumb,
.thumbeb,
=> return 8,
+
.aarch64,
.aarch64_be,
.alpha,
@@ -3017,18 +3056,23 @@ pub fn stackAlignment(target: *const Target) u16 {
.wasm64,
.x86_64,
=> return 16,
+
// Some of the following prongs should really be testing the ABI, but our current `Abi` enum
// can't handle that level of nuance yet.
.powerpc64,
.powerpc64le,
=> if (target.os.tag == .linux) return 16,
+
.riscv32,
.riscv32be,
.riscv64,
.riscv64be,
=> if (!target.cpu.has(.riscv, .e)) return 16,
+
.x86 => if (target.os.tag != .windows and target.os.tag != .uefi) return 16,
+
.kvx => return 32,
+
else => {},
}
@@ -3131,7 +3175,9 @@ pub fn cTypeByteSize(t: *const Target, c_type: CType) u16 {
pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
switch (target.os.tag) {
.freestanding, .other => switch (target.cpu.arch) {
- .msp430, .x86_16 => switch (c_type) {
+ .msp430,
+ .x86_16,
+ => switch (c_type) {
.char => return 8,
.short, .ushort, .int, .uint => return 16,
.float, .long, .ulong => return 32,
@@ -3143,12 +3189,14 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
.long, .ulong, .float, .double, .longdouble => return 32,
.longlong, .ulonglong => return 64,
},
- .mips64, .mips64el => switch (c_type) {
+ .mips64,
+ .mips64el,
+ => switch (c_type) {
.char => return 8,
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => switch (target.abi) {
- .gnuabin32, .muslabin32 => return 32,
+ .abin32 => return 32,
else => return 64,
},
.longlong, .ulonglong, .double => return 64,
@@ -3159,7 +3207,7 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => switch (target.abi) {
- .gnux32, .muslx32 => return 32,
+ .x32 => return 32,
else => return 64,
},
.longlong, .ulonglong, .double => return 64,
@@ -3172,25 +3220,7 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
.long, .ulong => return target.ptrBitWidth(),
.longlong, .ulonglong, .double => return 64,
.longdouble => switch (target.cpu.arch) {
- .x86 => switch (target.abi) {
- .android => return 64,
- else => return 80,
- },
-
- .powerpc,
- .powerpcle,
- .powerpc64,
- .powerpc64le,
- => switch (target.abi) {
- .musl,
- .muslabin32,
- .muslabi64,
- .musleabi,
- .musleabihf,
- .muslx32,
- => return 64,
- else => return 128,
- },
+ .x86 => return 80,
.alpha,
.riscv32,
@@ -3199,6 +3229,10 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
.riscv64be,
.aarch64,
.aarch64_be,
+ .powerpc,
+ .powerpcle,
+ .powerpc64,
+ .powerpc64le,
.s390x,
.sparc64,
.wasm32,
@@ -3232,23 +3266,25 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
.wasi,
.emscripten,
=> switch (target.cpu.arch) {
- .mips64, .mips64el => switch (c_type) {
+ .mips64,
+ .mips64el,
+ => switch (c_type) {
.char => return 8,
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => switch (target.abi) {
- .gnuabin32, .muslabin32 => return 32,
+ .gnuabin32, .muslabin32, .abin32 => return 32,
else => return 64,
},
.longlong, .ulonglong, .double => return 64,
- .longdouble => if (target.os.tag == .freebsd) return 64 else return 128,
+ .longdouble => return 128,
},
.x86_64 => switch (c_type) {
.char => return 8,
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => switch (target.abi) {
- .gnux32, .muslx32 => return 32,
+ .gnux32, .muslx32, .x32 => return 32,
else => return 64,
},
.longlong, .ulonglong, .double => return 64,
@@ -3269,15 +3305,11 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
.powerpc,
.powerpcle,
=> switch (target.abi) {
- .musl,
- .muslabin32,
- .muslabi64,
- .musleabi,
- .musleabihf,
- .muslx32,
- => return 64,
+ .musleabi, .musleabihf => return 64,
else => switch (target.os.tag) {
- .freebsd, .netbsd, .openbsd => return 64,
+ .netbsd,
+ .openbsd,
+ => return 64,
else => return 128,
},
},
@@ -3285,15 +3317,11 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
.powerpc64,
.powerpc64le,
=> switch (target.abi) {
- .musl,
- .muslabin32,
- .muslabi64,
- .musleabi,
- .musleabihf,
- .muslx32,
- => return 64,
+ .musl => return 64,
else => switch (target.os.tag) {
- .freebsd, .openbsd => return 64,
+ .freebsd,
+ .openbsd,
+ => return 64,
else => return 128,
},
},
@@ -3329,7 +3357,7 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
.long, .ulong => return 32,
.longlong, .ulonglong, .double => return 64,
.longdouble => switch (target.abi) {
- .gnu, .ilp32 => return 80,
+ .gnu => return 80,
else => return 64,
},
},
@@ -3340,7 +3368,7 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
.long, .ulong => return 32,
.longlong, .ulonglong, .double => return 64,
.longdouble => switch (target.abi) {
- .gnu, .ilp32 => return 80,
+ .gnu => return 80,
else => return 64,
},
},
@@ -3418,6 +3446,19 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
.longlong, .ulonglong, .double, .longdouble => return 64,
},
+ .wiiu => switch (c_type) {
+ .char => return 8,
+ .short, .ushort => return 16,
+ .int, .uint, .float, .long, .ulong => return 32,
+ .longlong, .ulonglong, .double, .longdouble => return 64,
+ },
+
+ .psx => switch (c_type) {
+ .char => return 8,
+ .short, .ushort => return 16,
+ .int, .uint, .long, .ulong, .float => return 32,
+ .longlong, .ulonglong, .double, .longdouble => return 64,
+ },
.ps4, .ps5 => switch (c_type) {
.char => return 8,
.short, .ushort => return 16,
@@ -3452,12 +3493,14 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 {
// Overrides for unusual alignments
switch (target.cpu.arch) {
- .avr, .ez80 => return 1,
+ .avr,
+ .ez80,
+ => return 1,
.x86 => switch (target.os.tag) {
.windows, .uefi => switch (c_type) {
.longlong, .ulonglong, .double => return 8,
.longdouble => switch (target.abi) {
- .gnu, .ilp32 => return 4,
+ .gnu => return 4,
else => return 8,
},
else => {},
@@ -3482,8 +3525,6 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 {
return @min(
std.math.ceilPowerOfTwoAssert(u16, (cTypeBitSize(target, c_type) + 7) / 8),
@as(u16, switch (target.cpu.arch) {
- .ez80 => 1,
-
.msp430,
.x86_16,
=> 2,
@@ -3551,6 +3592,7 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 {
=> 16,
.avr,
+ .ez80,
=> unreachable, // Handled above.
}),
);
@@ -3563,11 +3605,13 @@ pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 {
.longdouble => return 4,
else => {},
},
- .avr, .ez80 => return 1,
+ .avr,
+ .ez80,
+ => return 1,
.x86 => switch (target.os.tag) {
.windows, .uefi => switch (c_type) {
.longdouble => switch (target.abi) {
- .gnu, .ilp32 => return 4,
+ .gnu => return 4,
else => return 8,
},
else => {},
@@ -3595,9 +3639,9 @@ pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 {
return @min(
std.math.ceilPowerOfTwoAssert(u16, (cTypeBitSize(target, c_type) + 7) / 8),
@as(u16, switch (target.cpu.arch) {
- .ez80 => 1,
-
- .x86_16, .msp430 => 2,
+ .x86_16,
+ .msp430,
+ => 2,
.arc,
.arceb,
@@ -3662,6 +3706,7 @@ pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 {
=> 16,
.avr,
+ .ez80,
=> unreachable, // Handled above.
}),
);
@@ -3673,7 +3718,9 @@ pub fn cMaxIntAlignment(target: *const Target) u16 {
.ez80,
=> 1,
- .msp430, .x86_16 => 2,
+ .msp430,
+ .x86_16,
+ => 2,
.arc,
.arceb,
@@ -3742,14 +3789,18 @@ pub fn cMaxIntAlignment(target: *const Target) u16 {
pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention {
return switch (target.cpu.arch) {
.x86_64 => switch (target.os.tag) {
- .windows, .uefi => .{ .x86_64_win = .{} },
+ .windows,
+ .uefi,
+ => .{ .x86_64_win = .{} },
else => switch (target.abi) {
- .gnux32, .muslx32 => .{ .x86_64_x32 = .{} },
+ .gnux32, .muslx32, .x32 => .{ .x86_64_x32 = .{} },
else => .{ .x86_64_sysv = .{} },
},
},
.x86 => switch (target.os.tag) {
- .windows, .uefi => .{ .x86_win = .{} },
+ .windows,
+ .uefi,
+ => .{ .x86_win = .{} },
else => .{ .x86_sysv = .{} },
},
.x86_16 => .{ .x86_16_cdecl = .{} },
@@ -3765,7 +3816,7 @@ pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention
.hard => .{ .arm_aapcs_vfp = .{} },
},
.mips64, .mips64el => switch (target.abi) {
- .gnuabin32, .muslabin32 => .{ .mips64_n32 = .{} },
+ .gnuabin32, .muslabin32, .abin32 => .{ .mips64_n32 = .{} },
else => .{ .mips64_n64 = .{} },
},
.mips, .mipsel => .{ .mips_o32 = .{} },
diff --git a/lib/std/Target/mips.zig b/lib/std/Target/mips.zig
index 02ff2f6a9d338d52e5b188a13e4d8fbcd6673f6f..dad3a54940b45a9e9f2a7f45f8fb52cf34545f63 100644
--- a/lib/std/Target/mips.zig
+++ b/lib/std/Target/mips.zig
@@ -587,4 +587,13 @@ pub const cpu = struct {
.p5600,
}),
};
+ pub const r3000a: CpuModel = .{
+ .name = "r3000a",
+ .llvm_name = null,
+ .features = featureSet(&[_]Feature{
+ .mips1,
+ .notraps,
+ .soft_float,
+ }),
+ };
};
diff --git a/lib/std/Target/spirv.zig b/lib/std/Target/spirv.zig
index 04b4530978776a746b30ce12928ecedcc03a60e8..90d43cdbad5a9ccc699f94e5f53483ec94d7e502 100644
--- a/lib/std/Target/spirv.zig
+++ b/lib/std/Target/spirv.zig
@@ -5,12 +5,225 @@ const CpuFeature = std.Target.Cpu.Feature;
const CpuModel = std.Target.Cpu.Model;
pub const Feature = enum {
- arbitrary_precision_integers,
+ abort_khr,
+ addresses,
+ arithmetic_fence_ext,
+ atomic_float16add_ext,
+ atomic_float16min_max_ext,
+ atomic_float32add_ext,
+ atomic_float32min_max_ext,
+ atomic_float64add_ext,
+ atomic_float64min_max_ext,
+ atomic_storage,
+ atomic_storage_ops,
+ b_float16cooperative_matrix_khr,
+ b_float16dot_product_khr,
+ b_float16type_khr,
+ bit_instructions,
+ clip_distance,
+ compute_derivative_group_linear_khr,
+ compute_derivative_group_quads_khr,
+ constant_data_khr,
+ cooperative_matrix_khr,
+ cull_distance,
+ demote_to_helper_invocation,
+ denorm_flush_to_zero,
+ denorm_preserve,
+ derivative_control,
+ descriptor_heap_ext,
+ device_enqueue,
+ device_group,
+ dot_product,
+ dot_product_input4x8bit,
+ dot_product_input4x8bit_packed,
+ dot_product_input_all,
+ draw_parameters,
+ expect_assume_khr,
float16,
+ float16buffer,
float64,
+ float8cooperative_matrix_ext,
+ float8ext,
+ float_controls2,
+ fmakhr,
+ fragment_barycentric_khr,
+ fragment_density_ext,
+ fragment_fully_covered_ext,
+ fragment_shader_pixel_interlock_ext,
+ fragment_shader_sample_interlock_ext,
+ fragment_shader_shading_rate_interlock_ext,
+ fragment_shading_rate_khr,
generic_pointer,
+ geometry,
+ geometry_point_size,
+ geometry_streams,
+ group_non_uniform,
+ group_non_uniform_arithmetic,
+ group_non_uniform_ballot,
+ group_non_uniform_clustered,
+ group_non_uniform_partitioned_ext,
+ group_non_uniform_quad,
+ group_non_uniform_rotate_khr,
+ group_non_uniform_shuffle,
+ group_non_uniform_shuffle_relative,
+ group_non_uniform_vote,
+ group_uniform_arithmetic_khr,
+ groups,
+ image_basic,
+ image_buffer,
+ image_cube_array,
+ image_gather_extended,
+ image_mipmap,
+ image_ms_array,
+ image_query,
+ image_read_write,
+ image_rect,
+ input_attachment,
+ input_attachment_array_dynamic_indexing,
+ input_attachment_array_non_uniform_indexing,
+ int16,
int64,
+ int64atomics,
+ int64image_ext,
+ int8,
+ interpolation_function,
+ kernel,
+ linkage,
+ literal_sampler,
+ long_vector_ext,
+ matrix,
+ mesh_shading_ext,
+ min_lod,
+ multi_view,
+ multi_viewport,
+ named_barrier,
+ opt_none_ext,
+ physical_storage_buffer_addresses,
+ pipe_storage,
+ pipes,
+ poison_freeze_khr,
+ quad_control_khr,
+ ray_cull_mask_khr,
+ ray_query_khr,
+ ray_query_position_fetch_khr,
+ ray_query_provisional_khr,
+ ray_tracing_khr,
+ ray_tracing_opacity_micromap_ext,
+ ray_tracing_position_fetch_khr,
+ ray_tracing_provisional_khr,
+ ray_traversal_primitive_culling_khr,
+ replicated_composites_ext,
+ runtime_descriptor_array,
+ sample_mask_post_depth_coverage,
+ sample_rate_shading,
+ sampled_buffer,
+ sampled_cube_array,
+ sampled_image_array_dynamic_indexing,
+ sampled_image_array_non_uniform_indexing,
+ sampled_rect,
+ shader,
+ shader64bit_indexing_ext,
+ shader_clock_khr,
+ shader_invocation_reorder_ext,
+ shader_layer,
+ shader_non_uniform,
+ shader_viewport_index,
+ shader_viewport_index_layer_ext,
+ signed_zero_inf_nan_preserve,
+ sparse_residency,
+ SPV_EXT_arithmetic_fence,
+ SPV_EXT_demote_to_helper_invocation,
+ SPV_EXT_descriptor_heap,
+ SPV_EXT_descriptor_indexing,
+ SPV_EXT_float8,
+ SPV_EXT_fragment_fully_covered,
+ SPV_EXT_fragment_invocation_density,
+ SPV_EXT_fragment_shader_interlock,
+ SPV_EXT_long_vector,
+ SPV_EXT_mesh_shader,
+ SPV_EXT_opacity_micromap,
+ SPV_EXT_optnone,
+ SPV_EXT_physical_storage_buffer,
+ SPV_EXT_replicated_composites,
+ SPV_EXT_shader_64bit_indexing,
+ SPV_EXT_shader_atomic_float16_add,
+ SPV_EXT_shader_atomic_float_add,
+ SPV_EXT_shader_atomic_float_min_max,
+ SPV_EXT_shader_image_int64,
+ SPV_EXT_shader_invocation_reorder,
+ SPV_EXT_shader_stencil_export,
+ SPV_EXT_shader_subgroup_partitioned,
+ SPV_EXT_shader_tile_image,
+ SPV_EXT_shader_viewport_index_layer,
+ SPV_KHR_16bit_storage,
+ SPV_KHR_8bit_storage,
+ SPV_KHR_abort,
+ SPV_KHR_bfloat16,
+ SPV_KHR_bit_instructions,
+ SPV_KHR_compute_shader_derivatives,
+ SPV_KHR_constant_data,
+ SPV_KHR_cooperative_matrix,
+ SPV_KHR_device_group,
+ SPV_KHR_expect_assume,
+ SPV_KHR_float_controls,
+ SPV_KHR_float_controls2,
+ SPV_KHR_fma,
+ SPV_KHR_fragment_shader_barycentric,
+ SPV_KHR_fragment_shading_rate,
+ SPV_KHR_integer_dot_product,
+ SPV_KHR_multiview,
+ SPV_KHR_physical_storage_buffer,
+ SPV_KHR_poison_freeze,
+ SPV_KHR_post_depth_coverage,
+ SPV_KHR_quad_control,
+ SPV_KHR_ray_cull_mask,
+ SPV_KHR_ray_query,
+ SPV_KHR_ray_tracing,
+ SPV_KHR_ray_tracing_position_fetch,
+ SPV_KHR_shader_atomic_counter_ops,
+ SPV_KHR_shader_ballot,
+ SPV_KHR_shader_clock,
+ SPV_KHR_shader_draw_parameters,
+ SPV_KHR_subgroup_rotate,
+ SPV_KHR_subgroup_vote,
+ SPV_KHR_uniform_group_instructions,
+ SPV_KHR_untyped_pointers,
+ SPV_KHR_variable_pointers,
+ SPV_KHR_vulkan_memory_model,
+ SPV_KHR_workgroup_memory_explicit_layout,
+ stencil_export_ext,
+ storage_buffer16bit_access,
+ storage_buffer8bit_access,
+ storage_buffer_array_dynamic_indexing,
+ storage_buffer_array_non_uniform_indexing,
+ storage_image_array_dynamic_indexing,
+ storage_image_array_non_uniform_indexing,
+ storage_image_extended_formats,
+ storage_image_multisample,
+ storage_image_read_without_format,
+ storage_image_write_without_format,
+ storage_input_output16,
storage_push_constant16,
+ storage_push_constant8,
+ storage_texel_buffer_array_dynamic_indexing,
+ storage_texel_buffer_array_non_uniform_indexing,
+ subgroup_ballot_khr,
+ subgroup_dispatch,
+ subgroup_vote_khr,
+ tessellation,
+ tessellation_point_size,
+ tile_image_color_read_access_ext,
+ tile_image_depth_read_access_ext,
+ tile_image_stencil_read_access_ext,
+ transform_feedback,
+ uniform_and_storage_buffer16bit_access,
+ uniform_and_storage_buffer8bit_access,
+ uniform_buffer_array_dynamic_indexing,
+ uniform_buffer_array_non_uniform_indexing,
+ uniform_decoration,
+ uniform_texel_buffer_array_dynamic_indexing,
+ uniform_texel_buffer_array_non_uniform_indexing,
+ untyped_pointers_khr,
v1_0,
v1_1,
v1_2,
@@ -19,7 +232,13 @@ pub const Feature = enum {
v1_5,
v1_6,
variable_pointers,
+ variable_pointers_storage_buffer,
vector16,
+ vulkan_memory_model,
+ vulkan_memory_model_device_scope,
+ workgroup_memory_explicit_layout16bit_access_khr,
+ workgroup_memory_explicit_layout8bit_access_khr,
+ workgroup_memory_explicit_layout_khr,
};
pub const featureSet = CpuFeature.FeatureSetFns(Feature).featureSet;
@@ -32,109 +251,1611 @@ pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
- result[@intFromEnum(Feature.arbitrary_precision_integers)] = .{
+ result[@intFromEnum(Feature.abort_khr)] = .{
.llvm_name = null,
- .description = "Enable SPV_INTEL_arbitrary_precision_integers extension and the ArbitraryPrecisionIntegersINTEL capability",
+ .description = "Enable abort_khr Capability.",
.dependencies = featureSet(&[_]Feature{
- .v1_5,
+ .SPV_KHR_abort,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.addresses)] = .{
+ .llvm_name = null,
+ .description = "Enable addresses Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.arithmetic_fence_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable arithmetic_fence_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_arithmetic_fence,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.atomic_float16add_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable atomic_float16add_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_shader_atomic_float16_add,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.atomic_float16min_max_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable atomic_float16min_max_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_shader_atomic_float_min_max,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.atomic_float32add_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable atomic_float32add_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_shader_atomic_float_add,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.atomic_float32min_max_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable atomic_float32min_max_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_shader_atomic_float_min_max,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.atomic_float64add_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable atomic_float64add_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_shader_atomic_float_add,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.atomic_float64min_max_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable atomic_float64min_max_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_shader_atomic_float_min_max,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.atomic_storage)] = .{
+ .llvm_name = null,
+ .description = "Enable atomic_storage Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.atomic_storage_ops)] = .{
+ .llvm_name = null,
+ .description = "Enable atomic_storage_ops Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_shader_atomic_counter_ops,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.b_float16cooperative_matrix_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable b_float16cooperative_matrix_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_bfloat16,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.b_float16dot_product_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable b_float16dot_product_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_bfloat16,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.b_float16type_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable b_float16type_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_bfloat16,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.bit_instructions)] = .{
+ .llvm_name = null,
+ .description = "Enable bit_instructions Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_bit_instructions,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.clip_distance)] = .{
+ .llvm_name = null,
+ .description = "Enable clip_distance Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.compute_derivative_group_linear_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable compute_derivative_group_linear_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_compute_shader_derivatives,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.compute_derivative_group_quads_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable compute_derivative_group_quads_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_compute_shader_derivatives,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.constant_data_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable constant_data_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_constant_data,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.cooperative_matrix_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable cooperative_matrix_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_cooperative_matrix,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.cull_distance)] = .{
+ .llvm_name = null,
+ .description = "Enable cull_distance Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.demote_to_helper_invocation)] = .{
+ .llvm_name = null,
+ .description = "Enable demote_to_helper_invocation Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_demote_to_helper_invocation,
+ .v1_6,
+ }),
+ };
+ result[@intFromEnum(Feature.denorm_flush_to_zero)] = .{
+ .llvm_name = null,
+ .description = "Enable denorm_flush_to_zero Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_float_controls,
+ .v1_4,
+ }),
+ };
+ result[@intFromEnum(Feature.denorm_preserve)] = .{
+ .llvm_name = null,
+ .description = "Enable denorm_preserve Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_float_controls,
+ .v1_4,
+ }),
+ };
+ result[@intFromEnum(Feature.derivative_control)] = .{
+ .llvm_name = null,
+ .description = "Enable derivative_control Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.descriptor_heap_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable descriptor_heap_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_descriptor_heap,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.device_enqueue)] = .{
+ .llvm_name = null,
+ .description = "Enable device_enqueue Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.device_group)] = .{
+ .llvm_name = null,
+ .description = "Enable device_group Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_device_group,
+ .v1_3,
+ }),
+ };
+ result[@intFromEnum(Feature.dot_product)] = .{
+ .llvm_name = null,
+ .description = "Enable dot_product Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_integer_dot_product,
+ .v1_6,
+ }),
+ };
+ result[@intFromEnum(Feature.dot_product_input4x8bit)] = .{
+ .llvm_name = null,
+ .description = "Enable dot_product_input4x8bit Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_integer_dot_product,
+ .v1_6,
+ }),
+ };
+ result[@intFromEnum(Feature.dot_product_input4x8bit_packed)] = .{
+ .llvm_name = null,
+ .description = "Enable dot_product_input4x8bit_packed Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_integer_dot_product,
+ .v1_6,
+ }),
+ };
+ result[@intFromEnum(Feature.dot_product_input_all)] = .{
+ .llvm_name = null,
+ .description = "Enable dot_product_input_all Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_integer_dot_product,
+ .v1_6,
+ }),
+ };
+ result[@intFromEnum(Feature.draw_parameters)] = .{
+ .llvm_name = null,
+ .description = "Enable draw_parameters Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_shader_draw_parameters,
+ .v1_3,
+ }),
+ };
+ result[@intFromEnum(Feature.expect_assume_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable expect_assume_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_expect_assume,
+ .v1_0,
}),
};
result[@intFromEnum(Feature.float16)] = .{
.llvm_name = null,
- .description = "Enable Float16 capability",
+ .description = "Enable float16 Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.float16buffer)] = .{
+ .llvm_name = null,
+ .description = "Enable float16buffer Capability.",
.dependencies = featureSet(&[_]Feature{
.v1_0,
}),
};
result[@intFromEnum(Feature.float64)] = .{
.llvm_name = null,
- .description = "Enable Float64 capability",
+ .description = "Enable float64 Capability.",
.dependencies = featureSet(&[_]Feature{
.v1_0,
}),
};
+ result[@intFromEnum(Feature.float8cooperative_matrix_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable float8cooperative_matrix_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_float8,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.float8ext)] = .{
+ .llvm_name = null,
+ .description = "Enable float8ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_float8,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.float_controls2)] = .{
+ .llvm_name = null,
+ .description = "Enable float_controls2 Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_float_controls2,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.fmakhr)] = .{
+ .llvm_name = null,
+ .description = "Enable fmakhr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_fma,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.fragment_barycentric_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable fragment_barycentric_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_fragment_shader_barycentric,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.fragment_density_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable fragment_density_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_fragment_invocation_density,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.fragment_fully_covered_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable fragment_fully_covered_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_fragment_fully_covered,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.fragment_shader_pixel_interlock_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable fragment_shader_pixel_interlock_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_fragment_shader_interlock,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.fragment_shader_sample_interlock_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable fragment_shader_sample_interlock_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_fragment_shader_interlock,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.fragment_shader_shading_rate_interlock_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable fragment_shader_shading_rate_interlock_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_fragment_shader_interlock,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.fragment_shading_rate_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable fragment_shading_rate_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_fragment_shading_rate,
+ .v1_0,
+ }),
+ };
result[@intFromEnum(Feature.generic_pointer)] = .{
.llvm_name = null,
- .description = "Enable GenericPointer capability",
+ .description = "Enable generic_pointer Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.geometry)] = .{
+ .llvm_name = null,
+ .description = "Enable geometry Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.geometry_point_size)] = .{
+ .llvm_name = null,
+ .description = "Enable geometry_point_size Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.geometry_streams)] = .{
+ .llvm_name = null,
+ .description = "Enable geometry_streams Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.group_non_uniform)] = .{
+ .llvm_name = null,
+ .description = "Enable group_non_uniform Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_3,
+ }),
+ };
+ result[@intFromEnum(Feature.group_non_uniform_arithmetic)] = .{
+ .llvm_name = null,
+ .description = "Enable group_non_uniform_arithmetic Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_3,
+ }),
+ };
+ result[@intFromEnum(Feature.group_non_uniform_ballot)] = .{
+ .llvm_name = null,
+ .description = "Enable group_non_uniform_ballot Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_3,
+ }),
+ };
+ result[@intFromEnum(Feature.group_non_uniform_clustered)] = .{
+ .llvm_name = null,
+ .description = "Enable group_non_uniform_clustered Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_3,
+ }),
+ };
+ result[@intFromEnum(Feature.group_non_uniform_partitioned_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable group_non_uniform_partitioned_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_shader_subgroup_partitioned,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.group_non_uniform_quad)] = .{
+ .llvm_name = null,
+ .description = "Enable group_non_uniform_quad Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_3,
+ }),
+ };
+ result[@intFromEnum(Feature.group_non_uniform_rotate_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable group_non_uniform_rotate_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_subgroup_rotate,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.group_non_uniform_shuffle)] = .{
+ .llvm_name = null,
+ .description = "Enable group_non_uniform_shuffle Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_3,
+ }),
+ };
+ result[@intFromEnum(Feature.group_non_uniform_shuffle_relative)] = .{
+ .llvm_name = null,
+ .description = "Enable group_non_uniform_shuffle_relative Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_3,
+ }),
+ };
+ result[@intFromEnum(Feature.group_non_uniform_vote)] = .{
+ .llvm_name = null,
+ .description = "Enable group_non_uniform_vote Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_3,
+ }),
+ };
+ result[@intFromEnum(Feature.group_uniform_arithmetic_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable group_uniform_arithmetic_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_uniform_group_instructions,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.groups)] = .{
+ .llvm_name = null,
+ .description = "Enable groups Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.image_basic)] = .{
+ .llvm_name = null,
+ .description = "Enable image_basic Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.image_buffer)] = .{
+ .llvm_name = null,
+ .description = "Enable image_buffer Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.image_cube_array)] = .{
+ .llvm_name = null,
+ .description = "Enable image_cube_array Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.image_gather_extended)] = .{
+ .llvm_name = null,
+ .description = "Enable image_gather_extended Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.image_mipmap)] = .{
+ .llvm_name = null,
+ .description = "Enable image_mipmap Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.image_ms_array)] = .{
+ .llvm_name = null,
+ .description = "Enable image_ms_array Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.image_query)] = .{
+ .llvm_name = null,
+ .description = "Enable image_query Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.image_read_write)] = .{
+ .llvm_name = null,
+ .description = "Enable image_read_write Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.image_rect)] = .{
+ .llvm_name = null,
+ .description = "Enable image_rect Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.input_attachment)] = .{
+ .llvm_name = null,
+ .description = "Enable input_attachment Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.input_attachment_array_dynamic_indexing)] = .{
+ .llvm_name = null,
+ .description = "Enable input_attachment_array_dynamic_indexing Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_descriptor_indexing,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.input_attachment_array_non_uniform_indexing)] = .{
+ .llvm_name = null,
+ .description = "Enable input_attachment_array_non_uniform_indexing Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_descriptor_indexing,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.int16)] = .{
+ .llvm_name = null,
+ .description = "Enable int16 Capability.",
.dependencies = featureSet(&[_]Feature{
.v1_0,
}),
};
result[@intFromEnum(Feature.int64)] = .{
.llvm_name = null,
- .description = "Enable Int64 capability",
+ .description = "Enable int64 Capability.",
.dependencies = featureSet(&[_]Feature{
.v1_0,
}),
};
+ result[@intFromEnum(Feature.int64atomics)] = .{
+ .llvm_name = null,
+ .description = "Enable int64atomics Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.int64image_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable int64image_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_shader_image_int64,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.int8)] = .{
+ .llvm_name = null,
+ .description = "Enable int8 Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.interpolation_function)] = .{
+ .llvm_name = null,
+ .description = "Enable interpolation_function Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.kernel)] = .{
+ .llvm_name = null,
+ .description = "Enable kernel Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.linkage)] = .{
+ .llvm_name = null,
+ .description = "Enable linkage Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.literal_sampler)] = .{
+ .llvm_name = null,
+ .description = "Enable literal_sampler Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.long_vector_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable long_vector_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_long_vector,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.matrix)] = .{
+ .llvm_name = null,
+ .description = "Enable matrix Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.mesh_shading_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable mesh_shading_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_mesh_shader,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.min_lod)] = .{
+ .llvm_name = null,
+ .description = "Enable min_lod Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.multi_view)] = .{
+ .llvm_name = null,
+ .description = "Enable multi_view Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_multiview,
+ .v1_3,
+ }),
+ };
+ result[@intFromEnum(Feature.multi_viewport)] = .{
+ .llvm_name = null,
+ .description = "Enable multi_viewport Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.named_barrier)] = .{
+ .llvm_name = null,
+ .description = "Enable named_barrier Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_1,
+ }),
+ };
+ result[@intFromEnum(Feature.opt_none_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable opt_none_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_optnone,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.physical_storage_buffer_addresses)] = .{
+ .llvm_name = null,
+ .description = "Enable physical_storage_buffer_addresses Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_physical_storage_buffer,
+ .SPV_KHR_physical_storage_buffer,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.pipe_storage)] = .{
+ .llvm_name = null,
+ .description = "Enable pipe_storage Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_1,
+ }),
+ };
+ result[@intFromEnum(Feature.pipes)] = .{
+ .llvm_name = null,
+ .description = "Enable pipes Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.poison_freeze_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable poison_freeze_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_poison_freeze,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.quad_control_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable quad_control_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_quad_control,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.ray_cull_mask_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable ray_cull_mask_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_ray_cull_mask,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.ray_query_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable ray_query_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_ray_query,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.ray_query_position_fetch_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable ray_query_position_fetch_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_ray_tracing_position_fetch,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.ray_query_provisional_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable ray_query_provisional_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_ray_query,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.ray_tracing_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable ray_tracing_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_ray_tracing,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.ray_tracing_opacity_micromap_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable ray_tracing_opacity_micromap_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_opacity_micromap,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.ray_tracing_position_fetch_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable ray_tracing_position_fetch_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_ray_tracing_position_fetch,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.ray_tracing_provisional_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable ray_tracing_provisional_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_ray_tracing,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.ray_traversal_primitive_culling_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable ray_traversal_primitive_culling_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_ray_query,
+ .SPV_KHR_ray_tracing,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.replicated_composites_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable replicated_composites_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_replicated_composites,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.runtime_descriptor_array)] = .{
+ .llvm_name = null,
+ .description = "Enable runtime_descriptor_array Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_descriptor_indexing,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.sample_mask_post_depth_coverage)] = .{
+ .llvm_name = null,
+ .description = "Enable sample_mask_post_depth_coverage Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_post_depth_coverage,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.sample_rate_shading)] = .{
+ .llvm_name = null,
+ .description = "Enable sample_rate_shading Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.sampled_buffer)] = .{
+ .llvm_name = null,
+ .description = "Enable sampled_buffer Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.sampled_cube_array)] = .{
+ .llvm_name = null,
+ .description = "Enable sampled_cube_array Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.sampled_image_array_dynamic_indexing)] = .{
+ .llvm_name = null,
+ .description = "Enable sampled_image_array_dynamic_indexing Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.sampled_image_array_non_uniform_indexing)] = .{
+ .llvm_name = null,
+ .description = "Enable sampled_image_array_non_uniform_indexing Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_descriptor_indexing,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.sampled_rect)] = .{
+ .llvm_name = null,
+ .description = "Enable sampled_rect Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.shader)] = .{
+ .llvm_name = null,
+ .description = "Enable shader Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.shader64bit_indexing_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable shader64bit_indexing_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_shader_64bit_indexing,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.shader_clock_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable shader_clock_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_shader_clock,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.shader_invocation_reorder_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable shader_invocation_reorder_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_shader_invocation_reorder,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.shader_layer)] = .{
+ .llvm_name = null,
+ .description = "Enable shader_layer Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.shader_non_uniform)] = .{
+ .llvm_name = null,
+ .description = "Enable shader_non_uniform Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_descriptor_indexing,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.shader_viewport_index)] = .{
+ .llvm_name = null,
+ .description = "Enable shader_viewport_index Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.shader_viewport_index_layer_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable shader_viewport_index_layer_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_shader_viewport_index_layer,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.signed_zero_inf_nan_preserve)] = .{
+ .llvm_name = null,
+ .description = "Enable signed_zero_inf_nan_preserve Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_float_controls,
+ .v1_4,
+ }),
+ };
+ result[@intFromEnum(Feature.sparse_residency)] = .{
+ .llvm_name = null,
+ .description = "Enable sparse_residency Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_arithmetic_fence)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_arithmetic_fence Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_demote_to_helper_invocation)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_demote_to_helper_invocation Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_descriptor_heap)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_descriptor_heap Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_descriptor_indexing)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_descriptor_indexing Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_float8)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_float8 Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_fragment_fully_covered)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_fragment_fully_covered Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_fragment_invocation_density)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_fragment_invocation_density Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_fragment_shader_interlock)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_fragment_shader_interlock Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_long_vector)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_long_vector Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_mesh_shader)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_mesh_shader Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_opacity_micromap)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_opacity_micromap Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_optnone)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_optnone Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_physical_storage_buffer)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_physical_storage_buffer Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_replicated_composites)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_replicated_composites Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_shader_64bit_indexing)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_shader_64bit_indexing Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_shader_atomic_float16_add)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_shader_atomic_float16_add Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_shader_atomic_float_add)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_shader_atomic_float_add Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_shader_atomic_float_min_max)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_shader_atomic_float_min_max Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_shader_image_int64)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_shader_image_int64 Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_shader_invocation_reorder)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_shader_invocation_reorder Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_shader_stencil_export)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_shader_stencil_export Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_shader_subgroup_partitioned)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_shader_subgroup_partitioned Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_shader_tile_image)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_shader_tile_image Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_EXT_shader_viewport_index_layer)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_EXT_shader_viewport_index_layer Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_16bit_storage)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_16bit_storage Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_8bit_storage)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_8bit_storage Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_abort)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_abort Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_bfloat16)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_bfloat16 Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_bit_instructions)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_bit_instructions Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_compute_shader_derivatives)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_compute_shader_derivatives Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_constant_data)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_constant_data Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_cooperative_matrix)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_cooperative_matrix Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_device_group)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_device_group Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_expect_assume)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_expect_assume Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_float_controls)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_float_controls Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_float_controls2)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_float_controls2 Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_fma)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_fma Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_fragment_shader_barycentric)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_fragment_shader_barycentric Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_fragment_shading_rate)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_fragment_shading_rate Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_integer_dot_product)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_integer_dot_product Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_multiview)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_multiview Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_physical_storage_buffer)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_physical_storage_buffer Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_poison_freeze)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_poison_freeze Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_post_depth_coverage)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_post_depth_coverage Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_quad_control)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_quad_control Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_ray_cull_mask)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_ray_cull_mask Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_ray_query)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_ray_query Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_ray_tracing)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_ray_tracing Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_ray_tracing_position_fetch)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_ray_tracing_position_fetch Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_shader_atomic_counter_ops)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_shader_atomic_counter_ops Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_shader_ballot)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_shader_ballot Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_shader_clock)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_shader_clock Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_shader_draw_parameters)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_shader_draw_parameters Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_subgroup_rotate)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_subgroup_rotate Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_subgroup_vote)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_subgroup_vote Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_uniform_group_instructions)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_uniform_group_instructions Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_untyped_pointers)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_untyped_pointers Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_variable_pointers)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_variable_pointers Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_vulkan_memory_model)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_vulkan_memory_model Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.SPV_KHR_workgroup_memory_explicit_layout)] = .{
+ .llvm_name = null,
+ .description = "Enable SPV_KHR_workgroup_memory_explicit_layout Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@intFromEnum(Feature.stencil_export_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable stencil_export_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_shader_stencil_export,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.storage_buffer16bit_access)] = .{
+ .llvm_name = null,
+ .description = "Enable storage_buffer16bit_access Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_16bit_storage,
+ .v1_3,
+ }),
+ };
+ result[@intFromEnum(Feature.storage_buffer8bit_access)] = .{
+ .llvm_name = null,
+ .description = "Enable storage_buffer8bit_access Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_8bit_storage,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.storage_buffer_array_dynamic_indexing)] = .{
+ .llvm_name = null,
+ .description = "Enable storage_buffer_array_dynamic_indexing Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.storage_buffer_array_non_uniform_indexing)] = .{
+ .llvm_name = null,
+ .description = "Enable storage_buffer_array_non_uniform_indexing Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_descriptor_indexing,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.storage_image_array_dynamic_indexing)] = .{
+ .llvm_name = null,
+ .description = "Enable storage_image_array_dynamic_indexing Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.storage_image_array_non_uniform_indexing)] = .{
+ .llvm_name = null,
+ .description = "Enable storage_image_array_non_uniform_indexing Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_descriptor_indexing,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.storage_image_extended_formats)] = .{
+ .llvm_name = null,
+ .description = "Enable storage_image_extended_formats Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.storage_image_multisample)] = .{
+ .llvm_name = null,
+ .description = "Enable storage_image_multisample Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.storage_image_read_without_format)] = .{
+ .llvm_name = null,
+ .description = "Enable storage_image_read_without_format Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.storage_image_write_without_format)] = .{
+ .llvm_name = null,
+ .description = "Enable storage_image_write_without_format Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.storage_input_output16)] = .{
+ .llvm_name = null,
+ .description = "Enable storage_input_output16 Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_16bit_storage,
+ .v1_3,
+ }),
+ };
result[@intFromEnum(Feature.storage_push_constant16)] = .{
.llvm_name = null,
- .description = "Enable SPV_KHR_16bit_storage extension and the StoragePushConstant16 capability",
+ .description = "Enable storage_push_constant16 Capability.",
.dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_16bit_storage,
.v1_3,
}),
};
+ result[@intFromEnum(Feature.storage_push_constant8)] = .{
+ .llvm_name = null,
+ .description = "Enable storage_push_constant8 Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_8bit_storage,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.storage_texel_buffer_array_dynamic_indexing)] = .{
+ .llvm_name = null,
+ .description = "Enable storage_texel_buffer_array_dynamic_indexing Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_descriptor_indexing,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.storage_texel_buffer_array_non_uniform_indexing)] = .{
+ .llvm_name = null,
+ .description = "Enable storage_texel_buffer_array_non_uniform_indexing Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_descriptor_indexing,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.subgroup_ballot_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable subgroup_ballot_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_shader_ballot,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.subgroup_dispatch)] = .{
+ .llvm_name = null,
+ .description = "Enable subgroup_dispatch Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_1,
+ }),
+ };
+ result[@intFromEnum(Feature.subgroup_vote_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable subgroup_vote_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_subgroup_vote,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.tessellation)] = .{
+ .llvm_name = null,
+ .description = "Enable tessellation Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.tessellation_point_size)] = .{
+ .llvm_name = null,
+ .description = "Enable tessellation_point_size Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.tile_image_color_read_access_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable tile_image_color_read_access_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_shader_tile_image,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.tile_image_depth_read_access_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable tile_image_depth_read_access_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_shader_tile_image,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.tile_image_stencil_read_access_ext)] = .{
+ .llvm_name = null,
+ .description = "Enable tile_image_stencil_read_access_ext Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_shader_tile_image,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.transform_feedback)] = .{
+ .llvm_name = null,
+ .description = "Enable transform_feedback Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.uniform_and_storage_buffer16bit_access)] = .{
+ .llvm_name = null,
+ .description = "Enable uniform_and_storage_buffer16bit_access Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_16bit_storage,
+ .v1_3,
+ }),
+ };
+ result[@intFromEnum(Feature.uniform_and_storage_buffer8bit_access)] = .{
+ .llvm_name = null,
+ .description = "Enable uniform_and_storage_buffer8bit_access Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_8bit_storage,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.uniform_buffer_array_dynamic_indexing)] = .{
+ .llvm_name = null,
+ .description = "Enable uniform_buffer_array_dynamic_indexing Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.uniform_buffer_array_non_uniform_indexing)] = .{
+ .llvm_name = null,
+ .description = "Enable uniform_buffer_array_non_uniform_indexing Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_descriptor_indexing,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.uniform_decoration)] = .{
+ .llvm_name = null,
+ .description = "Enable uniform_decoration Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .v1_6,
+ }),
+ };
+ result[@intFromEnum(Feature.uniform_texel_buffer_array_dynamic_indexing)] = .{
+ .llvm_name = null,
+ .description = "Enable uniform_texel_buffer_array_dynamic_indexing Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_descriptor_indexing,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.uniform_texel_buffer_array_non_uniform_indexing)] = .{
+ .llvm_name = null,
+ .description = "Enable uniform_texel_buffer_array_non_uniform_indexing Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_EXT_descriptor_indexing,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.untyped_pointers_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable untyped_pointers_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_untyped_pointers,
+ .v1_0,
+ }),
+ };
result[@intFromEnum(Feature.v1_0)] = .{
.llvm_name = null,
- .description = "Enable version 1.0",
+ .description = "Enable v1_0 Extension.",
.dependencies = featureSet(&[_]Feature{}),
};
result[@intFromEnum(Feature.v1_1)] = .{
.llvm_name = null,
- .description = "Enable version 1.1",
- .dependencies = featureSet(&[_]Feature{
- .v1_0,
- }),
+ .description = "Enable v1_1 Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
};
result[@intFromEnum(Feature.v1_2)] = .{
.llvm_name = null,
- .description = "Enable version 1.2",
- .dependencies = featureSet(&[_]Feature{
- .v1_1,
- }),
+ .description = "Enable v1_2 Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
};
result[@intFromEnum(Feature.v1_3)] = .{
.llvm_name = null,
- .description = "Enable version 1.3",
- .dependencies = featureSet(&[_]Feature{
- .v1_2,
- }),
+ .description = "Enable v1_3 Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
};
result[@intFromEnum(Feature.v1_4)] = .{
.llvm_name = null,
- .description = "Enable version 1.4",
- .dependencies = featureSet(&[_]Feature{
- .v1_3,
- }),
+ .description = "Enable v1_4 Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
};
result[@intFromEnum(Feature.v1_5)] = .{
.llvm_name = null,
- .description = "Enable version 1.5",
- .dependencies = featureSet(&[_]Feature{
- .v1_4,
- }),
+ .description = "Enable v1_5 Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
};
result[@intFromEnum(Feature.v1_6)] = .{
.llvm_name = null,
- .description = "Enable version 1.6",
- .dependencies = featureSet(&[_]Feature{
- .v1_5,
- }),
+ .description = "Enable v1_6 Extension.",
+ .dependencies = featureSet(&[_]Feature{}),
};
result[@intFromEnum(Feature.variable_pointers)] = .{
.llvm_name = null,
- .description = "Enable SPV_KHR_variable_pointers extension and the VariablePointers capability",
+ .description = "Enable variable_pointers Capability.",
.dependencies = featureSet(&[_]Feature{
- .v1_0,
+ .SPV_KHR_variable_pointers,
+ .v1_3,
+ }),
+ };
+ result[@intFromEnum(Feature.variable_pointers_storage_buffer)] = .{
+ .llvm_name = null,
+ .description = "Enable variable_pointers_storage_buffer Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_variable_pointers,
+ .v1_3,
}),
};
result[@intFromEnum(Feature.vector16)] = .{
.llvm_name = null,
- .description = "Enable Vector16 capability",
+ .description = "Enable vector16 Capability.",
.dependencies = featureSet(&[_]Feature{
.v1_0,
}),
};
+ result[@intFromEnum(Feature.vulkan_memory_model)] = .{
+ .llvm_name = null,
+ .description = "Enable vulkan_memory_model Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_vulkan_memory_model,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.vulkan_memory_model_device_scope)] = .{
+ .llvm_name = null,
+ .description = "Enable vulkan_memory_model_device_scope Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_vulkan_memory_model,
+ .v1_5,
+ }),
+ };
+ result[@intFromEnum(Feature.workgroup_memory_explicit_layout16bit_access_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable workgroup_memory_explicit_layout16bit_access_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_workgroup_memory_explicit_layout,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.workgroup_memory_explicit_layout8bit_access_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable workgroup_memory_explicit_layout8bit_access_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_workgroup_memory_explicit_layout,
+ .v1_0,
+ }),
+ };
+ result[@intFromEnum(Feature.workgroup_memory_explicit_layout_khr)] = .{
+ .llvm_name = null,
+ .description = "Enable workgroup_memory_explicit_layout_khr Capability.",
+ .dependencies = featureSet(&[_]Feature{
+ .SPV_KHR_workgroup_memory_explicit_layout,
+ .v1_0,
+ }),
+ };
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig
index d7e4f0f0190058dbfa8baadd99cee183826cccc6..4f7b457c287f65311239290cce9019c6a9622cf7 100644
--- a/lib/std/Thread.zig
+++ b/lib/std/Thread.zig
@@ -1171,7 +1171,7 @@ const LinuxThreadImpl = struct {
[len] "{ecx}" (self.mapped.len),
),
.x86_64 => asm volatile (switch (target.abi) {
- .gnux32, .muslx32 =>
+ .gnux32, .muslx32, .x32 =>
\\ movl $0x4000000b, %%eax # SYS_munmap
\\ syscall
\\ movl $0x4000003c, %%eax # SYS_exit
@@ -1286,7 +1286,7 @@ const LinuxThreadImpl = struct {
[len] "{$5}" (self.mapped.len),
),
.mips64, .mips64el => asm volatile (switch (target.abi) {
- .gnuabin32, .muslabin32 =>
+ .gnuabin32, .muslabin32, .abin32 =>
\\ li $v0, 6011 # SYS_munmap
\\ syscall
\\ li $v0, 6058 # SYS_exit
diff --git a/lib/std/c.zig b/lib/std/c.zig
index 5c61cbb676d9e73309af48f0d898cb2e9ddab48d..13a2b7eb4e6607ba9ea1fba0fe6a19feec998890 100644
--- a/lib/std/c.zig
+++ b/lib/std/c.zig
@@ -11389,6 +11389,7 @@ pub const clock_res_t = darwin.clock_res_t;
pub const @"close$NOCANCEL" = darwin.@"close$NOCANCEL";
pub const dispatch = darwin.dispatch;
pub const fcopyfile = darwin.fcopyfile;
+pub const renameatx_np = darwin.renameatx_np;
pub const host_t = darwin.host_t;
pub const integer_t = darwin.integer_t;
pub const ipc_space_t = darwin.ipc_space_t;
diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig
index 7e475a057b87df7e68bbce4c5c681510405bd780..1a24cb11331fef306846d1686119f41b0be74010 100644
--- a/lib/std/c/darwin.zig
+++ b/lib/std/c/darwin.zig
@@ -380,6 +380,18 @@ pub const copyfile_state_t = *opaque {};
pub extern "c" fn fcopyfile(from: fd_t, to: fd_t, state: ?copyfile_state_t, flags: COPYFILE) c_int;
pub extern "c" fn __getdirentries64(fd: c_int, buf_ptr: [*]u8, buf_len: usize, basep: *i64) isize;
+pub const RENAME = packed struct(u32) {
+ SECLUDE: bool = false,
+ SWAP: bool = false,
+ EXCL: bool = false,
+ RESERVED1: bool = false,
+ NOFOLLOW_ANY: bool = false,
+ RESOLVE_BENEATH: bool = false,
+ _: u26 = 0,
+};
+
+pub extern "c" fn renameatx_np(fromfd: c_int, from: [*:0]const u8, tofd: c_int, to: [*:0]const u8, flags: RENAME) c_int;
+
pub extern "c" fn mach_absolute_time() u64;
pub extern "c" fn mach_continuous_time() u64;
pub extern "c" fn mach_timebase_info(tinfo: ?*mach_timebase_info_data) kern_return_t;
diff --git a/lib/std/coff.zig b/lib/std/coff.zig
index 6286ad5657b0a660baa2fb7d3966aadc02b3572b..d855495e399fff55db9a02ade2be45d0566a7095 100644
--- a/lib/std/coff.zig
+++ b/lib/std/coff.zig
@@ -2,6 +2,12 @@ const std = @import("std.zig");
const assert = std.debug.assert;
const mem = std.mem;
+pub const archive_signature = "!\n";
+pub const archive_end_of_header = "`\n";
+
+pub const pe_signature = "PE\x00\x00";
+pub const pe_pointer_offset = 0x3C;
+
pub const Header = extern struct {
/// The number that identifies the type of target machine.
machine: IMAGE.FILE.MACHINE,
@@ -367,6 +373,36 @@ pub const DebugType = enum(u32) {
_,
};
+pub fn TlsDirectoryEntry(comptime magic: std.coff.OptionalHeader.Magic) type {
+ return switch (magic) {
+ _ => comptime unreachable,
+ .PE32 => extern struct {
+ raw_data_start_va: u32,
+ raw_data_end_va: u32,
+ tls_index_va: u32,
+ callbacks_va: u32,
+ size_of_zero_fill: u32,
+ characteristics: packed struct(u32) {
+ _reserved_0: u19,
+ alignment: SectionHeader.Flags.Align,
+ _reserved_1: u9,
+ },
+ },
+ .@"PE32+" => extern struct {
+ raw_data_start_va: u64,
+ raw_data_end_va: u64,
+ tls_index_va: u64,
+ callbacks_va: u64,
+ size_of_zero_fill: u32,
+ characteristics: packed struct(u32) {
+ _reserved_0: u19,
+ alignment: SectionHeader.Flags.Align,
+ _reserved_1: u9,
+ },
+ },
+ };
+}
+
pub const ImportDirectoryEntry = extern struct {
/// The RVA of the import lookup table.
/// This table contains a name or ordinal for each import.
@@ -389,56 +425,28 @@ pub const ImportDirectoryEntry = extern struct {
import_address_table_rva: u32,
};
-pub const ImportLookupEntry32 = struct {
- pub const ByName = packed struct(u32) {
- name_table_rva: u31,
- flag: u1 = 0,
+pub fn ImportLookupTableEntry(comptime magic: std.coff.OptionalHeader.Magic) type {
+ const Payload = packed union(u31) {
+ ordinal: packed struct(u31) {
+ ordinal: u16,
+ _: u15 = 0,
+ },
+ hint_name_rva: u31,
};
- pub const ByOrdinal = packed struct(u32) {
- ordinal_number: u16,
- unused: u15 = 0,
- flag: u1 = 1,
+ return switch (magic) {
+ _ => comptime unreachable,
+ .PE32 => packed struct(u32) {
+ payload: Payload,
+ is_ordinal: bool,
+ },
+ .@"PE32+" => packed struct(u64) {
+ payload: Payload,
+ _: u32 = 0,
+ is_ordinal: bool,
+ },
};
-
- const mask = 0x80000000;
-
- pub fn getImportByName(raw: u32) ?ByName {
- if (mask & raw != 0) return null;
- return @as(ByName, @bitCast(raw));
- }
-
- pub fn getImportByOrdinal(raw: u32) ?ByOrdinal {
- if (mask & raw == 0) return null;
- return @as(ByOrdinal, @bitCast(raw));
- }
-};
-
-pub const ImportLookupEntry64 = struct {
- pub const ByName = packed struct(u64) {
- name_table_rva: u31,
- unused: u32 = 0,
- flag: u1 = 0,
- };
-
- pub const ByOrdinal = packed struct(u64) {
- ordinal_number: u16,
- unused: u47 = 0,
- flag: u1 = 1,
- };
-
- const mask = 0x8000000000000000;
-
- pub fn getImportByName(raw: u64) ?ByName {
- if (mask & raw != 0) return null;
- return @as(ByName, @bitCast(raw));
- }
-
- pub fn getImportByOrdinal(raw: u64) ?ByOrdinal {
- if (mask & raw == 0) return null;
- return @as(ByOrdinal, @bitCast(raw));
- }
-};
+}
/// Every name ends with a NULL byte. IF the NULL byte does not fall on
/// 2byte boundary, the entry structure is padded to ensure 2byte alignment.
@@ -452,6 +460,50 @@ pub const ImportHintNameEntry = extern struct {
name: [1]u8,
};
+pub const ExportDirectoryTable = extern struct {
+ /// Reserved
+ flags: u32,
+
+ /// Creation time of this table
+ time_date_stamp: u32,
+
+ major_version: u16,
+ minor_version: u16,
+
+ /// The address of an ASCII string that contains the name of the DLL.
+ /// This address is relative to the image base.
+ name_rva: u32,
+
+ /// The ordinal of the first export in this image
+ ordinal_base: u32,
+
+ /// Number of entries in the export address table
+ number_of_entries: u32,
+
+ /// Number of entries in the name pointer table and ordinal table
+ number_of_names: u32,
+
+ export_address_table_rva: u32,
+ name_pointer_table_rva: u32,
+ ordinal_table_rva: u32,
+};
+
+pub const ExportAddressTableEntry = extern struct {
+ /// If this address is within the export section, then this is the address of the export
+ /// Otherwise, this is the address of a string that specfies a symbol in another DLL:
+ /// .
+ /// .#
+ export_or_forwarder_rva: u32,
+};
+
+pub const ExportNamePointerTableEntry = extern struct {
+ name_rva: u32,
+};
+
+pub const ExportOrdinalTableEntry = extern struct {
+ unbiased_ordinal: u16,
+};
+
pub const SectionHeader = extern struct {
name: [8]u8,
virtual_size: u32,
@@ -610,11 +662,15 @@ pub const SectionHeader = extern struct {
std.debug.assert(std.math.isPowerOfTwo(n));
return @enumFromInt(@ctz(n) + 1);
}
+
+ pub fn alignment(a: Align) ?std.mem.Alignment {
+ return .fromByteUnitsOptional(a.toByteUnits() orelse null);
+ }
};
};
};
-pub const Symbol = struct {
+pub const Symbol = extern struct {
name: [8]u8,
value: u32,
section_number: SectionNumber,
@@ -622,7 +678,7 @@ pub const Symbol = struct {
storage_class: StorageClass,
number_of_aux_symbols: u8,
- pub fn sizeOf() usize {
+ pub fn sizeOf() comptime_int {
return 18;
}
@@ -639,18 +695,18 @@ pub const Symbol = struct {
}
};
-pub const SectionNumber = enum(u16) {
+pub const SectionNumber = enum(i16) {
/// The symbol record is not yet assigned a section.
/// A value of zero indicates that a reference to an external symbol is defined elsewhere.
/// A value of non-zero is a common symbol with a size that is specified by the value.
UNDEFINED = 0,
/// The symbol has an absolute (non-relocatable) value and is not an address.
- ABSOLUTE = 0xffff,
+ ABSOLUTE = -1,
/// The symbol provides general type or debugging information but does not correspond to a section.
/// Microsoft tools use this setting along with .file records (storage class FILE).
- DEBUG = 0xfffe,
+ DEBUG = -2,
_,
};
@@ -822,7 +878,7 @@ pub const StorageClass = enum(u8) {
_,
};
-pub const FunctionDefinition = struct {
+pub const FunctionDefinition = extern struct {
/// The symbol-table index of the corresponding .bf (begin function) symbol record.
tag_index: u32,
@@ -841,7 +897,7 @@ pub const FunctionDefinition = struct {
unused: [2]u8,
};
-pub const SectionDefinition = struct {
+pub const SectionDefinition = extern struct {
/// The size of section data; the same as SizeOfRawData in the section header.
length: u32,
@@ -863,7 +919,7 @@ pub const SectionDefinition = struct {
unused: [3]u8,
};
-pub const FileDefinition = struct {
+pub const FileDefinition = extern struct {
/// An ANSI string that gives the name of the source file.
/// This is padded with nulls if it is less than the maximum length.
file_name: [18]u8,
@@ -874,7 +930,7 @@ pub const FileDefinition = struct {
}
};
-pub const WeakExternalDefinition = struct {
+pub const WeakExternalDefinition = extern struct {
/// The symbol-table index of sym2, the symbol to be linked if sym1 is not found.
tag_index: u32,
@@ -885,7 +941,7 @@ pub const WeakExternalDefinition = struct {
unused: [10]u8,
- pub fn sizeOf() usize {
+ pub fn sizeOf() comptime_int {
return 18;
}
};
@@ -933,7 +989,7 @@ pub const ComdatSelection = enum(u8) {
_,
};
-pub const DebugInfoDefinition = struct {
+pub const DebugInfoDefinition = extern struct {
unused_1: [4]u8,
/// The actual ordinal line number (1, 2, 3, and so on) within the source file, corresponding to the .bf or .ef record.
@@ -971,13 +1027,10 @@ pub const Coff = struct {
// The lifetime of `data` must be longer than the lifetime of the returned Coff
pub fn init(data: []const u8, is_loaded: bool) error{ EndOfStream, MissingPEHeader }!Coff {
- const pe_pointer_offset = 0x3C;
- const pe_magic = "PE\x00\x00";
-
if (data.len < pe_pointer_offset + 4) return error.EndOfStream;
const header_offset = mem.readInt(u32, data[pe_pointer_offset..][0..4], .little);
if (data.len < header_offset + 4) return error.EndOfStream;
- const is_image = mem.eql(u8, data[header_offset..][0..4], pe_magic);
+ const is_image = mem.eql(u8, data[header_offset..][0..4], pe_signature);
const coff: Coff = .{
.data = data,
@@ -1348,6 +1401,10 @@ pub const Relocation = extern struct {
virtual_address: u32,
symbol_table_index: u32,
type: u16,
+
+ pub fn sizeOf() comptime_int {
+ return 10;
+ }
};
pub const IMAGE = struct {
@@ -1465,6 +1522,36 @@ pub const IMAGE = struct {
_,
/// AXP 64 (Same as Alpha 64)
pub const AXP64: IMAGE.FILE.MACHINE = .ALPHA64;
+
+ pub fn RelocationType(comptime machine: IMAGE.FILE.MACHINE) type {
+ return switch (machine) {
+ .AMD64,
+ => REL.AMD64,
+ .ARM,
+ .ARMNT,
+ => REL.ARM,
+ .ARM64,
+ .ARM64EC,
+ .ARM64X,
+ => REL.ARM64,
+ .I386 => REL.I386,
+ .IA64 => REL.IA64,
+ .M32R => REL.M32R,
+ .MIPS16,
+ .MIPSFPU,
+ .MIPSFPU16,
+ => REL.MIPS,
+ .POWERPC,
+ .POWERPCFP,
+ => REL.PPC,
+ .SH3,
+ .SH3DSP,
+ .SH4,
+ .SH5,
+ => REL.SH,
+ else => void,
+ };
+ }
};
};
@@ -1919,3 +2006,100 @@ pub const IMAGE = struct {
};
};
};
+
+pub const ArchiveMemberHeader = extern struct {
+ /// Left-justified '/' terminated member name
+ name: [16]u8,
+ /// Left-justified ASCII decimal: seconds since January 1st, 1970
+ date: [12]u8,
+ /// Left-justified ASCII decimal: user id
+ user_id: [6]u8,
+ /// Left-justified ASCII decimal: group id
+ group_id: [6]u8,
+ /// Left-justified ASCII octal: file mode
+ file_mode: [8]u8,
+ /// Left-justified ASCII decimal: size of the member following this header,
+ /// not including the size of this header.
+ size: [10]u8,
+ /// The literal string '`\n'
+ end_of_header: [2]u8,
+
+ /// Extracts the name of the member by either reading it directly from
+ /// the header, or by finding it inside the longnames member, if provided.
+ pub fn parseName(
+ self: *const ArchiveMemberHeader,
+ opt_longnames: ?[]const u8,
+ ) ![]const u8 {
+ const trim = std.mem.trimEnd(u8, &self.name, &.{' '});
+
+ if (trim.len == 0) return error.BadName;
+ return if (trim[0] == '/') name: {
+ if (trim.len == 1 or
+ trim.len == 2 and trim[1] == '/')
+ break :name trim;
+
+ const offset = std.fmt.parseUnsigned(u50, trim[1..], 10) catch
+ return error.BadName;
+
+ if (opt_longnames) |longnames| {
+ if (offset >= longnames.len) return error.BadName;
+ break :name std.mem.sliceTo(longnames[@intCast(offset)..], 0);
+ } else return error.NoLongNames;
+ } else if (trim[trim.len - 1] == '/')
+ trim[0 .. trim.len - 1]
+ else
+ return error.BadName;
+ }
+
+ fn parseField(field: []const u8, T: type, base: u8) !T {
+ if (std.mem.allEqual(u8, field, ' ')) return 0;
+ if (field[0] == '-')
+ return @bitCast(try std.fmt.parseInt(
+ @Int(.signed, @typeInfo(T).int.bits),
+ std.mem.trimEnd(u8, field, &.{' '}),
+ base,
+ ));
+
+ return std.fmt.parseUnsigned(T, std.mem.trimEnd(u8, field, &.{' '}), base);
+ }
+
+ pub fn parseDate(self: *const ArchiveMemberHeader) !u40 {
+ return parseField(&self.date, u40, 10);
+ }
+
+ pub fn parseUserId(self: *const ArchiveMemberHeader) !u20 {
+ return parseField(&self.user_id, u20, 10);
+ }
+
+ pub fn parseGroupId(self: *const ArchiveMemberHeader) !u20 {
+ return parseField(&self.group_id, u20, 10);
+ }
+
+ pub fn parseFileMode(self: *const ArchiveMemberHeader) !u20 {
+ return parseField(&self.group_id, u20, 8);
+ }
+
+ pub fn parseSize(self: *const ArchiveMemberHeader) !u34 {
+ return parseField(&self.size, u34, 10);
+ }
+
+ pub const Kind = enum {
+ first_linker,
+ second_linker,
+ longnames,
+ coff,
+ import,
+ };
+};
+
+pub const LineNumber = extern struct {
+ type: extern union {
+ symbol_table_index: u32,
+ virtual_address: u32,
+ },
+ line_number: u16,
+
+ pub fn sizeOf() comptime_int {
+ return 6;
+ }
+};
diff --git a/lib/std/compress/flate/Decompress.zig b/lib/std/compress/flate/Decompress.zig
index 27743e23bfd5d63f791297fa857143db88c21c5a..8251c0c5f230c42565d77b6b05dca38be0cd6e11 100644
--- a/lib/std/compress/flate/Decompress.zig
+++ b/lib/std/compress/flate/Decompress.zig
@@ -578,7 +578,7 @@ fn peekBitsShortEnding(d: *Decompress, n: u4) !u16 {
}
fn tossBitsShort(d: *Decompress, n: u4) !void {
- if (d.input.bufferedLen() * 8 + d.consumed_bits < n) return error.EndOfStream;
+ if (d.input.bufferedLen() * 8 - d.consumed_bits < n) return error.EndOfStream;
d.tossBits(n);
}
@@ -1064,6 +1064,15 @@ test "bug 18966" {
);
}
+test "truncated input ending when reading dynamic length bits" {
+ try testFailure(.raw, &[_]u8{
+ 0x15, 0xd5, 0x07, 0x3b, 0x16, 0x0c, 0x03, 0x86,
+ 0x61, 0x2b, 0xa3, 0xec, 0xec, 0x15, 0x95, 0x6c,
+ 0x92, 0x4d, 0x19, 0x95, 0x4a, 0xb6, 0x22, 0x23,
+ 0xc9,
+ }, error.EndOfStream);
+}
+
test "reading into empty buffer" {
// Inspired by https://github.com/ziglang/zig/issues/19895
const input = &[_]u8{
diff --git a/lib/std/compress/flate/testdata/rfc1951.txt b/lib/std/compress/flate/testdata/rfc1951.txt
deleted file mode 100644
index 403c8c722ff24ca034973876fa819d37715b9b6a..0000000000000000000000000000000000000000
--- a/lib/std/compress/flate/testdata/rfc1951.txt
+++ /dev/null
@@ -1,955 +0,0 @@
-
-
-
-
-
-
-Network Working Group P. Deutsch
-Request for Comments: 1951 Aladdin Enterprises
-Category: Informational May 1996
-
-
- DEFLATE Compressed Data Format Specification version 1.3
-
-Status of This Memo
-
- This memo provides information for the Internet community. This memo
- does not specify an Internet standard of any kind. Distribution of
- this memo is unlimited.
-
-IESG Note:
-
- The IESG takes no position on the validity of any Intellectual
- Property Rights statements contained in this document.
-
-Notices
-
- Copyright (c) 1996 L. Peter Deutsch
-
- Permission is granted to copy and distribute this document for any
- purpose and without charge, including translations into other
- languages and incorporation into compilations, provided that the
- copyright notice and this notice are preserved, and that any
- substantive changes or deletions from the original are clearly
- marked.
-
- A pointer to the latest version of this and related documentation in
- HTML format can be found at the URL
- .
-
-Abstract
-
- This specification defines a lossless compressed data format that
- compresses data using a combination of the LZ77 algorithm and Huffman
- coding, with efficiency comparable to the best currently available
- general-purpose compression methods. The data can be produced or
- consumed, even for an arbitrarily long sequentially presented input
- data stream, using only an a priori bounded amount of intermediate
- storage. The format can be implemented readily in a manner not
- covered by patents.
-
-
-
-
-
-
-
-
-Deutsch Informational [Page 1]
-
-RFC 1951 DEFLATE Compressed Data Format Specification May 1996
-
-
-Table of Contents
-
- 1. Introduction ................................................... 2
- 1.1. Purpose ................................................... 2
- 1.2. Intended audience ......................................... 3
- 1.3. Scope ..................................................... 3
- 1.4. Compliance ................................................ 3
- 1.5. Definitions of terms and conventions used ................ 3
- 1.6. Changes from previous versions ............................ 4
- 2. Compressed representation overview ............................. 4
- 3. Detailed specification ......................................... 5
- 3.1. Overall conventions ....................................... 5
- 3.1.1. Packing into bytes .................................. 5
- 3.2. Compressed block format ................................... 6
- 3.2.1. Synopsis of prefix and Huffman coding ............... 6
- 3.2.2. Use of Huffman coding in the "deflate" format ....... 7
- 3.2.3. Details of block format ............................. 9
- 3.2.4. Non-compressed blocks (BTYPE=00) ................... 11
- 3.2.5. Compressed blocks (length and distance codes) ...... 11
- 3.2.6. Compression with fixed Huffman codes (BTYPE=01) .... 12
- 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) .. 13
- 3.3. Compliance ............................................... 14
- 4. Compression algorithm details ................................. 14
- 5. References .................................................... 16
- 6. Security Considerations ....................................... 16
- 7. Source code ................................................... 16
- 8. Acknowledgements .............................................. 16
- 9. Author's Address .............................................. 17
-
-1. Introduction
-
- 1.1. Purpose
-
- The purpose of this specification is to define a lossless
- compressed data format that:
- * Is independent of CPU type, operating system, file system,
- and character set, and hence can be used for interchange;
- * Can be produced or consumed, even for an arbitrarily long
- sequentially presented input data stream, using only an a
- priori bounded amount of intermediate storage, and hence
- can be used in data communications or similar structures
- such as Unix filters;
- * Compresses data with efficiency comparable to the best
- currently available general-purpose compression methods,
- and in particular considerably better than the "compress"
- program;
- * Can be implemented readily in a manner not covered by
- patents, and hence can be practiced freely;
-
-
-
-Deutsch Informational [Page 2]
-
-RFC 1951 DEFLATE Compressed Data Format Specification May 1996
-
-
- * Is compatible with the file format produced by the current
- widely used gzip utility, in that conforming decompressors
- will be able to read data produced by the existing gzip
- compressor.
-
- The data format defined by this specification does not attempt to:
-
- * Allow random access to compressed data;
- * Compress specialized data (e.g., raster graphics) as well
- as the best currently available specialized algorithms.
-
- A simple counting argument shows that no lossless compression
- algorithm can compress every possible input data set. For the
- format defined here, the worst case expansion is 5 bytes per 32K-
- byte block, i.e., a size increase of 0.015% for large data sets.
- English text usually compresses by a factor of 2.5 to 3;
- executable files usually compress somewhat less; graphical data
- such as raster images may compress much more.
-
- 1.2. Intended audience
-
- This specification is intended for use by implementors of software
- to compress data into "deflate" format and/or decompress data from
- "deflate" format.
-
- The text of the specification assumes a basic background in
- programming at the level of bits and other primitive data
- representations. Familiarity with the technique of Huffman coding
- is helpful but not required.
-
- 1.3. Scope
-
- The specification specifies a method for representing a sequence
- of bytes as a (usually shorter) sequence of bits, and a method for
- packing the latter bit sequence into bytes.
-
- 1.4. Compliance
-
- Unless otherwise indicated below, a compliant decompressor must be
- able to accept and decompress any data set that conforms to all
- the specifications presented here; a compliant compressor must
- produce data sets that conform to all the specifications presented
- here.
-
- 1.5. Definitions of terms and conventions used
-
- Byte: 8 bits stored or transmitted as a unit (same as an octet).
- For this specification, a byte is exactly 8 bits, even on machines
-
-
-
-Deutsch Informational [Page 3]
-
-RFC 1951 DEFLATE Compressed Data Format Specification May 1996
-
-
- which store a character on a number of bits different from eight.
- See below, for the numbering of bits within a byte.
-
- String: a sequence of arbitrary bytes.
-
- 1.6. Changes from previous versions
-
- There have been no technical changes to the deflate format since
- version 1.1 of this specification. In version 1.2, some
- terminology was changed. Version 1.3 is a conversion of the
- specification to RFC style.
-
-2. Compressed representation overview
-
- A compressed data set consists of a series of blocks, corresponding
- to successive blocks of input data. The block sizes are arbitrary,
- except that non-compressible blocks are limited to 65,535 bytes.
-
- Each block is compressed using a combination of the LZ77 algorithm
- and Huffman coding. The Huffman trees for each block are independent
- of those for previous or subsequent blocks; the LZ77 algorithm may
- use a reference to a duplicated string occurring in a previous block,
- up to 32K input bytes before.
-
- Each block consists of two parts: a pair of Huffman code trees that
- describe the representation of the compressed data part, and a
- compressed data part. (The Huffman trees themselves are compressed
- using Huffman encoding.) The compressed data consists of a series of
- elements of two types: literal bytes (of strings that have not been
- detected as duplicated within the previous 32K input bytes), and
- pointers to duplicated strings, where a pointer is represented as a
- pair . The representation used in the
- "deflate" format limits distances to 32K bytes and lengths to 258
- bytes, but does not limit the size of a block, except for
- uncompressible blocks, which are limited as noted above.
-
- Each type of value (literals, distances, and lengths) in the
- compressed data is represented using a Huffman code, using one code
- tree for literals and lengths and a separate code tree for distances.
- The code trees for each block appear in a compact form just before
- the compressed data for that block.
-
-
-
-
-
-
-
-
-
-
-Deutsch Informational [Page 4]
-
-RFC 1951 DEFLATE Compressed Data Format Specification May 1996
-
-
-3. Detailed specification
-
- 3.1. Overall conventions In the diagrams below, a box like this:
-
- +---+
- | | <-- the vertical bars might be missing
- +---+
-
- represents one byte; a box like this:
-
- +==============+
- | |
- +==============+
-
- represents a variable number of bytes.
-
- Bytes stored within a computer do not have a "bit order", since
- they are always treated as a unit. However, a byte considered as
- an integer between 0 and 255 does have a most- and least-
- significant bit, and since we write numbers with the most-
- significant digit on the left, we also write bytes with the most-
- significant bit on the left. In the diagrams below, we number the
- bits of a byte so that bit 0 is the least-significant bit, i.e.,
- the bits are numbered:
-
- +--------+
- |76543210|
- +--------+
-
- Within a computer, a number may occupy multiple bytes. All
- multi-byte numbers in the format described here are stored with
- the least-significant byte first (at the lower memory address).
- For example, the decimal number 520 is stored as:
-
- 0 1
- +--------+--------+
- |00001000|00000010|
- +--------+--------+
- ^ ^
- | |
- | + more significant byte = 2 x 256
- + less significant byte = 8
-
- 3.1.1. Packing into bytes
-
- This document does not address the issue of the order in which
- bits of a byte are transmitted on a bit-sequential medium,
- since the final data format described here is byte- rather than
-
-
-
-Deutsch Informational [Page 5]
-
-RFC 1951 DEFLATE Compressed Data Format Specification May 1996
-
-
- bit-oriented. However, we describe the compressed block format
- in below, as a sequence of data elements of various bit
- lengths, not a sequence of bytes. We must therefore specify
- how to pack these data elements into bytes to form the final
- compressed byte sequence:
-
- * Data elements are packed into bytes in order of
- increasing bit number within the byte, i.e., starting
- with the least-significant bit of the byte.
- * Data elements other than Huffman codes are packed
- starting with the least-significant bit of the data
- element.
- * Huffman codes are packed starting with the most-
- significant bit of the code.
-
- In other words, if one were to print out the compressed data as
- a sequence of bytes, starting with the first byte at the
- *right* margin and proceeding to the *left*, with the most-
- significant bit of each byte on the left as usual, one would be
- able to parse the result from right to left, with fixed-width
- elements in the correct MSB-to-LSB order and Huffman codes in
- bit-reversed order (i.e., with the first bit of the code in the
- relative LSB position).
-
- 3.2. Compressed block format
-
- 3.2.1. Synopsis of prefix and Huffman coding
-
- Prefix coding represents symbols from an a priori known
- alphabet by bit sequences (codes), one code for each symbol, in
- a manner such that different symbols may be represented by bit
- sequences of different lengths, but a parser can always parse
- an encoded string unambiguously symbol-by-symbol.
-
- We define a prefix code in terms of a binary tree in which the
- two edges descending from each non-leaf node are labeled 0 and
- 1 and in which the leaf nodes correspond one-for-one with (are
- labeled with) the symbols of the alphabet; then the code for a
- symbol is the sequence of 0's and 1's on the edges leading from
- the root to the leaf labeled with that symbol. For example:
-
-
-
-
-
-
-
-
-
-
-
-Deutsch Informational [Page 6]
-
-RFC 1951 DEFLATE Compressed Data Format Specification May 1996
-
-
- /\ Symbol Code
- 0 1 ------ ----
- / \ A 00
- /\ B B 1
- 0 1 C 011
- / \ D 010
- A /\
- 0 1
- / \
- D C
-
- A parser can decode the next symbol from an encoded input
- stream by walking down the tree from the root, at each step
- choosing the edge corresponding to the next input bit.
-
- Given an alphabet with known symbol frequencies, the Huffman
- algorithm allows the construction of an optimal prefix code
- (one which represents strings with those symbol frequencies
- using the fewest bits of any possible prefix codes for that
- alphabet). Such a code is called a Huffman code. (See
- reference [1] in Chapter 5, references for additional
- information on Huffman codes.)
-
- Note that in the "deflate" format, the Huffman codes for the
- various alphabets must not exceed certain maximum code lengths.
- This constraint complicates the algorithm for computing code
- lengths from symbol frequencies. Again, see Chapter 5,
- references for details.
-
- 3.2.2. Use of Huffman coding in the "deflate" format
-
- The Huffman codes used for each alphabet in the "deflate"
- format have two additional rules:
-
- * All codes of a given bit length have lexicographically
- consecutive values, in the same order as the symbols
- they represent;
-
- * Shorter codes lexicographically precede longer codes.
-
-
-
-
-
-
-
-
-
-
-
-
-Deutsch Informational [Page 7]
-
-RFC 1951 DEFLATE Compressed Data Format Specification May 1996
-
-
- We could recode the example above to follow this rule as
- follows, assuming that the order of the alphabet is ABCD:
-
- Symbol Code
- ------ ----
- A 10
- B 0
- C 110
- D 111
-
- I.e., 0 precedes 10 which precedes 11x, and 110 and 111 are
- lexicographically consecutive.
-
- Given this rule, we can define the Huffman code for an alphabet
- just by giving the bit lengths of the codes for each symbol of
- the alphabet in order; this is sufficient to determine the
- actual codes. In our example, the code is completely defined
- by the sequence of bit lengths (2, 1, 3, 3). The following
- algorithm generates the codes as integers, intended to be read
- from most- to least-significant bit. The code lengths are
- initially in tree[I].Len; the codes are produced in
- tree[I].Code.
-
- 1) Count the number of codes for each code length. Let
- bl_count[N] be the number of codes of length N, N >= 1.
-
- 2) Find the numerical value of the smallest code for each
- code length:
-
- code = 0;
- bl_count[0] = 0;
- for (bits = 1; bits <= MAX_BITS; bits++) {
- code = (code + bl_count[bits-1]) << 1;
- next_code[bits] = code;
- }
-
- 3) Assign numerical values to all codes, using consecutive
- values for all codes of the same length with the base
- values determined at step 2. Codes that are never used
- (which have a bit length of zero) must not be assigned a
- value.
-
- for (n = 0; n <= max_code; n++) {
- len = tree[n].Len;
- if (len != 0) {
- tree[n].Code = next_code[len];
- next_code[len]++;
- }
-
-
-
-Deutsch Informational [Page 8]
-
-RFC 1951 DEFLATE Compressed Data Format Specification May 1996
-
-
- }
-
- Example:
-
- Consider the alphabet ABCDEFGH, with bit lengths (3, 3, 3, 3,
- 3, 2, 4, 4). After step 1, we have:
-
- N bl_count[N]
- - -----------
- 2 1
- 3 5
- 4 2
-
- Step 2 computes the following next_code values:
-
- N next_code[N]
- - ------------
- 1 0
- 2 0
- 3 2
- 4 14
-
- Step 3 produces the following code values:
-
- Symbol Length Code
- ------ ------ ----
- A 3 010
- B 3 011
- C 3 100
- D 3 101
- E 3 110
- F 2 00
- G 4 1110
- H 4 1111
-
- 3.2.3. Details of block format
-
- Each block of compressed data begins with 3 header bits
- containing the following data:
-
- first bit BFINAL
- next 2 bits BTYPE
-
- Note that the header bits do not necessarily begin on a byte
- boundary, since a block does not necessarily occupy an integral
- number of bytes.
-
-
-
-
-
-Deutsch Informational [Page 9]
-
-RFC 1951 DEFLATE Compressed Data Format Specification May 1996
-
-
- BFINAL is set if and only if this is the last block of the data
- set.
-
- BTYPE specifies how the data are compressed, as follows:
-
- 00 - no compression
- 01 - compressed with fixed Huffman codes
- 10 - compressed with dynamic Huffman codes
- 11 - reserved (error)
-
- The only difference between the two compressed cases is how the
- Huffman codes for the literal/length and distance alphabets are
- defined.
-
- In all cases, the decoding algorithm for the actual data is as
- follows:
-
- do
- read block header from input stream.
- if stored with no compression
- skip any remaining bits in current partially
- processed byte
- read LEN and NLEN (see next section)
- copy LEN bytes of data to output
- otherwise
- if compressed with dynamic Huffman codes
- read representation of code trees (see
- subsection below)
- loop (until end of block code recognized)
- decode literal/length value from input stream
- if value < 256
- copy value (literal byte) to output stream
- otherwise
- if value = end of block (256)
- break from loop
- otherwise (value = 257..285)
- decode distance from input stream
-
- move backwards distance bytes in the output
- stream, and copy length bytes from this
- position to the output stream.
- end loop
- while not last block
-
- Note that a duplicated string reference may refer to a string
- in a previous block; i.e., the backward distance may cross one
- or more block boundaries. However a distance cannot refer past
- the beginning of the output stream. (An application using a
-
-
-
-Deutsch Informational [Page 10]
-
-RFC 1951 DEFLATE Compressed Data Format Specification May 1996
-
-
- preset dictionary might discard part of the output stream; a
- distance can refer to that part of the output stream anyway)
- Note also that the referenced string may overlap the current
- position; for example, if the last 2 bytes decoded have values
- X and Y, a string reference with
- adds X,Y,X,Y,X to the output stream.
-
- We now specify each compression method in turn.
-
- 3.2.4. Non-compressed blocks (BTYPE=00)
-
- Any bits of input up to the next byte boundary are ignored.
- The rest of the block consists of the following information:
-
- 0 1 2 3 4...
- +---+---+---+---+================================+
- | LEN | NLEN |... LEN bytes of literal data...|
- +---+---+---+---+================================+
-
- LEN is the number of data bytes in the block. NLEN is the
- one's complement of LEN.
-
- 3.2.5. Compressed blocks (length and distance codes)
-
- As noted above, encoded data blocks in the "deflate" format
- consist of sequences of symbols drawn from three conceptually
- distinct alphabets: either literal bytes, from the alphabet of
- byte values (0..255), or pairs,
- where the length is drawn from (3..258) and the distance is
- drawn from (1..32,768). In fact, the literal and length
- alphabets are merged into a single alphabet (0..285), where
- values 0..255 represent literal bytes, the value 256 indicates
- end-of-block, and values 257..285 represent length codes
- (possibly in conjunction with extra bits following the symbol
- code) as follows:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Deutsch Informational [Page 11]
-
-RFC 1951 DEFLATE Compressed Data Format Specification May 1996
-
-
- Extra Extra Extra
- Code Bits Length(s) Code Bits Lengths Code Bits Length(s)
- ---- ---- ------ ---- ---- ------- ---- ---- -------
- 257 0 3 267 1 15,16 277 4 67-82
- 258 0 4 268 1 17,18 278 4 83-98
- 259 0 5 269 2 19-22 279 4 99-114
- 260 0 6 270 2 23-26 280 4 115-130
- 261 0 7 271 2 27-30 281 5 131-162
- 262 0 8 272 2 31-34 282 5 163-194
- 263 0 9 273 3 35-42 283 5 195-226
- 264 0 10 274 3 43-50 284 5 227-257
- 265 1 11,12 275 3 51-58 285 0 258
- 266 1 13,14 276 3 59-66
-
- The extra bits should be interpreted as a machine integer
- stored with the most-significant bit first, e.g., bits 1110
- represent the value 14.
-
- Extra Extra Extra
- Code Bits Dist Code Bits Dist Code Bits Distance
- ---- ---- ---- ---- ---- ------ ---- ---- --------
- 0 0 1 10 4 33-48 20 9 1025-1536
- 1 0 2 11 4 49-64 21 9 1537-2048
- 2 0 3 12 5 65-96 22 10 2049-3072
- 3 0 4 13 5 97-128 23 10 3073-4096
- 4 1 5,6 14 6 129-192 24 11 4097-6144
- 5 1 7,8 15 6 193-256 25 11 6145-8192
- 6 2 9-12 16 7 257-384 26 12 8193-12288
- 7 2 13-16 17 7 385-512 27 12 12289-16384
- 8 3 17-24 18 8 513-768 28 13 16385-24576
- 9 3 25-32 19 8 769-1024 29 13 24577-32768
-
- 3.2.6. Compression with fixed Huffman codes (BTYPE=01)
-
- The Huffman codes for the two alphabets are fixed, and are not
- represented explicitly in the data. The Huffman code lengths
- for the literal/length alphabet are:
-
- Lit Value Bits Codes
- --------- ---- -----
- 0 - 143 8 00110000 through
- 10111111
- 144 - 255 9 110010000 through
- 111111111
- 256 - 279 7 0000000 through
- 0010111
- 280 - 287 8 11000000 through
- 11000111
-
-
-
-Deutsch Informational [Page 12]
-
-RFC 1951 DEFLATE Compressed Data Format Specification May 1996
-
-
- The code lengths are sufficient to generate the actual codes,
- as described above; we show the codes in the table for added
- clarity. Literal/length values 286-287 will never actually
- occur in the compressed data, but participate in the code
- construction.
-
- Distance codes 0-31 are represented by (fixed-length) 5-bit
- codes, with possible additional bits as shown in the table
- shown in Paragraph 3.2.5, above. Note that distance codes 30-
- 31 will never actually occur in the compressed data.
-
- 3.2.7. Compression with dynamic Huffman codes (BTYPE=10)
-
- The Huffman codes for the two alphabets appear in the block
- immediately after the header bits and before the actual
- compressed data, first the literal/length code and then the
- distance code. Each code is defined by a sequence of code
- lengths, as discussed in Paragraph 3.2.2, above. For even
- greater compactness, the code length sequences themselves are
- compressed using a Huffman code. The alphabet for code lengths
- is as follows:
-
- 0 - 15: Represent code lengths of 0 - 15
- 16: Copy the previous code length 3 - 6 times.
- The next 2 bits indicate repeat length
- (0 = 3, ... , 3 = 6)
- Example: Codes 8, 16 (+2 bits 11),
- 16 (+2 bits 10) will expand to
- 12 code lengths of 8 (1 + 6 + 5)
- 17: Repeat a code length of 0 for 3 - 10 times.
- (3 bits of length)
- 18: Repeat a code length of 0 for 11 - 138 times
- (7 bits of length)
-
- A code length of 0 indicates that the corresponding symbol in
- the literal/length or distance alphabet will not occur in the
- block, and should not participate in the Huffman code
- construction algorithm given earlier. If only one distance
- code is used, it is encoded using one bit, not zero bits; in
- this case there is a single code length of one, with one unused
- code. One distance code of zero bits means that there are no
- distance codes used at all (the data is all literals).
-
- We can now define the format of the block:
-
- 5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286)
- 5 Bits: HDIST, # of Distance codes - 1 (1 - 32)
- 4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19)
-
-
-
-Deutsch Informational [Page 13]
-
-RFC 1951 DEFLATE Compressed Data Format Specification May 1996
-
-
- (HCLEN + 4) x 3 bits: code lengths for the code length
- alphabet given just above, in the order: 16, 17, 18,
- 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
-
- These code lengths are interpreted as 3-bit integers
- (0-7); as above, a code length of 0 means the
- corresponding symbol (literal/length or distance code
- length) is not used.
-
- HLIT + 257 code lengths for the literal/length alphabet,
- encoded using the code length Huffman code
-
- HDIST + 1 code lengths for the distance alphabet,
- encoded using the code length Huffman code
-
- The actual compressed data of the block,
- encoded using the literal/length and distance Huffman
- codes
-
- The literal/length symbol 256 (end of data),
- encoded using the literal/length Huffman code
-
- The code length repeat codes can cross from HLIT + 257 to the
- HDIST + 1 code lengths. In other words, all code lengths form
- a single sequence of HLIT + HDIST + 258 values.
-
- 3.3. Compliance
-
- A compressor may limit further the ranges of values specified in
- the previous section and still be compliant; for example, it may
- limit the range of backward pointers to some value smaller than
- 32K. Similarly, a compressor may limit the size of blocks so that
- a compressible block fits in memory.
-
- A compliant decompressor must accept the full range of possible
- values defined in the previous section, and must accept blocks of
- arbitrary size.
-
-4. Compression algorithm details
-
- While it is the intent of this document to define the "deflate"
- compressed data format without reference to any particular
- compression algorithm, the format is related to the compressed
- formats produced by LZ77 (Lempel-Ziv 1977, see reference [2] below);
- since many variations of LZ77 are patented, it is strongly
- recommended that the implementor of a compressor follow the general
- algorithm presented here, which is known not to be patented per se.
- The material in this section is not part of the definition of the
-
-
-
-Deutsch Informational [Page 14]
-
-RFC 1951 DEFLATE Compressed Data Format Specification May 1996
-
-
- specification per se, and a compressor need not follow it in order to
- be compliant.
-
- The compressor terminates a block when it determines that starting a
- new block with fresh trees would be useful, or when the block size
- fills up the compressor's block buffer.
-
- The compressor uses a chained hash table to find duplicated strings,
- using a hash function that operates on 3-byte sequences. At any
- given point during compression, let XYZ be the next 3 input bytes to
- be examined (not necessarily all different, of course). First, the
- compressor examines the hash chain for XYZ. If the chain is empty,
- the compressor simply writes out X as a literal byte and advances one
- byte in the input. If the hash chain is not empty, indicating that
- the sequence XYZ (or, if we are unlucky, some other 3 bytes with the
- same hash function value) has occurred recently, the compressor
- compares all strings on the XYZ hash chain with the actual input data
- sequence starting at the current point, and selects the longest
- match.
-
- The compressor searches the hash chains starting with the most recent
- strings, to favor small distances and thus take advantage of the
- Huffman encoding. The hash chains are singly linked. There are no
- deletions from the hash chains; the algorithm simply discards matches
- that are too old. To avoid a worst-case situation, very long hash
- chains are arbitrarily truncated at a certain length, determined by a
- run-time parameter.
-
- To improve overall compression, the compressor optionally defers the
- selection of matches ("lazy matching"): after a match of length N has
- been found, the compressor searches for a longer match starting at
- the next input byte. If it finds a longer match, it truncates the
- previous match to a length of one (thus producing a single literal
- byte) and then emits the longer match. Otherwise, it emits the
- original match, and, as described above, advances N bytes before
- continuing.
-
- Run-time parameters also control this "lazy match" procedure. If
- compression ratio is most important, the compressor attempts a
- complete second search regardless of the length of the first match.
- In the normal case, if the current match is "long enough", the
- compressor reduces the search for a longer match, thus speeding up
- the process. If speed is most important, the compressor inserts new
- strings in the hash table only when no match was found, or when the
- match is not "too long". This degrades the compression ratio but
- saves time since there are both fewer insertions and fewer searches.
-
-
-
-
-
-Deutsch Informational [Page 15]
-
-RFC 1951 DEFLATE Compressed Data Format Specification May 1996
-
-
-5. References
-
- [1] Huffman, D. A., "A Method for the Construction of Minimum
- Redundancy Codes", Proceedings of the Institute of Radio
- Engineers, September 1952, Volume 40, Number 9, pp. 1098-1101.
-
- [2] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data
- Compression", IEEE Transactions on Information Theory, Vol. 23,
- No. 3, pp. 337-343.
-
- [3] Gailly, J.-L., and Adler, M., ZLIB documentation and sources,
- available in ftp://ftp.uu.net/pub/archiving/zip/doc/
-
- [4] Gailly, J.-L., and Adler, M., GZIP documentation and sources,
- available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/
-
- [5] Schwartz, E. S., and Kallick, B. "Generating a canonical prefix
- encoding." Comm. ACM, 7,3 (Mar. 1964), pp. 166-169.
-
- [6] Hirschberg and Lelewer, "Efficient decoding of prefix codes,"
- Comm. ACM, 33,4, April 1990, pp. 449-459.
-
-6. Security Considerations
-
- Any data compression method involves the reduction of redundancy in
- the data. Consequently, any corruption of the data is likely to have
- severe effects and be difficult to correct. Uncompressed text, on
- the other hand, will probably still be readable despite the presence
- of some corrupted bytes.
-
- It is recommended that systems using this data format provide some
- means of validating the integrity of the compressed data. See
- reference [3], for example.
-
-7. Source code
-
- Source code for a C language implementation of a "deflate" compliant
- compressor and decompressor is available within the zlib package at
- ftp://ftp.uu.net/pub/archiving/zip/zlib/.
-
-8. Acknowledgements
-
- Trademarks cited in this document are the property of their
- respective owners.
-
- Phil Katz designed the deflate format. Jean-Loup Gailly and Mark
- Adler wrote the related software described in this specification.
- Glenn Randers-Pehrson converted this document to RFC and HTML format.
-
-
-
-Deutsch Informational [Page 16]
-
-RFC 1951 DEFLATE Compressed Data Format Specification May 1996
-
-
-9. Author's Address
-
- L. Peter Deutsch
- Aladdin Enterprises
- 203 Santa Margarita Ave.
- Menlo Park, CA 94025
-
- Phone: (415) 322-0103 (AM only)
- FAX: (415) 322-1734
- EMail:
-
- Questions about the technical content of this specification can be
- sent by email to:
-
- Jean-Loup Gailly and
- Mark Adler
-
- Editorial comments on this specification can be sent by email to:
-
- L. Peter Deutsch and
- Glenn Randers-Pehrson
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Deutsch Informational [Page 17]
-
diff --git a/lib/std/compress/testdata/rfc8478.txt b/lib/std/compress/testdata/rfc8478.txt
deleted file mode 100644
index e4ac22a302bd209796f2de1dd7d7bdc861fe9f63..0000000000000000000000000000000000000000
--- a/lib/std/compress/testdata/rfc8478.txt
+++ /dev/null
@@ -1,3027 +0,0 @@
-
-
-
-
-
-
-Internet Engineering Task Force (IETF) Y. Collet
-Request for Comments: 8478 M. Kucherawy, Ed.
-Category: Informational Facebook
-ISSN: 2070-1721 October 2018
-
-
- Zstandard Compression and the application/zstd Media Type
-
-Abstract
-
- Zstandard, or "zstd" (pronounced "zee standard"), is a data
- compression mechanism. This document describes the mechanism and
- registers a media type and content encoding to be used when
- transporting zstd-compressed content via Multipurpose Internet Mail
- Extensions (MIME).
-
- Despite use of the word "standard" as part of its name, readers are
- advised that this document is not an Internet Standards Track
- specification; it is being published for informational purposes only.
-
-Status of This Memo
-
- This document is not an Internet Standards Track specification; it is
- published for informational purposes.
-
- This document is a product of the Internet Engineering Task Force
- (IETF). It represents the consensus of the IETF community. It has
- received public review and has been approved for publication by the
- Internet Engineering Steering Group (IESG). Not all documents
- approved by the IESG are candidates for any level of Internet
- Standard; see Section 2 of RFC 7841.
-
- Information about the current status of this document, any errata,
- and how to provide feedback on it may be obtained at
- https://www.rfc-editor.org/info/rfc8478.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 1]
-
-RFC 8478 application/zstd October 2018
-
-
-Copyright Notice
-
- Copyright (c) 2018 IETF Trust and the persons identified as the
- document authors. All rights reserved.
-
- This document is subject to BCP 78 and the IETF Trust's Legal
- Provisions Relating to IETF Documents
- (https://trustee.ietf.org/license-info) in effect on the date of
- publication of this document. Please review these documents
- carefully, as they describe your rights and restrictions with respect
- to this document. Code Components extracted from this document must
- include Simplified BSD License text as described in Section 4.e of
- the Trust Legal Provisions and are provided without warranty as
- described in the Simplified BSD License.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 2]
-
-RFC 8478 application/zstd October 2018
-
-
-Table of Contents
-
- 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4
- 2. Definitions . . . . . . . . . . . . . . . . . . . . . . . . . 4
- 3. Compression Algorithm . . . . . . . . . . . . . . . . . . . . 5
- 3.1. Frames . . . . . . . . . . . . . . . . . . . . . . . . . 6
- 3.1.1. Zstandard Frames . . . . . . . . . . . . . . . . . . 6
- 3.1.1.1. Frame Header . . . . . . . . . . . . . . . . . . 7
- 3.1.1.2. Blocks . . . . . . . . . . . . . . . . . . . . . 12
- 3.1.1.3. Compressed Blocks . . . . . . . . . . . . . . . . 14
- 3.1.1.4. Sequence Execution . . . . . . . . . . . . . . . 28
- 3.1.1.5. Repeat Offsets . . . . . . . . . . . . . . . . . 29
- 3.1.2. Skippable Frames . . . . . . . . . . . . . . . . . . 30
- 4. Entropy Encoding . . . . . . . . . . . . . . . . . . . . . . 30
- 4.1. FSE . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
- 4.1.1. FSE Table Description . . . . . . . . . . . . . . . . 31
- 4.2. Huffman Coding . . . . . . . . . . . . . . . . . . . . . 34
- 4.2.1. Huffman Tree Description . . . . . . . . . . . . . . 35
- 4.2.1.1. Huffman Tree Header . . . . . . . . . . . . . . . 36
- 4.2.1.2. FSE Compression of Huffman Weights . . . . . . . 37
- 4.2.1.3. Conversion from Weights to Huffman Prefix Codes . 38
- 4.2.2. Huffman-Coded Streams . . . . . . . . . . . . . . . . 39
- 5. Dictionary Format . . . . . . . . . . . . . . . . . . . . . . 40
- 6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 42
- 6.1. The 'application/zstd' Media Type . . . . . . . . . . . . 42
- 6.2. Content Encoding . . . . . . . . . . . . . . . . . . . . 43
- 6.3. Dictionaries . . . . . . . . . . . . . . . . . . . . . . 43
- 7. Security Considerations . . . . . . . . . . . . . . . . . . . 43
- 8. Implementation Status . . . . . . . . . . . . . . . . . . . . 44
- 9. References . . . . . . . . . . . . . . . . . . . . . . . . . 45
- 9.1. Normative References . . . . . . . . . . . . . . . . . . 45
- 9.2. Informative References . . . . . . . . . . . . . . . . . 45
- Appendix A. Decoding Tables for Predefined Codes . . . . . . . . 46
- A.1. Literal Length Code Table . . . . . . . . . . . . . . . . 46
- A.2. Match Length Code Table . . . . . . . . . . . . . . . . . 49
- A.3. Offset Code Table . . . . . . . . . . . . . . . . . . . . 52
- Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 53
- Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 54
-
-
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 3]
-
-RFC 8478 application/zstd October 2018
-
-
-1. Introduction
-
- Zstandard, or "zstd" (pronounced "zee standard"), is a data
- compression mechanism, akin to gzip [RFC1952].
-
- Despite use of the word "standard" as part of its name, readers are
- advised that this document is not an Internet Standards Track
- specification; it is being published for informational purposes only.
-
- This document describes the Zstandard format. Also, to enable the
- transport of a data object compressed with Zstandard, this document
- registers a media type that can be used to identify such content when
- it is used in a payload encoded using Multipurpose Internet Mail
- Extensions (MIME).
-
-2. Definitions
-
- Some terms used elsewhere in this document are defined here for
- clarity.
-
- uncompressed: Describes an arbitrary set of bytes in their original
- form, prior to being subjected to compression.
-
- compress, compression: The act of processing a set of bytes via the
- compression mechanism described here.
-
- compressed: Describes the result of passing a set of bytes through
- this mechanism. The original input has thus been compressed.
-
- decompress, decompression: The act of processing a set of bytes
- through the inverse of the compression mechanism described here,
- in an attempt to recover the original set of bytes prior to
- compression.
-
- decompressed: Describes the result of passing a set of bytes through
- the reverse of this mechanism. When this is successful, the
- decompressed payload and the uncompressed payload are
- indistinguishable.
-
- encode: The process of translating data from one form to another;
- this may include compression or it may refer to other translations
- done as part of this specification.
-
- decode: The reverse of "encode"; describes a process of reversing a
- prior encoding to recover the original content.
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 4]
-
-RFC 8478 application/zstd October 2018
-
-
- frame: Content compressed by Zstandard is transformed into a
- Zstandard frame. Multiple frames can be appended into a single
- file or stream. A frame is completely independent, has a defined
- beginning and end, and has a set of parameters that tells the
- decoder how to decompress it.
-
- block: A frame encapsulates one or multiple blocks. Each block
- contains arbitrary content, which is described by its header, and
- has a guaranteed maximum content size that depends upon frame
- parameters. Unlike frames, each block depends on previous blocks
- for proper decoding. However, each block can be decompressed
- without waiting for its successor, allowing streaming operations.
-
- natural order: A sequence or ordering of objects or values that is
- typical of that type of object or value. A set of unique
- integers, for example, is in "natural order" if when progressing
- from one element in the set or sequence to the next, there is
- never a decrease in value.
-
- The naming convention for identifiers within the specification is
- Mixed_Case_With_Underscores. Identifiers inside square brackets
- indicate that the identifier is optional in the presented context.
-
-3. Compression Algorithm
-
- This section describes the Zstandard algorithm.
-
- The purpose of this document is to define a lossless compressed data
- format that is a) independent of the CPU type, operating system, file
- system, and character set and b) is suitable for file compression and
- pipe and streaming compression, using the Zstandard algorithm. The
- text of the specification assumes a basic background in programming
- at the level of bits and other primitive data representations.
-
- The data can be produced or consumed, even for an arbitrarily long
- sequentially presented input data stream, using only an a priori
- bounded amount of intermediate storage, and hence can be used in data
- communications. The format uses the Zstandard compression method,
- and an optional xxHash-64 checksum method [XXHASH], for detection of
- data corruption.
-
- The data format defined by this specification does not attempt to
- allow random access to compressed data.
-
- Unless otherwise indicated below, a compliant compressor must produce
- data sets that conform to the specifications presented here.
- However, it does not need to support all options.
-
-
-
-
-Collet & Kucherawy Informational [Page 5]
-
-RFC 8478 application/zstd October 2018
-
-
- A compliant decompressor must be able to decompress at least one
- working set of parameters that conforms to the specifications
- presented here. It may also ignore informative fields, such as the
- checksum. Whenever it does not support a parameter defined in the
- compressed stream, it must produce a non-ambiguous error code and
- associated error message explaining which parameter is unsupported.
-
- This specification is intended for use by implementers of software to
- compress data into Zstandard format and/or decompress data from
- Zstandard format. The Zstandard format is supported by an open
- source reference implementation, written in portable C, and available
- at [ZSTD].
-
-3.1. Frames
-
- Zstandard compressed data is made up of one or more frames. Each
- frame is independent and can be decompressed independently of other
- frames. The decompressed content of multiple concatenated frames is
- the concatenation of each frame's decompressed content.
-
- There are two frame formats defined for Zstandard: Zstandard frames
- and skippable frames. Zstandard frames contain compressed data,
- while skippable frames contain custom user metadata.
-
-3.1.1. Zstandard Frames
-
- The structure of a single Zstandard frame is as follows:
-
- +--------------------+------------+
- | Magic_Number | 4 bytes |
- +--------------------+------------+
- | Frame_Header | 2-14 bytes |
- +--------------------+------------+
- | Data_Block | n bytes |
- +--------------------+------------+
- | [More Data_Blocks] | |
- +--------------------+------------+
- | [Content_Checksum] | 0-4 bytes |
- +--------------------+------------+
-
- Magic_Number: 4 bytes, little-endian format. Value: 0xFD2FB528.
-
- Frame_Header: 2 to 14 bytes, detailed in Section 3.1.1.1.
-
- Data_Block: Detailed in Section 3.1.1.2. This is where data
- appears.
-
-
-
-
-
-Collet & Kucherawy Informational [Page 6]
-
-RFC 8478 application/zstd October 2018
-
-
- Content_Checksum: An optional 32-bit checksum, only present if
- Content_Checksum_Flag is set. The content checksum is the result
- of the XXH64() hash function [XXHASH] digesting the original
- (decoded) data as input, and a seed of zero. The low 4 bytes of
- the checksum are stored in little-endian format.
-
- The magic number was selected to be less probable to find at the
- beginning of an arbitrary file. It avoids trivial patterns (0x00,
- 0xFF, repeated bytes, increasing bytes, etc.), contains byte values
- outside of ASCII range, and doesn't map into UTF-8 space, all of
- which reduce the likelihood of its appearance at the top of a text
- file.
-
-3.1.1.1. Frame Header
-
- The frame header has a variable size, with a minimum of 2 bytes and
- up to 14 bytes depending on optional parameters. The structure of
- Frame_Header is as follows:
-
- +-------------------------+-----------+
- | Frame_Header_Descriptor | 1 byte |
- +-------------------------+-----------+
- | [Window_Descriptor] | 0-1 byte |
- +-------------------------+-----------+
- | [Dictionary_ID] | 0-4 bytes |
- +-------------------------+-----------+
- | [Frame_Content_Size] | 0-8 bytes |
- +-------------------------+-----------+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 7]
-
-RFC 8478 application/zstd October 2018
-
-
-3.1.1.1.1. Frame_Header_Descriptor
-
- The first header's byte is called the Frame_Header_Descriptor. It
- describes which other fields are present. Decoding this byte is
- enough to tell the size of Frame_Header.
-
- +------------+-------------------------+
- | Bit Number | Field Name |
- +------------+-------------------------+
- | 7-6 | Frame_Content_Size_Flag |
- +------------+-------------------------+
- | 5 | Single_Segment_Flag |
- +------------+-------------------------+
- | 4 | (unused) |
- +------------+-------------------------+
- | 3 | (reserved) |
- +------------+-------------------------+
- | 2 | Content_Checksum_Flag |
- +------------+-------------------------+
- | 1-0 | Dictionary_ID_Flag |
- +------------+-------------------------+
-
- In this table, bit 7 is the highest bit, while bit 0 is the lowest
- one.
-
-3.1.1.1.1.1. Frame_Content_Size_Flag
-
- This is a 2-bit flag (equivalent to Frame_Header_Descriptor right-
- shifted 6 bits) specifying whether Frame_Content_Size (the
- decompressed data size) is provided within the header. Flag_Value
- provides FCS_Field_Size, which is the number of bytes used by
- Frame_Content_Size according to the following table:
-
- +----------------+--------+---+---+---+
- | Flag_Value | 0 | 1 | 2 | 3 |
- +----------------+--------+---+---+---+
- | FCS_Field_Size | 0 or 1 | 2 | 4 | 8 |
- +----------------+--------+---+---+---+
-
- When Flag_Value is 0, FCS_Field_Size depends on Single_Segment_Flag:
- If Single_Segment_Flag is set, FCS_Field_Size is 1. Otherwise,
- FCS_Field_Size is 0; Frame_Content_Size is not provided.
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 8]
-
-RFC 8478 application/zstd October 2018
-
-
-3.1.1.1.1.2. Single_Segment_Flag
-
- If this flag is set, data must be regenerated within a single
- continuous memory segment.
-
- In this case, Window_Descriptor byte is skipped, but
- Frame_Content_Size is necessarily present. As a consequence, the
- decoder must allocate a memory segment of size equal or larger than
- Frame_Content_Size.
-
- In order to protect the decoder from unreasonable memory
- requirements, a decoder is allowed to reject a compressed frame that
- requests a memory size beyond the decoder's authorized range.
-
- For broader compatibility, decoders are recommended to support memory
- sizes of at least 8 MB. This is only a recommendation; each decoder
- is free to support higher or lower limits, depending on local
- limitations.
-
-3.1.1.1.1.3. Unused Bit
-
- A decoder compliant with this specification version shall not
- interpret this bit. It might be used in a future version, to signal
- a property that is not mandatory to properly decode the frame. An
- encoder compliant with this specification must set this bit to zero.
-
-3.1.1.1.1.4. Reserved Bit
-
- This bit is reserved for some future feature. Its value must be
- zero. A decoder compliant with this specification version must
- ensure it is not set. This bit may be used in a future revision, to
- signal a feature that must be interpreted to decode the frame
- correctly.
-
-3.1.1.1.1.5. Content_Checksum_Flag
-
- If this flag is set, a 32-bit Content_Checksum will be present at the
- frame's end. See the description of Content_Checksum above.
-
-
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 9]
-
-RFC 8478 application/zstd October 2018
-
-
-3.1.1.1.1.6. Dictionary_ID_Flag
-
- This is a 2-bit flag (= Frame_Header_Descriptor & 0x3) indicating
- whether a dictionary ID is provided within the header. It also
- specifies the size of this field as DID_Field_Size:
-
- +----------------+---+---+---+---+
- | Flag_Value | 0 | 1 | 2 | 3 |
- +----------------+---+---+---+---+
- | DID_Field_Size | 0 | 1 | 2 | 4 |
- +----------------+---+---+---+---+
-
-3.1.1.1.2. Window Descriptor
-
- This provides guarantees about the minimum memory buffer required to
- decompress a frame. This information is important for decoders to
- allocate enough memory.
-
- The Window_Descriptor byte is optional. When Single_Segment_Flag is
- set, Window_Descriptor is not present. In this case, Window_Size is
- Frame_Content_Size, which can be any value from 0 to 2^64-1 bytes (16
- ExaBytes).
-
- +------------+----------+----------+
- | Bit Number | 7-3 | 2-0 |
- +------------+----------+----------+
- | Field Name | Exponent | Mantissa |
- +------------+----------+----------+
-
- The minimum memory buffer size is called Window_Size. It is
- described by the following formulae:
-
- windowLog = 10 + Exponent;
- windowBase = 1 << windowLog;
- windowAdd = (windowBase / 8) * Mantissa;
- Window_Size = windowBase + windowAdd;
-
- The minimum Window_Size is 1 KB. The maximum Window_Size is (1<<41)
- + 7*(1<<38) bytes, which is 3.75 TB.
-
- In general, larger Window_Size values tend to improve the compression
- ratio, but at the cost of increased memory usage.
-
- To properly decode compressed data, a decoder will need to allocate a
- buffer of at least Window_Size bytes.
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 10]
-
-RFC 8478 application/zstd October 2018
-
-
- In order to protect decoders from unreasonable memory requirements, a
- decoder is allowed to reject a compressed frame that requests a
- memory size beyond decoder's authorized range.
-
- For improved interoperability, it's recommended for decoders to
- support values of Window_Size up to 8 MB and for encoders not to
- generate frames requiring a Window_Size larger than 8 MB. It's
- merely a recommendation though, and decoders are free to support
- larger or lower limits, depending on local limitations.
-
-3.1.1.1.3. Dictionary_ID
-
- This is a variable size field, which contains the ID of the
- dictionary required to properly decode the frame. This field is
- optional. When it's not present, it's up to the decoder to know
- which dictionary to use.
-
- Dictionary_ID field size is provided by DID_Field_Size.
- DID_Field_Size is directly derived from the value of
- Dictionary_ID_Flag. One byte can represent an ID 0-255; 2 bytes can
- represent an ID 0-65535; 4 bytes can represent an ID 0-4294967295.
- Format is little-endian.
-
- It is permitted to represent a small ID (for example, 13) with a
- large 4-byte dictionary ID, even if it is less efficient.
-
- Within private environments, any dictionary ID can be used. However,
- for frames and dictionaries distributed in public space,
- Dictionary_ID must be attributed carefully. The following ranges are
- reserved for use only with dictionaries that have been registered
- with IANA (see Section 6.3):
-
- low range: <= 32767
- high range: >= (1 << 31)
-
- Any other value for Dictionary_ID can be used by private arrangement
- between participants.
-
- Any payload presented for decompression that references an
- unregistered reserved dictionary ID results in an error.
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 11]
-
-RFC 8478 application/zstd October 2018
-
-
-3.1.1.1.4. Frame Content Size
-
- This is the original (uncompressed) size. This information is
- optional. Frame_Content_Size uses a variable number of bytes,
- provided by FCS_Field_Size. FCS_Field_Size is provided by the value
- of Frame_Content_Size_Flag. FCS_Field_Size can be equal to 0 (not
- present), 1, 2, 4, or 8 bytes.
-
- +----------------+--------------+
- | FCS Field Size | Range |
- +----------------+--------------+
- | 0 | unknown |
- +----------------+--------------+
- | 1 | 0 - 255 |
- +----------------+--------------+
- | 2 | 256 - 65791 |
- +----------------+--------------+
- | 4 | 0 - 2^32 - 1 |
- +----------------+--------------+
- | 8 | 0 - 2^64 - 1 |
- +----------------+--------------+
-
- Frame_Content_Size format is little-endian. When FCS_Field_Size is
- 1, 4, or 8 bytes, the value is read directly. When FCS_Field_Size is
- 2, the offset of 256 is added. It's allowed to represent a small
- size (for example 18) using any compatible variant.
-
-3.1.1.2. Blocks
-
- After Magic_Number and Frame_Header, there are some number of blocks.
- Each frame must have at least 1 block, but there is no upper limit on
- the number of blocks per frame.
-
- The structure of a block is as follows:
-
- +--------------+---------------+
- | Block_Header | Block_Content |
- +--------------+---------------+
- | 3 bytes | n bytes |
- +--------------+---------------+
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 12]
-
-RFC 8478 application/zstd October 2018
-
-
- Block_Header uses 3 bytes, written using little-endian convention.
- It contains three fields:
-
- +------------+------------+------------+
- | Last_Block | Block_Type | Block_Size |
- +------------+------------+------------+
- | bit 0 | bits 1-2 | bits 3-23 |
- +------------+------------+------------+
-
-3.1.1.2.1. Last_Block
-
- The lowest bit (Last_Block) signals whether this block is the last
- one. The frame will end after this last block. It may be followed
- by an optional Content_Checksum (see Section 3.1.1).
-
-3.1.1.2.2. Block_Type
-
- The next 2 bits represent the Block_Type. There are four block
- types:
-
- +-----------+------------------+
- | Value | Block_Type |
- +-----------+------------------+
- | 0 | Raw_Block |
- +-----------+------------------+
- | 1 | RLE_Block |
- +-----------+------------------+
- | 2 | Compressed_Block |
- +-----------+------------------+
- | 3 | Reserved |
- +-----------+------------------+
-
- Raw_Block: This is an uncompressed block. Block_Content contains
- Block_Size bytes.
-
- RLE_Block: This is a single byte, repeated Block_Size times.
- Block_Content consists of a single byte. On the decompression
- side, this byte must be repeated Block_Size times.
-
- Compressed_Block: This is a compressed block as described in
- Section 3.1.1.3. Block_Size is the length of Block_Content,
- namely the compressed data. The decompressed size is not known,
- but its maximum possible value is guaranteed (see below).
-
- Reserved: This is not a block. This value cannot be used with the
- current specification. If such a value is present, it is
- considered to be corrupt data.
-
-
-
-
-Collet & Kucherawy Informational [Page 13]
-
-RFC 8478 application/zstd October 2018
-
-
-3.1.1.2.3. Block_Size
-
- The upper 21 bits of Block_Header represent the Block_Size.
- Block_Size is the size of the block excluding the header. A block
- can contain any number of bytes (even zero), up to
- Block_Maximum_Decompressed_Size, which is the smallest of:
-
- o Window_Size
-
- o 128 KB
-
- A Compressed_Block has the extra restriction that Block_Size is
- always strictly less than the decompressed size. If this condition
- cannot be respected, the block must be sent uncompressed instead
- (i.e., treated as a Raw_Block).
-
-3.1.1.3. Compressed Blocks
-
- To decompress a compressed block, the compressed size must be
- provided from the Block_Size field within Block_Header.
-
- A compressed block consists of two sections: a Literals
- Section (Section 3.1.1.3.1) and a
- Sequences_Section (Section 3.1.1.3.2). The results of the two
- sections are then combined to produce the decompressed data in
- Sequence Execution (Section 3.1.1.4).
-
- To decode a compressed block, the following elements are necessary:
-
- o Previous decoded data, up to a distance of Window_Size, or the
- beginning of the Frame, whichever is smaller. Single_Segment_Flag
- will be set in the latter case.
-
- o List of "recent offsets" from the previous Compressed_Block.
-
- o The previous Huffman tree, required by Treeless_Literals_Block
- type.
-
- o Previous Finite State Entropy (FSE) decoding tables, required by
- Repeat_Mode, for each symbol type (literals lengths, match
- lengths, offsets).
-
- Note that decoding tables are not always from the previous
- Compressed_Block:
-
- o Every decoding table can come from a dictionary.
-
-
-
-
-
-Collet & Kucherawy Informational [Page 14]
-
-RFC 8478 application/zstd October 2018
-
-
- o The Huffman tree comes from the previous
- Compressed_Literals_Block.
-
-3.1.1.3.1. Literals_Section_Header
-
- All literals are regrouped in the first part of the block. They can
- be decoded first and then copied during Sequence Execution (see
- Section 3.1.1.4), or they can be decoded on the flow during Sequence
- Execution.
-
- Literals can be stored uncompressed or compressed using Huffman
- prefix codes. When compressed, an optional tree description can be
- present, followed by 1 or 4 streams.
-
- +----------------------------+
- | Literals_Section_Header |
- +----------------------------+
- | [Huffman_Tree_Description] |
- +----------------------------+
- | [Jump_Table] |
- +----------------------------+
- | Stream_1 |
- +----------------------------+
- | [Stream_2] |
- +----------------------------+
- | [Stream_3] |
- +----------------------------+
- | [Stream_4] |
- +----------------------------+
-
-3.1.1.3.1.1. Literals_Section_Header
-
- This field describes how literals are packed. It's a byte-aligned
- variable-size bit field, ranging from 1 to 5 bytes, using little-
- endian convention.
-
- +---------------------+-----------+
- | Literals_Block_Type | 2 bits |
- +---------------------+-----------+
- | Size_Format | 1-2 bits |
- +---------------------+-----------+
- | Regenerated_Size | 5-20 bits |
- +---------------------+-----------+
- | [Compressed_Size] | 0-18 bits |
- +---------------------+-----------+
-
- In this representation, bits at the top are the lowest bits.
-
-
-
-
-Collet & Kucherawy Informational [Page 15]
-
-RFC 8478 application/zstd October 2018
-
-
- The Literals_Block_Type field uses the two lowest bits of the first
- byte, describing four different block types:
-
- +---------------------------+-------+
- | Literals_Block_Type | Value |
- +---------------------------+-------+
- | Raw_Literals_Block | 0 |
- +---------------------------+-------+
- | RLE_Literals_Block | 1 |
- +---------------------------+-------+
- | Compressed_Literals_Block | 2 |
- +---------------------------+-------+
- | Treeless_Literals_Block | 3 |
- +---------------------------+-------+
-
- Raw_Literals_Block: Literals are stored uncompressed.
- Literals_Section_Content is Regenerated_Size.
-
- RLE_Literals_Block: Literals consist of a single-byte value repeated
- Regenerated_Size times. Literals_Section_Content is 1.
-
- Compressed_Literals_Block: This is a standard Huffman-compressed
- block, starting with a Huffman tree description. See details
- below. Literals_Section_Content is Compressed_Size.
-
- Treeless_Literals_Block: This is a Huffman-compressed block, using
- the Huffman tree from the previous Compressed_Literals_Block, or a
- dictionary if there is no previous Huffman-compressed literals
- block. Huffman_Tree_Description will be skipped. Note that if
- this mode is triggered without any previous Huffman-table in the
- frame (or dictionary, per Section 5), it should be treated as data
- corruption. Literals_Section_Content is Compressed_Size.
-
- The Size_Format is divided into two families:
-
- o For Raw_Literals_Block and RLE_Literals_Block, it's only necessary
- to decode Regenerated_Size. There is no Compressed_Size field.
-
- o For Compressed_Block and Treeless_Literals_Block, it's required to
- decode both Compressed_Size and Regenerated_Size (the decompressed
- size). It's also necessary to decode the number of streams (1 or
- 4).
-
- For values spanning several bytes, the convention is little endian.
-
- Size_Format for Raw_Literals_Block and RLE_Literals_Block uses 1 or 2
- bits. Its value is (Literals_Section_Header[0]>>2) & 0x3.
-
-
-
-
-Collet & Kucherawy Informational [Page 16]
-
-RFC 8478 application/zstd October 2018
-
-
- Size_Format == 00 or 10: Size_Format uses 1 bit. Regenerated_Size
- uses 5 bits (value 0-31). Literals_Section_Header uses 1 byte.
- Regenerated_Size = Literal_Section_Header[0]>>3.
-
- Size_Format == 01: Size_Format uses 2 bits. Regenerated_Size uses
- 12 bits (values 0-4095). Literals_Section_Header uses 2 bytes.
- Regenerated_Size = (Literals_Section_Header[0]>>4) +
- (Literals_Section_Header[1]<<4).
-
- Size_Format == 11: Size_Format uses 2 bits. Regenerated_Size uses
- 20 bits (values 0-1048575). Literals_Section_Header uses 3 bytes.
- Regenerated_Size = (Literals_Section_Header[0]>>4) +
- (Literals_Section_Header[1]<<4) + (Literals_Section_Header[2]<<12)
-
- Only Stream_1 is present for these cases. Note that it is permitted
- to represent a short value (for example, 13) using a long format,
- even if it's less efficient.
-
- Size_Format for Compressed_Literals_Block and Treeless_Literals_Block
- always uses 2 bits.
-
- Size_Format == 00: A single stream. Both Regenerated_Size and
- Compressed_Size use 10 bits (values 0-1023).
- Literals_Section_Header uses 3 bytes.
-
- Size_Format == 01: 4 streams. Both Regenerated_Size and
- Compressed_Size use 10 bits (values 0-1023).
- Literals_Section_Header uses 3 bytes.
-
- Size_Format == 10: 4 streams. Both Regenerated_Size and
- Compressed_Size use 14 bits (values 0-16383).
- Literals_Section_Header uses 4 bytes.
-
- Size_Format == 11: 4 streams. Both Regenerated_Size and
- Compressed_Size use 18 bits (values 0-262143).
- Literals_Section_Header uses 5 bytes.
-
- Both the Compressed_Size and Regenerated_Size fields follow little-
- endian convention. Note that Compressed_Size includes the size of
- the Huffman_Tree_Description when it is present.
-
-3.1.1.3.1.2. Raw_Literals_Block
-
- The data in Stream_1 is Regenerated_Size bytes long. It contains the
- raw literals data to be used during Sequence Execution
- (Section 3.1.1.3.2).
-
-
-
-
-
-Collet & Kucherawy Informational [Page 17]
-
-RFC 8478 application/zstd October 2018
-
-
-3.1.1.3.1.3. RLE_Literals_Block
-
- Stream_1 consists of a single byte that should be repeated
- Regenerated_Size times to generate the decoded literals.
-
-3.1.1.3.1.4. Compressed_Literals_Block and Treeless_Literals_Block
-
- Both of these modes contain Huffman-encoded data. For
- Treeless_Literals_Block, the Huffman table comes from the previously
- compressed literals block, or from a dictionary; see Section 5.
-
-3.1.1.3.1.5. Huffman_Tree_Description
-
- This section is only present when the Literals_Block_Type type is
- Compressed_Literals_Block (2). The format of
- Huffman_Tree_Description can be found in Section 4.2.1. The size of
- Huffman_Tree_Description is determined during the decoding process.
- It must be used to determine where streams begin.
-
- Total_Streams_Size = Compressed_Size
- - Huffman_Tree_Description_Size
-
-3.1.1.3.1.6. Jump_Table
-
- The Jump_Table is only present when there are 4 Huffman-coded
- streams.
-
- (Reminder: Huffman-compressed data consists of either 1 or 4 Huffman-
- coded streams.)
-
- If only 1 stream is present, it is a single bitstream occupying the
- entire remaining portion of the literals block, encoded as described
- within Section 4.2.2.
-
- If there are 4 streams, Literals_Section_Header only provides enough
- information to know the decompressed and compressed sizes of all 4
- streams combined. The decompressed size of each stream is equal to
- (Regenerated_Size+3)/4, except for the last stream, which may be up
- to 3 bytes smaller, to reach a total decompressed size as specified
- in Regenerated_Size.
-
- The compressed size of each stream is provided explicitly in the
- Jump_Table. The Jump_Table is 6 bytes long and consists of three
- 2-byte little-endian fields, describing the compressed sizes of the
- first 3 streams. Stream4_Size is computed from Total_Streams_Size
- minus sizes of other streams.
-
-
-
-
-
-Collet & Kucherawy Informational [Page 18]
-
-RFC 8478 application/zstd October 2018
-
-
- Stream4_Size = Total_Streams_Size - 6
- - Stream1_Size - Stream2_Size
- - Stream3_Size
-
- Note that if Stream1_Size + Stream2_Size + Stream3_Size exceeds
- Total_Streams_Size, the data are considered corrupted.
-
- Each of these 4 bitstreams is then decoded independently as a
- Huffman-Coded stream, as described in Section 4.2.2.
-
-3.1.1.3.2. Sequences_Section
-
- A compressed block is a succession of sequences. A sequence is a
- literal copy command, followed by a match copy command. A literal
- copy command specifies a length. It is the number of bytes to be
- copied (or extracted) from the Literals Section. A match copy
- command specifies an offset and a length.
-
- When all sequences are decoded, if there are literals left in the
- literals section, these bytes are added at the end of the block.
-
- This is described in more detail in Section 3.1.1.4.
-
- The Sequences_Section regroups all symbols required to decode
- commands. There are three symbol types: literals lengths, offsets,
- and match lengths. They are encoded together, interleaved, in a
- single "bitstream".
-
- The Sequences_Section starts by a header, followed by optional
- probability tables for each symbol type, followed by the bitstream.
-
- Sequences_Section_Header
- [Literals_Length_Table]
- [Offset_Table]
- [Match_Length_Table]
- bitStream
-
- To decode the Sequences_Section, it's necessary to know its size.
- This size is deduced from the size of the Literals_Section:
- Sequences_Section_Size = Block_Size - Literals_Section_Header -
- Literals_Section_Content
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 19]
-
-RFC 8478 application/zstd October 2018
-
-
-3.1.1.3.2.1. Sequences_Section_Header
-
- This header consists of two items:
-
- o Number_of_Sequences
-
- o Symbol_Compression_Modes
-
- Number_of_Sequences is a variable size field using between 1 and 3
- bytes. If the first byte is "byte0":
-
- o if (byte0 == 0): there are no sequences. The sequence section
- stops here. Decompressed content is defined entirely as Literals
- Section content. The FSE tables used in Repeat_Mode are not
- updated.
-
- o if (byte0 < 128): Number_of_Sequences = byte0. Uses 1 byte.
-
- o if (byte0 < 255): Number_of_Sequences = ((byte0 - 128) << 8) +
- byte1. Uses 2 bytes.
-
- o if (byte0 == 255): Number_of_Sequences = byte1 + (byte2 << 8) +
- 0x7F00. Uses 3 bytes.
-
- Symbol_Compression_Modes is a single byte, defining the compression
- mode of each symbol type.
-
- +-------------+----------------------+
- | Bit Number | Field Name |
- +-------------+----------------------+
- | 7-6 | Literal_Lengths_Mode |
- +-------------+----------------------+
- | 5-4 | Offsets_Mode |
- +-------------+----------------------+
- | 3-2 | Match_Lengths_Mode |
- +-------------+----------------------+
- | 1-0 | Reserved |
- +-------------+----------------------+
-
- The last field, Reserved, must be all zeroes.
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 20]
-
-RFC 8478 application/zstd October 2018
-
-
- Literals_Lengths_Mode, Offsets_Mode, and Match_Lengths_Mode define
- the Compression_Mode of literals lengths, offsets, and match lengths
- symbols, respectively. They follow the same enumeration:
-
- +-------+---------------------+
- | Value | Compression_Mode |
- +-------+---------------------+
- | 0 | Predefined_Mode |
- +-------+---------------------+
- | 1 | RLE_Mode |
- +-------+---------------------+
- | 2 | FSE_Compressed_Mode |
- +-------+---------------------+
- | 3 | Repeat_Mode |
- +-------+---------------------+
-
- Predefined_Mode: A predefined FSE (see Section 4.1) distribution
- table is used, as defined in Section 3.1.1.3.2.2. No distribution
- table will be present.
-
- RLE_Mode: The table description consists of a single byte, which
- contains the symbol's value. This symbol will be used for all
- sequences.
-
- FSE_Compressed_Mode: Standard FSE compression. A distribution table
- will be present. The format of this distribution table is
- described in Section 4.1.1. Note that the maximum allowed
- accuracy log for literals length and match length tables is 9, and
- the maximum accuracy log for the offsets table is 8. This mode
- must not be used when only one symbol is present; RLE_Mode should
- be used instead (although any other mode will work).
-
- Repeat_Mode: The table used in the previous Compressed_Block with
- Number_Of_Sequences > 0 will be used again, or if this is the
- first block, the table in the dictionary will be used. Note that
- this includes RLE_Mode, so if Repeat_Mode follows RLE_Mode, the
- same symbol will be repeated. It also includes Predefined_Mode,
- in which case Repeat_Mode will have the same outcome as
- Predefined_Mode. No distribution table will be present. If this
- mode is used without any previous sequence table in the frame (or
- dictionary; see Section 5) to repeat, this should be treated as
- corruption.
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 21]
-
-RFC 8478 application/zstd October 2018
-
-
-3.1.1.3.2.1.1. Sequence Codes for Lengths and Offsets
-
- Each symbol is a code in its own context, which specifies Baseline
- and Number_of_Bits to add. Codes are FSE compressed and interleaved
- with raw additional bits in the same bitstream.
-
- Literals length codes are values ranging from 0 to 35 inclusive.
- They define lengths from 0 to 131071 bytes. The literals length is
- equal to the decoded Baseline plus the result of reading
- Number_of_Bits bits from the bitstream, as a little-endian value.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 22]
-
-RFC 8478 application/zstd October 2018
-
-
- +----------------------+----------+----------------+
- | Literals_Length_Code | Baseline | Number_of_Bits |
- +----------------------+----------+----------------+
- | 0-15 | length | 0 |
- +----------------------+----------+----------------+
- | 16 | 16 | 1 |
- +----------------------+----------+----------------+
- | 17 | 18 | 1 |
- +----------------------+----------+----------------+
- | 18 | 20 | 1 |
- +----------------------+----------+----------------+
- | 19 | 22 | 1 |
- +----------------------+----------+----------------+
- | 20 | 24 | 2 |
- +----------------------+----------+----------------+
- | 21 | 28 | 2 |
- +----------------------+----------+----------------+
- | 22 | 32 | 3 |
- +----------------------+----------+----------------+
- | 23 | 40 | 3 |
- +----------------------+----------+----------------+
- | 24 | 48 | 4 |
- +----------------------+----------+----------------+
- | 25 | 64 | 6 |
- +----------------------+----------+----------------+
- | 26 | 128 | 7 |
- +----------------------+----------+----------------+
- | 27 | 256 | 8 |
- +----------------------+----------+----------------+
- | 28 | 512 | 9 |
- +----------------------+----------+----------------+
- | 29 | 1024 | 10 |
- +----------------------+----------+----------------+
- | 30 | 2048 | 11 |
- +----------------------+----------+----------------+
- | 31 | 4096 | 12 |
- +----------------------+----------+----------------+
- | 32 | 8192 | 13 |
- +----------------------+----------+----------------+
- | 33 | 16384 | 14 |
- +----------------------+----------+----------------+
- | 34 | 32768 | 15 |
- +----------------------+----------+----------------+
- | 35 | 65536 | 16 |
- +----------------------+----------+----------------+
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 23]
-
-RFC 8478 application/zstd October 2018
-
-
- Match length codes are values ranging from 0 to 52 inclusive. They
- define lengths from 3 to 131074 bytes. The match length is equal to
- the decoded Baseline plus the result of reading Number_of_Bits bits
- from the bitstream, as a little-endian value.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 24]
-
-RFC 8478 application/zstd October 2018
-
-
- +-------------------+-----------------------+----------------+
- | Match_Length_Code | Baseline | Number_of_Bits |
- +-------------------+-----------------------+----------------+
- | 0-31 | Match_Length_Code + 3 | 0 |
- +-------------------+-----------------------+----------------+
- | 32 | 35 | 1 |
- +-------------------+-----------------------+----------------+
- | 33 | 37 | 1 |
- +-------------------+-----------------------+----------------+
- | 34 | 39 | 1 |
- +-------------------+-----------------------+----------------+
- | 35 | 41 | 1 |
- +-------------------+-----------------------+----------------+
- | 36 | 43 | 2 |
- +-------------------+-----------------------+----------------+
- | 37 | 47 | 2 |
- +-------------------+-----------------------+----------------+
- | 38 | 51 | 3 |
- +-------------------+-----------------------+----------------+
- | 39 | 59 | 3 |
- +-------------------+-----------------------+----------------+
- | 40 | 67 | 4 |
- +-------------------+-----------------------+----------------+
- | 41 | 83 | 4 |
- +-------------------+-----------------------+----------------+
- | 42 | 99 | 5 |
- +-------------------+-----------------------+----------------+
- | 43 | 131 | 7 |
- +-------------------+-----------------------+----------------+
- | 44 | 259 | 8 |
- +-------------------+-----------------------+----------------+
- | 45 | 515 | 9 |
- +-------------------+-----------------------+----------------+
- | 46 | 1027 | 10 |
- +-------------------+-----------------------+----------------+
- | 47 | 2051 | 11 |
- +-------------------+-----------------------+----------------+
- | 48 | 4099 | 12 |
- +-------------------+-----------------------+----------------+
- | 49 | 8195 | 13 |
- +-------------------+-----------------------+----------------+
- | 50 | 16387 | 14 |
- +-------------------+-----------------------+----------------+
- | 51 | 32771 | 15 |
- +-------------------+-----------------------+----------------+
- | 52 | 65539 | 16 |
- +-------------------+-----------------------+----------------+
-
-
-
-
-Collet & Kucherawy Informational [Page 25]
-
-RFC 8478 application/zstd October 2018
-
-
- Offset codes are values ranging from 0 to N.
-
- A decoder is free to limit its maximum supported value for N.
- Support for values of at least 22 is recommended. At the time of
- this writing, the reference decoder supports a maximum N value of 31.
-
- An offset code is also the number of additional bits to read in
- little-endian fashion and can be translated into an Offset_Value
- using the following formulas:
-
- Offset_Value = (1 << offsetCode) + readNBits(offsetCode);
- if (Offset_Value > 3) Offset = Offset_Value - 3;
-
- This means that maximum Offset_Value is (2^(N+1))-1, supporting back-
- reference distance up to (2^(N+1))-4, but it is limited by the
- maximum back-reference distance (see Section 3.1.1.1.2).
-
- Offset_Value from 1 to 3 are special: they define "repeat codes".
- This is described in more detail in Section 3.1.1.5.
-
-3.1.1.3.2.1.2. Decoding Sequences
-
- FSE bitstreams are read in reverse of the direction they are written.
- In zstd, the compressor writes bits forward into a block, and the
- decompressor must read the bitstream backwards.
-
- To find the start of the bitstream, it is therefore necessary to know
- the offset of the last byte of the block, which can be found by
- counting Block_Size bytes after the block header.
-
- After writing the last bit containing information, the compressor
- writes a single 1 bit and then fills the byte with 0-7 zero bits of
- padding. The last byte of the compressed bitstream cannot be zero
- for that reason.
-
- When decompressing, the last byte containing the padding is the first
- byte to read. The decompressor needs to skip 0-7 initial zero bits
- until the first 1 bit occurs. Afterwards, the useful part of the
- bitstream begins.
-
- FSE decoding requires a 'state' to be carried from symbol to symbol.
- For more explanation on FSE decoding, see Section 4.1.
-
- For sequence decoding, a separate state keeps track of each literal
- lengths, offsets, and match lengths symbols. Some FSE primitives are
- also used. For more details on the operation of these primitives,
- see Section 4.1.
-
-
-
-
-Collet & Kucherawy Informational [Page 26]
-
-RFC 8478 application/zstd October 2018
-
-
- The bitstream starts with initial FSE state values, each using the
- required number of bits in their respective accuracy, decoded
- previously from their normalized distribution. It starts with
- Literals_Length_State, followed by Offset_State, and finally
- Match_Length_State.
-
- Note that all values are read backward, so the 'start' of the
- bitstream is at the highest position in memory, immediately before
- the last 1 bit for padding.
-
- After decoding the starting states, a single sequence is decoded
- Number_Of_Sequences times. These sequences are decoded in order from
- first to last. Since the compressor writes the bitstream in the
- forward direction, this means the compressor must encode the
- sequences starting with the last one and ending with the first.
-
- For each of the symbol types, the FSE state can be used to determine
- the appropriate code. The code then defines the Baseline and
- Number_of_Bits to read for each type. The description of the codes
- for how to determine these values can be found in
- Section 3.1.1.3.2.1.
-
- Decoding starts by reading the Number_of_Bits required to decode
- offset. It does the same for Match_Length and then for
- Literals_Length. This sequence is then used for Sequence Execution
- (see Section 3.1.1.4).
-
- If it is not the last sequence in the block, the next operation is to
- update states. Using the rules pre-calculated in the decoding
- tables, Literals_Length_State is updated, followed by
- Match_Length_State, and then Offset_State. See Section 4.1 for
- details on how to update states from the bitstream.
-
- This operation will be repeated Number_of_Sequences times. At the
- end, the bitstream shall be entirely consumed; otherwise, the
- bitstream is considered corrupted.
-
-3.1.1.3.2.2. Default Distributions
-
- If Predefined_Mode is selected for a symbol type, its FSE decoding
- table is generated from a predefined distribution table defined here.
- For details on how to convert this distribution into a decoding
- table, see Section 4.1.
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 27]
-
-RFC 8478 application/zstd October 2018
-
-
-3.1.1.3.2.2.1. Literals Length
-
- The decoding table uses an accuracy log of 6 bits (64 states).
-
- short literalsLength_defaultDistribution[36] =
- { 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,
- -1,-1,-1,-1
- };
-
-3.1.1.3.2.2.2. Match Length
-
- The decoding table uses an accuracy log of 6 bits (64 states).
-
- short matchLengths_defaultDistribution[53] =
- { 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,
- -1,-1,-1,-1,-1
- };
-
-3.1.1.3.2.2.3. Offset Codes
-
- The decoding table uses an accuracy log of 5 bits (32 states), and
- supports a maximum N value of 28, allowing offset values up to
- 536,870,908.
-
- If any sequence in the compressed block requires a larger offset than
- this, it's not possible to use the default distribution to represent
- it.
-
- short offsetCodes_defaultDistribution[29] =
- { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1
- };
-
-3.1.1.4. Sequence Execution
-
- Once literals and sequences have been decoded, they are combined to
- produce the decoded content of a block.
-
- Each sequence consists of a tuple of (literals_length, offset_value,
- match_length), decoded as described in the
- Sequences_Section (Section 3.1.1.3.2). To execute a sequence, first
- copy literals_length bytes from the decoded literals to the output.
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 28]
-
-RFC 8478 application/zstd October 2018
-
-
- Then, match_length bytes are copied from previous decoded data. The
- offset to copy from is determined by offset_value:
-
- o if Offset_Value > 3, then the offset is Offset_Value - 3;
-
- o if Offset_Value is from 1-3, the offset is a special repeat offset
- value. See Section 3.1.1.5 for how the offset is determined in
- this case.
-
- The offset is defined as from the current position (after copying the
- literals), so an offset of 6 and a match length of 3 means that 3
- bytes should be copied from 6 bytes back. Note that all offsets
- leading to previously decoded data must be smaller than Window_Size
- defined in Frame_Header_Descriptor (Section 3.1.1.1.1).
-
-3.1.1.5. Repeat Offsets
-
- As seen above, the first three values define a repeated offset; we
- will call them Repeated_Offset1, Repeated_Offset2, and
- Repeated_Offset3. They are sorted in recency order, with
- Repeated_Offset1 meaning "most recent one".
-
- If offset_value is 1, then the offset used is Repeated_Offset1, etc.
-
- There is one exception: When the current sequence's literals_length
- is 0, repeated offsets are shifted by 1, so an offset_value of 1
- means Repeated_Offset2, an offset_value of 2 means Repeated_Offset3,
- and an offset_value of 3 means Repeated_Offset1 - 1_byte.
-
- For the first block, the starting offset history is populated with
- the following values: Repeated_Offset1 (1), Repeated_Offset2 (4), and
- Repeated_Offset3 (8), unless a dictionary is used, in which case they
- come from the dictionary.
-
- Then each block gets its starting offset history from the ending
- values of the most recent Compressed_Block. Note that blocks that
- are not Compressed_Block are skipped; they do not contribute to
- offset history.
-
- The newest offset takes the lead in offset history, shifting others
- back (up to its previous place if it was already present). This
- means that when Repeated_Offset1 (most recent) is used, history is
- unmodified. When Repeated_Offset2 is used, it is swapped with
- Repeated_Offset1. If any other offset is used, it becomes
- Repeated_Offset1, and the rest are shifted back by 1.
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 29]
-
-RFC 8478 application/zstd October 2018
-
-
-3.1.2. Skippable Frames
-
- +--------------+------------+-----------+
- | Magic_Number | Frame_Size | User_Data |
- +--------------+------------+-----------+
- | 4 bytes | 4 bytes | n bytes |
- +--------------+------------+-----------+
-
- Skippable frames allow the insertion of user-defined metadata into a
- flow of concatenated frames.
-
- Skippable frames defined in this specification are compatible with
- skippable frames in [LZ4].
-
- From a compliant decoder perspective, skippable frames simply need to
- be skipped, and their content ignored, resuming decoding after the
- skippable frame.
-
- It should be noted that a skippable frame can be used to watermark a
- stream of concatenated frames embedding any kind of tracking
- information (even just a Universally Unique Identifier (UUID)).
- Users wary of such possibility should scan the stream of concatenated
- frames in an attempt to detect such frames for analysis or removal.
-
- The fields are:
-
- Magic_Number: 4 bytes, little-endian format. Value: 0x184D2A5?,
- which means any value from 0x184D2A50 to 0x184D2A5F. All 16
- values are valid to identify a skippable frame. This
- specification does not detail any specific tagging methods for
- skippable frames.
-
- Frame_Size: This is the size, in bytes, of the following User_Data
- (without including the magic number nor the size field itself).
- This field is represented using 4 bytes, little-endian format,
- unsigned 32 bits. This means User_Data can't be bigger than
- (2^32-1) bytes.
-
- User_Data: This field can be anything. Data will just be skipped by
- the decoder.
-
-4. Entropy Encoding
-
- Two types of entropy encoding are used by the Zstandard format: FSE
- and Huffman coding. Huffman is used to compress literals, while FSE
- is used for all other symbols (Literals_Length_Code,
- Match_Length_Code, and offset codes) and to compress Huffman headers.
-
-
-
-
-Collet & Kucherawy Informational [Page 30]
-
-RFC 8478 application/zstd October 2018
-
-
-4.1. FSE
-
- FSE, short for Finite State Entropy, is an entropy codec based on
- [ANS]. FSE encoding/decoding involves a state that is carried over
- between symbols, so decoding must be done in the opposite direction
- as encoding. Therefore, all FSE bitstreams are read from end to
- beginning. Note that the order of the bits in the stream is not
- reversed; they are simply read in the reverse order from which they
- were written.
-
- For additional details on FSE, see Finite State Entropy [FSE].
-
- FSE decoding involves a decoding table that has a power of 2 size and
- contains three elements: Symbol, Num_Bits, and Baseline. The base 2
- logarithm of the table size is its Accuracy_Log. An FSE state value
- represents an index in this table.
-
- To obtain the initial state value, consume Accuracy_Log bits from the
- stream as a little-endian value. The next symbol in the stream is
- the Symbol indicated in the table for that state. To obtain the next
- state value, the decoder should consume Num_Bits bits from the stream
- as a little-endian value and add it to Baseline.
-
-4.1.1. FSE Table Description
-
- To decode FSE streams, it is necessary to construct the decoding
- table. The Zstandard format encodes FSE table descriptions as
- described here.
-
- An FSE distribution table describes the probabilities of all symbols
- from 0 to the last present one (included) on a normalized scale of
- (1 << Accuracy_Log). Note that there must be two or more symbols
- with non-zero probability.
-
- A bitstream is read forward, in little-endian fashion. It is not
- necessary to know its exact size, since the size will be discovered
- and reported by the decoding process. The bitstream starts by
- reporting on which scale it operates. If low4bits designates the
- lowest 4 bits of the first byte, then Accuracy_Log = low4bits + 5.
-
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 31]
-
-RFC 8478 application/zstd October 2018
-
-
- This is followed by each symbol value, from 0 to the last present
- one. The number of bits used by each field is variable and depends
- on:
-
- Remaining probabilities + 1: For example, presuming an Accuracy_Log
- of 8, and presuming 100 probabilities points have already been
- distributed, the decoder may read any value from 0 to
- (256 - 100 + 1) == 157, inclusive. Therefore, it must read
- log2sup(157) == 8 bits.
-
- Value decoded: Small values use 1 fewer bit. For example, presuming
- values from 0 to 157 (inclusive) are possible, 255 - 157 = 98
- values are remaining in an 8-bit field. The first 98 values
- (hence from 0 to 97) use only 7 bits, and values from 98 to 157
- use 8 bits. This is achieved through this scheme:
-
- +------------+---------------+-----------+
- | Value Read | Value Decoded | Bits Used |
- +------------+---------------+-----------+
- | 0 - 97 | 0 - 97 | 7 |
- +------------+---------------+-----------+
- | 98 - 127 | 98 - 127 | 8 |
- +------------+---------------+-----------+
- | 128 - 225 | 0 - 97 | 7 |
- +------------+---------------+-----------+
- | 226 - 255 | 128 - 157 | 8 |
- +------------+---------------+-----------+
-
- Symbol probabilities are read one by one, in order. The probability
- is obtained from Value decoded using the formula P = Value - 1. This
- means the value 0 becomes the negative probability -1. This is a
- special probability that means "less than 1". Its effect on the
- distribution table is described below. For the purpose of
- calculating total allocated probability points, it counts as 1.
-
- When a symbol has a probability of zero, it is followed by a 2-bit
- repeat flag. This repeat flag tells how many probabilities of zeroes
- follow the current one. It provides a number ranging from 0 to 3.
- If it is a 3, another 2-bit repeat flag follows, and so on.
-
- When the last symbol reaches a cumulated total of
- (1 << Accuracy_Log), decoding is complete. If the last symbol makes
- the cumulated total go above (1 << Accuracy_Log), distribution is
- considered corrupted.
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 32]
-
-RFC 8478 application/zstd October 2018
-
-
- Finally, the decoder can tell how many bytes were used in this
- process and how many symbols are present. The bitstream consumes a
- round number of bytes. Any remaining bit within the last byte is
- simply unused.
-
- The distribution of normalized probabilities is enough to create a
- unique decoding table. The table has a size of (1 << Accuracy_Log).
- Each cell describes the symbol decoded and instructions to get the
- next state.
-
- Symbols are scanned in their natural order for "less than 1"
- probabilities as described above. Symbols with this probability are
- being attributed a single cell, starting from the end of the table
- and retreating. These symbols define a full state reset, reading
- Accuracy_Log bits.
-
- All remaining symbols are allocated in their natural order. Starting
- from symbol 0 and table position 0, each symbol gets allocated as
- many cells as its probability. Cell allocation is spread, not
- linear; each successor position follows this rule:
-
- position += (tableSize >> 1) + (tableSize >> 3) + 3;
- position &= tableSize - 1;
-
- A position is skipped if it is already occupied by a "less than 1"
- probability symbol. Position does not reset between symbols; it
- simply iterates through each position in the table, switching to the
- next symbol when enough states have been allocated to the current
- one.
-
- The result is a list of state values. Each state will decode the
- current symbol.
-
- To get the Number_of_Bits and Baseline required for the next state,
- it is first necessary to sort all states in their natural order. The
- lower states will need 1 more bit than higher ones. The process is
- repeated for each symbol.
-
- For example, presuming a symbol has a probability of 5, it receives
- five state values. States are sorted in natural order. The next
- power of 2 is 8. The space of probabilities is divided into 8 equal
- parts. Presuming the Accuracy_Log is 7, this defines 128 states, and
- each share (divided by 8) is 16 in size. In order to reach 8, 8 - 5
- = 3 lowest states will count "double", doubling the number of shares
- (32 in width), requiring 1 more bit in the process.
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 33]
-
-RFC 8478 application/zstd October 2018
-
-
- Baseline is assigned starting from the higher states using fewer
- bits, and proceeding naturally, then resuming at the first state,
- each taking its allocated width from Baseline.
-
- +----------------+-------+-------+--------+------+-------+
- | state order | 0 | 1 | 2 | 3 | 4 |
- +----------------+-------+-------+--------+------+-------+
- | width | 32 | 32 | 32 | 16 | 16 |
- +----------------+-------+-------+--------+------+-------+
- | Number_of_Bits | 5 | 5 | 5 | 4 | 4 |
- +----------------+-------+-------+--------+------+-------+
- | range number | 2 | 4 | 6 | 0 | 1 |
- +----------------+-------+-------+--------+------+-------+
- | Baseline | 32 | 64 | 96 | 0 | 16 |
- +----------------+-------+-------+--------+------+-------+
- | range | 32-63 | 64-95 | 96-127 | 0-15 | 16-31 |
- +----------------+-------+-------+--------+------+-------+
-
- The next state is determined from the current state by reading the
- required Number_of_Bits and adding the specified Baseline.
-
- See Appendix A for the results of this process that are applied to
- the default distributions.
-
-4.2. Huffman Coding
-
- Zstandard Huffman-coded streams are read backwards, similar to the
- FSE bitstreams. Therefore, to find the start of the bitstream, it is
- necessary to know the offset of the last byte of the Huffman-coded
- stream.
-
- After writing the last bit containing information, the compressor
- writes a single 1 bit and then fills the byte with 0-7 0 bits of
- padding. The last byte of the compressed bitstream cannot be 0 for
- that reason.
-
- When decompressing, the last byte containing the padding is the first
- byte to read. The decompressor needs to skip 0-7 initial 0 bits and
- the first 1 bit that occurs. Afterwards, the useful part of the
- bitstream begins.
-
- The bitstream contains Huffman-coded symbols in little-endian order,
- with the codes defined by the method below.
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 34]
-
-RFC 8478 application/zstd October 2018
-
-
-4.2.1. Huffman Tree Description
-
- Prefix coding represents symbols from an a priori known alphabet by
- bit sequences (codewords), one codeword for each symbol, in a manner
- such that different symbols may be represented by bit sequences of
- different lengths, but a parser can always parse an encoded string
- unambiguously symbol by symbol.
-
- Given an alphabet with known symbol frequencies, the Huffman
- algorithm allows the construction of an optimal prefix code using the
- fewest bits of any possible prefix codes for that alphabet.
-
- The prefix code must not exceed a maximum code length. More bits
- improve accuracy but yield a larger header size and require more
- memory or more complex decoding operations. This specification
- limits the maximum code length to 11 bits.
-
- All literal values from zero (included) to the last present one
- (excluded) are represented by Weight with values from 0 to
- Max_Number_of_Bits. Transformation from Weight to Number_of_Bits
- follows this pseudocode:
-
- if Weight == 0
- Number_of_Bits = 0
- else
- Number_of_Bits = Max_Number_of_Bits + 1 - Weight
-
- The last symbol's Weight is deduced from previously decoded ones, by
- completing to the nearest power of 2. This power of 2 gives
- Max_Number_of_Bits the depth of the current tree.
-
- For example, presume the following Huffman tree must be described:
-
- +---------------+----------------+
- | Literal Value | Number_of_Bits |
- +---------------+----------------+
- | 0 | 1 |
- +---------------+----------------+
- | 1 | 2 |
- +---------------+----------------+
- | 2 | 3 |
- +---------------+----------------+
- | 3 | 0 |
- +---------------+----------------+
- | 4 | 4 |
- +---------------+----------------+
- | 5 | 4 |
- +---------------+----------------+
-
-
-
-Collet & Kucherawy Informational [Page 35]
-
-RFC 8478 application/zstd October 2018
-
-
- The tree depth is 4, since its longest element uses 4 bits. (The
- longest elements are those with the smallest frequencies.) Value 5
- will not be listed as it can be determined from the values for 0-4,
- nor will values above 5 as they are all 0. Values from 0 to 4 will
- be listed using Weight instead of Number_of_Bits. The pseudocode to
- determine Weight is:
-
- if Number_of_Bits == 0
- Weight = 0
- else
- Weight = Max_Number_of_Bits + 1 - Number_of_Bits
-
- It gives the following series of weights:
-
- +---------------+--------+
- | Literal Value | Weight |
- +---------------+--------+
- | 0 | 4 |
- +---------------+--------+
- | 1 | 3 |
- +---------------+--------+
- | 2 | 2 |
- +---------------+--------+
- | 3 | 0 |
- +---------------+--------+
- | 4 | 1 |
- +---------------+--------+
-
- The decoder will do the inverse operation: having collected weights
- of literals from 0 to 4, it knows the last literal, 5, is present
- with a non-zero Weight. The Weight of 5 can be determined by
- advancing to the next power of 2. The sum of 2^(Weight-1) (excluding
- 0's) is 15. The nearest power of 2 is 16. Therefore,
- Max_Number_of_Bits = 4 and Weight[5] = 16 - 15 = 1.
-
-4.2.1.1. Huffman Tree Header
-
- This is a single byte value (0-255), which describes how the series
- of weights is encoded.
-
- headerByte < 128: The series of weights is compressed using FSE (see
- below). The length of the FSE-compressed series is equal to
- headerByte (0-127).
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 36]
-
-RFC 8478 application/zstd October 2018
-
-
- headerByte >= 128: This is a direct representation, where each
- Weight is written directly as a 4-bit field (0-15). They are
- encoded forward, 2 weights to a byte with the first weight taking
- the top 4 bits and the second taking the bottom 4; for example,
- the following operations could be used to read the weights:
-
- Weight[0] = (Byte[0] >> 4)
- Weight[1] = (Byte[0] & 0xf),
- etc.
-
- The full representation occupies ceiling(Number_of_Symbols/2)
- bytes, meaning it uses only full bytes even if Number_of_Symbols
- is odd. Number_of_Symbols = headerByte - 127. Note that maximum
- Number_of_Symbols is 255 - 127 = 128. If any literal has a value
- over 128, raw header mode is not possible, and it is necessary to
- use FSE compression.
-
-4.2.1.2. FSE Compression of Huffman Weights
-
- In this case, the series of Huffman weights is compressed using FSE
- compression. It is a single bitstream with two interleaved states,
- sharing a single distribution table.
-
- To decode an FSE bitstream, it is necessary to know its compressed
- size. Compressed size is provided by headerByte. It's also
- necessary to know its maximum possible decompressed size, which is
- 255, since literal values span from 0 to 255, and the last symbol's
- Weight is not represented.
-
- An FSE bitstream starts by a header, describing probabilities
- distribution. It will create a decoding table. For a list of
- Huffman weights, the maximum accuracy log is 6 bits. For more
- details, see Section 4.1.1.
-
- The Huffman header compression uses two states, which share the same
- FSE distribution table. The first state (State1) encodes the even-
- numbered index symbols, and the second (State2) encodes the odd-
- numbered index symbols. State1 is initialized first, and then
- State2, and they take turns decoding a single symbol and updating
- their state. For more details on these FSE operations, see
- Section 4.1.
-
- The number of symbols to be decoded is determined by tracking the
- bitStream overflow condition: If updating state after decoding a
- symbol would require more bits than remain in the stream, it is
- assumed that extra bits are zero. Then, symbols for each of the
- final states are decoded and the process is complete.
-
-
-
-
-Collet & Kucherawy Informational [Page 37]
-
-RFC 8478 application/zstd October 2018
-
-
-4.2.1.3. Conversion from Weights to Huffman Prefix Codes
-
- All present symbols will now have a Weight value. It is possible to
- transform weights into Number_of_Bits, using this formula:
-
- if Weight > 0
- Number_of_Bits = Max_Number_of_Bits + 1 - Weight
- else
- Number_of_Bits = 0
-
- Symbols are sorted by Weight. Within the same Weight, symbols keep
- natural sequential order. Symbols with a Weight of zero are removed.
- Then, starting from the lowest Weight, prefix codes are distributed
- in sequential order.
-
- For example, assume the following list of weights has been decoded:
-
- +---------+--------+
- | Literal | Weight |
- +---------+--------+
- | 0 | 4 |
- +---------+--------+
- | 1 | 3 |
- +---------+--------+
- | 2 | 2 |
- +---------+--------+
- | 3 | 0 |
- +---------+--------+
- | 4 | 1 |
- +---------+--------+
- | 5 | 1 |
- +---------+--------+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 38]
-
-RFC 8478 application/zstd October 2018
-
-
- Sorting by weight and then the natural sequential order yields the
- following distribution:
-
- +---------+--------+----------------+--------------+
- | Literal | Weight | Number_Of_Bits | Prefix Codes |
- +---------+--------+----------------|--------------+
- | 3 | 0 | 0 | N/A |
- +---------+--------+----------------|--------------+
- | 4 | 1 | 4 | 0000 |
- +---------+--------+----------------|--------------+
- | 5 | 1 | 4 | 0001 |
- +---------+--------+----------------|--------------+
- | 2 | 2 | 3 | 001 |
- +---------+--------+----------------|--------------+
- | 1 | 3 | 2 | 01 |
- +---------+--------+----------------|--------------+
- | 0 | 4 | 1 | 1 |
- +---------+--------+----------------|--------------+
-
-4.2.2. Huffman-Coded Streams
-
- Given a Huffman decoding table, it is possible to decode a Huffman-
- coded stream.
-
- Each bitstream must be read backward, which starts from the end and
- goes up to the beginning. Therefore, it is necessary to know the
- size of each bitstream.
-
- It is also necessary to know exactly which bit is the last. This is
- detected by a final bit flag: the highest bit of the last byte is a
- final-bit-flag. Consequently, a last byte of 0 is not possible. And
- the final-bit-flag itself is not part of the useful bitstream.
- Hence, the last byte contains between 0 and 7 useful bits.
-
- Starting from the end, it is possible to read the bitstream in a
- little-endian fashion, keeping track of already used bits. Since the
- bitstream is encoded in reverse order, starting from the end, read
- symbols in forward order.
-
-
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 39]
-
-RFC 8478 application/zstd October 2018
-
-
- For example, if the literal sequence "0145" was encoded using the
- above prefix code, it would be encoded (in reverse order) as:
-
- +---------+----------+
- | Symbol | Encoding |
- +---------+----------+
- | 5 | 0000 |
- +---------+----------+
- | 4 | 0001 |
- +---------+----------+
- | 1 | 01 |
- +---------+----------+
- | 0 | 1 |
- +---------+----------+
- | Padding | 00001 |
- +---------+----------+
-
- This results in the following 2-byte bitstream:
-
- 00010000 00001101
-
- Here is an alternative representation with the symbol codes separated
- by underscores:
-
- 0001_0000 00001_1_01
-
- Reading the highest Max_Number_of_Bits bits, it's possible to compare
- the extracted value to the decoding table, determining the symbol to
- decode and number of bits to discard.
-
- The process continues reading up to the required number of symbols
- per stream. If a bitstream is not entirely and exactly consumed,
- hence reaching exactly its beginning position with all bits consumed,
- the decoding process is considered faulty.
-
-5. Dictionary Format
-
- Zstandard is compatible with "raw content" dictionaries, free of any
- format restriction, except that they must be at least 8 bytes. These
- dictionaries function as if they were just the content part of a
- formatted dictionary.
-
- However, dictionaries created by "zstd --train" in the reference
- implementation follow a specific format, described here.
-
- Dictionaries are not included in the compressed content but rather
- are provided out of band. That is, the Dictionary_ID identifies
- which should be used, but this specification does not describe the
-
-
-
-Collet & Kucherawy Informational [Page 40]
-
-RFC 8478 application/zstd October 2018
-
-
- mechanism by which the dictionary is obtained prior to use during
- compression or decompression.
-
- A dictionary has a size, defined either by a buffer limit or a file
- size. The general format is:
-
- +--------------+---------------+----------------+---------+
- | Magic_Number | Dictionary_ID | Entropy_Tables | Content |
- +--------------+---------------+----------------+---------+
-
- Magic_Number: 4 bytes ID, value 0xEC30A437, little-endian format.
-
- Dictionary_ID: 4 bytes, stored in little-endian format.
- Dictionary_ID can be any value, except 0 (which means no
- Dictionary_ID). It is used by decoders to check if they use the
- correct dictionary. If the frame is going to be distributed in a
- private environment, any Dictionary_ID can be used. However, for
- public distribution of compressed frames, the following ranges are
- reserved and shall not be used:
-
- low range: <= 32767
- high range: >= (2^31)
-
- Entropy_Tables: Follow the same format as the tables in compressed
- blocks. See the relevant FSE and Huffman sections for how to
- decode these tables. They are stored in the following order:
- Huffman table for literals, FSE table for offsets, FSE table for
- match lengths, and FSE table for literals lengths. These tables
- populate the Repeat Stats literals mode and Repeat distribution
- mode for sequence decoding. It is finally followed by 3 offset
- values, populating repeat offsets (instead of using {1,4,8}),
- stored in order, 4-bytes little-endian each, for a total of 12
- bytes. Each repeat offset must have a value less than the
- dictionary size.
-
- Content: The rest of the dictionary is its content. The content
- acts as a "past" in front of data to be compressed or
- decompressed, so it can be referenced in sequence commands. As
- long as the amount of data decoded from this frame is less than or
- equal to Window_Size, sequence commands may specify offsets longer
- than the total length of decoded output so far to reference back
- to the dictionary, even parts of the dictionary with offsets
- larger than Window_Size. After the total output has surpassed
- Window_Size, however, this is no longer allowed, and the
- dictionary is no longer accessible.
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 41]
-
-RFC 8478 application/zstd October 2018
-
-
-6. IANA Considerations
-
- IANA has made two registrations, as described below.
-
-6.1. The 'application/zstd' Media Type
-
- The 'application/zstd' media type identifies a block of data that is
- compressed using zstd compression. The data is a stream of bytes as
- described in this document. IANA has added the following to the
- "Media Types" registry:
-
- Type name: application
-
- Subtype name: zstd
-
- Required parameters: N/A
-
- Optional parameters: N/A
-
- Encoding considerations: binary
-
- Security considerations: See Section 7 of RFC 8478
-
- Interoperability considerations: N/A
-
- Published specification: RFC 8478
-
- Applications that use this media type: anywhere data size is an
- issue
-
- Additional information:
-
- Magic number(s): 4 bytes, little-endian format.
- Value: 0xFD2FB528
-
- File extension(s): zst
-
- Macintosh file type code(s): N/A
-
- For further information: See [ZSTD]
-
- Intended usage: common
-
- Restrictions on usage: N/A
-
- Author: Murray S. Kucherawy
-
- Change Controller: IETF
-
-
-
-Collet & Kucherawy Informational [Page 42]
-
-RFC 8478 application/zstd October 2018
-
-
- Provisional registration: no
-
-6.2. Content Encoding
-
- IANA has added the following entry to the "HTTP Content Coding
- Registry" within the "Hypertext Transfer Protocol (HTTP) Parameters"
- registry:
-
- Name: zstd
-
- Description: A stream of bytes compressed using the Zstandard
- protocol
-
- Pointer to specification text: RFC 8478
-
-6.3. Dictionaries
-
- Work in progress includes development of dictionaries that will
- optimize compression and decompression of particular types of data.
- Specification of such dictionaries for public use will necessitate
- registration of a code point from the reserved range described in
- Section 3.1.1.1.3 and its association with a specific dictionary.
-
- However, there are at present no such dictionaries published for
- public use, so this document makes no immediate request of IANA to
- create such a registry.
-
-7. Security Considerations
-
- Any data compression method involves the reduction of redundancy in
- the data. Zstandard is no exception, and the usual precautions
- apply.
-
- One should never compress a message whose content must remain secret
- with a message generated by a third party. Such a compression can be
- used to guess the content of the secret message through analysis of
- entropy reduction. This was demonstrated in the Compression Ratio
- Info-leak Made Easy (CRIME) attack [CRIME], for example.
-
- A decoder has to demonstrate capabilities to detect and prevent any
- kind of data tampering in the compressed frame from triggering system
- faults, such as reading or writing beyond allowed memory ranges.
- This can be guaranteed by either the implementation language or
- careful bound checkings. Of particular note is the encoding of
- Number_of_Sequences values that cause the decoder to read into the
- block header (and beyond), as well as the indication of a
- Frame_Content_Size that is smaller than the actual decompressed data,
- in an attempt to trigger a buffer overflow. It is highly recommended
-
-
-
-Collet & Kucherawy Informational [Page 43]
-
-RFC 8478 application/zstd October 2018
-
-
- to fuzz-test (i.e., provide invalid, unexpected, or random input and
- verify safe operation of) decoder implementations to test and harden
- their capability to detect bad frames and deal with them without any
- adverse system side effect.
-
- An attacker may provide correctly formed compressed frames with
- unreasonable memory requirements. A decoder must always control
- memory requirements and enforce some (system-specific) limits in
- order to protect memory usage from such scenarios.
-
- Compression can be optimized by training a dictionary on a variety of
- related content payloads. This dictionary must then be available at
- the decoder for decompression of the payload to be possible. While
- this document does not specify how to acquire a dictionary for a
- given compressed payload, it is worth noting that third-party
- dictionaries may interact unexpectedly with a decoder, leading to
- possible memory or other resource exhaustion attacks. We expect such
- topics to be discussed in further detail in the Security
- Considerations section of a forthcoming RFC for dictionary
- acquisition and transmission, but highlight this issue now out of an
- abundance of caution.
-
- As discussed in Section 3.1.2, it is possible to store arbitrary user
- metadata in skippable frames. While such frames are ignored during
- decompression of the data, they can be used as a watermark to track
- the path of the compressed payload.
-
-8. Implementation Status
-
- Source code for a C language implementation of a Zstandard-compliant
- library is available at [ZSTD-GITHUB]. This implementation is
- considered to be the reference implementation and is production
- ready; it implements the full range of the specification. It is
- routinely tested against security hazards and widely deployed within
- Facebook infrastructure.
-
- The reference version is optimized for speed and is highly portable.
- It has been proven to run safely on multiple architectures (e.g.,
- x86, x64, ARM, MIPS, PowerPC, IA64) featuring 32- or 64-bit
- addressing schemes, a little- or big-endian storage scheme, a number
- of different operating systems (e.g., UNIX (including Linux, BSD,
- OS-X, and Solaris) and Windows), and a number of compilers (e.g.,
- gcc, clang, visual, and icc).
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 44]
-
-RFC 8478 application/zstd October 2018
-
-
-9. References
-
-9.1. Normative References
-
- [ZSTD] "Zstandard", .
-
-9.2. Informative References
-
- [ANS] Duda, J., "Asymmetric numeral systems: entropy coding
- combining speed of Huffman coding with compression rate of
- arithmetic coding", January 2014,
- .
-
- [CRIME] "CRIME", June 2018, .
-
- [FSE] "FiniteStateEntropy", commit 6efa78a, June 2018,
- .
-
- [LZ4] "LZ4 Frame Format Description", commit d03224b, January
- 2018, .
-
- [RFC1952] Deutsch, P., "GZIP file format specification version 4.3",
- RFC 1952, DOI 10.17487/RFC1952, May 1996,
- .
-
- [XXHASH] "XXHASH Algorithm", .
-
- [ZSTD-GITHUB]
- "zstd", commit 8514bd8, August 2018,
- .
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 45]
-
-RFC 8478 application/zstd October 2018
-
-
-Appendix A. Decoding Tables for Predefined Codes
-
- This appendix contains FSE decoding tables for the predefined literal
- length, match length, and offset codes. The tables have been
- constructed using the algorithm as given above in Section 4.1.1. The
- tables here can be used as examples to crosscheck that an
- implementation has built its decoding tables correctly.
-
-A.1. Literal Length Code Table
-
- +-------+--------+----------------+------+
- | State | Symbol | Number_Of_Bits | Base |
- +-------+--------+----------------+------+
- | 0 | 0 | 0 | 0 |
- +-------+--------+----------------+------+
- | 0 | 0 | 4 | 0 |
- +-------+--------+----------------+------+
- | 1 | 0 | 4 | 16 |
- +-------+--------+----------------+------+
- | 2 | 1 | 5 | 32 |
- +-------+--------+----------------+------+
- | 3 | 3 | 5 | 0 |
- +-------+--------+----------------+------+
- | 4 | 4 | 5 | 0 |
- +-------+--------+----------------+------+
- | 5 | 6 | 5 | 0 |
- +-------+--------+----------------+------+
- | 6 | 7 | 5 | 0 |
- +-------+--------+----------------+------+
- | 7 | 9 | 5 | 0 |
- +-------+--------+----------------+------+
- | 8 | 10 | 5 | 0 |
- +-------+--------+----------------+------+
- | 9 | 12 | 5 | 0 |
- +-------+--------+----------------+------+
- | 10 | 14 | 6 | 0 |
- +-------+--------+----------------+------+
- | 11 | 16 | 5 | 0 |
- +-------+--------+----------------+------+
- | 12 | 18 | 5 | 0 |
- +-------+--------+----------------+------+
- | 13 | 19 | 5 | 0 |
- +-------+--------+----------------+------+
- | 14 | 21 | 5 | 0 |
- +-------+--------+----------------+------+
- | 15 | 22 | 5 | 0 |
- +-------+--------+----------------+------+
- | 16 | 24 | 5 | 0 |
-
-
-
-Collet & Kucherawy Informational [Page 46]
-
-RFC 8478 application/zstd October 2018
-
-
- +-------+--------+----------------+------+
- | 17 | 25 | 5 | 32 |
- +-------+--------+----------------+------+
- | 18 | 26 | 5 | 0 |
- +-------+--------+----------------+------+
- | 19 | 27 | 6 | 0 |
- +-------+--------+----------------+------+
- | 20 | 29 | 6 | 0 |
- +-------+--------+----------------+------+
- | 21 | 31 | 6 | 0 |
- +-------+--------+----------------+------+
- | 22 | 0 | 4 | 32 |
- +-------+--------+----------------+------+
- | 23 | 1 | 4 | 0 |
- +-------+--------+----------------+------+
- | 24 | 2 | 5 | 0 |
- +-------+--------+----------------+------+
- | 25 | 4 | 5 | 32 |
- +-------+--------+----------------+------+
- | 26 | 5 | 5 | 0 |
- +-------+--------+----------------+------+
- | 27 | 7 | 5 | 32 |
- +-------+--------+----------------+------+
- | 28 | 8 | 5 | 0 |
- +-------+--------+----------------+------+
- | 29 | 10 | 5 | 32 |
- +-------+--------+----------------+------+
- | 30 | 11 | 5 | 0 |
- +-------+--------+----------------+------+
- | 31 | 13 | 6 | 0 |
- +-------+--------+----------------+------+
- | 32 | 16 | 5 | 32 |
- +-------+--------+----------------+------+
- | 33 | 17 | 5 | 0 |
- +-------+--------+----------------+------+
- | 34 | 19 | 5 | 32 |
- +-------+--------+----------------+------+
- | 35 | 20 | 5 | 0 |
- +-------+--------+----------------+------+
- | 36 | 22 | 5 | 32 |
- +-------+--------+----------------+------+
- | 37 | 23 | 5 | 0 |
- +-------+--------+----------------+------+
- | 38 | 25 | 4 | 0 |
- +-------+--------+----------------+------+
- | 39 | 25 | 4 | 16 |
- +-------+--------+----------------+------+
- | 40 | 26 | 5 | 32 |
-
-
-
-Collet & Kucherawy Informational [Page 47]
-
-RFC 8478 application/zstd October 2018
-
-
- +-------+--------+----------------+------+
- | 41 | 28 | 6 | 0 |
- +-------+--------+----------------+------+
- | 42 | 30 | 6 | 0 |
- +-------+--------+----------------+------+
- | 43 | 0 | 4 | 48 |
- +-------+--------+----------------+------+
- | 44 | 1 | 4 | 16 |
- +-------+--------+----------------+------+
- | 45 | 2 | 5 | 32 |
- +-------+--------+----------------+------+
- | 46 | 3 | 5 | 32 |
- +-------+--------+----------------+------+
- | 47 | 5 | 5 | 32 |
- +-------+--------+----------------+------+
- | 48 | 6 | 5 | 32 |
- +-------+--------+----------------+------+
- | 49 | 8 | 5 | 32 |
- +-------+--------+----------------+------+
- | 50 | 9 | 5 | 32 |
- +-------+--------+----------------+------+
- | 51 | 11 | 5 | 32 |
- +-------+--------+----------------+------+
- | 52 | 12 | 5 | 32 |
- +-------+--------+----------------+------+
- | 53 | 15 | 6 | 0 |
- +-------+--------+----------------+------+
- | 54 | 17 | 5 | 32 |
- +-------+--------+----------------+------+
- | 55 | 18 | 5 | 32 |
- +-------+--------+----------------+------+
- | 56 | 20 | 5 | 32 |
- +-------+--------+----------------+------+
- | 57 | 21 | 5 | 32 |
- +-------+--------+----------------+------+
- | 58 | 23 | 5 | 32 |
- +-------+--------+----------------+------+
- | 59 | 24 | 5 | 32 |
- +-------+--------+----------------+------+
- | 60 | 35 | 6 | 0 |
- +-------+--------+----------------+------+
- | 61 | 34 | 6 | 0 |
- +-------+--------+----------------+------+
- | 62 | 33 | 6 | 0 |
- +-------+--------+----------------+------+
- | 63 | 32 | 6 | 0 |
- +-------+--------+----------------+------+
-
-
-
-
-Collet & Kucherawy Informational [Page 48]
-
-RFC 8478 application/zstd October 2018
-
-
-A.2. Match Length Code Table
-
- +-------+--------+----------------+------+
- | State | Symbol | Number_Of_Bits | Base |
- +-------+--------+----------------+------+
- | 0 | 0 | 0 | 0 |
- +-------+--------+----------------+------+
- | 0 | 0 | 6 | 0 |
- +-------+--------+----------------+------+
- | 1 | 1 | 4 | 0 |
- +-------+--------+----------------+------+
- | 2 | 2 | 5 | 32 |
- +-------+--------+----------------+------+
- | 3 | 3 | 5 | 0 |
- +-------+--------+----------------+------+
- | 4 | 5 | 5 | 0 |
- +-------+--------+----------------+------+
- | 5 | 6 | 5 | 0 |
- +-------+--------+----------------+------+
- | 6 | 8 | 5 | 0 |
- +-------+--------+----------------+------+
- | 7 | 10 | 6 | 0 |
- +-------+--------+----------------+------+
- | 8 | 13 | 6 | 0 |
- +-------+--------+----------------+------+
- | 9 | 16 | 6 | 0 |
- +-------+--------+----------------+------+
- | 10 | 19 | 6 | 0 |
- +-------+--------+----------------+------+
- | 11 | 22 | 6 | 0 |
- +-------+--------+----------------+------+
- | 12 | 25 | 6 | 0 |
- +-------+--------+----------------+------+
- | 13 | 28 | 6 | 0 |
- +-------+--------+----------------+------+
- | 14 | 31 | 6 | 0 |
- +-------+--------+----------------+------+
- | 15 | 33 | 6 | 0 |
- +-------+--------+----------------+------+
- | 16 | 35 | 6 | 0 |
- +-------+--------+----------------+------+
- | 17 | 37 | 6 | 0 |
- +-------+--------+----------------+------+
- | 18 | 39 | 6 | 0 |
- +-------+--------+----------------+------+
- | 19 | 41 | 6 | 0 |
- +-------+--------+----------------+------+
- | 20 | 43 | 6 | 0 |
-
-
-
-Collet & Kucherawy Informational [Page 49]
-
-RFC 8478 application/zstd October 2018
-
-
- +-------+--------+----------------+------+
- | 21 | 45 | 6 | 0 |
- +-------+--------+----------------+------+
- | 22 | 1 | 4 | 16 |
- +-------+--------+----------------+------+
- | 23 | 2 | 4 | 0 |
- +-------+--------+----------------+------+
- | 24 | 3 | 5 | 32 |
- +-------+--------+----------------+------+
- | 25 | 4 | 5 | 0 |
- +-------+--------+----------------+------+
- | 26 | 6 | 5 | 32 |
- +-------+--------+----------------+------+
- | 27 | 7 | 5 | 0 |
- +-------+--------+----------------+------+
- | 28 | 9 | 6 | 0 |
- +-------+--------+----------------+------+
- | 29 | 12 | 6 | 0 |
- +-------+--------+----------------+------+
- | 30 | 15 | 6 | 0 |
- +-------+--------+----------------+------+
- | 31 | 18 | 6 | 0 |
- +-------+--------+----------------+------+
- | 32 | 21 | 6 | 0 |
- +-------+--------+----------------+------+
- | 33 | 24 | 6 | 0 |
- +-------+--------+----------------+------+
- | 34 | 27 | 6 | 0 |
- +-------+--------+----------------+------+
- | 35 | 30 | 6 | 0 |
- +-------+--------+----------------+------+
- | 36 | 32 | 6 | 0 |
- +-------+--------+----------------+------+
- | 37 | 34 | 6 | 0 |
- +-------+--------+----------------+------+
- | 38 | 36 | 6 | 0 |
- +-------+--------+----------------+------+
- | 39 | 38 | 6 | 0 |
- +-------+--------+----------------+------+
- | 40 | 40 | 6 | 0 |
- +-------+--------+----------------+------+
- | 41 | 42 | 6 | 0 |
- +-------+--------+----------------+------+
- | 42 | 44 | 6 | 0 |
- +-------+--------+----------------+------+
- | 43 | 1 | 4 | 32 |
- +-------+--------+----------------+------+
- | 44 | 1 | 4 | 48 |
-
-
-
-Collet & Kucherawy Informational [Page 50]
-
-RFC 8478 application/zstd October 2018
-
-
- +-------+--------+----------------+------+
- | 45 | 2 | 4 | 16 |
- +-------+--------+----------------+------+
- | 46 | 4 | 5 | 32 |
- +-------+--------+----------------+------+
- | 47 | 5 | 5 | 32 |
- +-------+--------+----------------+------+
- | 48 | 7 | 5 | 32 |
- +-------+--------+----------------+------+
- | 49 | 8 | 5 | 32 |
- +-------+--------+----------------+------+
- | 50 | 11 | 6 | 0 |
- +-------+--------+----------------+------+
- | 51 | 14 | 6 | 0 |
- +-------+--------+----------------+------+
- | 52 | 17 | 6 | 0 |
- +-------+--------+----------------+------+
- | 53 | 20 | 6 | 0 |
- +-------+--------+----------------+------+
- | 54 | 23 | 6 | 0 |
- +-------+--------+----------------+------+
- | 55 | 26 | 6 | 0 |
- +-------+--------+----------------+------+
- | 56 | 29 | 6 | 0 |
- +-------+--------+----------------+------+
- | 57 | 52 | 6 | 0 |
- +-------+--------+----------------+------+
- | 58 | 51 | 6 | 0 |
- +-------+--------+----------------+------+
- | 59 | 50 | 6 | 0 |
- +-------+--------+----------------+------+
- | 60 | 49 | 6 | 0 |
- +-------+--------+----------------+------+
- | 61 | 48 | 6 | 0 |
- +-------+--------+----------------+------+
- | 62 | 47 | 6 | 0 |
- +-------+--------+----------------+------+
- | 63 | 46 | 6 | 0 |
- +-------+--------+----------------+------+
-
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 51]
-
-RFC 8478 application/zstd October 2018
-
-
-A.3. Offset Code Table
-
- +-------+--------+----------------+------+
- | State | Symbol | Number_Of_Bits | Base |
- +-------+--------+----------------+------+
- | 0 | 0 | 0 | 0 |
- +-------+--------+----------------+------+
- | 0 | 0 | 5 | 0 |
- +-------+--------+----------------+------+
- | 1 | 6 | 4 | 0 |
- +-------+--------+----------------+------+
- | 2 | 9 | 5 | 0 |
- +-------+--------+----------------+------+
- | 3 | 15 | 5 | 0 |
- +-------+--------+----------------+------+
- | 4 | 21 | 5 | 0 |
- +-------+--------+----------------+------+
- | 5 | 3 | 5 | 0 |
- +-------+--------+----------------+------+
- | 6 | 7 | 4 | 0 |
- +-------+--------+----------------+------+
- | 7 | 12 | 5 | 0 |
- +-------+--------+----------------+------+
- | 8 | 18 | 5 | 0 |
- +-------+--------+----------------+------+
- | 9 | 23 | 5 | 0 |
- +-------+--------+----------------+------+
- | 10 | 5 | 5 | 0 |
- +-------+--------+----------------+------+
- | 11 | 8 | 4 | 0 |
- +-------+--------+----------------+------+
- | 12 | 14 | 5 | 0 |
- +-------+--------+----------------+------+
- | 13 | 20 | 5 | 0 |
- +-------+--------+----------------+------+
- | 14 | 2 | 5 | 0 |
- +-------+--------+----------------+------+
- | 15 | 7 | 4 | 16 |
- +-------+--------+----------------+------+
- | 16 | 11 | 5 | 0 |
- +-------+--------+----------------+------+
- | 17 | 17 | 5 | 0 |
- +-------+--------+----------------+------+
- | 18 | 22 | 5 | 0 |
- +-------+--------+----------------+------+
- | 19 | 4 | 5 | 0 |
- +-------+--------+----------------+------+
- | 20 | 8 | 4 | 16 |
-
-
-
-Collet & Kucherawy Informational [Page 52]
-
-RFC 8478 application/zstd October 2018
-
-
- +-------+--------+----------------+------+
- | 21 | 13 | 5 | 0 |
- +-------+--------+----------------+------+
- | 22 | 19 | 5 | 0 |
- +-------+--------+----------------+------+
- | 23 | 1 | 5 | 0 |
- +-------+--------+----------------+------+
- | 24 | 6 | 4 | 16 |
- +-------+--------+----------------+------+
- | 25 | 10 | 5 | 0 |
- +-------+--------+----------------+------+
- | 26 | 16 | 5 | 0 |
- +-------+--------+----------------+------+
- | 27 | 28 | 5 | 0 |
- +-------+--------+----------------+------+
- | 28 | 27 | 5 | 0 |
- +-------+--------+----------------+------+
- | 29 | 26 | 5 | 0 |
- +-------+--------+----------------+------+
- | 30 | 25 | 5 | 0 |
- +-------+--------+----------------+------+
- | 31 | 24 | 5 | 0 |
- +-------+--------+----------------+------+
-
-Acknowledgments
-
- zstd was developed by Yann Collet.
-
- Bobo Bose-Kolanu, Felix Handte, Kyle Nekritz, Nick Terrell, and David
- Schleimer provided helpful feedback during the development of this
- document.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 53]
-
-RFC 8478 application/zstd October 2018
-
-
-Authors' Addresses
-
- Yann Collet
- Facebook
- 1 Hacker Way
- Menlo Park, CA 94025
- United States of America
-
- Email: cyan@fb.com
-
-
- Murray S. Kucherawy (editor)
- Facebook
- 1 Hacker Way
- Menlo Park, CA 94025
- United States of America
-
- Email: msk@fb.com
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Collet & Kucherawy Informational [Page 54]
-
diff --git a/lib/std/compress/testdata/rfc8478.txt.zst.19 b/lib/std/compress/testdata/rfc8478.txt.zst.19
deleted file mode 100644
index e0cf325af238aaf25c2d4ec05107381a28bd481f..0000000000000000000000000000000000000000
Binary files a/lib/std/compress/testdata/rfc8478.txt.zst.19 and /dev/null differ
diff --git a/lib/std/compress/testdata/rfc8478.txt.zst.3 b/lib/std/compress/testdata/rfc8478.txt.zst.3
deleted file mode 100644
index 781601a8a2c9150aad00ee56d7997d2a96396404..0000000000000000000000000000000000000000
Binary files a/lib/std/compress/testdata/rfc8478.txt.zst.3 and /dev/null differ
diff --git a/lib/std/compress/xz/Decompress.zig b/lib/std/compress/xz/Decompress.zig
index 2fff561c73862a382eb5ff30e3d0a8418ad2bec6..5fc5a6068eb41137c604a6ba26e7fe35ed5ab7d3 100644
--- a/lib/std/compress/xz/Decompress.zig
+++ b/lib/std/compress/xz/Decompress.zig
@@ -2,8 +2,8 @@ const Decompress = @This();
const std = @import("../../std.zig");
const Allocator = std.mem.Allocator;
const ArrayList = std.ArrayList;
-const Crc32 = std.hash.Crc32;
-const Crc64 = std.hash.crc.Crc64Xz;
+const Crc32 = std.hash.crc.@"CRC-32/ISO-HDLC";
+const Crc64 = std.hash.crc.@"CRC-64/XZ";
const Sha256 = std.crypto.hash.sha2.Sha256;
const lzma2 = std.compress.lzma2;
const Writer = std.Io.Writer;
diff --git a/lib/std/compress/zstd.zig b/lib/std/compress/zstd.zig
index 51168889c6355b7952e9fe54576c7b74edc6d197..8471f38ba2e87bfb05ae08663e836cfc5339b853 100644
--- a/lib/std/compress/zstd.zig
+++ b/lib/std/compress/zstd.zig
@@ -121,17 +121,6 @@ fn testExpectDecompressError(err: anyerror, compressed: []const u8) !void {
try std.testing.expectError(err, zstd_stream.err orelse {});
}
-test Decompress {
- const uncompressed = @embedFile("testdata/rfc8478.txt");
- const compressed3 = @embedFile("testdata/rfc8478.txt.zst.3");
- const compressed19 = @embedFile("testdata/rfc8478.txt.zst.19");
-
- try testExpectDecompress(uncompressed, compressed3);
- try testExpectDecompress(uncompressed, compressed19);
- try std.testing.expectEqual(uncompressed.len, testDiscard(std.testing.allocator, compressed3));
- try std.testing.expectEqual(uncompressed.len, testDiscard(std.testing.allocator, compressed19));
-}
-
test "partial magic number" {
const input_raw =
"\x28\xb5\x2f"; // 3 bytes of the 4-byte zstandard frame magic number
diff --git a/lib/std/crypto/argon2.zig b/lib/std/crypto/argon2.zig
index 9add038b95bb5d46432fcaaeacf59a2f077185fb..e3550abe1d7cfcad3cdc738ac5f2f01e2606e0a5 100644
--- a/lib/std/crypto/argon2.zig
+++ b/lib/std/crypto/argon2.zig
@@ -609,10 +609,8 @@ pub fn strHash(
}
/// Options for hash verification.
-///
-/// Allocator is required for argon2.
pub const VerifyOptions = struct {
- allocator: ?mem.Allocator,
+ allocator: mem.Allocator,
};
/// Verify that a previously computed hash is valid for a given password.
@@ -622,8 +620,7 @@ pub fn strVerify(
options: VerifyOptions,
io: Io,
) Error!void {
- const allocator = options.allocator orelse return Error.AllocatorRequired;
- return PhcFormatHasher.verify(allocator, str, password, io);
+ return PhcFormatHasher.verify(options.allocator, str, password, io);
}
test "argon2d" {
diff --git a/lib/std/crypto/scrypt.zig b/lib/std/crypto/scrypt.zig
index 913feb4b380e909b816924a95131df14ef97cf69..9939188ebff47ad0a631255d7a2bf4be49c30e57 100644
--- a/lib/std/crypto/scrypt.zig
+++ b/lib/std/crypto/scrypt.zig
@@ -566,10 +566,8 @@ pub fn strHashWithSalt(
}
/// Options for hash verification.
-///
-/// Allocator is required for scrypt.
pub const VerifyOptions = struct {
- allocator: ?mem.Allocator,
+ allocator: mem.Allocator,
};
/// Verify that a previously computed hash is valid for a given password.
@@ -578,11 +576,10 @@ pub fn strVerify(
password: []const u8,
options: VerifyOptions,
) Error!void {
- const allocator = options.allocator orelse return Error.AllocatorRequired;
if (mem.startsWith(u8, str, crypt_format.prefix)) {
- return CryptFormatHasher.verify(allocator, str, password);
+ return CryptFormatHasher.verify(options.allocator, str, password);
} else {
- return PhcFormatHasher.verify(allocator, str, password);
+ return PhcFormatHasher.verify(options.allocator, str, password);
}
}
@@ -693,7 +690,7 @@ test "strHash and strVerify" {
const password = "testpass";
const params = Params.interactive;
- const verify_options = VerifyOptions{ .allocator = alloc };
+ const verify_options: VerifyOptions = .{ .allocator = alloc };
var buf: [128]u8 = undefined;
{
diff --git a/lib/std/crypto/tls/Client.zig b/lib/std/crypto/tls/Client.zig
index 4a0a8c6ddaf1c9231a89dce253c01c4eef8bf2fa..11eb30f226f217f9f28771f01aa53b8ccb21ccc0 100644
--- a/lib/std/crypto/tls/Client.zig
+++ b/lib/std/crypto/tls/Client.zig
@@ -376,7 +376,7 @@ pub fn init(input: *Reader, output: *Writer, options: Options) InitError!Client
const nonce = nonce: {
const V = @Vector(P.AEAD.nonce_length, u8);
const pad: [P.AEAD.nonce_length - 8]u8 = @splat(0);
- const operand: V = pad ++ @as([8]u8, @bitCast(big(read_seq)));
+ const operand: V = pad ++ @as([8]u8, @bitCast(@byteSwap(read_seq)));
break :nonce @as(V, pv.server_handshake_iv) ^ operand;
};
P.AEAD.decrypt(cleartext, ciphertext, auth_tag, record_header, nonce, pv.server_handshake_key) catch
@@ -416,7 +416,7 @@ pub fn init(input: *Reader, output: *Writer, options: Options) InitError!Client
const nonce: [P.AEAD.nonce_length]u8 = nonce: {
const V = @Vector(P.AEAD.nonce_length, u8);
const pad: [P.AEAD.nonce_length - 8]u8 = @splat(0);
- const operand: V = pad ++ @as([8]u8, @bitCast(big(masked_read_seq)));
+ const operand: V = pad ++ @as([8]u8, @bitCast(@byteSwap(masked_read_seq)));
break :nonce @as(V, pv.app_cipher.server_write_IV ++ record_iv) ^ operand;
};
const ciphertext = record_decoder.slice(message_len);
@@ -792,7 +792,7 @@ pub fn init(input: *Reader, output: *Writer, options: Options) InitError!Client
const nonce: [P.AEAD.nonce_length]u8 = nonce: {
const V = @Vector(P.AEAD.nonce_length, u8);
const pad: [P.AEAD.nonce_length - 8]u8 = @splat(0);
- const operand: V = pad ++ @as([8]u8, @bitCast(big(write_seq)));
+ const operand: V = pad ++ @as([8]u8, @bitCast(@byteSwap(write_seq)));
break :nonce @as(V, pv.app_cipher.client_write_IV ++ pv.app_cipher.client_salt) ^ operand;
};
var client_verify_msg = .{@intFromEnum(tls.ContentType.handshake)} ++
@@ -1105,7 +1105,7 @@ fn prepareCiphertextRecord(
const nonce: [P.AEAD.nonce_length]u8 = nonce: {
const V = @Vector(P.AEAD.nonce_length, u8);
const pad: [P.AEAD.nonce_length - 8]u8 = @splat(0);
- const operand: V = pad ++ @as([8]u8, @bitCast(big(c.write_seq)));
+ const operand: V = pad ++ @as([8]u8, @bitCast(@byteSwap(c.write_seq)));
break :nonce @as(V, pv.client_write_IV ++ pv.client_salt) ^ operand;
};
record_iv.* = nonce[P.fixed_iv_length..].*;
@@ -1214,7 +1214,7 @@ fn readIndirect(c: *Client) Reader.Error!usize {
const nonce: [P.AEAD.nonce_length]u8 = nonce: {
const V = @Vector(P.AEAD.nonce_length, u8);
const pad: [P.AEAD.nonce_length - 8]u8 = @splat(0);
- const operand: V = pad ++ @as([8]u8, @bitCast(big(masked_read_seq)));
+ const operand: V = pad ++ @as([8]u8, @bitCast(@byteSwap(masked_read_seq)));
break :nonce @as(V, pv.server_write_IV ++ record_iv) ^ operand;
};
const ciphertext = input.take(message_len) catch unreachable; // already peeked
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
index dd6de989cbff6b9a6f0c12a8b3e857b765b03a9b..578d06fd3f5ddefdf64d8ea3af2e6b510a7513d3 100644
--- a/lib/std/debug.zig
+++ b/lib/std/debug.zig
@@ -63,16 +63,22 @@ pub const cpu_context = @import("debug/cpu_context.zig");
/// ```
pub const SelfInfo = if (@hasDecl(root, "debug") and @hasDecl(root.debug, "SelfInfo"))
root.debug.SelfInfo
-else switch (std.Target.ObjectFormat.default(native_os, native_arch)) {
- .coff => if (native_os == .windows) @import("debug/SelfInfo/Windows.zig") else void,
- .elf => switch (native_os) {
- .freestanding, .other => void,
- else => @import("debug/SelfInfo/Elf.zig"),
- },
- .macho => @import("debug/SelfInfo/MachO.zig"),
- .plan9, .spirv, .wasm => void,
- .c, .hex, .raw => unreachable,
-};
+else
+ TargetInfo(native_os, native_arch);
+
+/// Returns the default `SelfInfo` for the given `os` and `arch`.
+pub fn TargetInfo(os: std.Target.Os.Tag, arch: std.Target.Cpu.Arch) type {
+ return switch (std.Target.ObjectFormat.default(os, arch)) {
+ .coff => if (os == .windows) @import("debug/SelfInfo/Windows.zig") else void,
+ .elf => switch (os) {
+ .freestanding, .other => void,
+ else => @import("debug/SelfInfo/Elf.zig"),
+ },
+ .macho => @import("debug/SelfInfo/MachO.zig"),
+ .plan9, .spirv, .wasm => void,
+ .c, .hex, .raw => unreachable,
+ };
+}
pub const SelfInfoError = error{
/// The required debug info is invalid or corrupted.
@@ -308,6 +314,9 @@ pub fn unlockStderr() void {
/// Alternatively, use the higher-level `std.log` or `Io.lockStderr` to
/// integrate with the application's chosen `Io` implementation.
pub fn print(comptime fmt: []const u8, args: anytype) void {
+ const io = std.Options.debug_io;
+ const prev = io.swapCancelProtection(.blocked);
+ defer _ = io.swapCancelProtection(prev);
var buffer: [64]u8 = undefined;
const stderr = lockStderr(&buffer);
defer unlockStderr();
@@ -326,6 +335,9 @@ pub inline fn getSelfDebugInfo() !*SelfInfo {
/// Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned.
/// Obtains the stderr mutex while dumping.
pub fn dumpHex(bytes: []const u8) void {
+ const io = std.Options.debug_io;
+ const prev = io.swapCancelProtection(.blocked);
+ defer _ = io.swapCancelProtection(prev);
const stderr = lockStderr(&.{}).terminal();
defer unlockStderr();
dumpHexFallible(stderr, bytes) catch {};
@@ -495,7 +507,16 @@ pub fn defaultPanic(msg: []const u8, first_trace_addr: ?usize) noreturn {
if (use_trap_panic) @trap();
switch (builtin.os.tag) {
- .freestanding, .other, .@"3ds", .psp, .vita => {
+ .freestanding,
+ .other,
+
+ .@"3ds",
+ .wiiu,
+
+ .psx,
+ .psp,
+ .vita,
+ => {
@trap();
},
.uefi => {
@@ -789,6 +810,9 @@ pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, t: Io.Termin
}
/// A thin wrapper around `writeCurrentStackTrace` which writes to stderr and ignores write errors.
pub fn dumpCurrentStackTrace(options: StackUnwindOptions) void {
+ const io = std.Options.debug_io;
+ const prev = io.swapCancelProtection(.blocked);
+ defer _ = io.swapCancelProtection(prev);
const stderr = lockStderr(&.{}).terminal();
defer unlockStderr();
writeCurrentStackTrace(.{
@@ -879,6 +903,9 @@ fn writeTrace(
}
/// A thin wrapper around `writeStackTrace` which writes to stderr and ignores write errors.
pub fn dumpStackTrace(st: *const StackTrace) void {
+ const io = std.Options.debug_io;
+ const prev = io.swapCancelProtection(.blocked);
+ defer _ = io.swapCancelProtection(prev);
const stderr = lockStderr(&.{}).terminal();
defer unlockStderr();
writeStackTrace(st, stderr) catch |err| switch (err) {
@@ -888,6 +915,9 @@ pub fn dumpStackTrace(st: *const StackTrace) void {
/// A thin wrapper around `writeErrorReturnTrace` which writes to stderr and ignores write errors.
pub fn dumpErrorReturnTrace(et: *const std.builtin.StackTrace) void {
+ const io = std.Options.debug_io;
+ const prev = io.swapCancelProtection(.blocked);
+ defer _ = io.swapCancelProtection(prev);
const stderr = lockStderr(&.{}).terminal();
defer unlockStderr();
writeErrorReturnTrace(et, stderr) catch |err| switch (err) {
diff --git a/lib/std/debug/Coverage.zig b/lib/std/debug/Coverage.zig
index b3e16382cc45dff17d34b9bf57f7accb63d918e5..7bbc58a5b71f541734aafd75d75fdfb2c3858efb 100644
--- a/lib/std/debug/Coverage.zig
+++ b/lib/std/debug/Coverage.zig
@@ -15,13 +15,13 @@ const assert = std.debug.assert;
/// String memory references the memory-mapped debug information.
///
/// Protected by `mutex`.
-directories: std.ArrayHashMapUnmanaged(String, void, String.MapContext, false),
+directories: std.array_hash_map.Custom(String, void, String.MapContext, false),
/// Provides a globally-scoped integer index for files.
///
/// String memory references the memory-mapped debug information.
///
/// Protected by `mutex`.
-files: std.ArrayHashMapUnmanaged(File, void, File.MapContext, false),
+files: std.array_hash_map.Custom(File, void, File.MapContext, false),
string_bytes: std.ArrayList(u8),
/// Protects the other fields.
mutex: Io.Mutex,
diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig
index 439e590daed71cf16c70d1ebea2a6943978f719f..a5f290039f4c57138832360a7fecf4183ecc04b5 100644
--- a/lib/std/debug/Dwarf.zig
+++ b/lib/std/debug/Dwarf.zig
@@ -134,7 +134,7 @@ pub const CompileUnit = struct {
files: []FileEntry,
version: u16,
- pub const LineTable = std.AutoArrayHashMapUnmanaged(u64, LineEntry);
+ pub const LineTable = std.array_hash_map.Auto(u64, LineEntry);
pub const LineEntry = struct {
line: u32,
diff --git a/lib/std/debug/Dwarf/SelfUnwinder.zig b/lib/std/debug/Dwarf/SelfUnwinder.zig
index 0f5253844de3cdcd97d57e18c8d0ca6c4ed231c8..6eef056e86866d66b94564dae6b94d71484829ac 100644
--- a/lib/std/debug/Dwarf/SelfUnwinder.zig
+++ b/lib/std/debug/Dwarf/SelfUnwinder.zig
@@ -168,7 +168,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
.none => return error.InvalidDebugInfo,
.reg_off => |ro| cfa: {
const ptr = try regNative(&unwinder.cpu_state, ro.register);
- break :cfa try applyOffset(ptr.*, ro.offset);
+ break :cfa try applyOffset(@intCast(ptr.*), ro.offset);
},
.expression => |expr| cfa: {
// On most implemented architectures, the CFA is defined to be the previous frame's SP.
@@ -181,7 +181,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
const value = try unwinder.expr_vm.run(expr, gpa, .{
.format = format,
.cpu_context = &unwinder.cpu_state,
- }, prev_cfa_val) orelse return error.InvalidDebugInfo;
+ }, @intCast(prev_cfa_val)) orelse return error.InvalidDebugInfo;
switch (value) {
.generic => |g| break :cfa g,
else => return error.InvalidDebugInfo,
@@ -203,7 +203,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
const new_val: union(enum) {
same,
undefined,
- val: usize,
+ val: std.debug.cpu_context.Native.Gpr,
bytes: []const u8,
} = switch (rule) {
.default => val: {
@@ -219,7 +219,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
.undefined => .undefined,
.same_value => .same,
.offset => |offset| val: {
- const ptr: *const usize = @ptrFromInt(try applyOffset(cfa, offset));
+ const ptr: *const std.debug.cpu_context.Native.Gpr = @ptrFromInt(try applyOffset(cfa, offset));
break :val .{ .val = ptr.* };
},
.val_offset => |offset| .{ .val = try applyOffset(cfa, offset) },
@@ -260,12 +260,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
has_return_address = false;
}
},
- .val => |val| {
- const dest = try new_cpu_state.dwarfRegisterBytes(@intCast(register));
- if (dest.len != @sizeOf(usize)) return error.InvalidDebugInfo;
- const dest_ptr: *align(1) usize = @ptrCast(dest);
- dest_ptr.* = val;
- },
+ .val => |val| (try regNative(&new_cpu_state, register)).* = val,
.bytes => |src| {
const dest = try new_cpu_state.dwarfRegisterBytes(@intCast(register));
if (dest.len != src.len) return error.InvalidDebugInfo;
@@ -275,7 +270,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
}
const return_address = if (has_return_address)
- stripInstructionPtrAuthCode((try regNative(&new_cpu_state, return_address_register)).*)
+ stripInstructionPtrAuthCode(@intCast((try regNative(&new_cpu_state, return_address_register)).*))
else
0;
@@ -303,9 +298,9 @@ pub fn regNative(ctx: *std.debug.cpu_context.Native, num: u16) error{
InvalidRegister,
UnsupportedRegister,
IncompatibleRegisterSize,
-}!*align(1) usize {
+}!*align(1) std.debug.cpu_context.Native.Gpr {
const bytes = try ctx.dwarfRegisterBytes(num);
- if (bytes.len != @sizeOf(usize)) return error.IncompatibleRegisterSize;
+ if (bytes.len != @sizeOf(std.debug.cpu_context.Native.Gpr)) return error.IncompatibleRegisterSize;
return @ptrCast(bytes);
}
diff --git a/lib/std/debug/Dwarf/expression.zig b/lib/std/debug/Dwarf/expression.zig
index 626af96d4a8391f031e17a5ca5e2003910481897..9b506dd4da0c1dff4d47711e6b4f367d662edca0 100644
--- a/lib/std/debug/Dwarf/expression.zig
+++ b/lib/std/debug/Dwarf/expression.zig
@@ -387,7 +387,7 @@ pub fn StackMachine(comptime options: Options) type {
.regval_type = .{
.type_offset = rt.type_offset,
.type_size = @sizeOf(addr_type),
- .value = (try regNative(cpu_context, rt.register)).*,
+ .value = @intCast((try regNative(cpu_context, rt.register)).*),
},
});
},
@@ -738,7 +738,7 @@ pub fn StackMachine(comptime options: Options) type {
var block_stream: std.Io.Reader = .fixed(block);
const register = (try readOperand(&block_stream, block[0], context)).?.register;
const value = (try regNative(cpu_context, register)).*;
- try self.stack.append(allocator, .{ .generic = value });
+ try self.stack.append(allocator, .{ .generic = @intCast(value) });
} else {
var stack_machine: Self = .{};
defer stack_machine.deinit(allocator);
@@ -1158,7 +1158,7 @@ test "basics" {
// TODO: Test fbreg (once implemented): mock a DIE and point compile_unit.frame_base at it
- mem.writeInt(usize, reg_bytes[0..@sizeOf(usize)], 0xee, native_endian);
+ mem.writeInt(std.debug.cpu_context.Native.Gpr, reg_bytes[0..@sizeOf(std.debug.cpu_context.Native.Gpr)], 0xee, native_endian);
(try regNative(&cpu_context, fp_reg_num)).* = 1;
(try regNative(&cpu_context, ip_reg_num)).* = 2;
@@ -1566,7 +1566,7 @@ test "basics" {
context = .{ .cpu_context = &cpu_context };
const reg_bytes = try cpu_context.dwarfRegisterBytes(0);
- mem.writeInt(usize, reg_bytes[0..@sizeOf(usize)], 0xee, native_endian);
+ mem.writeInt(std.debug.cpu_context.Native.Gpr, reg_bytes[0..@sizeOf(std.debug.cpu_context.Native.Gpr)], 0xee, native_endian);
var sub_program: std.Io.Writer.Allocating = .init(allocator);
defer sub_program.deinit();
diff --git a/lib/std/debug/ElfFile.zig b/lib/std/debug/ElfFile.zig
index 22ea71af4443d78f05f45ae90b13708c0ceb5610..0ea4207c3521830ca4a1b9b1a1a0567cb97b5201 100644
--- a/lib/std/debug/ElfFile.zig
+++ b/lib/std/debug/ElfFile.zig
@@ -455,7 +455,7 @@ fn loadInner(
};
if (opt_crc) |crc| {
- if (std.hash.crc.Crc32.hash(mapped_mem) != crc) {
+ if (std.hash.Crc32.hash(mapped_mem) != crc) {
return error.CrcMismatch;
}
}
diff --git a/lib/std/debug/MachOFile.zig b/lib/std/debug/MachOFile.zig
index 4b2fb524bcdab99802e9001b0d340d484e6f86e2..369ee8c4bc41bf87ac8f9c3356a7ab1c532bfdad 100644
--- a/lib/std/debug/MachOFile.zig
+++ b/lib/std/debug/MachOFile.zig
@@ -4,7 +4,7 @@ strings: []const u8,
text_vmaddr: u64,
/// Key is index into `strings` of the file path.
-ofiles: std.AutoArrayHashMapUnmanaged(u32, Error!OFile),
+ofiles: std.array_hash_map.Auto(u32, Error!OFile),
pub const Error = error{
InvalidMachO,
@@ -115,7 +115,7 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)
// necessary because we prefer to use STAB ("symbolic debugging table") symbols,
// but they might not be present, so we track normal symbols too.
// Indices match 1-1 with those of `symbols`.
- var symbol_names: std.StringArrayHashMapUnmanaged(void) = .empty;
+ var symbol_names: std.array_hash_map.String(void) = .empty;
defer symbol_names.deinit(gpa);
try symbol_names.ensureUnusedCapacity(gpa, symtab.nsyms);
@@ -305,7 +305,7 @@ const OFile = struct {
symtab_raw: []align(1) const macho.nlist_64,
/// All named symbols in `symtab_raw`. Stored `u32` key is the index into `symtab_raw`. Accessed
/// through `SymbolAdapter`, so that the symbol name is used as the logical key.
- symbols_by_name: std.ArrayHashMapUnmanaged(u32, void, void, true),
+ symbols_by_name: std.array_hash_map.Custom(u32, void, void, true),
const SymbolAdapter = struct {
strtab: []const u8,
@@ -380,7 +380,7 @@ test {
fn appendStabSymbol(
symbols: *std.ArrayList(Symbol),
- symbol_names: *std.StringArrayHashMapUnmanaged(void),
+ symbol_names: *std.array_hash_map.String(void),
strings: []const u8,
last_sym: Symbol,
) void {
@@ -476,7 +476,7 @@ fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {
const symtab_raw: []align(1) const macho.nlist_64 = @ptrCast(mapped_ofile[symtab_cmd.symoff..][0..n_sym_bytes]);
// TODO handle tentative (common) symbols
- var symbols_by_name: std.ArrayHashMapUnmanaged(u32, void, void, true) = .empty;
+ var symbols_by_name: std.array_hash_map.Custom(u32, void, void, true) = .empty;
defer symbols_by_name.deinit(gpa);
try symbols_by_name.ensureUnusedCapacity(gpa, @intCast(symtab_raw.len));
for (symtab_raw, 0..) |sym_raw, sym_index| {
diff --git a/lib/std/debug/SelfInfo/Elf.zig b/lib/std/debug/SelfInfo/Elf.zig
index c3124902008f0b45347b939b0d49aff7164c5c34..9e8153555f4a68dfde3996328263aee2dd39d582 100644
--- a/lib/std/debug/SelfInfo/Elf.zig
+++ b/lib/std/debug/SelfInfo/Elf.zig
@@ -92,16 +92,6 @@ pub fn getModuleSlide(si: *SelfInfo, io: Io, address: usize) Error!usize {
}
pub const can_unwind: bool = s: {
- // The DWARF code can't deal with ILP32 ABIs yet: https://github.com/ziglang/zig/issues/25447
- switch (builtin.target.abi) {
- .gnuabin32,
- .muslabin32,
- .gnux32,
- .muslx32,
- => break :s false,
- else => {},
- }
-
// Notably, we are yet to support unwinding on ARM. There, unwinding is not done through
// `.eh_frame`, but instead with the `.ARM.exidx` section, which has a different format.
const archs: []const std.Target.Cpu.Arch = switch (builtin.target.os.tag) {
diff --git a/lib/std/debug/SelfInfo/MachO.zig b/lib/std/debug/SelfInfo/MachO.zig
index 431108cd3f6164769359902f1abccdec720516df..e771d7a9f5e45b3b5c217053f3394fd7b713a029 100644
--- a/lib/std/debug/SelfInfo/MachO.zig
+++ b/lib/std/debug/SelfInfo/MachO.zig
@@ -1,6 +1,6 @@
mutex: Io.Mutex,
/// Accessed through `Module.Adapter`.
-modules: std.ArrayHashMapUnmanaged(Module, void, Module.Context, false),
+modules: std.array_hash_map.Custom(Module, void, Module.Context, false),
pub const init: SelfInfo = .{
.mutex = .init,
diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig
index 6f6a07a86ffc0a867da5534b440966e6f12451bc..36be9fe60e0ebe084ab2e045702bc91628ff9bf6 100644
--- a/lib/std/debug/cpu_context.zig
+++ b/lib/std/debug/cpu_context.zig
@@ -240,9 +240,11 @@ pub fn fromWindowsContext(ctx: *const std.os.windows.CONTEXT) Native {
/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
const Aarch64 = extern struct {
/// The numbered general-purpose registers X0 - X30.
- x: [31]u64,
- sp: u64,
- pc: u64,
+ x: [31]Gpr,
+ sp: Gpr,
+ pc: Gpr,
+
+ pub const Gpr = u64;
pub inline fn current() Aarch64 {
var ctx: Aarch64 = undefined;
@@ -273,10 +275,10 @@ const Aarch64 = extern struct {
return ctx;
}
- pub fn getFp(ctx: *const Aarch64) u64 {
+ pub fn getFp(ctx: *const Aarch64) usize {
return ctx.x[29];
}
- pub fn getPc(ctx: *const Aarch64) u64 {
+ pub fn getPc(ctx: *const Aarch64) usize {
return ctx.pc;
}
@@ -308,8 +310,10 @@ const Aarch64 = extern struct {
const Alpha = extern struct {
/// The numbered general-purpose registers R0 - R31.
- r: [32]u64,
- pc: u64,
+ r: [32]Gpr,
+ pc: Gpr,
+
+ pub const Gpr = u64;
pub inline fn current() Alpha {
var ctx: Alpha = undefined;
@@ -355,10 +359,10 @@ const Alpha = extern struct {
return ctx;
}
- pub fn getFp(ctx: *const Alpha) u64 {
+ pub fn getFp(ctx: *const Alpha) usize {
return ctx.r[15];
}
- pub fn getPc(ctx: *const Alpha) u64 {
+ pub fn getPc(ctx: *const Alpha) usize {
return ctx.pc;
}
@@ -378,8 +382,10 @@ const Alpha = extern struct {
/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
const Arc = extern struct {
/// The numbered general-purpose registers r0 - r31.
- r: [32]u32,
- pcl: u32,
+ r: [32]Gpr,
+ pcl: Gpr,
+
+ pub const Gpr = u32;
pub inline fn current() Arc {
var ctx: Arc = undefined;
@@ -423,10 +429,10 @@ const Arc = extern struct {
return ctx;
}
- pub fn getFp(ctx: *const Arc) u32 {
+ pub fn getFp(ctx: *const Arc) usize {
return ctx.r[27];
}
- pub fn getPc(ctx: *const Arc) u32 {
+ pub fn getPc(ctx: *const Arc) usize {
return ctx.pcl;
}
@@ -446,7 +452,9 @@ const Arc = extern struct {
const Arm = struct {
/// The numbered general-purpose registers R0 - R15.
- r: [16]u32,
+ r: [16]Gpr,
+
+ pub const Gpr = u32;
pub inline fn current() Arm {
var ctx: Arm = undefined;
@@ -462,10 +470,10 @@ const Arm = struct {
return ctx;
}
- pub fn getFp(ctx: *const Arm) u32 {
+ pub fn getFp(ctx: *const Arm) usize {
return ctx.r[11];
}
- pub fn getPc(ctx: *const Arm) u32 {
+ pub fn getPc(ctx: *const Arm) usize {
return ctx.r[15];
}
@@ -512,8 +520,10 @@ const Arm = struct {
/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
const Csky = extern struct {
/// The numbered general-purpose registers r0 - r31.
- r: [32]u32,
- pc: u32,
+ r: [32]Gpr,
+ pc: Gpr,
+
+ pub const Gpr = u32;
pub inline fn current() Csky {
var ctx: Csky = undefined;
@@ -528,10 +538,10 @@ const Csky = extern struct {
return ctx;
}
- pub fn getFp(ctx: *const Csky) u32 {
+ pub fn getFp(ctx: *const Csky) usize {
return ctx.r[14];
}
- pub fn getPc(ctx: *const Csky) u32 {
+ pub fn getPc(ctx: *const Csky) usize {
return ctx.pc;
}
@@ -550,8 +560,10 @@ const Csky = extern struct {
/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
const Hexagon = extern struct {
/// The numbered general-purpose registers r0 - r31.
- r: [32]u32,
- pc: u32,
+ r: [32]Gpr,
+ pc: Gpr,
+
+ pub const Gpr = u32;
pub inline fn current() Hexagon {
var ctx: Hexagon = undefined;
@@ -596,10 +608,10 @@ const Hexagon = extern struct {
return ctx;
}
- pub fn getFp(ctx: *const Hexagon) u32 {
+ pub fn getFp(ctx: *const Hexagon) usize {
return ctx.r[30];
}
- pub fn getPc(ctx: *const Hexagon) u32 {
+ pub fn getPc(ctx: *const Hexagon) usize {
return ctx.pc;
}
@@ -623,9 +635,11 @@ const Hexagon = extern struct {
/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
const Kvx = extern struct {
- r: [64]u64,
- ra: u64,
- pc: u64,
+ r: [64]Gpr,
+ ra: Gpr,
+ pc: Gpr,
+
+ pub const Gpr = u64;
pub inline fn current() Kvx {
var ctx: Kvx = undefined;
@@ -671,10 +685,10 @@ const Kvx = extern struct {
return ctx;
}
- pub fn getFp(ctx: *const Kvx) u64 {
+ pub fn getFp(ctx: *const Kvx) usize {
return ctx.r[14];
}
- pub fn getPc(ctx: *const Kvx) u64 {
+ pub fn getPc(ctx: *const Kvx) usize {
return ctx.pc;
}
@@ -695,7 +709,9 @@ const Kvx = extern struct {
/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
const Lanai = extern struct {
- r: [32]u32,
+ r: [32]Gpr,
+
+ pub const Gpr = u32;
pub inline fn current() Lanai {
var ctx: Lanai = undefined;
@@ -738,10 +754,10 @@ const Lanai = extern struct {
return ctx;
}
- pub fn getFp(ctx: *const Lanai) u32 {
+ pub fn getFp(ctx: *const Lanai) usize {
return ctx.r[5];
}
- pub fn getPc(ctx: *const Lanai) u32 {
+ pub fn getPc(ctx: *const Lanai) usize {
return ctx.r[2];
}
@@ -842,10 +858,10 @@ const LoongArch = extern struct {
return ctx;
}
- pub fn getFp(ctx: *const LoongArch) Gpr {
+ pub fn getFp(ctx: *const LoongArch) usize {
return ctx.r[22];
}
- pub fn getPc(ctx: *const LoongArch) Gpr {
+ pub fn getPc(ctx: *const LoongArch) usize {
return ctx.pc;
}
@@ -864,10 +880,12 @@ const LoongArch = extern struct {
/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
const M68k = extern struct {
/// The numbered data registers d0 - d7.
- d: [8]u32,
+ d: [8]Gpr,
/// The numbered address registers a0 - a7.
- a: [8]u32,
- pc: u32,
+ a: [8]Gpr,
+ pc: Gpr,
+
+ pub const Gpr = u32;
pub inline fn current() M68k {
var ctx: M68k = undefined;
@@ -881,10 +899,10 @@ const M68k = extern struct {
return ctx;
}
- pub fn getFp(ctx: *const M68k) u32 {
+ pub fn getFp(ctx: *const M68k) usize {
return ctx.a[6];
}
- pub fn getPc(ctx: *const M68k) u32 {
+ pub fn getPc(ctx: *const M68k) usize {
return ctx.pc;
}
@@ -905,8 +923,10 @@ const M68k = extern struct {
/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
const M88k = extern struct {
/// The numbered general-purpose registers r0 - r31.
- r: [32]u32,
- xip: u32,
+ r: [32]Gpr,
+ xip: Gpr,
+
+ pub const Gpr = u32;
pub inline fn current() M88k {
var ctx: M88k = undefined;
@@ -952,10 +972,10 @@ const M88k = extern struct {
return ctx;
}
- pub fn getFp(ctx: *const M88k) u32 {
+ pub fn getFp(ctx: *const M88k) usize {
return ctx.r[30];
}
- pub fn getPc(ctx: *const M88k) u32 {
+ pub fn getPc(ctx: *const M88k) usize {
return ctx.xip;
}
@@ -1103,8 +1123,10 @@ const Mips = extern struct {
/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
const Or1k = extern struct {
/// The numbered general-purpose registers r0 - r31.
- r: [32]u32,
- pc: u32,
+ r: [32]Gpr,
+ pc: Gpr,
+
+ pub const Gpr = u32;
pub inline fn current() Or1k {
var ctx: Or1k = undefined;
@@ -1150,10 +1172,10 @@ const Or1k = extern struct {
return ctx;
}
- pub fn getFp(ctx: *const Or1k) u32 {
+ pub fn getFp(ctx: *const Or1k) usize {
return ctx.r[2];
}
- pub fn getPc(ctx: *const Or1k) u32 {
+ pub fn getPc(ctx: *const Or1k) usize {
return ctx.pc;
}
@@ -1262,10 +1284,10 @@ const Powerpc = extern struct {
return ctx;
}
- pub fn getFp(ctx: *const Powerpc) Gpr {
+ pub fn getFp(ctx: *const Powerpc) usize {
return ctx.r[1];
}
- pub fn getPc(ctx: *const Powerpc) Gpr {
+ pub fn getPc(ctx: *const Powerpc) usize {
return ctx.pc;
}
@@ -1415,10 +1437,10 @@ const Riscv = extern struct {
return ctx;
}
- pub fn getFp(ctx: *const Riscv) Gpr {
+ pub fn getFp(ctx: *const Riscv) usize {
return ctx.x[8];
}
- pub fn getPc(ctx: *const Riscv) Gpr {
+ pub fn getPc(ctx: *const Riscv) usize {
return ctx.pc;
}
@@ -1441,13 +1463,15 @@ const Riscv = extern struct {
/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
const S390x = extern struct {
/// The numbered general-purpose registers r0 - r15.
- r: [16]u64,
+ r: [16]Gpr,
/// The program counter.
psw: extern struct {
- mask: u64,
- addr: u64,
+ mask: Gpr,
+ addr: Gpr,
},
+ pub const Gpr = u64;
+
pub inline fn current() S390x {
var ctx: S390x = undefined;
asm volatile (
@@ -1462,10 +1486,10 @@ const S390x = extern struct {
return ctx;
}
- pub fn getFp(ctx: *const S390x) u64 {
+ pub fn getFp(ctx: *const S390x) usize {
return ctx.r[11];
}
- pub fn getPc(ctx: *const S390x) u64 {
+ pub fn getPc(ctx: *const S390x) usize {
return ctx.psw.addr;
}
@@ -1571,10 +1595,10 @@ const Sparc = extern struct {
asm volatile ("ta 3" ::: .{ .memory = true }); // ST_FLUSH_WINDOWS
}
- pub fn getFp(ctx: *const Sparc) Gpr {
+ pub fn getFp(ctx: *const Sparc) usize {
return ctx.i[6];
}
- pub fn getPc(ctx: *const Sparc) Gpr {
+ pub fn getPc(ctx: *const Sparc) usize {
return ctx.pc;
}
@@ -1593,8 +1617,10 @@ const Sparc = extern struct {
/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
const Ve = extern struct {
- s: [64]u64,
- ic: u64,
+ s: [64]Gpr,
+ ic: Gpr,
+
+ pub const Gpr = u64;
pub inline fn current() Ve {
var ctx: Ve = undefined;
@@ -1672,10 +1698,10 @@ const Ve = extern struct {
return ctx;
}
- pub fn getFp(ctx: *const Ve) u64 {
+ pub fn getFp(ctx: *const Ve) usize {
return ctx.s[9];
}
- pub fn getPc(ctx: *const Ve) u64 {
+ pub fn getPc(ctx: *const Ve) usize {
return ctx.ic;
}
@@ -1693,14 +1719,15 @@ const Ve = extern struct {
};
const X86_16 = struct {
- pub const Register = enum {
+ regs: std.enums.EnumArray(GprName, Gpr),
+
+ pub const GprName = enum {
// zig fmt: off
sp, bp, ss,
ip, cs,
// zig fmt: on
};
-
- regs: std.enums.EnumArray(Register, u16),
+ pub const Gpr = u16;
pub inline fn current() X86_16 {
var ctx: X86_16 = undefined;
@@ -1719,10 +1746,10 @@ const X86_16 = struct {
return ctx;
}
- pub fn getFp(ctx: *const X86_16) u16 {
+ pub fn getFp(ctx: *const X86_16) usize {
return ctx.regs.get(.bp);
}
- pub fn getPc(ctx: *const X86_16) u16 {
+ pub fn getPc(ctx: *const X86_16) usize {
return ctx.regs.get(.ip);
}
@@ -1740,17 +1767,19 @@ const X86_16 = struct {
};
const X86 = struct {
+ gprs: std.enums.EnumArray(GprName, Gpr),
+
/// The first 8 registers here intentionally match the order of registers in the x86 instruction
/// encoding. This order is inherited by the PUSHA instruction and the DWARF register mappings,
/// among other things.
- pub const Gpr = enum {
+ pub const GprName = enum {
// zig fmt: off
eax, ecx, edx, ebx,
esp, ebp, esi, edi,
eip,
// zig fmt: on
};
- gprs: std.enums.EnumArray(Gpr, u32),
+ pub const Gpr = u32;
pub inline fn current() X86 {
var ctx: X86 = undefined;
@@ -1772,10 +1801,10 @@ const X86 = struct {
return ctx;
}
- pub fn getFp(ctx: *const X86) u32 {
+ pub fn getFp(ctx: *const X86) usize {
return ctx.gprs.get(.ebp);
}
- pub fn getPc(ctx: *const X86) u32 {
+ pub fn getPc(ctx: *const X86) usize {
return ctx.gprs.get(.eip);
}
@@ -1806,10 +1835,12 @@ const X86 = struct {
};
const X86_64 = struct {
+ gprs: std.enums.EnumArray(GprName, Gpr),
+
/// The order here intentionally matches the order of the DWARF register mappings. It's unclear
/// where those mappings actually originated from---the ordering of the first 4 registers seems
/// quite unusual---but it is currently convenient for us to match DWARF.
- pub const Gpr = enum {
+ pub const GprName = enum {
// zig fmt: off
rax, rdx, rcx, rbx,
rsi, rdi, rbp, rsp,
@@ -1818,7 +1849,7 @@ const X86_64 = struct {
rip,
// zig fmt: on
};
- gprs: std.enums.EnumArray(Gpr, u64),
+ pub const Gpr = u64;
pub inline fn current() X86_64 {
var ctx: X86_64 = undefined;
diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig
index d7cea3b3cd3699e4e0a4d5700b241fdc4656ac4e..3f39089510ee6ccf85f90625dfcf542cfb11bf70 100644
--- a/lib/std/dynamic_library.zig
+++ b/lib/std/dynamic_library.zig
@@ -302,27 +302,14 @@ pub const ElfDynLib = struct {
const extended_memsz = mem.alignForward(usize, ph.p_memsz + extra_bytes, page_size);
const ptr = @as([*]align(std.heap.page_size_min) u8, @ptrFromInt(aligned_addr));
const prot = elfToProt(ph.p_flags);
- if ((ph.p_flags & elf.PF_W) == 0) {
- // If it does not need write access, it can be mapped from the fd.
- _ = try posix.mmap(
- ptr,
- extended_memsz,
- prot,
- .{ .TYPE = .PRIVATE, .FIXED = true },
- file.handle,
- ph.p_offset - extra_bytes,
- );
- } else {
- const sect_mem = try posix.mmap(
- ptr,
- extended_memsz,
- prot,
- .{ .TYPE = .PRIVATE, .FIXED = true, .ANONYMOUS = true },
- -1,
- 0,
- );
- @memcpy(sect_mem[0..ph.p_filesz], file_bytes[0..ph.p_filesz]);
- }
+ _ = try posix.mmap(
+ ptr,
+ extended_memsz,
+ prot,
+ .{ .TYPE = .PRIVATE, .FIXED = true },
+ file.handle,
+ ph.p_offset - extra_bytes,
+ );
},
else => {},
}
diff --git a/lib/std/elf.zig b/lib/std/elf.zig
index 81de3f7f501d4c54e3f9048921a6a9a90cc21a77..d3215291852537cd82a03abf0f8b33fc1e2a6ea6 100644
--- a/lib/std/elf.zig
+++ b/lib/std/elf.zig
@@ -3001,6 +3001,141 @@ pub const R_PPC64 = enum(u32) {
_,
};
+/// LoongArch relocations, as of v2.50 of the ABI specs.
+pub const R_LARCH = enum(u32) {
+ NONE = 0,
+ @"32" = 1,
+ @"64" = 2,
+ RELATIVE = 3,
+ COPY = 4,
+ JUMP_SLOT = 5,
+ TLS_DTPMOD32 = 6,
+ TLS_DTPMOD64 = 7,
+ TLS_DTPREL32 = 8,
+ TLS_DTPREL64 = 9,
+ TLS_TPREL32 = 10,
+ TLS_TPREL64 = 11,
+ IRELATIVE = 12,
+ TLS_DESC32 = 13,
+ TLS_DESC64 = 14,
+ MARK_LA = 20,
+ MARK_PCREL = 21,
+ SOP_PUSH_PCREL = 22,
+ SOP_PUSH_ABSOLUTE = 23,
+ SOP_PUSH_DUP = 24,
+ SOP_PUSH_GPREL = 25,
+ SOP_PUSH_TLS_TPREL = 26,
+ SOP_PUSH_TLS_GOT = 27,
+ SOP_PUSH_TLS_GD = 28,
+ SOP_PUSH_PLT_PCREL = 29,
+ SOP_ASSERT = 30,
+ SOP_NOT = 31,
+ SOP_SUB = 32,
+ SOP_SL = 33,
+ SOP_SR = 34,
+ SOP_ADD = 35,
+ SOP_AND = 36,
+ SOP_IF_ELSE = 37,
+ SOP_POP_32_S_10_5 = 38,
+ SOP_POP_32_U_10_12 = 39,
+ SOP_POP_32_S_10_12 = 40,
+ SOP_POP_32_S_10_16 = 41,
+ SOP_POP_32_S_10_16_S2 = 42,
+ SOP_POP_32_S_5_20 = 43,
+ SOP_POP_32_S_0_5_10_16_S2 = 44,
+ SOP_POP_32_S_0_10_10_16_S2 = 45,
+ SOP_POP_32_U = 46,
+ ADD8 = 47,
+ ADD16 = 48,
+ ADD24 = 49,
+ ADD32 = 50,
+ ADD64 = 51,
+ SUB8 = 52,
+ SUB16 = 53,
+ SUB24 = 54,
+ SUB32 = 55,
+ SUB64 = 56,
+ GNU_VTINHERIT = 57,
+ GNU_VTENTRY = 58,
+ B16 = 64,
+ B21 = 65,
+ B26 = 66,
+ ABS_HI20 = 67,
+ ABS_LO12 = 68,
+ ABS64_LO20 = 69,
+ ABS64_HI12 = 70,
+ PCALA_HI20 = 71,
+ PCALA_LO12 = 72,
+ PCALA64_LO20 = 73,
+ PCALA64_HI12 = 74,
+ GOT_PC_HI20 = 75,
+ GOT_PC_LO12 = 76,
+ GOT64_PC_LO20 = 77,
+ GOT64_PC_HI12 = 78,
+ GOT_HI20 = 79,
+ GOT_LO12 = 80,
+ GOT64_LO20 = 81,
+ GOT64_HI12 = 82,
+ TLS_LE_HI20 = 83,
+ TLS_LE_LO12 = 84,
+ TLS_LE64_LO20 = 85,
+ TLS_LE64_HI12 = 86,
+ TLS_IE_PC_HI20 = 87,
+ TLS_IE_PC_LO12 = 88,
+ TLS_IE64_PC_LO20 = 89,
+ TLS_IE64_PC_HI12 = 90,
+ TLS_IE_HI20 = 91,
+ TLS_IE_LO12 = 92,
+ TLS_IE64_LO20 = 93,
+ TLS_IE64_HI12 = 94,
+ TLS_LD_PC_HI20 = 95,
+ TLS_LD_HI20 = 96,
+ TLS_GD_PC_HI20 = 97,
+ TLS_GD_HI20 = 98,
+ @"32_PCREL" = 99,
+ RELAX = 100,
+ DELETE = 101,
+ ALIGN = 102,
+ PCREL20_S2 = 103,
+ CFA = 104,
+ ADD6 = 105,
+ SUB6 = 106,
+ ADD_ULEB128 = 107,
+ SUB_ULEB128 = 108,
+ @"64_PCREL" = 109,
+ CALL36 = 110,
+ TLS_DESC_PC_HI20 = 111,
+ TLS_DESC_PC_LO12 = 112,
+ TLS_DESC64_PC_LO20 = 113,
+ TLS_DESC64_PC_HI12 = 114,
+ TLS_DESC_HI20 = 115,
+ TLS_DESC_LO12 = 116,
+ TLS_DESC64_LO20 = 117,
+ TLS_DESC64_HI12 = 118,
+ TLS_DESC_LD = 119,
+ TLS_DESC_CALL = 120,
+ TLS_LE_HI20_R = 121,
+ TLS_LE_ADD_R = 122,
+ TLS_LE_LO12_R = 123,
+ TLS_LD_PCREL20_S2 = 124,
+ TLS_GD_PCREL20_S2 = 125,
+ TLS_DESC_PCREL20_S2 = 126,
+ CALL30 = 127,
+ PCADD_HI20 = 128,
+ PCADD_LO12 = 129,
+ GOT_PCADD_HI20 = 130,
+ GOT_PCADD_LO12 = 131,
+ TLS_IE_PCADD_HI20 = 132,
+ TLS_IE_PCADD_LO12 = 133,
+ TLS_LD_PCADD_HI20 = 134,
+ TLS_LD_PCADD_LO12 = 135,
+ TLS_GD_PCADD_HI20 = 136,
+ TLS_GD_PCADD_LO12 = 137,
+ TLS_DESC_PCADD_HI20 = 138,
+ TLS_DESC_PCADD_LO12 = 139,
+ _,
+};
+
pub const ar_hdr = extern struct {
/// Member file name, sometimes / terminated.
ar_name: [16]u8,
@@ -3128,3 +3263,21 @@ pub const gnu_hash = struct {
try std.testing.expectEqual(0x8ae9f18e, calculate("flapenguin.me"));
}
};
+
+pub const loongarch = struct {
+ /// Ehdr.e_flags bits of LoongArch
+ pub const EFlags = packed struct(Word) {
+ base_abi_modifier: BaseAbiModifier,
+ abi_extension: AbiExtension,
+ abi_version: u2,
+ reserved: u24 = 0,
+
+ pub const BaseAbiModifier = enum(u3) {
+ s = 1,
+ f = 2,
+ d = 3,
+ _,
+ };
+ pub const AbiExtension = enum(u3) { base = 0, _ };
+ };
+};
diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig
index df762e8fbe7a170ea62820a45a97f148c30d5811..edb1de18fc27228353d8fccea3227893c3eeeac3 100644
--- a/lib/std/fmt.zig
+++ b/lib/std/fmt.zig
@@ -6,8 +6,6 @@ const std = @import("std.zig");
const math = std.math;
const assert = std.debug.assert;
const mem = std.mem;
-const meta = std.meta;
-const lossyCast = math.lossyCast;
const expectFmt = std.testing.expectFmt;
const testing = std.testing;
const Allocator = std.mem.Allocator;
@@ -254,6 +252,13 @@ pub fn printInt(buffer: []u8, value: anytype, base: u8, case: Case, options: Opt
return w.end;
}
+test printInt {
+ const x: i32 = -3;
+ var buffer: [64]u8 = undefined;
+ const s = buffer[0..printInt(&buffer, x, 10, .lower, .{})];
+ try testing.expectEqualStrings("-3", s);
+}
+
/// Converts values in the range [0, 100) to a base 10 string.
pub fn digits2(value: u8) [2]u8 {
if (builtin.mode == .ReleaseSmall) {
@@ -332,63 +337,63 @@ pub fn parseIntWithGenericCharacter(
}
test parseInt {
- try std.testing.expectEqual(-10, try parseInt(i32, "-10", 10));
- try std.testing.expectEqual(10, try parseInt(i32, "+10", 10));
- try std.testing.expectEqual(10, try parseInt(u32, "+10", 10));
- try std.testing.expectError(error.Overflow, parseInt(u32, "-10", 10));
- try std.testing.expectError(error.InvalidCharacter, parseInt(u32, " 10", 10));
- try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "10 ", 10));
- try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "_10_", 10));
- try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0x_10_", 10));
- try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0x10_", 10));
- try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0x_10", 10));
- try std.testing.expectEqual(255, try parseInt(u8, "255", 10));
- try std.testing.expectError(error.Overflow, parseInt(u8, "256", 10));
+ try testing.expectEqual(-10, try parseInt(i32, "-10", 10));
+ try testing.expectEqual(10, try parseInt(i32, "+10", 10));
+ try testing.expectEqual(10, try parseInt(u32, "+10", 10));
+ try testing.expectError(error.Overflow, parseInt(u32, "-10", 10));
+ try testing.expectError(error.InvalidCharacter, parseInt(u32, " 10", 10));
+ try testing.expectError(error.InvalidCharacter, parseInt(u32, "10 ", 10));
+ try testing.expectError(error.InvalidCharacter, parseInt(u32, "_10_", 10));
+ try testing.expectError(error.InvalidCharacter, parseInt(u32, "0x_10_", 10));
+ try testing.expectError(error.InvalidCharacter, parseInt(u32, "0x10_", 10));
+ try testing.expectError(error.InvalidCharacter, parseInt(u32, "0x_10", 10));
+ try testing.expectEqual(255, try parseInt(u8, "255", 10));
+ try testing.expectError(error.Overflow, parseInt(u8, "256", 10));
// +0 and -0 should work for unsigned
- try std.testing.expectEqual(0, try parseInt(u8, "-0", 10));
- try std.testing.expectEqual(0, try parseInt(u8, "+0", 10));
+ try testing.expectEqual(0, try parseInt(u8, "-0", 10));
+ try testing.expectEqual(0, try parseInt(u8, "+0", 10));
// ensure minInt is parsed correctly
- try std.testing.expectEqual(math.minInt(i1), try parseInt(i1, "-1", 10));
- try std.testing.expectEqual(math.minInt(i8), try parseInt(i8, "-128", 10));
- try std.testing.expectEqual(math.minInt(i43), try parseInt(i43, "-4398046511104", 10));
+ try testing.expectEqual(math.minInt(i1), try parseInt(i1, "-1", 10));
+ try testing.expectEqual(math.minInt(i8), try parseInt(i8, "-128", 10));
+ try testing.expectEqual(math.minInt(i43), try parseInt(i43, "-4398046511104", 10));
// empty string or bare +- is invalid
- try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "", 10));
- try std.testing.expectError(error.InvalidCharacter, parseInt(i32, "", 10));
- try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "+", 10));
- try std.testing.expectError(error.InvalidCharacter, parseInt(i32, "+", 10));
- try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "-", 10));
- try std.testing.expectError(error.InvalidCharacter, parseInt(i32, "-", 10));
+ try testing.expectError(error.InvalidCharacter, parseInt(u32, "", 10));
+ try testing.expectError(error.InvalidCharacter, parseInt(i32, "", 10));
+ try testing.expectError(error.InvalidCharacter, parseInt(u32, "+", 10));
+ try testing.expectError(error.InvalidCharacter, parseInt(i32, "+", 10));
+ try testing.expectError(error.InvalidCharacter, parseInt(u32, "-", 10));
+ try testing.expectError(error.InvalidCharacter, parseInt(i32, "-", 10));
// autodectect the base
- try std.testing.expectEqual(111, try parseInt(i32, "111", 0));
- try std.testing.expectEqual(111, try parseInt(i32, "1_1_1", 0));
- try std.testing.expectEqual(111, try parseInt(i32, "1_1_1", 0));
- try std.testing.expectEqual(7, try parseInt(i32, "+0b111", 0));
- try std.testing.expectEqual(7, try parseInt(i32, "+0B111", 0));
- try std.testing.expectEqual(7, try parseInt(i32, "+0b1_11", 0));
- try std.testing.expectEqual(73, try parseInt(i32, "+0o111", 0));
- try std.testing.expectEqual(73, try parseInt(i32, "+0O111", 0));
- try std.testing.expectEqual(73, try parseInt(i32, "+0o11_1", 0));
- try std.testing.expectEqual(273, try parseInt(i32, "+0x111", 0));
- try std.testing.expectEqual(-7, try parseInt(i32, "-0b111", 0));
- try std.testing.expectEqual(-7, try parseInt(i32, "-0b11_1", 0));
- try std.testing.expectEqual(-73, try parseInt(i32, "-0o111", 0));
- try std.testing.expectEqual(-273, try parseInt(i32, "-0x111", 0));
- try std.testing.expectEqual(-273, try parseInt(i32, "-0X111", 0));
- try std.testing.expectEqual(-273, try parseInt(i32, "-0x1_11", 0));
+ try testing.expectEqual(111, try parseInt(i32, "111", 0));
+ try testing.expectEqual(111, try parseInt(i32, "1_1_1", 0));
+ try testing.expectEqual(111, try parseInt(i32, "1_1_1", 0));
+ try testing.expectEqual(7, try parseInt(i32, "+0b111", 0));
+ try testing.expectEqual(7, try parseInt(i32, "+0B111", 0));
+ try testing.expectEqual(7, try parseInt(i32, "+0b1_11", 0));
+ try testing.expectEqual(73, try parseInt(i32, "+0o111", 0));
+ try testing.expectEqual(73, try parseInt(i32, "+0O111", 0));
+ try testing.expectEqual(73, try parseInt(i32, "+0o11_1", 0));
+ try testing.expectEqual(273, try parseInt(i32, "+0x111", 0));
+ try testing.expectEqual(-7, try parseInt(i32, "-0b111", 0));
+ try testing.expectEqual(-7, try parseInt(i32, "-0b11_1", 0));
+ try testing.expectEqual(-73, try parseInt(i32, "-0o111", 0));
+ try testing.expectEqual(-273, try parseInt(i32, "-0x111", 0));
+ try testing.expectEqual(-273, try parseInt(i32, "-0X111", 0));
+ try testing.expectEqual(-273, try parseInt(i32, "-0x1_11", 0));
// bare binary/octal/decimal prefix is invalid
- try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0b", 0));
- try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0o", 0));
- try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0x", 0));
+ try testing.expectError(error.InvalidCharacter, parseInt(u32, "0b", 0));
+ try testing.expectError(error.InvalidCharacter, parseInt(u32, "0o", 0));
+ try testing.expectError(error.InvalidCharacter, parseInt(u32, "0x", 0));
// edge cases which previously errored due to base overflowing T
- try std.testing.expectEqual(@as(i2, -2), try std.fmt.parseInt(i2, "-10", 2));
- try std.testing.expectEqual(@as(i4, -8), try std.fmt.parseInt(i4, "-10", 8));
- try std.testing.expectEqual(@as(i5, -16), try std.fmt.parseInt(i5, "-10", 16));
+ try testing.expectEqual(@as(i2, -2), try std.fmt.parseInt(i2, "-10", 2));
+ try testing.expectEqual(@as(i4, -8), try std.fmt.parseInt(i4, "-10", 8));
+ try testing.expectEqual(@as(i5, -16), try std.fmt.parseInt(i5, "-10", 16));
}
fn parseIntWithSign(
@@ -475,39 +480,39 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, base: u8) ParseIntError!
}
test parseUnsigned {
- try std.testing.expectEqual(50124, try parseUnsigned(u16, "050124", 10));
- try std.testing.expectEqual(65535, try parseUnsigned(u16, "65535", 10));
- try std.testing.expectEqual(65535, try parseUnsigned(u16, "65_535", 10));
- try std.testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
+ try testing.expectEqual(50124, try parseUnsigned(u16, "050124", 10));
+ try testing.expectEqual(65535, try parseUnsigned(u16, "65535", 10));
+ try testing.expectEqual(65535, try parseUnsigned(u16, "65_535", 10));
+ try testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
- try std.testing.expectEqual(0xffffffffffffffff, try parseUnsigned(u64, "0ffffffffffffffff", 16));
- try std.testing.expectEqual(0xffffffffffffffff, try parseUnsigned(u64, "0f_fff_fff_fff_fff_fff", 16));
- try std.testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16));
+ try testing.expectEqual(0xffffffffffffffff, try parseUnsigned(u64, "0ffffffffffffffff", 16));
+ try testing.expectEqual(0xffffffffffffffff, try parseUnsigned(u64, "0f_fff_fff_fff_fff_fff", 16));
+ try testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16));
- try std.testing.expectEqual(0xDEADBEEF, try parseUnsigned(u32, "DeadBeef", 16));
+ try testing.expectEqual(0xDEADBEEF, try parseUnsigned(u32, "DeadBeef", 16));
- try std.testing.expectEqual(1, try parseUnsigned(u7, "1", 10));
- try std.testing.expectEqual(8, try parseUnsigned(u7, "1000", 2));
+ try testing.expectEqual(1, try parseUnsigned(u7, "1", 10));
+ try testing.expectEqual(8, try parseUnsigned(u7, "1000", 2));
- try std.testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));
- try std.testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8));
+ try testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));
+ try testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8));
- try std.testing.expectEqual(1442151747, try parseUnsigned(u32, "NUMBER", 36));
+ try testing.expectEqual(1442151747, try parseUnsigned(u32, "NUMBER", 36));
// these numbers should fit even though the base itself doesn't fit in the destination type
- try std.testing.expectEqual(0, try parseUnsigned(u1, "0", 10));
- try std.testing.expectEqual(1, try parseUnsigned(u1, "1", 10));
- try std.testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));
- try std.testing.expectEqual(1, try parseUnsigned(u1, "001", 16));
- try std.testing.expectEqual(3, try parseUnsigned(u2, "3", 16));
- try std.testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));
+ try testing.expectEqual(0, try parseUnsigned(u1, "0", 10));
+ try testing.expectEqual(1, try parseUnsigned(u1, "1", 10));
+ try testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));
+ try testing.expectEqual(1, try parseUnsigned(u1, "001", 16));
+ try testing.expectEqual(3, try parseUnsigned(u2, "3", 16));
+ try testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));
// parseUnsigned does not expect a sign
- try std.testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "+0", 10));
- try std.testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "-0", 10));
+ try testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "+0", 10));
+ try testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "-0", 10));
// test empty string error
- try std.testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "", 10));
+ try testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "", 10));
}
/// Parses a number like '2G', '2Gi', or '2GiB'.
@@ -549,15 +554,15 @@ pub fn parseIntSizeSuffix(buf: []const u8, digit_base: u8) ParseIntError!usize {
}
test parseIntSizeSuffix {
- try std.testing.expectEqual(2, try parseIntSizeSuffix("2", 10));
- try std.testing.expectEqual(2, try parseIntSizeSuffix("2B", 10));
- try std.testing.expectEqual(2000, try parseIntSizeSuffix("2kB", 10));
- try std.testing.expectEqual(2000, try parseIntSizeSuffix("2k", 10));
- try std.testing.expectEqual(2048, try parseIntSizeSuffix("2KiB", 10));
- try std.testing.expectEqual(2048, try parseIntSizeSuffix("2Ki", 10));
- try std.testing.expectEqual(10240, try parseIntSizeSuffix("aKiB", 16));
- try std.testing.expectError(error.InvalidCharacter, parseIntSizeSuffix("", 10));
- try std.testing.expectError(error.InvalidCharacter, parseIntSizeSuffix("2iB", 10));
+ try testing.expectEqual(2, try parseIntSizeSuffix("2", 10));
+ try testing.expectEqual(2, try parseIntSizeSuffix("2B", 10));
+ try testing.expectEqual(2000, try parseIntSizeSuffix("2kB", 10));
+ try testing.expectEqual(2000, try parseIntSizeSuffix("2k", 10));
+ try testing.expectEqual(2048, try parseIntSizeSuffix("2KiB", 10));
+ try testing.expectEqual(2048, try parseIntSizeSuffix("2Ki", 10));
+ try testing.expectEqual(10240, try parseIntSizeSuffix("aKiB", 16));
+ try testing.expectError(error.InvalidCharacter, parseIntSizeSuffix("", 10));
+ try testing.expectError(error.InvalidCharacter, parseIntSizeSuffix("2iB", 10));
}
pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;
@@ -588,28 +593,22 @@ pub fn digitToChar(digit: u8, case: Case) u8 {
};
}
-pub const BufPrintError = error{
- /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.
- NoSpaceLeft,
-};
+/// Deprecated in favor of `mem.PrintError`.
+pub const BufPrintError = mem.PrintError;
-/// Print a format string into `buf`. Returns a slice of the bytes printed.
+/// Deprecated in favor of `mem.print`.
pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintError![]u8 {
- var w: Writer = .fixed(buf);
- w.print(fmt, args) catch |err| switch (err) {
- error.WriteFailed => return error.NoSpaceLeft,
- };
- return w.buffered();
+ return mem.print(buf, fmt, args);
}
+/// Deprecated in favor of `mem.printSentinel`.
pub fn bufPrintSentinel(
buf: []u8,
comptime fmt: []const u8,
args: anytype,
comptime sentinel: u8,
) BufPrintError![:sentinel]u8 {
- const result = try bufPrint(buf, fmt ++ [_]u8{sentinel}, args);
- return result[0 .. result.len - 1 :sentinel];
+ return mem.printSentinel(buf, fmt, args, sentinel);
}
/// Count the characters needed for format.
@@ -622,33 +621,25 @@ pub fn count(comptime fmt: []const u8, args: anytype) usize {
return @intCast(dw.count + dw.writer.end);
}
+/// Deprecated in favor of `Allocator.print`.
pub fn allocPrint(gpa: Allocator, comptime fmt: []const u8, args: anytype) Allocator.Error![]u8 {
- var aw = try Writer.Allocating.initCapacity(gpa, fmt.len);
- defer aw.deinit();
- aw.writer.print(fmt, args) catch |err| switch (err) {
- error.WriteFailed => return error.OutOfMemory,
- };
- return aw.toOwnedSlice();
+ return gpa.print(fmt, args);
}
+/// Deprecated in favor of `Allocator.printSentinel`.
pub fn allocPrintSentinel(
gpa: Allocator,
comptime fmt: []const u8,
args: anytype,
comptime sentinel: u8,
) Allocator.Error![:sentinel]u8 {
- var aw = try Writer.Allocating.initCapacity(gpa, fmt.len);
- defer aw.deinit();
- aw.writer.print(fmt, args) catch |err| switch (err) {
- error.WriteFailed => return error.OutOfMemory,
- };
- return aw.toOwnedSliceSentinel(sentinel);
+ return gpa.printSentinel(fmt, args, sentinel);
}
pub inline fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args):0]u8 {
comptime {
var buf: [count(fmt, args):0]u8 = undefined;
- _ = bufPrint(&buf, fmt, args) catch unreachable;
+ _ = mem.print(&buf, fmt, args) catch unreachable;
buf[buf.len] = 0;
const final = buf;
return &final;
@@ -657,12 +648,12 @@ pub inline fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [cou
test comptimePrint {
@setEvalBranchQuota(2000);
- try std.testing.expectEqual(*const [3:0]u8, @TypeOf(comptimePrint("{}", .{100})));
- try std.testing.expectEqualSlices(u8, "100", comptimePrint("{}", .{100}));
- try std.testing.expectEqualStrings("30", comptimePrint("{d}", .{30.0}));
- try std.testing.expectEqualStrings("30.0", comptimePrint("{d:3.1}", .{30.0}));
- try std.testing.expectEqualStrings("0.05", comptimePrint("{d}", .{0.05}));
- try std.testing.expectEqualStrings("5e-2", comptimePrint("{e}", .{0.05}));
+ try testing.expectEqual(*const [3:0]u8, @TypeOf(comptimePrint("{}", .{100})));
+ try testing.expectEqualSlices(u8, "100", comptimePrint("{}", .{100}));
+ try testing.expectEqualStrings("30", comptimePrint("{d}", .{30.0}));
+ try testing.expectEqualStrings("30.0", comptimePrint("{d:3.1}", .{30.0}));
+ try testing.expectEqualStrings("0.05", comptimePrint("{d}", .{0.05}));
+ try testing.expectEqualStrings("5e-2", comptimePrint("{e}", .{0.05}));
}
test "parse u64 digit too big" {
@@ -675,7 +666,7 @@ test "parse u64 digit too big" {
test "parse unsigned comptime" {
comptime {
- try std.testing.expectEqual(2, try parseUnsigned(usize, "2", 10));
+ try testing.expectEqual(2, try parseUnsigned(usize, "2", 10));
}
}
@@ -780,15 +771,15 @@ test "buffer" {
var buf1: [32]u8 = undefined;
var w: Writer = .fixed(&buf1);
try w.printValue("", .{}, 1234, std.options.fmt_max_depth);
- try std.testing.expectEqualStrings("1234", w.buffered());
+ try testing.expectEqualStrings("1234", w.buffered());
w = .fixed(&buf1);
try w.printValue("c", .{}, 'a', std.options.fmt_max_depth);
- try std.testing.expectEqualStrings("a", w.buffered());
+ try testing.expectEqualStrings("a", w.buffered());
w = .fixed(&buf1);
try w.printValue("b", .{}, 0b1100, std.options.fmt_max_depth);
- try std.testing.expectEqualStrings("1100", w.buffered());
+ try testing.expectEqualStrings("1100", w.buffered());
}
}
@@ -809,7 +800,7 @@ test "array" {
var buf: [100]u8 = undefined;
try expectFmt(
- try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@intFromPtr(&value)}),
+ try mem.print(buf[0..], "array: [3]u8@{x}\n", .{@intFromPtr(&value)}),
"array: {*}\n",
.{&value},
);
@@ -1185,7 +1176,7 @@ test bytesToHex {
const input = "input slice";
const encoded = bytesToHex(input, .lower);
var decoded: [input.len]u8 = undefined;
- try std.testing.expectEqualSlices(u8, input, try hexToBytes(&decoded, &encoded));
+ try testing.expectEqualSlices(u8, input, try hexToBytes(&decoded, &encoded));
}
test hexToBytes {
@@ -1197,9 +1188,9 @@ test hexToBytes {
try expectFmt(repeated, "{X}", .{try hexToBytes(&buf, repeated)});
try expectFmt("ABCD", "{X}", .{try hexToBytes(&buf, "ABCD")});
try expectFmt("", "{X}", .{try hexToBytes(&buf, "")});
- try std.testing.expectError(error.InvalidCharacter, hexToBytes(&buf, "012Z"));
- try std.testing.expectError(error.InvalidLength, hexToBytes(&buf, "AAA"));
- try std.testing.expectError(error.NoSpaceLeft, hexToBytes(buf[0..1], "ABAB"));
+ try testing.expectError(error.InvalidCharacter, hexToBytes(&buf, "012Z"));
+ try testing.expectError(error.InvalidLength, hexToBytes(&buf, "AAA"));
+ try testing.expectError(error.NoSpaceLeft, hexToBytes(buf[0..1], "ABAB"));
}
test "positional" {
@@ -1234,12 +1225,12 @@ test "vector" {
const vop: @Vector(4, ?*const u64) = [_]?*const u64{ &x[0], null, null, &x[3] };
var expect_buffer: [@sizeOf(usize) * 2 * 4 + 64]u8 = undefined;
- try expectFmt(try bufPrint(
+ try expectFmt(try mem.print(
&expect_buffer,
"{{ {}, {}, {}, {} }}",
.{ &x[0], &x[1], &x[2], &x[3] },
), "{}", .{vp});
- try expectFmt(try bufPrint(
+ try expectFmt(try mem.print(
&expect_buffer,
"{{ {?}, null, null, {?} }}",
.{ &x[0], &x[3] },
@@ -1356,18 +1347,18 @@ pub fn hex(x: anytype) [@typeInfo(@TypeOf(x)).int.bits / 4]u8 {
test hex {
{
const x = hex(@as(u32, 0xdeadbeef));
- try std.testing.expect(x.len == 8);
- try std.testing.expectEqualStrings("efbeadde", &x);
+ try testing.expect(x.len == 8);
+ try testing.expectEqualStrings("efbeadde", &x);
}
{
const s = "[" ++ hex(@as(u48, 0x12345678_abcd)) ++ "]";
- try std.testing.expect(s.len == 14);
- try std.testing.expectEqualStrings("[cdab78563412]", s);
+ try testing.expect(s.len == 14);
+ try testing.expectEqualStrings("[cdab78563412]", s);
}
{
const s = "[" ++ hex(@as(u64, 0x12345678_abcdef00)) ++ "]";
- try std.testing.expect(s.len == 18);
- try std.testing.expectEqualStrings("[00efcdab78563412]", s);
+ try testing.expect(s.len == 18);
+ try testing.expectEqualStrings("[00efcdab78563412]", s);
}
}
diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig
index d9d8f011e381cd9c345af49878530968e02cf871..bf16a7c216b4f9087195c7a98160e6b765687960 100644
--- a/lib/std/fs/test.zig
+++ b/lib/std/fs/test.zig
@@ -1096,8 +1096,10 @@ test "Dir.renamePreserve onto existing" {
// file -> dir
try expectError(error.PathAlreadyExists, ctx.dir.renamePreserve(test_file_path, ctx.dir, target_dir_path, io));
- // TODO: fix dir renaming on non-Linux, non-Windows systems, see https://codeberg.org/ziglang/zig/issues/35340
- if (native_os != .windows and native_os != .linux) return;
+ // TODO: fix dir renaming on other systems, see https://codeberg.org/ziglang/zig/issues/35340
+ if (native_os != .windows and native_os != .linux and !native_os.isDarwin()) {
+ return;
+ }
// dir -> file
try expectError(error.PathAlreadyExists, ctx.dir.renamePreserve(test_dir_path, ctx.dir, target_file_path, io));
diff --git a/lib/std/gpu.zig b/lib/std/gpu.zig
deleted file mode 100644
index 0e00eccb62f74979c42b704f57ada7ff24668731..0000000000000000000000000000000000000000
--- a/lib/std/gpu.zig
+++ /dev/null
@@ -1,104 +0,0 @@
-const std = @import("std.zig");
-
-pub const position_in = @extern(*addrspace(.input) @Vector(4, f32), .{ .name = "position" });
-pub const position_out = @extern(*addrspace(.output) @Vector(4, f32), .{ .name = "position" });
-pub const point_size_in = @extern(*addrspace(.input) f32, .{ .name = "point_size" });
-pub const point_size_out = @extern(*addrspace(.output) f32, .{ .name = "point_size" });
-pub extern const invocation_id: u32 addrspace(.input);
-pub extern const frag_coord: @Vector(4, f32) addrspace(.input);
-pub extern const point_coord: @Vector(2, f32) addrspace(.input);
-// TODO: direct/indirect values
-// pub extern const front_facing: bool addrspace(.input);
-// TODO: runtime array
-// pub extern const sample_mask;
-pub extern var frag_depth: f32 addrspace(.output);
-pub extern const num_workgroups: @Vector(3, u32) addrspace(.input);
-pub extern const workgroup_size: @Vector(3, u32) addrspace(.input);
-pub extern const workgroup_id: @Vector(3, u32) addrspace(.input);
-pub extern const local_invocation_id: @Vector(3, u32) addrspace(.input);
-pub extern const global_invocation_id: @Vector(3, u32) addrspace(.input);
-pub extern const vertex_index: u32 addrspace(.input);
-pub extern const instance_index: u32 addrspace(.input);
-
-pub const ExecutionMode = union(Tag) {
- /// Sets origin of the framebuffer to the upper-left corner
- origin_upper_left,
- /// Sets origin of the framebuffer to the lower-left corner
- origin_lower_left,
- /// Indicates that the fragment shader writes to `frag_depth`,
- /// replacing the fixed-function depth value.
- depth_replacing,
- /// Indicates that per-fragment tests may assume that
- /// any `frag_depth` built in-decorated value written by the shader is
- /// greater-than-or-equal to the fragment’s interpolated depth value
- depth_greater,
- /// Indicates that per-fragment tests may assume that
- /// any `frag_depth` built in-decorated value written by the shader is
- /// less-than-or-equal to the fragment’s interpolated depth value
- depth_less,
- /// Indicates that per-fragment tests may assume that
- /// any `frag_depth` built in-decorated value written by the shader is
- /// the same as the fragment’s interpolated depth value
- depth_unchanged,
- /// Indicates the workgroup size in the x, y, and z dimensions.
- local_size: LocalSize,
-
- pub const Tag = enum(u32) {
- origin_upper_left = 7,
- origin_lower_left = 8,
- depth_replacing = 12,
- depth_greater = 14,
- depth_less = 15,
- depth_unchanged = 16,
- local_size = 17,
- };
-
- pub const LocalSize = struct { x: u32, y: u32, z: u32 };
-};
-
-/// Declare the mode entry point executes in.
-pub fn executionMode(comptime entry_point: anytype, comptime mode: ExecutionMode) void {
- const cc = @typeInfo(@TypeOf(entry_point)).@"fn".attrs.@"callconv";
- switch (mode) {
- .origin_upper_left,
- .origin_lower_left,
- .depth_replacing,
- .depth_greater,
- .depth_less,
- .depth_unchanged,
- => {
- if (cc != .spirv_fragment) {
- @compileError(
- \\invalid execution mode '
- ++ @tagName(mode) ++
- \\' for function with '
- ++ @tagName(cc) ++
- \\' calling convention
- );
- }
- asm volatile (
- \\OpExecutionMode %entry_point $mode
- :
- : [entry_point] "" (entry_point),
- [mode] "c" (@intFromEnum(mode)),
- );
- },
- .local_size => |size| {
- if (cc != .spirv_kernel) {
- @compileError(
- \\invalid execution mode 'local_size' for function with '
- ++ @tagName(cc) ++
- \\' calling convention
- );
- }
- asm volatile (
- \\OpExecutionMode %entry_point LocalSize $x $y $z
- :
- : [entry_point] "" (entry_point),
- [x] "c" (size.x),
- [y] "c" (size.y),
- [z] "c" (size.z),
- );
- },
- }
-}
diff --git a/lib/std/hash.zig b/lib/std/hash.zig
index e8d2aa85b13e7dbec1ffbc541bcbeb95a9264261..5ae3734ad2d8c30837b4c69f30866658016f8698 100644
--- a/lib/std/hash.zig
+++ b/lib/std/hash.zig
@@ -5,9 +5,8 @@ pub const autoHash = auto_hash.autoHash;
pub const autoHashStrat = auto_hash.hash;
pub const Strategy = auto_hash.HashStrategy;
-// pub for polynomials + generic crc32 construction
pub const crc = @import("hash/crc.zig");
-pub const Crc32 = crc.Crc32;
+pub const Crc32 = crc.@"CRC-32/ISO-HDLC";
const fnv = @import("hash/fnv.zig");
pub const Fnv1a_32 = fnv.Fnv1a_32;
diff --git a/lib/std/hash/auto_hash.zig b/lib/std/hash/auto_hash.zig
index edfe870f27099104cc3b4f589a5cd94c9e373be0..2562c5157355aa312b3fdd5a89e652a131035d61 100644
--- a/lib/std/hash/auto_hash.zig
+++ b/lib/std/hash/auto_hash.zig
@@ -76,6 +76,7 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
switch (@typeInfo(Key)) {
.noreturn,
.@"opaque",
+ .spirv,
.undefined,
.null,
.comptime_float,
diff --git a/lib/std/hash/benchmark.zig b/lib/std/hash/benchmark.zig
index e5467f421154747181b0d14c1bada7ac28a462ee..3f5b763d9b0f2eb207b597c8e41098f272a090d0 100644
--- a/lib/std/hash/benchmark.zig
+++ b/lib/std/hash/benchmark.zig
@@ -61,7 +61,7 @@ const hashes = [_]Hash{
.init_default = true,
},
Hash{
- .ty = hash.crc.Crc32,
+ .ty = hash.Crc32,
.name = "crc32",
},
Hash{
diff --git a/lib/std/hash/crc.zig b/lib/std/hash/crc.zig
index c0a418a0c2cd236e89df6eeec979dddd33537b8a..795f6a5f5e61ba60b3cbb33efd6605848a91cff8 100644
--- a/lib/std/hash/crc.zig
+++ b/lib/std/hash/crc.zig
@@ -1,19 +1,8 @@
//! This file is auto-generated by tools/update_crc_catalog.zig.
-const impl = @import("crc/impl.zig");
+const builtin = @import("builtin");
-pub const Crc = impl.Crc;
-pub const Polynomial = impl.Polynomial;
-pub const Crc32WithPoly = impl.Crc32WithPoly;
-pub const Crc32SmallWithPoly = impl.Crc32SmallWithPoly;
-
-pub const Crc32 = Crc32IsoHdlc;
-
-test {
- _ = @import("crc/test.zig");
-}
-
-pub const Crc3Gsm = Crc(u3, .{
+pub const @"CRC-3/GSM" = Generic(u3, .{
.polynomial = 0x3,
.initial = 0x0,
.reflect_input = false,
@@ -21,7 +10,7 @@ pub const Crc3Gsm = Crc(u3, .{
.xor_output = 0x7,
});
-pub const Crc3Rohc = Crc(u3, .{
+pub const @"CRC-3/ROHC" = Generic(u3, .{
.polynomial = 0x3,
.initial = 0x7,
.reflect_input = true,
@@ -29,7 +18,7 @@ pub const Crc3Rohc = Crc(u3, .{
.xor_output = 0x0,
});
-pub const Crc4G704 = Crc(u4, .{
+pub const @"CRC-4/G-704" = Generic(u4, .{
.polynomial = 0x3,
.initial = 0x0,
.reflect_input = true,
@@ -37,7 +26,7 @@ pub const Crc4G704 = Crc(u4, .{
.xor_output = 0x0,
});
-pub const Crc4Interlaken = Crc(u4, .{
+pub const @"CRC-4/INTERLAKEN" = Generic(u4, .{
.polynomial = 0x3,
.initial = 0xf,
.reflect_input = false,
@@ -45,7 +34,7 @@ pub const Crc4Interlaken = Crc(u4, .{
.xor_output = 0xf,
});
-pub const Crc5EpcC1g2 = Crc(u5, .{
+pub const @"CRC-5/EPC-C1G2" = Generic(u5, .{
.polynomial = 0x09,
.initial = 0x09,
.reflect_input = false,
@@ -53,7 +42,7 @@ pub const Crc5EpcC1g2 = Crc(u5, .{
.xor_output = 0x00,
});
-pub const Crc5G704 = Crc(u5, .{
+pub const @"CRC-5/G-704" = Generic(u5, .{
.polynomial = 0x15,
.initial = 0x00,
.reflect_input = true,
@@ -61,7 +50,7 @@ pub const Crc5G704 = Crc(u5, .{
.xor_output = 0x00,
});
-pub const Crc5Usb = Crc(u5, .{
+pub const @"CRC-5/USB" = Generic(u5, .{
.polynomial = 0x05,
.initial = 0x1f,
.reflect_input = true,
@@ -69,7 +58,7 @@ pub const Crc5Usb = Crc(u5, .{
.xor_output = 0x1f,
});
-pub const Crc6Cdma2000A = Crc(u6, .{
+pub const @"CRC-6/CDMA2000-A" = Generic(u6, .{
.polynomial = 0x27,
.initial = 0x3f,
.reflect_input = false,
@@ -77,7 +66,7 @@ pub const Crc6Cdma2000A = Crc(u6, .{
.xor_output = 0x00,
});
-pub const Crc6Cdma2000B = Crc(u6, .{
+pub const @"CRC-6/CDMA2000-B" = Generic(u6, .{
.polynomial = 0x07,
.initial = 0x3f,
.reflect_input = false,
@@ -85,7 +74,7 @@ pub const Crc6Cdma2000B = Crc(u6, .{
.xor_output = 0x00,
});
-pub const Crc6Darc = Crc(u6, .{
+pub const @"CRC-6/DARC" = Generic(u6, .{
.polynomial = 0x19,
.initial = 0x00,
.reflect_input = true,
@@ -93,7 +82,7 @@ pub const Crc6Darc = Crc(u6, .{
.xor_output = 0x00,
});
-pub const Crc6G704 = Crc(u6, .{
+pub const @"CRC-6/G-704" = Generic(u6, .{
.polynomial = 0x03,
.initial = 0x00,
.reflect_input = true,
@@ -101,7 +90,7 @@ pub const Crc6G704 = Crc(u6, .{
.xor_output = 0x00,
});
-pub const Crc6Gsm = Crc(u6, .{
+pub const @"CRC-6/GSM" = Generic(u6, .{
.polynomial = 0x2f,
.initial = 0x00,
.reflect_input = false,
@@ -109,7 +98,7 @@ pub const Crc6Gsm = Crc(u6, .{
.xor_output = 0x3f,
});
-pub const Crc7Mmc = Crc(u7, .{
+pub const @"CRC-7/MMC" = Generic(u7, .{
.polynomial = 0x09,
.initial = 0x00,
.reflect_input = false,
@@ -117,7 +106,7 @@ pub const Crc7Mmc = Crc(u7, .{
.xor_output = 0x00,
});
-pub const Crc7Rohc = Crc(u7, .{
+pub const @"CRC-7/ROHC" = Generic(u7, .{
.polynomial = 0x4f,
.initial = 0x7f,
.reflect_input = true,
@@ -125,7 +114,7 @@ pub const Crc7Rohc = Crc(u7, .{
.xor_output = 0x00,
});
-pub const Crc7Umts = Crc(u7, .{
+pub const @"CRC-7/UMTS" = Generic(u7, .{
.polynomial = 0x45,
.initial = 0x00,
.reflect_input = false,
@@ -133,7 +122,7 @@ pub const Crc7Umts = Crc(u7, .{
.xor_output = 0x00,
});
-pub const Crc8Autosar = Crc(u8, .{
+pub const @"CRC-8/AUTOSAR" = Generic(u8, .{
.polynomial = 0x2f,
.initial = 0xff,
.reflect_input = false,
@@ -141,7 +130,7 @@ pub const Crc8Autosar = Crc(u8, .{
.xor_output = 0xff,
});
-pub const Crc8Bluetooth = Crc(u8, .{
+pub const @"CRC-8/BLUETOOTH" = Generic(u8, .{
.polynomial = 0xa7,
.initial = 0x00,
.reflect_input = true,
@@ -149,7 +138,7 @@ pub const Crc8Bluetooth = Crc(u8, .{
.xor_output = 0x00,
});
-pub const Crc8Cdma2000 = Crc(u8, .{
+pub const @"CRC-8/CDMA2000" = Generic(u8, .{
.polynomial = 0x9b,
.initial = 0xff,
.reflect_input = false,
@@ -157,7 +146,7 @@ pub const Crc8Cdma2000 = Crc(u8, .{
.xor_output = 0x00,
});
-pub const Crc8Darc = Crc(u8, .{
+pub const @"CRC-8/DARC" = Generic(u8, .{
.polynomial = 0x39,
.initial = 0x00,
.reflect_input = true,
@@ -165,7 +154,7 @@ pub const Crc8Darc = Crc(u8, .{
.xor_output = 0x00,
});
-pub const Crc8DvbS2 = Crc(u8, .{
+pub const @"CRC-8/DVB-S2" = Generic(u8, .{
.polynomial = 0xd5,
.initial = 0x00,
.reflect_input = false,
@@ -173,7 +162,7 @@ pub const Crc8DvbS2 = Crc(u8, .{
.xor_output = 0x00,
});
-pub const Crc8GsmA = Crc(u8, .{
+pub const @"CRC-8/GSM-A" = Generic(u8, .{
.polynomial = 0x1d,
.initial = 0x00,
.reflect_input = false,
@@ -181,7 +170,7 @@ pub const Crc8GsmA = Crc(u8, .{
.xor_output = 0x00,
});
-pub const Crc8GsmB = Crc(u8, .{
+pub const @"CRC-8/GSM-B" = Generic(u8, .{
.polynomial = 0x49,
.initial = 0x00,
.reflect_input = false,
@@ -189,7 +178,7 @@ pub const Crc8GsmB = Crc(u8, .{
.xor_output = 0xff,
});
-pub const Crc8Hitag = Crc(u8, .{
+pub const @"CRC-8/HITAG" = Generic(u8, .{
.polynomial = 0x1d,
.initial = 0xff,
.reflect_input = false,
@@ -197,7 +186,7 @@ pub const Crc8Hitag = Crc(u8, .{
.xor_output = 0x00,
});
-pub const Crc8I4321 = Crc(u8, .{
+pub const @"CRC-8/I-432-1" = Generic(u8, .{
.polynomial = 0x07,
.initial = 0x00,
.reflect_input = false,
@@ -205,7 +194,7 @@ pub const Crc8I4321 = Crc(u8, .{
.xor_output = 0x55,
});
-pub const Crc8ICode = Crc(u8, .{
+pub const @"CRC-8/I-CODE" = Generic(u8, .{
.polynomial = 0x1d,
.initial = 0xfd,
.reflect_input = false,
@@ -213,7 +202,7 @@ pub const Crc8ICode = Crc(u8, .{
.xor_output = 0x00,
});
-pub const Crc8Lte = Crc(u8, .{
+pub const @"CRC-8/LTE" = Generic(u8, .{
.polynomial = 0x9b,
.initial = 0x00,
.reflect_input = false,
@@ -221,7 +210,7 @@ pub const Crc8Lte = Crc(u8, .{
.xor_output = 0x00,
});
-pub const Crc8MaximDow = Crc(u8, .{
+pub const @"CRC-8/MAXIM-DOW" = Generic(u8, .{
.polynomial = 0x31,
.initial = 0x00,
.reflect_input = true,
@@ -229,7 +218,7 @@ pub const Crc8MaximDow = Crc(u8, .{
.xor_output = 0x00,
});
-pub const Crc8MifareMad = Crc(u8, .{
+pub const @"CRC-8/MIFARE-MAD" = Generic(u8, .{
.polynomial = 0x1d,
.initial = 0xc7,
.reflect_input = false,
@@ -237,7 +226,7 @@ pub const Crc8MifareMad = Crc(u8, .{
.xor_output = 0x00,
});
-pub const Crc8Nrsc5 = Crc(u8, .{
+pub const @"CRC-8/NRSC-5" = Generic(u8, .{
.polynomial = 0x31,
.initial = 0xff,
.reflect_input = false,
@@ -245,7 +234,7 @@ pub const Crc8Nrsc5 = Crc(u8, .{
.xor_output = 0x00,
});
-pub const Crc8Opensafety = Crc(u8, .{
+pub const @"CRC-8/OPENSAFETY" = Generic(u8, .{
.polynomial = 0x2f,
.initial = 0x00,
.reflect_input = false,
@@ -253,7 +242,7 @@ pub const Crc8Opensafety = Crc(u8, .{
.xor_output = 0x00,
});
-pub const Crc8Rohc = Crc(u8, .{
+pub const @"CRC-8/ROHC" = Generic(u8, .{
.polynomial = 0x07,
.initial = 0xff,
.reflect_input = true,
@@ -261,7 +250,7 @@ pub const Crc8Rohc = Crc(u8, .{
.xor_output = 0x00,
});
-pub const Crc8SaeJ1850 = Crc(u8, .{
+pub const @"CRC-8/SAE-J1850" = Generic(u8, .{
.polynomial = 0x1d,
.initial = 0xff,
.reflect_input = false,
@@ -269,7 +258,7 @@ pub const Crc8SaeJ1850 = Crc(u8, .{
.xor_output = 0xff,
});
-pub const Crc8Smbus = Crc(u8, .{
+pub const @"CRC-8/SMBUS" = Generic(u8, .{
.polynomial = 0x07,
.initial = 0x00,
.reflect_input = false,
@@ -277,7 +266,7 @@ pub const Crc8Smbus = Crc(u8, .{
.xor_output = 0x00,
});
-pub const Crc8Tech3250 = Crc(u8, .{
+pub const @"CRC-8/TECH-3250" = Generic(u8, .{
.polynomial = 0x1d,
.initial = 0xff,
.reflect_input = true,
@@ -285,7 +274,7 @@ pub const Crc8Tech3250 = Crc(u8, .{
.xor_output = 0x00,
});
-pub const Crc8Wcdma = Crc(u8, .{
+pub const @"CRC-8/WCDMA" = Generic(u8, .{
.polynomial = 0x9b,
.initial = 0x00,
.reflect_input = true,
@@ -293,7 +282,7 @@ pub const Crc8Wcdma = Crc(u8, .{
.xor_output = 0x00,
});
-pub const Crc10Atm = Crc(u10, .{
+pub const @"CRC-10/ATM" = Generic(u10, .{
.polynomial = 0x233,
.initial = 0x000,
.reflect_input = false,
@@ -301,7 +290,7 @@ pub const Crc10Atm = Crc(u10, .{
.xor_output = 0x000,
});
-pub const Crc10Cdma2000 = Crc(u10, .{
+pub const @"CRC-10/CDMA2000" = Generic(u10, .{
.polynomial = 0x3d9,
.initial = 0x3ff,
.reflect_input = false,
@@ -309,7 +298,7 @@ pub const Crc10Cdma2000 = Crc(u10, .{
.xor_output = 0x000,
});
-pub const Crc10Gsm = Crc(u10, .{
+pub const @"CRC-10/GSM" = Generic(u10, .{
.polynomial = 0x175,
.initial = 0x000,
.reflect_input = false,
@@ -317,7 +306,7 @@ pub const Crc10Gsm = Crc(u10, .{
.xor_output = 0x3ff,
});
-pub const Crc11Flexray = Crc(u11, .{
+pub const @"CRC-11/FLEXRAY" = Generic(u11, .{
.polynomial = 0x385,
.initial = 0x01a,
.reflect_input = false,
@@ -325,7 +314,7 @@ pub const Crc11Flexray = Crc(u11, .{
.xor_output = 0x000,
});
-pub const Crc11Umts = Crc(u11, .{
+pub const @"CRC-11/UMTS" = Generic(u11, .{
.polynomial = 0x307,
.initial = 0x000,
.reflect_input = false,
@@ -333,7 +322,7 @@ pub const Crc11Umts = Crc(u11, .{
.xor_output = 0x000,
});
-pub const Crc12Cdma2000 = Crc(u12, .{
+pub const @"CRC-12/CDMA2000" = Generic(u12, .{
.polynomial = 0xf13,
.initial = 0xfff,
.reflect_input = false,
@@ -341,7 +330,7 @@ pub const Crc12Cdma2000 = Crc(u12, .{
.xor_output = 0x000,
});
-pub const Crc12Dect = Crc(u12, .{
+pub const @"CRC-12/DECT" = Generic(u12, .{
.polynomial = 0x80f,
.initial = 0x000,
.reflect_input = false,
@@ -349,7 +338,7 @@ pub const Crc12Dect = Crc(u12, .{
.xor_output = 0x000,
});
-pub const Crc12Gsm = Crc(u12, .{
+pub const @"CRC-12/GSM" = Generic(u12, .{
.polynomial = 0xd31,
.initial = 0x000,
.reflect_input = false,
@@ -357,7 +346,7 @@ pub const Crc12Gsm = Crc(u12, .{
.xor_output = 0xfff,
});
-pub const Crc12Umts = Crc(u12, .{
+pub const @"CRC-12/UMTS" = Generic(u12, .{
.polynomial = 0x80f,
.initial = 0x000,
.reflect_input = false,
@@ -365,7 +354,7 @@ pub const Crc12Umts = Crc(u12, .{
.xor_output = 0x000,
});
-pub const Crc13Bbc = Crc(u13, .{
+pub const @"CRC-13/BBC" = Generic(u13, .{
.polynomial = 0x1cf5,
.initial = 0x0000,
.reflect_input = false,
@@ -373,7 +362,7 @@ pub const Crc13Bbc = Crc(u13, .{
.xor_output = 0x0000,
});
-pub const Crc14Darc = Crc(u14, .{
+pub const @"CRC-14/DARC" = Generic(u14, .{
.polynomial = 0x0805,
.initial = 0x0000,
.reflect_input = true,
@@ -381,7 +370,7 @@ pub const Crc14Darc = Crc(u14, .{
.xor_output = 0x0000,
});
-pub const Crc14Gsm = Crc(u14, .{
+pub const @"CRC-14/GSM" = Generic(u14, .{
.polynomial = 0x202d,
.initial = 0x0000,
.reflect_input = false,
@@ -389,7 +378,7 @@ pub const Crc14Gsm = Crc(u14, .{
.xor_output = 0x3fff,
});
-pub const Crc15Can = Crc(u15, .{
+pub const @"CRC-15/CAN" = Generic(u15, .{
.polynomial = 0x4599,
.initial = 0x0000,
.reflect_input = false,
@@ -397,7 +386,7 @@ pub const Crc15Can = Crc(u15, .{
.xor_output = 0x0000,
});
-pub const Crc15Mpt1327 = Crc(u15, .{
+pub const @"CRC-15/MPT1327" = Generic(u15, .{
.polynomial = 0x6815,
.initial = 0x0000,
.reflect_input = false,
@@ -405,7 +394,7 @@ pub const Crc15Mpt1327 = Crc(u15, .{
.xor_output = 0x0001,
});
-pub const Crc16Arc = Crc(u16, .{
+pub const @"CRC-16/ARC" = Generic(u16, .{
.polynomial = 0x8005,
.initial = 0x0000,
.reflect_input = true,
@@ -413,7 +402,7 @@ pub const Crc16Arc = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16Cdma2000 = Crc(u16, .{
+pub const @"CRC-16/CDMA2000" = Generic(u16, .{
.polynomial = 0xc867,
.initial = 0xffff,
.reflect_input = false,
@@ -421,7 +410,7 @@ pub const Crc16Cdma2000 = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16Cms = Crc(u16, .{
+pub const @"CRC-16/CMS" = Generic(u16, .{
.polynomial = 0x8005,
.initial = 0xffff,
.reflect_input = false,
@@ -429,7 +418,7 @@ pub const Crc16Cms = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16Dds110 = Crc(u16, .{
+pub const @"CRC-16/DDS-110" = Generic(u16, .{
.polynomial = 0x8005,
.initial = 0x800d,
.reflect_input = false,
@@ -437,7 +426,7 @@ pub const Crc16Dds110 = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16DectR = Crc(u16, .{
+pub const @"CRC-16/DECT-R" = Generic(u16, .{
.polynomial = 0x0589,
.initial = 0x0000,
.reflect_input = false,
@@ -445,7 +434,7 @@ pub const Crc16DectR = Crc(u16, .{
.xor_output = 0x0001,
});
-pub const Crc16DectX = Crc(u16, .{
+pub const @"CRC-16/DECT-X" = Generic(u16, .{
.polynomial = 0x0589,
.initial = 0x0000,
.reflect_input = false,
@@ -453,7 +442,7 @@ pub const Crc16DectX = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16Dnp = Crc(u16, .{
+pub const @"CRC-16/DNP" = Generic(u16, .{
.polynomial = 0x3d65,
.initial = 0x0000,
.reflect_input = true,
@@ -461,7 +450,7 @@ pub const Crc16Dnp = Crc(u16, .{
.xor_output = 0xffff,
});
-pub const Crc16En13757 = Crc(u16, .{
+pub const @"CRC-16/EN-13757" = Generic(u16, .{
.polynomial = 0x3d65,
.initial = 0x0000,
.reflect_input = false,
@@ -469,7 +458,7 @@ pub const Crc16En13757 = Crc(u16, .{
.xor_output = 0xffff,
});
-pub const Crc16Genibus = Crc(u16, .{
+pub const @"CRC-16/GENIBUS" = Generic(u16, .{
.polynomial = 0x1021,
.initial = 0xffff,
.reflect_input = false,
@@ -477,7 +466,7 @@ pub const Crc16Genibus = Crc(u16, .{
.xor_output = 0xffff,
});
-pub const Crc16Gsm = Crc(u16, .{
+pub const @"CRC-16/GSM" = Generic(u16, .{
.polynomial = 0x1021,
.initial = 0x0000,
.reflect_input = false,
@@ -485,7 +474,7 @@ pub const Crc16Gsm = Crc(u16, .{
.xor_output = 0xffff,
});
-pub const Crc16Ibm3740 = Crc(u16, .{
+pub const @"CRC-16/IBM-3740" = Generic(u16, .{
.polynomial = 0x1021,
.initial = 0xffff,
.reflect_input = false,
@@ -493,7 +482,7 @@ pub const Crc16Ibm3740 = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16IbmSdlc = Crc(u16, .{
+pub const @"CRC-16/IBM-SDLC" = Generic(u16, .{
.polynomial = 0x1021,
.initial = 0xffff,
.reflect_input = true,
@@ -501,7 +490,7 @@ pub const Crc16IbmSdlc = Crc(u16, .{
.xor_output = 0xffff,
});
-pub const Crc16IsoIec144433A = Crc(u16, .{
+pub const @"CRC-16/ISO-IEC-14443-3-A" = Generic(u16, .{
.polynomial = 0x1021,
.initial = 0xc6c6,
.reflect_input = true,
@@ -509,7 +498,7 @@ pub const Crc16IsoIec144433A = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16Kermit = Crc(u16, .{
+pub const @"CRC-16/KERMIT" = Generic(u16, .{
.polynomial = 0x1021,
.initial = 0x0000,
.reflect_input = true,
@@ -517,7 +506,7 @@ pub const Crc16Kermit = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16Lj1200 = Crc(u16, .{
+pub const @"CRC-16/LJ1200" = Generic(u16, .{
.polynomial = 0x6f63,
.initial = 0x0000,
.reflect_input = false,
@@ -525,7 +514,7 @@ pub const Crc16Lj1200 = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16M17 = Crc(u16, .{
+pub const @"CRC-16/M17" = Generic(u16, .{
.polynomial = 0x5935,
.initial = 0xffff,
.reflect_input = false,
@@ -533,7 +522,7 @@ pub const Crc16M17 = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16MaximDow = Crc(u16, .{
+pub const @"CRC-16/MAXIM-DOW" = Generic(u16, .{
.polynomial = 0x8005,
.initial = 0x0000,
.reflect_input = true,
@@ -541,7 +530,7 @@ pub const Crc16MaximDow = Crc(u16, .{
.xor_output = 0xffff,
});
-pub const Crc16Mcrf4xx = Crc(u16, .{
+pub const @"CRC-16/MCRF4XX" = Generic(u16, .{
.polynomial = 0x1021,
.initial = 0xffff,
.reflect_input = true,
@@ -549,7 +538,7 @@ pub const Crc16Mcrf4xx = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16Modbus = Crc(u16, .{
+pub const @"CRC-16/MODBUS" = Generic(u16, .{
.polynomial = 0x8005,
.initial = 0xffff,
.reflect_input = true,
@@ -557,7 +546,7 @@ pub const Crc16Modbus = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16Nrsc5 = Crc(u16, .{
+pub const @"CRC-16/NRSC-5" = Generic(u16, .{
.polynomial = 0x080b,
.initial = 0xffff,
.reflect_input = true,
@@ -565,7 +554,7 @@ pub const Crc16Nrsc5 = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16OpensafetyA = Crc(u16, .{
+pub const @"CRC-16/OPENSAFETY-A" = Generic(u16, .{
.polynomial = 0x5935,
.initial = 0x0000,
.reflect_input = false,
@@ -573,7 +562,7 @@ pub const Crc16OpensafetyA = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16OpensafetyB = Crc(u16, .{
+pub const @"CRC-16/OPENSAFETY-B" = Generic(u16, .{
.polynomial = 0x755b,
.initial = 0x0000,
.reflect_input = false,
@@ -581,7 +570,7 @@ pub const Crc16OpensafetyB = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16Profibus = Crc(u16, .{
+pub const @"CRC-16/PROFIBUS" = Generic(u16, .{
.polynomial = 0x1dcf,
.initial = 0xffff,
.reflect_input = false,
@@ -589,7 +578,7 @@ pub const Crc16Profibus = Crc(u16, .{
.xor_output = 0xffff,
});
-pub const Crc16Riello = Crc(u16, .{
+pub const @"CRC-16/RIELLO" = Generic(u16, .{
.polynomial = 0x1021,
.initial = 0xb2aa,
.reflect_input = true,
@@ -597,7 +586,7 @@ pub const Crc16Riello = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16SpiFujitsu = Crc(u16, .{
+pub const @"CRC-16/SPI-FUJITSU" = Generic(u16, .{
.polynomial = 0x1021,
.initial = 0x1d0f,
.reflect_input = false,
@@ -605,7 +594,7 @@ pub const Crc16SpiFujitsu = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16T10Dif = Crc(u16, .{
+pub const @"CRC-16/T10-DIF" = Generic(u16, .{
.polynomial = 0x8bb7,
.initial = 0x0000,
.reflect_input = false,
@@ -613,7 +602,7 @@ pub const Crc16T10Dif = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16Teledisk = Crc(u16, .{
+pub const @"CRC-16/TELEDISK" = Generic(u16, .{
.polynomial = 0xa097,
.initial = 0x0000,
.reflect_input = false,
@@ -621,7 +610,7 @@ pub const Crc16Teledisk = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16Tms37157 = Crc(u16, .{
+pub const @"CRC-16/TMS37157" = Generic(u16, .{
.polynomial = 0x1021,
.initial = 0x89ec,
.reflect_input = true,
@@ -629,7 +618,7 @@ pub const Crc16Tms37157 = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16Umts = Crc(u16, .{
+pub const @"CRC-16/UMTS" = Generic(u16, .{
.polynomial = 0x8005,
.initial = 0x0000,
.reflect_input = false,
@@ -637,7 +626,7 @@ pub const Crc16Umts = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc16Usb = Crc(u16, .{
+pub const @"CRC-16/USB" = Generic(u16, .{
.polynomial = 0x8005,
.initial = 0xffff,
.reflect_input = true,
@@ -645,7 +634,7 @@ pub const Crc16Usb = Crc(u16, .{
.xor_output = 0xffff,
});
-pub const Crc16Xmodem = Crc(u16, .{
+pub const @"CRC-16/XMODEM" = Generic(u16, .{
.polynomial = 0x1021,
.initial = 0x0000,
.reflect_input = false,
@@ -653,7 +642,7 @@ pub const Crc16Xmodem = Crc(u16, .{
.xor_output = 0x0000,
});
-pub const Crc17CanFd = Crc(u17, .{
+pub const @"CRC-17/CAN-FD" = Generic(u17, .{
.polynomial = 0x1685b,
.initial = 0x00000,
.reflect_input = false,
@@ -661,7 +650,7 @@ pub const Crc17CanFd = Crc(u17, .{
.xor_output = 0x00000,
});
-pub const Crc21CanFd = Crc(u21, .{
+pub const @"CRC-21/CAN-FD" = Generic(u21, .{
.polynomial = 0x102899,
.initial = 0x000000,
.reflect_input = false,
@@ -669,7 +658,7 @@ pub const Crc21CanFd = Crc(u21, .{
.xor_output = 0x000000,
});
-pub const Crc24Ble = Crc(u24, .{
+pub const @"CRC-24/BLE" = Generic(u24, .{
.polynomial = 0x00065b,
.initial = 0x555555,
.reflect_input = true,
@@ -677,7 +666,7 @@ pub const Crc24Ble = Crc(u24, .{
.xor_output = 0x000000,
});
-pub const Crc24FlexrayA = Crc(u24, .{
+pub const @"CRC-24/FLEXRAY-A" = Generic(u24, .{
.polynomial = 0x5d6dcb,
.initial = 0xfedcba,
.reflect_input = false,
@@ -685,7 +674,7 @@ pub const Crc24FlexrayA = Crc(u24, .{
.xor_output = 0x000000,
});
-pub const Crc24FlexrayB = Crc(u24, .{
+pub const @"CRC-24/FLEXRAY-B" = Generic(u24, .{
.polynomial = 0x5d6dcb,
.initial = 0xabcdef,
.reflect_input = false,
@@ -693,7 +682,7 @@ pub const Crc24FlexrayB = Crc(u24, .{
.xor_output = 0x000000,
});
-pub const Crc24Interlaken = Crc(u24, .{
+pub const @"CRC-24/INTERLAKEN" = Generic(u24, .{
.polynomial = 0x328b63,
.initial = 0xffffff,
.reflect_input = false,
@@ -701,7 +690,7 @@ pub const Crc24Interlaken = Crc(u24, .{
.xor_output = 0xffffff,
});
-pub const Crc24LteA = Crc(u24, .{
+pub const @"CRC-24/LTE-A" = Generic(u24, .{
.polynomial = 0x864cfb,
.initial = 0x000000,
.reflect_input = false,
@@ -709,7 +698,7 @@ pub const Crc24LteA = Crc(u24, .{
.xor_output = 0x000000,
});
-pub const Crc24LteB = Crc(u24, .{
+pub const @"CRC-24/LTE-B" = Generic(u24, .{
.polynomial = 0x800063,
.initial = 0x000000,
.reflect_input = false,
@@ -717,7 +706,7 @@ pub const Crc24LteB = Crc(u24, .{
.xor_output = 0x000000,
});
-pub const Crc24Openpgp = Crc(u24, .{
+pub const @"CRC-24/OPENPGP" = Generic(u24, .{
.polynomial = 0x864cfb,
.initial = 0xb704ce,
.reflect_input = false,
@@ -725,7 +714,7 @@ pub const Crc24Openpgp = Crc(u24, .{
.xor_output = 0x000000,
});
-pub const Crc24Os9 = Crc(u24, .{
+pub const @"CRC-24/OS-9" = Generic(u24, .{
.polynomial = 0x800063,
.initial = 0xffffff,
.reflect_input = false,
@@ -733,7 +722,7 @@ pub const Crc24Os9 = Crc(u24, .{
.xor_output = 0xffffff,
});
-pub const Crc30Cdma = Crc(u30, .{
+pub const @"CRC-30/CDMA" = Generic(u30, .{
.polynomial = 0x2030b9c7,
.initial = 0x3fffffff,
.reflect_input = false,
@@ -741,7 +730,7 @@ pub const Crc30Cdma = Crc(u30, .{
.xor_output = 0x3fffffff,
});
-pub const Crc31Philips = Crc(u31, .{
+pub const @"CRC-31/PHILIPS" = Generic(u31, .{
.polynomial = 0x04c11db7,
.initial = 0x7fffffff,
.reflect_input = false,
@@ -749,7 +738,7 @@ pub const Crc31Philips = Crc(u31, .{
.xor_output = 0x7fffffff,
});
-pub const Crc32Aixm = Crc(u32, .{
+pub const @"CRC-32/AIXM" = Generic(u32, .{
.polynomial = 0x814141ab,
.initial = 0x00000000,
.reflect_input = false,
@@ -757,7 +746,7 @@ pub const Crc32Aixm = Crc(u32, .{
.xor_output = 0x00000000,
});
-pub const Crc32Autosar = Crc(u32, .{
+pub const @"CRC-32/AUTOSAR" = Generic(u32, .{
.polynomial = 0xf4acfb13,
.initial = 0xffffffff,
.reflect_input = true,
@@ -765,7 +754,7 @@ pub const Crc32Autosar = Crc(u32, .{
.xor_output = 0xffffffff,
});
-pub const Crc32Base91D = Crc(u32, .{
+pub const @"CRC-32/BASE91-D" = Generic(u32, .{
.polynomial = 0xa833982b,
.initial = 0xffffffff,
.reflect_input = true,
@@ -773,7 +762,7 @@ pub const Crc32Base91D = Crc(u32, .{
.xor_output = 0xffffffff,
});
-pub const Crc32Bzip2 = Crc(u32, .{
+pub const @"CRC-32/BZIP2" = Generic(u32, .{
.polynomial = 0x04c11db7,
.initial = 0xffffffff,
.reflect_input = false,
@@ -781,7 +770,7 @@ pub const Crc32Bzip2 = Crc(u32, .{
.xor_output = 0xffffffff,
});
-pub const Crc32CdRomEdc = Crc(u32, .{
+pub const @"CRC-32/CD-ROM-EDC" = Generic(u32, .{
.polynomial = 0x8001801b,
.initial = 0x00000000,
.reflect_input = true,
@@ -789,7 +778,7 @@ pub const Crc32CdRomEdc = Crc(u32, .{
.xor_output = 0x00000000,
});
-pub const Crc32Cksum = Crc(u32, .{
+pub const @"CRC-32/CKSUM" = Generic(u32, .{
.polynomial = 0x04c11db7,
.initial = 0x00000000,
.reflect_input = false,
@@ -797,15 +786,18 @@ pub const Crc32Cksum = Crc(u32, .{
.xor_output = 0xffffffff,
});
-pub const Crc32Iscsi = Crc(u32, .{
- .polynomial = 0x1edc6f41,
- .initial = 0xffffffff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0xffffffff,
-});
+pub const @"CRC-32/ISCSI" = if (builtin.cpu.hasAll(.x86, &.{ .@"64bit", .crc32 }))
+ @import("crc/Crc32c.zig")
+else
+ Generic(u32, .{
+ .polynomial = 0x1edc6f41,
+ .initial = 0xffffffff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0xffffffff,
+ });
-pub const Crc32IsoHdlc = Crc(u32, .{
+pub const @"CRC-32/ISO-HDLC" = Generic(u32, .{
.polynomial = 0x04c11db7,
.initial = 0xffffffff,
.reflect_input = true,
@@ -813,7 +805,7 @@ pub const Crc32IsoHdlc = Crc(u32, .{
.xor_output = 0xffffffff,
});
-pub const Crc32Jamcrc = Crc(u32, .{
+pub const @"CRC-32/JAMCRC" = Generic(u32, .{
.polynomial = 0x04c11db7,
.initial = 0xffffffff,
.reflect_input = true,
@@ -821,7 +813,7 @@ pub const Crc32Jamcrc = Crc(u32, .{
.xor_output = 0x00000000,
});
-pub const Crc32Koopman = Crc(u32, .{
+pub const @"CRC-32/KOOPMAN" = Generic(u32, .{
.polynomial = 0x741b8cd7,
.initial = 0xffffffff,
.reflect_input = true,
@@ -829,7 +821,7 @@ pub const Crc32Koopman = Crc(u32, .{
.xor_output = 0xffffffff,
});
-pub const Crc32Mef = Crc(u32, .{
+pub const @"CRC-32/MEF" = Generic(u32, .{
.polynomial = 0x741b8cd7,
.initial = 0xffffffff,
.reflect_input = true,
@@ -837,7 +829,7 @@ pub const Crc32Mef = Crc(u32, .{
.xor_output = 0x00000000,
});
-pub const Crc32Mpeg2 = Crc(u32, .{
+pub const @"CRC-32/MPEG-2" = Generic(u32, .{
.polynomial = 0x04c11db7,
.initial = 0xffffffff,
.reflect_input = false,
@@ -845,7 +837,7 @@ pub const Crc32Mpeg2 = Crc(u32, .{
.xor_output = 0x00000000,
});
-pub const Crc32Xfer = Crc(u32, .{
+pub const @"CRC-32/XFER" = Generic(u32, .{
.polynomial = 0x000000af,
.initial = 0x00000000,
.reflect_input = false,
@@ -853,7 +845,7 @@ pub const Crc32Xfer = Crc(u32, .{
.xor_output = 0x00000000,
});
-pub const Crc40Gsm = Crc(u40, .{
+pub const @"CRC-40/GSM" = Generic(u40, .{
.polynomial = 0x0004820009,
.initial = 0x0000000000,
.reflect_input = false,
@@ -861,7 +853,7 @@ pub const Crc40Gsm = Crc(u40, .{
.xor_output = 0xffffffffff,
});
-pub const Crc64Ecma182 = Crc(u64, .{
+pub const @"CRC-64/ECMA-182" = Generic(u64, .{
.polynomial = 0x42f0e1eba9ea3693,
.initial = 0x0000000000000000,
.reflect_input = false,
@@ -869,7 +861,7 @@ pub const Crc64Ecma182 = Crc(u64, .{
.xor_output = 0x0000000000000000,
});
-pub const Crc64GoIso = Crc(u64, .{
+pub const @"CRC-64/GO-ISO" = Generic(u64, .{
.polynomial = 0x000000000000001b,
.initial = 0xffffffffffffffff,
.reflect_input = true,
@@ -877,7 +869,7 @@ pub const Crc64GoIso = Crc(u64, .{
.xor_output = 0xffffffffffffffff,
});
-pub const Crc64Ms = Crc(u64, .{
+pub const @"CRC-64/MS" = Generic(u64, .{
.polynomial = 0x259c84cba6426349,
.initial = 0xffffffffffffffff,
.reflect_input = true,
@@ -885,7 +877,7 @@ pub const Crc64Ms = Crc(u64, .{
.xor_output = 0x0000000000000000,
});
-pub const Crc64Redis = Crc(u64, .{
+pub const @"CRC-64/REDIS" = Generic(u64, .{
.polynomial = 0xad93d23594c935a9,
.initial = 0x0000000000000000,
.reflect_input = true,
@@ -893,7 +885,7 @@ pub const Crc64Redis = Crc(u64, .{
.xor_output = 0x0000000000000000,
});
-pub const Crc64We = Crc(u64, .{
+pub const @"CRC-64/WE" = Generic(u64, .{
.polynomial = 0x42f0e1eba9ea3693,
.initial = 0xffffffffffffffff,
.reflect_input = false,
@@ -901,7 +893,7 @@ pub const Crc64We = Crc(u64, .{
.xor_output = 0xffffffffffffffff,
});
-pub const Crc64Xz = Crc(u64, .{
+pub const @"CRC-64/XZ" = Generic(u64, .{
.polynomial = 0x42f0e1eba9ea3693,
.initial = 0xffffffffffffffff,
.reflect_input = true,
@@ -909,10 +901,109 @@ pub const Crc64Xz = Crc(u64, .{
.xor_output = 0xffffffffffffffff,
});
-pub const Crc82Darc = Crc(u82, .{
+pub const @"CRC-82/DARC" = Generic(u82, .{
.polynomial = 0x0308c0111011401440411,
.initial = 0x000000000000000000000,
.reflect_input = true,
.reflect_output = true,
.xor_output = 0x000000000000000000000,
});
+
+pub fn Algorithm(comptime W: type) type {
+ return struct {
+ polynomial: W,
+ initial: W,
+ reflect_input: bool,
+ reflect_output: bool,
+ xor_output: W,
+ };
+}
+
+pub fn Generic(comptime W: type, comptime algorithm: Algorithm(W)) type {
+ return struct {
+ const Self = @This();
+ const I = if (@bitSizeOf(W) < 8) u8 else W;
+ const lookup_table = blk: {
+ @setEvalBranchQuota(2500);
+ const poly = reflect(algorithm.polynomial);
+ var table: [256]I = undefined;
+ for (&table, 0..) |*e, i| {
+ var crc: I = i;
+ if (algorithm.reflect_input) {
+ var j: usize = 0;
+ while (j < 8) : (j += 1) {
+ crc = (crc >> 1) ^ ((crc & 1) * poly);
+ }
+ } else {
+ crc <<= @bitSizeOf(I) - 8;
+ var j: usize = 0;
+ while (j < 8) : (j += 1) {
+ crc = (crc << 1) ^ (((crc >> (@bitSizeOf(I) - 1)) & 1) * poly);
+ }
+ }
+ e.* = crc;
+ }
+ break :blk table;
+ };
+
+ crc: I,
+
+ pub fn init() Self {
+ const initial = reflect(algorithm.initial);
+ return .{ .crc = initial };
+ }
+
+ inline fn tableEntry(index: I) I {
+ const short: u8 = @truncate(index);
+ return lookup_table[short];
+ }
+
+ pub fn update(self: *Self, bytes: []const u8) void {
+ var i: usize = 0;
+ if (@bitSizeOf(I) <= 8) {
+ while (i < bytes.len) : (i += 1) {
+ self.crc = tableEntry(self.crc ^ bytes[i]);
+ }
+ } else if (algorithm.reflect_input) {
+ while (i < bytes.len) : (i += 1) {
+ const table_index = self.crc ^ bytes[i];
+ self.crc = tableEntry(table_index) ^ (self.crc >> 8);
+ }
+ } else {
+ while (i < bytes.len) : (i += 1) {
+ const table_index = (self.crc >> (@bitSizeOf(I) - 8)) ^ bytes[i];
+ self.crc = tableEntry(table_index) ^ (self.crc << 8);
+ }
+ }
+ }
+
+ pub fn final(self: Self) W {
+ var c = self.crc;
+ if (algorithm.reflect_input != algorithm.reflect_output) {
+ c = @bitReverse(c);
+ }
+ if (!algorithm.reflect_output) {
+ c >>= @bitSizeOf(I) - @bitSizeOf(W);
+ }
+ return @intCast(c ^ algorithm.xor_output);
+ }
+
+ pub fn hash(bytes: []const u8) W {
+ var c = Self.init();
+ c.update(bytes);
+ return c.final();
+ }
+
+ fn reflect(x: I) I {
+ const offset = @bitSizeOf(I) - @bitSizeOf(W);
+ if (algorithm.reflect_input)
+ return @bitReverse(x) >> offset
+ else
+ return x << offset;
+ }
+ };
+}
+
+test {
+ _ = @import("crc/test.zig");
+}
diff --git a/lib/std/hash/crc/Crc32c.zig b/lib/std/hash/crc/Crc32c.zig
new file mode 100644
index 0000000000000000000000000000000000000000..7405dc949d1f80abb01b94500c0b3613763fc62c
--- /dev/null
+++ b/lib/std/hash/crc/Crc32c.zig
@@ -0,0 +1,238 @@
+//! Implements CRC-32C (Castagnoli) using the SSE4.2 Intel CRC32 instruction.
+//!
+//! A couple useful links for understanding the approach taken here:
+//! - https://github.com/madler/brotli/blob/1d428d3a9baade233ebc3ac108293256bcb813d1/crc32c.c
+//! - https://github.com/madler/zlib/blob/5a82f71ed1dfc0bec044d9702463dbdf84ea3b71/crc32.c
+//! - http://www.ross.net/crc/download/crc_v3.txt
+
+// Reflected CRC-32C polynomial in binary form.
+const POLY = 0x82f63b78;
+
+const LONG = 8192;
+const SHORT = 256;
+const long_lookup_table = genTable(LONG);
+const short_lookup_table = genTable(SHORT);
+
+const Wrapper = @This();
+
+crc: u32,
+
+pub fn init() Wrapper {
+ return .{ .crc = 0 };
+}
+
+pub fn update(w: *Wrapper, bytes: []const u8) void {
+ w.crc = crc32(w.crc, bytes);
+}
+
+pub fn final(w: Wrapper) u32 {
+ return w.crc;
+}
+
+pub fn hash(bytes: []const u8) u32 {
+ var c = init();
+ c.update(bytes);
+ return c.final();
+}
+
+/// Generates the lookup table for efficiently combining CRCs over a block of a given length `length`.
+/// This works by building an operator that advances the CRC state as if `length` zero-bytes were appended.
+/// We pre-compute 4 tables of 256 entries each (one per byte offset).
+///
+///
+/// The idea behind this table is quite interesting. The CRC state is equivalent to the
+/// remainder of dividing the message polynomial (over GF(2)) by the CRC polynomial.
+///
+/// Advancing the CRC register by `k` zero bits is equivalent to multiplying the current
+/// CRC state by `x^k` modulo the CRC polynomial. This operation can be represented
+/// as a linear transformation in GF(2), i.e, a matrix.
+///
+/// We build up this matrix via repeated squaring:
+/// - odd represents the operator for 1 zero bit (i.e, multiplication by `x^1 mod POLY`)
+/// - even represents the operator for 2 zero bits (`x^2 mod POLY`)
+/// - squaring again gives `x^4 mod POLY`, and so on until we get to the right size.
+///
+/// By squaring the shifting `len`, we build the operator for `x^l mod POLY`.
+fn genTable(length: usize) [4][256]u32 {
+ @setEvalBranchQuota(250000);
+
+ var even: [32]u32 = undefined;
+ zeroes: {
+ var odd: [32]u32 = undefined;
+
+ // Initialize our `odd` array with the operator for a single zero bit:
+ // - odd[0] is the polynomial itself (acts on the MSB).
+ // - odd[1..32] represent shifting a single bit through 31 positions.
+ odd[0] = POLY;
+ var row: u32 = 1;
+ for (1..32) |n| {
+ odd[n] = row;
+ row <<= 1;
+ }
+
+ // even = odd squared: even represents `x^2 mod POLY`.
+ square(&even, &odd);
+ // odd = even squared: odd now represents `x^4 mod POLY`.
+ square(&odd, &even);
+
+ // Continue squaring to double the number of zeroes encoded each time:
+ //
+ // At each point in the process:
+ // - square(even, odd): even gets the operator for twice the current length.
+ // - square(odd, even): odd gets the operator for 4 times the original length.
+ var len = length;
+ while (true) {
+ square(&even, &odd);
+ len >>= 1;
+ if (len == 0) break :zeroes;
+ square(&odd, &even);
+ len >>= 1;
+ if (len == 0) break;
+ }
+
+ @memcpy(&even, &odd);
+ }
+
+ var zeroes: [4][256]u32 = undefined;
+ for (0..256) |n| {
+ zeroes[0][n] = times(&even, n);
+ zeroes[1][n] = times(&even, n << 8);
+ zeroes[2][n] = times(&even, n << 16);
+ zeroes[3][n] = times(&even, n << 24);
+ }
+ return zeroes;
+}
+
+/// Computes `mat * vec` over `GF(2)`, where `mat` is a 32x32 binary matrix and `vec`
+/// is a 32-bit vector. This somewhat "simulates" how bits propagate through the CRC register
+/// during shifting.
+///
+/// - In GF(2) (aka a field where the only values are 0 and 1, aka binary), multiplication is
+/// an `AND`, and addition is `XOR`.
+/// - This dot product determines how each bit in the input vector "contributes" to
+/// the final CRC state, by XORing (adding) rows of the matrix where `vec` has 1s.
+fn times(mat: *const [32]u32, vec: u32) u32 {
+ var sum: u32 = 0;
+ var v = vec;
+ var i: u32 = 0;
+ while (v != 0) {
+ if (v & 1 != 0) sum ^= mat[i];
+ v >>= 1;
+ i += 1;
+ }
+ return sum;
+}
+
+/// Computes the square of a matrix in GF(2), i.e `dst = dst x src`.
+///
+/// This produces the operator for doubling the number of zeroes:
+/// if `src` represents advancing the CRC by `k` zeroes, then `dest` will
+/// represent advancing by 2k zeroes.
+///
+/// Since polynomial multiplication mod POLY is linear, `mat(mat(x)) = mat^2(x)`
+/// gives the effect of two sequential applications of the operator.
+fn square(dst: *[32]u32, src: *const [32]u32) void {
+ for (dst, src) |*d, s| {
+ d.* = times(src, s);
+ }
+}
+
+fn shift(table: *const [4][256]u32, crc: u32) u32 {
+ return table[0][crc & 0xFF] ^ table[1][(crc >> 8) & 0xFF] ^ table[2][(crc >> 16) & 0xFF] ^ table[3][crc >> 24];
+}
+
+fn crc32(crc: u32, input: []const u8) u32 {
+ var crc0: u64 = ~crc;
+
+ // Compute the CRC for up to seven leading bytes to bring the
+ // `next` pointer to an eight-byte boundary.
+ var next = input;
+ while (next.len > 0 and @intFromPtr(next.ptr) & 7 != 0) {
+ asm volatile ("crc32b %[out], %[in]"
+ : [in] "+r" (crc0),
+ : [out] "rm" (next[0]),
+ );
+ next = next[1..];
+ }
+
+ // Compute the CRC on sets of LONG * 3 bytes, executing three independent
+ // CRC instructions, each on LONG bytes. This is an optimization for
+ // targets where the CRC instruction has a throughput of one CRC per
+ // cycle, but a latency of three cycles.
+ while (next.len >= LONG * 3) {
+ var crc1: u64 = 0;
+ var crc2: u64 = 0;
+
+ const start = next.len;
+ while (true) {
+ // Safe @alignCast(), since we've aligned the pointer to 8 bytes before this loop.
+ const long: [*]const u64 = @ptrCast(@alignCast(next));
+ asm volatile (
+ \\crc32q %[out0], %[in0]
+ \\crc32q %[out1], %[in1]
+ \\crc32q %[out2], %[in2]
+ : [in0] "+r" (crc0),
+ [in1] "+r" (crc1),
+ [in2] "+r" (crc2),
+ : [out0] "rm" (long[0 * LONG / 8]),
+ [out1] "rm" (long[1 * LONG / 8]),
+ [out2] "rm" (long[2 * LONG / 8]),
+ );
+ next = next[8..];
+ if (next.len <= start - LONG) break;
+ }
+
+ crc0 = shift(&long_lookup_table, @truncate(crc0)) ^ crc1;
+ crc0 = shift(&long_lookup_table, @truncate(crc0)) ^ crc2;
+ next = next[LONG * 2 ..];
+ }
+
+ // Same thing as above, but for smaller chunks of SHORT bytes.
+ while (next.len >= SHORT * 3) {
+ var crc1: u64 = 0;
+ var crc2: u64 = 0;
+
+ const start = next.len;
+ while (true) {
+ const long: [*]const u64 = @ptrCast(@alignCast(next));
+ asm volatile (
+ \\crc32q %[out0], %[in0]
+ \\crc32q %[out1], %[in1]
+ \\crc32q %[out2], %[in2]
+ : [in0] "+r" (crc0),
+ [in1] "+r" (crc1),
+ [in2] "+r" (crc2),
+ : [out0] "rm" (long[0 * SHORT / 8]),
+ [out1] "rm" (long[1 * SHORT / 8]),
+ [out2] "rm" (long[2 * SHORT / 8]),
+ );
+ next = next[8..];
+ if (next.len <= start - SHORT) break;
+ }
+
+ crc0 = shift(&short_lookup_table, @truncate(crc0)) ^ crc1;
+ crc0 = shift(&short_lookup_table, @truncate(crc0)) ^ crc2;
+ next = next[SHORT * 2 ..];
+ }
+
+ // Compute via 8-byte chunks, until we're left with less than 8 bytes.
+ while (next.len >= 8) {
+ const long: [*]const u64 = @ptrCast(@alignCast(next));
+ asm volatile ("crc32q %[out], %[in]"
+ : [in] "+r" (crc0),
+ : [out] "rm" (long[0]),
+ );
+ next = next[8..];
+ }
+
+ // Finish the last bytes with just single instructions.
+ while (next.len > 0) {
+ asm volatile ("crc32b %[out], %[in]"
+ : [in] "+r" (crc0),
+ : [out] "rm" (next[0]),
+ );
+ next = next[1..];
+ }
+
+ return @truncate(~crc0);
+}
diff --git a/lib/std/hash/crc/impl.zig b/lib/std/hash/crc/impl.zig
deleted file mode 100644
index 6638d13d806bb51e1ff4f4f3c48221130a1bab38..0000000000000000000000000000000000000000
--- a/lib/std/hash/crc/impl.zig
+++ /dev/null
@@ -1,102 +0,0 @@
-// There is a generic CRC implementation "Crc()" which can be parameterized via
-// the Algorithm struct for a plethora of uses.
-//
-// The primary interface for all of the standard CRC algorithms is the
-// generated file "crc.zig", which uses the implementation code here to define
-// many standard CRCs.
-
-const std = @import("std");
-
-pub fn Algorithm(comptime W: type) type {
- return struct {
- polynomial: W,
- initial: W,
- reflect_input: bool,
- reflect_output: bool,
- xor_output: W,
- };
-}
-
-pub fn Crc(comptime W: type, comptime algorithm: Algorithm(W)) type {
- return struct {
- const Self = @This();
- const I = if (@bitSizeOf(W) < 8) u8 else W;
- const lookup_table = blk: {
- @setEvalBranchQuota(2500);
-
- const poly = if (algorithm.reflect_input)
- @bitReverse(@as(I, algorithm.polynomial)) >> (@bitSizeOf(I) - @bitSizeOf(W))
- else
- @as(I, algorithm.polynomial) << (@bitSizeOf(I) - @bitSizeOf(W));
-
- var table: [256]I = undefined;
- for (&table, 0..) |*e, i| {
- var crc: I = i;
- if (algorithm.reflect_input) {
- var j: usize = 0;
- while (j < 8) : (j += 1) {
- crc = (crc >> 1) ^ ((crc & 1) * poly);
- }
- } else {
- crc <<= @bitSizeOf(I) - 8;
- var j: usize = 0;
- while (j < 8) : (j += 1) {
- crc = (crc << 1) ^ (((crc >> (@bitSizeOf(I) - 1)) & 1) * poly);
- }
- }
- e.* = crc;
- }
- break :blk table;
- };
-
- crc: I,
-
- pub fn init() Self {
- const initial = if (algorithm.reflect_input)
- @bitReverse(@as(I, algorithm.initial)) >> (@bitSizeOf(I) - @bitSizeOf(W))
- else
- @as(I, algorithm.initial) << (@bitSizeOf(I) - @bitSizeOf(W));
- return Self{ .crc = initial };
- }
-
- inline fn tableEntry(index: I) I {
- return lookup_table[@as(u8, @intCast(index & 0xFF))];
- }
-
- pub fn update(self: *Self, bytes: []const u8) void {
- var i: usize = 0;
- if (@bitSizeOf(I) <= 8) {
- while (i < bytes.len) : (i += 1) {
- self.crc = tableEntry(self.crc ^ bytes[i]);
- }
- } else if (algorithm.reflect_input) {
- while (i < bytes.len) : (i += 1) {
- const table_index = self.crc ^ bytes[i];
- self.crc = tableEntry(table_index) ^ (self.crc >> 8);
- }
- } else {
- while (i < bytes.len) : (i += 1) {
- const table_index = (self.crc >> (@bitSizeOf(I) - 8)) ^ bytes[i];
- self.crc = tableEntry(table_index) ^ (self.crc << 8);
- }
- }
- }
-
- pub fn final(self: Self) W {
- var c = self.crc;
- if (algorithm.reflect_input != algorithm.reflect_output) {
- c = @bitReverse(c);
- }
- if (!algorithm.reflect_output) {
- c >>= @bitSizeOf(I) - @bitSizeOf(W);
- }
- return @as(W, @intCast(c ^ algorithm.xor_output));
- }
-
- pub fn hash(bytes: []const u8) W {
- var c = Self.init();
- c.update(bytes);
- return c.final();
- }
- };
-}
diff --git a/lib/std/hash/crc/test.zig b/lib/std/hash/crc/test.zig
index a6c2641853e01b0653f86a1202ba701adb8bd30b..68183d1050b37133d19663971357f32f53284267 100644
--- a/lib/std/hash/crc/test.zig
+++ b/lib/std/hash/crc/test.zig
@@ -6,1264 +6,1264 @@ const verify = @import("../verify.zig");
const crc = @import("../crc.zig");
test "crc32 ieee regression" {
- const crc32 = crc.Crc32IsoHdlc;
- try testing.expectEqual(crc32.hash(""), 0x00000000);
- try testing.expectEqual(crc32.hash("a"), 0xe8b7be43);
- try testing.expectEqual(crc32.hash("abc"), 0x352441c2);
+ const Crc = crc.@"CRC-32/ISO-HDLC";
+ try testing.expectEqual(Crc.hash(""), 0x00000000);
+ try testing.expectEqual(Crc.hash("a"), 0xe8b7be43);
+ try testing.expectEqual(Crc.hash("abc"), 0x352441c2);
}
test "crc32 castagnoli regression" {
- const crc32 = crc.Crc32Iscsi;
- try testing.expectEqual(crc32.hash(""), 0x00000000);
- try testing.expectEqual(crc32.hash("a"), 0xc1d04330);
- try testing.expectEqual(crc32.hash("abc"), 0x364b3fb7);
+ const Crc = crc.@"CRC-32/ISCSI";
+ try testing.expectEqual(Crc.hash(""), 0x00000000);
+ try testing.expectEqual(Crc.hash("a"), 0xc1d04330);
+ try testing.expectEqual(Crc.hash("abc"), 0x364b3fb7);
}
test "crc32 koopman regression" {
- const crc32 = crc.Crc32Koopman;
- try testing.expectEqual(crc32.hash(""), 0x00000000);
- try testing.expectEqual(crc32.hash("a"), 0x0da2aa8a);
- try testing.expectEqual(crc32.hash("abc"), 0xba2322ac);
+ const Crc = crc.@"CRC-32/KOOPMAN";
+ try testing.expectEqual(Crc.hash(""), 0x00000000);
+ try testing.expectEqual(Crc.hash("a"), 0x0da2aa8a);
+ try testing.expectEqual(Crc.hash("abc"), 0xba2322ac);
}
test "CRC-3/GSM" {
- const Crc3Gsm = crc.Crc3Gsm;
+ const Crc = crc.@"CRC-3/GSM";
- try testing.expectEqual(@as(u3, 0x4), Crc3Gsm.hash("123456789"));
+ try testing.expectEqual(@as(u3, 0x4), Crc.hash("123456789"));
- var c = Crc3Gsm.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u3, 0x4), c.final());
}
test "CRC-3/ROHC" {
- const Crc3Rohc = crc.Crc3Rohc;
+ const Crc = crc.@"CRC-3/ROHC";
- try testing.expectEqual(@as(u3, 0x6), Crc3Rohc.hash("123456789"));
+ try testing.expectEqual(@as(u3, 0x6), Crc.hash("123456789"));
- var c = Crc3Rohc.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u3, 0x6), c.final());
}
test "CRC-4/G-704" {
- const Crc4G704 = crc.Crc4G704;
+ const Crc = crc.@"CRC-4/G-704";
- try testing.expectEqual(@as(u4, 0x7), Crc4G704.hash("123456789"));
+ try testing.expectEqual(@as(u4, 0x7), Crc.hash("123456789"));
- var c = Crc4G704.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u4, 0x7), c.final());
}
test "CRC-4/INTERLAKEN" {
- const Crc4Interlaken = crc.Crc4Interlaken;
+ const Crc = crc.@"CRC-4/INTERLAKEN";
- try testing.expectEqual(@as(u4, 0xb), Crc4Interlaken.hash("123456789"));
+ try testing.expectEqual(@as(u4, 0xb), Crc.hash("123456789"));
- var c = Crc4Interlaken.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u4, 0xb), c.final());
}
test "CRC-5/EPC-C1G2" {
- const Crc5EpcC1g2 = crc.Crc5EpcC1g2;
+ const Crc = crc.@"CRC-5/EPC-C1G2";
- try testing.expectEqual(@as(u5, 0x00), Crc5EpcC1g2.hash("123456789"));
+ try testing.expectEqual(@as(u5, 0x00), Crc.hash("123456789"));
- var c = Crc5EpcC1g2.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u5, 0x00), c.final());
}
test "CRC-5/G-704" {
- const Crc5G704 = crc.Crc5G704;
+ const Crc = crc.@"CRC-5/G-704";
- try testing.expectEqual(@as(u5, 0x07), Crc5G704.hash("123456789"));
+ try testing.expectEqual(@as(u5, 0x07), Crc.hash("123456789"));
- var c = Crc5G704.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u5, 0x07), c.final());
}
test "CRC-5/USB" {
- const Crc5Usb = crc.Crc5Usb;
+ const Crc = crc.@"CRC-5/USB";
- try testing.expectEqual(@as(u5, 0x19), Crc5Usb.hash("123456789"));
+ try testing.expectEqual(@as(u5, 0x19), Crc.hash("123456789"));
- var c = Crc5Usb.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u5, 0x19), c.final());
}
test "CRC-6/CDMA2000-A" {
- const Crc6Cdma2000A = crc.Crc6Cdma2000A;
+ const Crc = crc.@"CRC-6/CDMA2000-A";
- try testing.expectEqual(@as(u6, 0x0d), Crc6Cdma2000A.hash("123456789"));
+ try testing.expectEqual(@as(u6, 0x0d), Crc.hash("123456789"));
- var c = Crc6Cdma2000A.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u6, 0x0d), c.final());
}
test "CRC-6/CDMA2000-B" {
- const Crc6Cdma2000B = crc.Crc6Cdma2000B;
+ const Crc = crc.@"CRC-6/CDMA2000-B";
- try testing.expectEqual(@as(u6, 0x3b), Crc6Cdma2000B.hash("123456789"));
+ try testing.expectEqual(@as(u6, 0x3b), Crc.hash("123456789"));
- var c = Crc6Cdma2000B.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u6, 0x3b), c.final());
}
test "CRC-6/DARC" {
- const Crc6Darc = crc.Crc6Darc;
+ const Crc = crc.@"CRC-6/DARC";
- try testing.expectEqual(@as(u6, 0x26), Crc6Darc.hash("123456789"));
+ try testing.expectEqual(@as(u6, 0x26), Crc.hash("123456789"));
- var c = Crc6Darc.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u6, 0x26), c.final());
}
test "CRC-6/G-704" {
- const Crc6G704 = crc.Crc6G704;
+ const Crc = crc.@"CRC-6/G-704";
- try testing.expectEqual(@as(u6, 0x06), Crc6G704.hash("123456789"));
+ try testing.expectEqual(@as(u6, 0x06), Crc.hash("123456789"));
- var c = Crc6G704.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u6, 0x06), c.final());
}
test "CRC-6/GSM" {
- const Crc6Gsm = crc.Crc6Gsm;
+ const Crc = crc.@"CRC-6/GSM";
- try testing.expectEqual(@as(u6, 0x13), Crc6Gsm.hash("123456789"));
+ try testing.expectEqual(@as(u6, 0x13), Crc.hash("123456789"));
- var c = Crc6Gsm.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u6, 0x13), c.final());
}
test "CRC-7/MMC" {
- const Crc7Mmc = crc.Crc7Mmc;
+ const Crc = crc.@"CRC-7/MMC";
- try testing.expectEqual(@as(u7, 0x75), Crc7Mmc.hash("123456789"));
+ try testing.expectEqual(@as(u7, 0x75), Crc.hash("123456789"));
- var c = Crc7Mmc.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u7, 0x75), c.final());
}
test "CRC-7/ROHC" {
- const Crc7Rohc = crc.Crc7Rohc;
+ const Crc = crc.@"CRC-7/ROHC";
- try testing.expectEqual(@as(u7, 0x53), Crc7Rohc.hash("123456789"));
+ try testing.expectEqual(@as(u7, 0x53), Crc.hash("123456789"));
- var c = Crc7Rohc.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u7, 0x53), c.final());
}
test "CRC-7/UMTS" {
- const Crc7Umts = crc.Crc7Umts;
+ const Crc = crc.@"CRC-7/UMTS";
- try testing.expectEqual(@as(u7, 0x61), Crc7Umts.hash("123456789"));
+ try testing.expectEqual(@as(u7, 0x61), Crc.hash("123456789"));
- var c = Crc7Umts.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u7, 0x61), c.final());
}
test "CRC-8/AUTOSAR" {
- const Crc8Autosar = crc.Crc8Autosar;
+ const Crc = crc.@"CRC-8/AUTOSAR";
- try testing.expectEqual(@as(u8, 0xdf), Crc8Autosar.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0xdf), Crc.hash("123456789"));
- var c = Crc8Autosar.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0xdf), c.final());
}
test "CRC-8/BLUETOOTH" {
- const Crc8Bluetooth = crc.Crc8Bluetooth;
+ const Crc = crc.@"CRC-8/BLUETOOTH";
- try testing.expectEqual(@as(u8, 0x26), Crc8Bluetooth.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0x26), Crc.hash("123456789"));
- var c = Crc8Bluetooth.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0x26), c.final());
}
test "CRC-8/CDMA2000" {
- const Crc8Cdma2000 = crc.Crc8Cdma2000;
+ const Crc = crc.@"CRC-8/CDMA2000";
- try testing.expectEqual(@as(u8, 0xda), Crc8Cdma2000.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0xda), Crc.hash("123456789"));
- var c = Crc8Cdma2000.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0xda), c.final());
}
test "CRC-8/DARC" {
- const Crc8Darc = crc.Crc8Darc;
+ const Crc = crc.@"CRC-8/DARC";
- try testing.expectEqual(@as(u8, 0x15), Crc8Darc.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0x15), Crc.hash("123456789"));
- var c = Crc8Darc.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0x15), c.final());
}
test "CRC-8/DVB-S2" {
- const Crc8DvbS2 = crc.Crc8DvbS2;
+ const Crc = crc.@"CRC-8/DVB-S2";
- try testing.expectEqual(@as(u8, 0xbc), Crc8DvbS2.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0xbc), Crc.hash("123456789"));
- var c = Crc8DvbS2.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0xbc), c.final());
}
test "CRC-8/GSM-A" {
- const Crc8GsmA = crc.Crc8GsmA;
+ const Crc = crc.@"CRC-8/GSM-A";
- try testing.expectEqual(@as(u8, 0x37), Crc8GsmA.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0x37), Crc.hash("123456789"));
- var c = Crc8GsmA.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0x37), c.final());
}
test "CRC-8/GSM-B" {
- const Crc8GsmB = crc.Crc8GsmB;
+ const Crc = crc.@"CRC-8/GSM-B";
- try testing.expectEqual(@as(u8, 0x94), Crc8GsmB.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0x94), Crc.hash("123456789"));
- var c = Crc8GsmB.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0x94), c.final());
}
test "CRC-8/HITAG" {
- const Crc8Hitag = crc.Crc8Hitag;
+ const Crc = crc.@"CRC-8/HITAG";
- try testing.expectEqual(@as(u8, 0xb4), Crc8Hitag.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0xb4), Crc.hash("123456789"));
- var c = Crc8Hitag.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0xb4), c.final());
}
test "CRC-8/I-432-1" {
- const Crc8I4321 = crc.Crc8I4321;
+ const Crc = crc.@"CRC-8/I-432-1";
- try testing.expectEqual(@as(u8, 0xa1), Crc8I4321.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0xa1), Crc.hash("123456789"));
- var c = Crc8I4321.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0xa1), c.final());
}
test "CRC-8/I-CODE" {
- const Crc8ICode = crc.Crc8ICode;
+ const Crc = crc.@"CRC-8/I-CODE";
- try testing.expectEqual(@as(u8, 0x7e), Crc8ICode.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0x7e), Crc.hash("123456789"));
- var c = Crc8ICode.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0x7e), c.final());
}
test "CRC-8/LTE" {
- const Crc8Lte = crc.Crc8Lte;
+ const Crc = crc.@"CRC-8/LTE";
- try testing.expectEqual(@as(u8, 0xea), Crc8Lte.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0xea), Crc.hash("123456789"));
- var c = Crc8Lte.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0xea), c.final());
}
test "CRC-8/MAXIM-DOW" {
- const Crc8MaximDow = crc.Crc8MaximDow;
+ const Crc = crc.@"CRC-8/MAXIM-DOW";
- try testing.expectEqual(@as(u8, 0xa1), Crc8MaximDow.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0xa1), Crc.hash("123456789"));
- var c = Crc8MaximDow.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0xa1), c.final());
}
test "CRC-8/MIFARE-MAD" {
- const Crc8MifareMad = crc.Crc8MifareMad;
+ const Crc = crc.@"CRC-8/MIFARE-MAD";
- try testing.expectEqual(@as(u8, 0x99), Crc8MifareMad.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0x99), Crc.hash("123456789"));
- var c = Crc8MifareMad.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0x99), c.final());
}
test "CRC-8/NRSC-5" {
- const Crc8Nrsc5 = crc.Crc8Nrsc5;
+ const Crc = crc.@"CRC-8/NRSC-5";
- try testing.expectEqual(@as(u8, 0xf7), Crc8Nrsc5.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0xf7), Crc.hash("123456789"));
- var c = Crc8Nrsc5.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0xf7), c.final());
}
test "CRC-8/OPENSAFETY" {
- const Crc8Opensafety = crc.Crc8Opensafety;
+ const Crc = crc.@"CRC-8/OPENSAFETY";
- try testing.expectEqual(@as(u8, 0x3e), Crc8Opensafety.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0x3e), Crc.hash("123456789"));
- var c = Crc8Opensafety.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0x3e), c.final());
}
test "CRC-8/ROHC" {
- const Crc8Rohc = crc.Crc8Rohc;
+ const Crc = crc.@"CRC-8/ROHC";
- try testing.expectEqual(@as(u8, 0xd0), Crc8Rohc.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0xd0), Crc.hash("123456789"));
- var c = Crc8Rohc.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0xd0), c.final());
}
test "CRC-8/SAE-J1850" {
- const Crc8SaeJ1850 = crc.Crc8SaeJ1850;
+ const Crc = crc.@"CRC-8/SAE-J1850";
- try testing.expectEqual(@as(u8, 0x4b), Crc8SaeJ1850.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0x4b), Crc.hash("123456789"));
- var c = Crc8SaeJ1850.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0x4b), c.final());
}
test "CRC-8/SMBUS" {
- const Crc8Smbus = crc.Crc8Smbus;
+ const Crc = crc.@"CRC-8/SMBUS";
- try testing.expectEqual(@as(u8, 0xf4), Crc8Smbus.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0xf4), Crc.hash("123456789"));
- var c = Crc8Smbus.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0xf4), c.final());
}
test "CRC-8/TECH-3250" {
- const Crc8Tech3250 = crc.Crc8Tech3250;
+ const Crc = crc.@"CRC-8/TECH-3250";
- try testing.expectEqual(@as(u8, 0x97), Crc8Tech3250.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0x97), Crc.hash("123456789"));
- var c = Crc8Tech3250.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0x97), c.final());
}
test "CRC-8/WCDMA" {
- const Crc8Wcdma = crc.Crc8Wcdma;
+ const Crc = crc.@"CRC-8/WCDMA";
- try testing.expectEqual(@as(u8, 0x25), Crc8Wcdma.hash("123456789"));
+ try testing.expectEqual(@as(u8, 0x25), Crc.hash("123456789"));
- var c = Crc8Wcdma.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u8, 0x25), c.final());
}
test "CRC-10/ATM" {
- const Crc10Atm = crc.Crc10Atm;
+ const Crc = crc.@"CRC-10/ATM";
- try testing.expectEqual(@as(u10, 0x199), Crc10Atm.hash("123456789"));
+ try testing.expectEqual(@as(u10, 0x199), Crc.hash("123456789"));
- var c = Crc10Atm.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u10, 0x199), c.final());
}
test "CRC-10/CDMA2000" {
- const Crc10Cdma2000 = crc.Crc10Cdma2000;
+ const Crc = crc.@"CRC-10/CDMA2000";
- try testing.expectEqual(@as(u10, 0x233), Crc10Cdma2000.hash("123456789"));
+ try testing.expectEqual(@as(u10, 0x233), Crc.hash("123456789"));
- var c = Crc10Cdma2000.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u10, 0x233), c.final());
}
test "CRC-10/GSM" {
- const Crc10Gsm = crc.Crc10Gsm;
+ const Crc = crc.@"CRC-10/GSM";
- try testing.expectEqual(@as(u10, 0x12a), Crc10Gsm.hash("123456789"));
+ try testing.expectEqual(@as(u10, 0x12a), Crc.hash("123456789"));
- var c = Crc10Gsm.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u10, 0x12a), c.final());
}
test "CRC-11/FLEXRAY" {
- const Crc11Flexray = crc.Crc11Flexray;
+ const Crc = crc.@"CRC-11/FLEXRAY";
- try testing.expectEqual(@as(u11, 0x5a3), Crc11Flexray.hash("123456789"));
+ try testing.expectEqual(@as(u11, 0x5a3), Crc.hash("123456789"));
- var c = Crc11Flexray.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u11, 0x5a3), c.final());
}
test "CRC-11/UMTS" {
- const Crc11Umts = crc.Crc11Umts;
+ const Crc = crc.@"CRC-11/UMTS";
- try testing.expectEqual(@as(u11, 0x061), Crc11Umts.hash("123456789"));
+ try testing.expectEqual(@as(u11, 0x061), Crc.hash("123456789"));
- var c = Crc11Umts.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u11, 0x061), c.final());
}
test "CRC-12/CDMA2000" {
- const Crc12Cdma2000 = crc.Crc12Cdma2000;
+ const Crc = crc.@"CRC-12/CDMA2000";
- try testing.expectEqual(@as(u12, 0xd4d), Crc12Cdma2000.hash("123456789"));
+ try testing.expectEqual(@as(u12, 0xd4d), Crc.hash("123456789"));
- var c = Crc12Cdma2000.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u12, 0xd4d), c.final());
}
test "CRC-12/DECT" {
- const Crc12Dect = crc.Crc12Dect;
+ const Crc = crc.@"CRC-12/DECT";
- try testing.expectEqual(@as(u12, 0xf5b), Crc12Dect.hash("123456789"));
+ try testing.expectEqual(@as(u12, 0xf5b), Crc.hash("123456789"));
- var c = Crc12Dect.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u12, 0xf5b), c.final());
}
test "CRC-12/GSM" {
- const Crc12Gsm = crc.Crc12Gsm;
+ const Crc = crc.@"CRC-12/GSM";
- try testing.expectEqual(@as(u12, 0xb34), Crc12Gsm.hash("123456789"));
+ try testing.expectEqual(@as(u12, 0xb34), Crc.hash("123456789"));
- var c = Crc12Gsm.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u12, 0xb34), c.final());
}
test "CRC-12/UMTS" {
- const Crc12Umts = crc.Crc12Umts;
+ const Crc = crc.@"CRC-12/UMTS";
- try testing.expectEqual(@as(u12, 0xdaf), Crc12Umts.hash("123456789"));
+ try testing.expectEqual(@as(u12, 0xdaf), Crc.hash("123456789"));
- var c = Crc12Umts.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u12, 0xdaf), c.final());
}
test "CRC-13/BBC" {
- const Crc13Bbc = crc.Crc13Bbc;
+ const Crc = crc.@"CRC-13/BBC";
- try testing.expectEqual(@as(u13, 0x04fa), Crc13Bbc.hash("123456789"));
+ try testing.expectEqual(@as(u13, 0x04fa), Crc.hash("123456789"));
- var c = Crc13Bbc.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u13, 0x04fa), c.final());
}
test "CRC-14/DARC" {
- const Crc14Darc = crc.Crc14Darc;
+ const Crc = crc.@"CRC-14/DARC";
- try testing.expectEqual(@as(u14, 0x082d), Crc14Darc.hash("123456789"));
+ try testing.expectEqual(@as(u14, 0x082d), Crc.hash("123456789"));
- var c = Crc14Darc.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u14, 0x082d), c.final());
}
test "CRC-14/GSM" {
- const Crc14Gsm = crc.Crc14Gsm;
+ const Crc = crc.@"CRC-14/GSM";
- try testing.expectEqual(@as(u14, 0x30ae), Crc14Gsm.hash("123456789"));
+ try testing.expectEqual(@as(u14, 0x30ae), Crc.hash("123456789"));
- var c = Crc14Gsm.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u14, 0x30ae), c.final());
}
test "CRC-15/CAN" {
- const Crc15Can = crc.Crc15Can;
+ const Crc = crc.@"CRC-15/CAN";
- try testing.expectEqual(@as(u15, 0x059e), Crc15Can.hash("123456789"));
+ try testing.expectEqual(@as(u15, 0x059e), Crc.hash("123456789"));
- var c = Crc15Can.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u15, 0x059e), c.final());
}
test "CRC-15/MPT1327" {
- const Crc15Mpt1327 = crc.Crc15Mpt1327;
+ const Crc = crc.@"CRC-15/MPT1327";
- try testing.expectEqual(@as(u15, 0x2566), Crc15Mpt1327.hash("123456789"));
+ try testing.expectEqual(@as(u15, 0x2566), Crc.hash("123456789"));
- var c = Crc15Mpt1327.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u15, 0x2566), c.final());
}
test "CRC-16/ARC" {
- const Crc16Arc = crc.Crc16Arc;
+ const Crc = crc.@"CRC-16/ARC";
- try testing.expectEqual(@as(u16, 0xbb3d), Crc16Arc.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0xbb3d), Crc.hash("123456789"));
- var c = Crc16Arc.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0xbb3d), c.final());
}
test "CRC-16/CDMA2000" {
- const Crc16Cdma2000 = crc.Crc16Cdma2000;
+ const Crc = crc.@"CRC-16/CDMA2000";
- try testing.expectEqual(@as(u16, 0x4c06), Crc16Cdma2000.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x4c06), Crc.hash("123456789"));
- var c = Crc16Cdma2000.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x4c06), c.final());
}
test "CRC-16/CMS" {
- const Crc16Cms = crc.Crc16Cms;
+ const Crc = crc.@"CRC-16/CMS";
- try testing.expectEqual(@as(u16, 0xaee7), Crc16Cms.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0xaee7), Crc.hash("123456789"));
- var c = Crc16Cms.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0xaee7), c.final());
}
test "CRC-16/DDS-110" {
- const Crc16Dds110 = crc.Crc16Dds110;
+ const Crc = crc.@"CRC-16/DDS-110";
- try testing.expectEqual(@as(u16, 0x9ecf), Crc16Dds110.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x9ecf), Crc.hash("123456789"));
- var c = Crc16Dds110.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x9ecf), c.final());
}
test "CRC-16/DECT-R" {
- const Crc16DectR = crc.Crc16DectR;
+ const Crc = crc.@"CRC-16/DECT-R";
- try testing.expectEqual(@as(u16, 0x007e), Crc16DectR.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x007e), Crc.hash("123456789"));
- var c = Crc16DectR.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x007e), c.final());
}
test "CRC-16/DECT-X" {
- const Crc16DectX = crc.Crc16DectX;
+ const Crc = crc.@"CRC-16/DECT-X";
- try testing.expectEqual(@as(u16, 0x007f), Crc16DectX.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x007f), Crc.hash("123456789"));
- var c = Crc16DectX.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x007f), c.final());
}
test "CRC-16/DNP" {
- const Crc16Dnp = crc.Crc16Dnp;
+ const Crc = crc.@"CRC-16/DNP";
- try testing.expectEqual(@as(u16, 0xea82), Crc16Dnp.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0xea82), Crc.hash("123456789"));
- var c = Crc16Dnp.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0xea82), c.final());
}
test "CRC-16/EN-13757" {
- const Crc16En13757 = crc.Crc16En13757;
+ const Crc = crc.@"CRC-16/EN-13757";
- try testing.expectEqual(@as(u16, 0xc2b7), Crc16En13757.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0xc2b7), Crc.hash("123456789"));
- var c = Crc16En13757.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0xc2b7), c.final());
}
test "CRC-16/GENIBUS" {
- const Crc16Genibus = crc.Crc16Genibus;
+ const Crc = crc.@"CRC-16/GENIBUS";
- try testing.expectEqual(@as(u16, 0xd64e), Crc16Genibus.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0xd64e), Crc.hash("123456789"));
- var c = Crc16Genibus.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0xd64e), c.final());
}
test "CRC-16/GSM" {
- const Crc16Gsm = crc.Crc16Gsm;
+ const Crc = crc.@"CRC-16/GSM";
- try testing.expectEqual(@as(u16, 0xce3c), Crc16Gsm.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0xce3c), Crc.hash("123456789"));
- var c = Crc16Gsm.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0xce3c), c.final());
}
test "CRC-16/IBM-3740" {
- const Crc16Ibm3740 = crc.Crc16Ibm3740;
+ const Crc = crc.@"CRC-16/IBM-3740";
- try testing.expectEqual(@as(u16, 0x29b1), Crc16Ibm3740.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x29b1), Crc.hash("123456789"));
- var c = Crc16Ibm3740.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x29b1), c.final());
}
test "CRC-16/IBM-SDLC" {
- const Crc16IbmSdlc = crc.Crc16IbmSdlc;
+ const Crc = crc.@"CRC-16/IBM-SDLC";
- try testing.expectEqual(@as(u16, 0x906e), Crc16IbmSdlc.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x906e), Crc.hash("123456789"));
- var c = Crc16IbmSdlc.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x906e), c.final());
}
test "CRC-16/ISO-IEC-14443-3-A" {
- const Crc16IsoIec144433A = crc.Crc16IsoIec144433A;
+ const Crc = crc.@"CRC-16/ISO-IEC-14443-3-A";
- try testing.expectEqual(@as(u16, 0xbf05), Crc16IsoIec144433A.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0xbf05), Crc.hash("123456789"));
- var c = Crc16IsoIec144433A.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0xbf05), c.final());
}
test "CRC-16/KERMIT" {
- const Crc16Kermit = crc.Crc16Kermit;
+ const Crc = crc.@"CRC-16/KERMIT";
- try testing.expectEqual(@as(u16, 0x2189), Crc16Kermit.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x2189), Crc.hash("123456789"));
- var c = Crc16Kermit.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x2189), c.final());
}
test "CRC-16/LJ1200" {
- const Crc16Lj1200 = crc.Crc16Lj1200;
+ const Crc = crc.@"CRC-16/LJ1200";
- try testing.expectEqual(@as(u16, 0xbdf4), Crc16Lj1200.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0xbdf4), Crc.hash("123456789"));
- var c = Crc16Lj1200.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0xbdf4), c.final());
}
test "CRC-16/M17" {
- const Crc16M17 = crc.Crc16M17;
+ const Crc = crc.@"CRC-16/M17";
- try testing.expectEqual(@as(u16, 0x772b), Crc16M17.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x772b), Crc.hash("123456789"));
- var c = Crc16M17.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x772b), c.final());
}
test "CRC-16/MAXIM-DOW" {
- const Crc16MaximDow = crc.Crc16MaximDow;
+ const Crc = crc.@"CRC-16/MAXIM-DOW";
- try testing.expectEqual(@as(u16, 0x44c2), Crc16MaximDow.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x44c2), Crc.hash("123456789"));
- var c = Crc16MaximDow.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x44c2), c.final());
}
test "CRC-16/MCRF4XX" {
- const Crc16Mcrf4xx = crc.Crc16Mcrf4xx;
+ const Crc = crc.@"CRC-16/MCRF4XX";
- try testing.expectEqual(@as(u16, 0x6f91), Crc16Mcrf4xx.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x6f91), Crc.hash("123456789"));
- var c = Crc16Mcrf4xx.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x6f91), c.final());
}
test "CRC-16/MODBUS" {
- const Crc16Modbus = crc.Crc16Modbus;
+ const Crc = crc.@"CRC-16/MODBUS";
- try testing.expectEqual(@as(u16, 0x4b37), Crc16Modbus.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x4b37), Crc.hash("123456789"));
- var c = Crc16Modbus.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x4b37), c.final());
}
test "CRC-16/NRSC-5" {
- const Crc16Nrsc5 = crc.Crc16Nrsc5;
+ const Crc = crc.@"CRC-16/NRSC-5";
- try testing.expectEqual(@as(u16, 0xa066), Crc16Nrsc5.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0xa066), Crc.hash("123456789"));
- var c = Crc16Nrsc5.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0xa066), c.final());
}
test "CRC-16/OPENSAFETY-A" {
- const Crc16OpensafetyA = crc.Crc16OpensafetyA;
+ const Crc = crc.@"CRC-16/OPENSAFETY-A";
- try testing.expectEqual(@as(u16, 0x5d38), Crc16OpensafetyA.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x5d38), Crc.hash("123456789"));
- var c = Crc16OpensafetyA.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x5d38), c.final());
}
test "CRC-16/OPENSAFETY-B" {
- const Crc16OpensafetyB = crc.Crc16OpensafetyB;
+ const Crc = crc.@"CRC-16/OPENSAFETY-B";
- try testing.expectEqual(@as(u16, 0x20fe), Crc16OpensafetyB.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x20fe), Crc.hash("123456789"));
- var c = Crc16OpensafetyB.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x20fe), c.final());
}
test "CRC-16/PROFIBUS" {
- const Crc16Profibus = crc.Crc16Profibus;
+ const Crc = crc.@"CRC-16/PROFIBUS";
- try testing.expectEqual(@as(u16, 0xa819), Crc16Profibus.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0xa819), Crc.hash("123456789"));
- var c = Crc16Profibus.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0xa819), c.final());
}
test "CRC-16/RIELLO" {
- const Crc16Riello = crc.Crc16Riello;
+ const Crc = crc.@"CRC-16/RIELLO";
- try testing.expectEqual(@as(u16, 0x63d0), Crc16Riello.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x63d0), Crc.hash("123456789"));
- var c = Crc16Riello.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x63d0), c.final());
}
test "CRC-16/SPI-FUJITSU" {
- const Crc16SpiFujitsu = crc.Crc16SpiFujitsu;
+ const Crc = crc.@"CRC-16/SPI-FUJITSU";
- try testing.expectEqual(@as(u16, 0xe5cc), Crc16SpiFujitsu.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0xe5cc), Crc.hash("123456789"));
- var c = Crc16SpiFujitsu.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0xe5cc), c.final());
}
test "CRC-16/T10-DIF" {
- const Crc16T10Dif = crc.Crc16T10Dif;
+ const Crc = crc.@"CRC-16/T10-DIF";
- try testing.expectEqual(@as(u16, 0xd0db), Crc16T10Dif.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0xd0db), Crc.hash("123456789"));
- var c = Crc16T10Dif.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0xd0db), c.final());
}
test "CRC-16/TELEDISK" {
- const Crc16Teledisk = crc.Crc16Teledisk;
+ const Crc = crc.@"CRC-16/TELEDISK";
- try testing.expectEqual(@as(u16, 0x0fb3), Crc16Teledisk.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x0fb3), Crc.hash("123456789"));
- var c = Crc16Teledisk.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x0fb3), c.final());
}
test "CRC-16/TMS37157" {
- const Crc16Tms37157 = crc.Crc16Tms37157;
+ const Crc = crc.@"CRC-16/TMS37157";
- try testing.expectEqual(@as(u16, 0x26b1), Crc16Tms37157.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x26b1), Crc.hash("123456789"));
- var c = Crc16Tms37157.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x26b1), c.final());
}
test "CRC-16/UMTS" {
- const Crc16Umts = crc.Crc16Umts;
+ const Crc = crc.@"CRC-16/UMTS";
- try testing.expectEqual(@as(u16, 0xfee8), Crc16Umts.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0xfee8), Crc.hash("123456789"));
- var c = Crc16Umts.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0xfee8), c.final());
}
test "CRC-16/USB" {
- const Crc16Usb = crc.Crc16Usb;
+ const Crc = crc.@"CRC-16/USB";
- try testing.expectEqual(@as(u16, 0xb4c8), Crc16Usb.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0xb4c8), Crc.hash("123456789"));
- var c = Crc16Usb.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0xb4c8), c.final());
}
test "CRC-16/XMODEM" {
- const Crc16Xmodem = crc.Crc16Xmodem;
+ const Crc = crc.@"CRC-16/XMODEM";
- try testing.expectEqual(@as(u16, 0x31c3), Crc16Xmodem.hash("123456789"));
+ try testing.expectEqual(@as(u16, 0x31c3), Crc.hash("123456789"));
- var c = Crc16Xmodem.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u16, 0x31c3), c.final());
}
test "CRC-17/CAN-FD" {
- const Crc17CanFd = crc.Crc17CanFd;
+ const Crc = crc.@"CRC-17/CAN-FD";
- try testing.expectEqual(@as(u17, 0x04f03), Crc17CanFd.hash("123456789"));
+ try testing.expectEqual(@as(u17, 0x04f03), Crc.hash("123456789"));
- var c = Crc17CanFd.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u17, 0x04f03), c.final());
}
test "CRC-21/CAN-FD" {
- const Crc21CanFd = crc.Crc21CanFd;
+ const Crc = crc.@"CRC-21/CAN-FD";
- try testing.expectEqual(@as(u21, 0x0ed841), Crc21CanFd.hash("123456789"));
+ try testing.expectEqual(@as(u21, 0x0ed841), Crc.hash("123456789"));
- var c = Crc21CanFd.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u21, 0x0ed841), c.final());
}
test "CRC-24/BLE" {
- const Crc24Ble = crc.Crc24Ble;
+ const Crc = crc.@"CRC-24/BLE";
- try testing.expectEqual(@as(u24, 0xc25a56), Crc24Ble.hash("123456789"));
+ try testing.expectEqual(@as(u24, 0xc25a56), Crc.hash("123456789"));
- var c = Crc24Ble.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u24, 0xc25a56), c.final());
}
test "CRC-24/FLEXRAY-A" {
- const Crc24FlexrayA = crc.Crc24FlexrayA;
+ const Crc = crc.@"CRC-24/FLEXRAY-A";
- try testing.expectEqual(@as(u24, 0x7979bd), Crc24FlexrayA.hash("123456789"));
+ try testing.expectEqual(@as(u24, 0x7979bd), Crc.hash("123456789"));
- var c = Crc24FlexrayA.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u24, 0x7979bd), c.final());
}
test "CRC-24/FLEXRAY-B" {
- const Crc24FlexrayB = crc.Crc24FlexrayB;
+ const Crc = crc.@"CRC-24/FLEXRAY-B";
- try testing.expectEqual(@as(u24, 0x1f23b8), Crc24FlexrayB.hash("123456789"));
+ try testing.expectEqual(@as(u24, 0x1f23b8), Crc.hash("123456789"));
- var c = Crc24FlexrayB.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u24, 0x1f23b8), c.final());
}
test "CRC-24/INTERLAKEN" {
- const Crc24Interlaken = crc.Crc24Interlaken;
+ const Crc = crc.@"CRC-24/INTERLAKEN";
- try testing.expectEqual(@as(u24, 0xb4f3e6), Crc24Interlaken.hash("123456789"));
+ try testing.expectEqual(@as(u24, 0xb4f3e6), Crc.hash("123456789"));
- var c = Crc24Interlaken.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u24, 0xb4f3e6), c.final());
}
test "CRC-24/LTE-A" {
- const Crc24LteA = crc.Crc24LteA;
+ const Crc = crc.@"CRC-24/LTE-A";
- try testing.expectEqual(@as(u24, 0xcde703), Crc24LteA.hash("123456789"));
+ try testing.expectEqual(@as(u24, 0xcde703), Crc.hash("123456789"));
- var c = Crc24LteA.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u24, 0xcde703), c.final());
}
test "CRC-24/LTE-B" {
- const Crc24LteB = crc.Crc24LteB;
+ const Crc = crc.@"CRC-24/LTE-B";
- try testing.expectEqual(@as(u24, 0x23ef52), Crc24LteB.hash("123456789"));
+ try testing.expectEqual(@as(u24, 0x23ef52), Crc.hash("123456789"));
- var c = Crc24LteB.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u24, 0x23ef52), c.final());
}
test "CRC-24/OPENPGP" {
- const Crc24Openpgp = crc.Crc24Openpgp;
+ const Crc = crc.@"CRC-24/OPENPGP";
- try testing.expectEqual(@as(u24, 0x21cf02), Crc24Openpgp.hash("123456789"));
+ try testing.expectEqual(@as(u24, 0x21cf02), Crc.hash("123456789"));
- var c = Crc24Openpgp.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u24, 0x21cf02), c.final());
}
test "CRC-24/OS-9" {
- const Crc24Os9 = crc.Crc24Os9;
+ const Crc = crc.@"CRC-24/OS-9";
- try testing.expectEqual(@as(u24, 0x200fa5), Crc24Os9.hash("123456789"));
+ try testing.expectEqual(@as(u24, 0x200fa5), Crc.hash("123456789"));
- var c = Crc24Os9.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u24, 0x200fa5), c.final());
}
test "CRC-30/CDMA" {
- const Crc30Cdma = crc.Crc30Cdma;
+ const Crc = crc.@"CRC-30/CDMA";
- try testing.expectEqual(@as(u30, 0x04c34abf), Crc30Cdma.hash("123456789"));
+ try testing.expectEqual(@as(u30, 0x04c34abf), Crc.hash("123456789"));
- var c = Crc30Cdma.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u30, 0x04c34abf), c.final());
}
test "CRC-31/PHILIPS" {
- const Crc31Philips = crc.Crc31Philips;
+ const Crc = crc.@"CRC-31/PHILIPS";
- try testing.expectEqual(@as(u31, 0x0ce9e46c), Crc31Philips.hash("123456789"));
+ try testing.expectEqual(@as(u31, 0x0ce9e46c), Crc.hash("123456789"));
- var c = Crc31Philips.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u31, 0x0ce9e46c), c.final());
}
test "CRC-32/AIXM" {
- const Crc32Aixm = crc.Crc32Aixm;
+ const Crc = crc.@"CRC-32/AIXM";
- try testing.expectEqual(@as(u32, 0x3010bf7f), Crc32Aixm.hash("123456789"));
+ try testing.expectEqual(@as(u32, 0x3010bf7f), Crc.hash("123456789"));
- var c = Crc32Aixm.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u32, 0x3010bf7f), c.final());
}
test "CRC-32/AUTOSAR" {
- const Crc32Autosar = crc.Crc32Autosar;
+ const Crc = crc.@"CRC-32/AUTOSAR";
- try testing.expectEqual(@as(u32, 0x1697d06a), Crc32Autosar.hash("123456789"));
+ try testing.expectEqual(@as(u32, 0x1697d06a), Crc.hash("123456789"));
- var c = Crc32Autosar.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u32, 0x1697d06a), c.final());
}
test "CRC-32/BASE91-D" {
- const Crc32Base91D = crc.Crc32Base91D;
+ const Crc = crc.@"CRC-32/BASE91-D";
- try testing.expectEqual(@as(u32, 0x87315576), Crc32Base91D.hash("123456789"));
+ try testing.expectEqual(@as(u32, 0x87315576), Crc.hash("123456789"));
- var c = Crc32Base91D.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u32, 0x87315576), c.final());
}
test "CRC-32/BZIP2" {
- const Crc32Bzip2 = crc.Crc32Bzip2;
+ const Crc = crc.@"CRC-32/BZIP2";
- try testing.expectEqual(@as(u32, 0xfc891918), Crc32Bzip2.hash("123456789"));
+ try testing.expectEqual(@as(u32, 0xfc891918), Crc.hash("123456789"));
- var c = Crc32Bzip2.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u32, 0xfc891918), c.final());
}
test "CRC-32/CD-ROM-EDC" {
- const Crc32CdRomEdc = crc.Crc32CdRomEdc;
+ const Crc = crc.@"CRC-32/CD-ROM-EDC";
- try testing.expectEqual(@as(u32, 0x6ec2edc4), Crc32CdRomEdc.hash("123456789"));
+ try testing.expectEqual(@as(u32, 0x6ec2edc4), Crc.hash("123456789"));
- var c = Crc32CdRomEdc.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u32, 0x6ec2edc4), c.final());
}
test "CRC-32/CKSUM" {
- const Crc32Cksum = crc.Crc32Cksum;
+ const Crc = crc.@"CRC-32/CKSUM";
- try testing.expectEqual(@as(u32, 0x765e7680), Crc32Cksum.hash("123456789"));
+ try testing.expectEqual(@as(u32, 0x765e7680), Crc.hash("123456789"));
- var c = Crc32Cksum.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u32, 0x765e7680), c.final());
}
test "CRC-32/ISCSI" {
- const Crc32Iscsi = crc.Crc32Iscsi;
+ const Crc = crc.@"CRC-32/ISCSI";
- try testing.expectEqual(@as(u32, 0xe3069283), Crc32Iscsi.hash("123456789"));
+ try testing.expectEqual(@as(u32, 0xe3069283), Crc.hash("123456789"));
- var c = Crc32Iscsi.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u32, 0xe3069283), c.final());
}
test "CRC-32/ISO-HDLC" {
- const Crc32IsoHdlc = crc.Crc32IsoHdlc;
+ const Crc = crc.@"CRC-32/ISO-HDLC";
- try testing.expectEqual(@as(u32, 0xcbf43926), Crc32IsoHdlc.hash("123456789"));
+ try testing.expectEqual(@as(u32, 0xcbf43926), Crc.hash("123456789"));
- var c = Crc32IsoHdlc.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u32, 0xcbf43926), c.final());
}
test "CRC-32/JAMCRC" {
- const Crc32Jamcrc = crc.Crc32Jamcrc;
+ const Crc = crc.@"CRC-32/JAMCRC";
- try testing.expectEqual(@as(u32, 0x340bc6d9), Crc32Jamcrc.hash("123456789"));
+ try testing.expectEqual(@as(u32, 0x340bc6d9), Crc.hash("123456789"));
- var c = Crc32Jamcrc.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u32, 0x340bc6d9), c.final());
}
test "CRC-32/KOOPMAN" {
- const Crc32Koopman = crc.Crc32Koopman;
+ const Crc = crc.@"CRC-32/KOOPMAN";
- try testing.expectEqual(@as(u32, 0x2d3dd0ae), Crc32Koopman.hash("123456789"));
+ try testing.expectEqual(@as(u32, 0x2d3dd0ae), Crc.hash("123456789"));
- var c = Crc32Koopman.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u32, 0x2d3dd0ae), c.final());
}
test "CRC-32/MEF" {
- const Crc32Mef = crc.Crc32Mef;
+ const Crc = crc.@"CRC-32/MEF";
- try testing.expectEqual(@as(u32, 0xd2c22f51), Crc32Mef.hash("123456789"));
+ try testing.expectEqual(@as(u32, 0xd2c22f51), Crc.hash("123456789"));
- var c = Crc32Mef.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u32, 0xd2c22f51), c.final());
}
test "CRC-32/MPEG-2" {
- const Crc32Mpeg2 = crc.Crc32Mpeg2;
+ const Crc = crc.@"CRC-32/MPEG-2";
- try testing.expectEqual(@as(u32, 0x0376e6e7), Crc32Mpeg2.hash("123456789"));
+ try testing.expectEqual(@as(u32, 0x0376e6e7), Crc.hash("123456789"));
- var c = Crc32Mpeg2.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u32, 0x0376e6e7), c.final());
}
test "CRC-32/XFER" {
- const Crc32Xfer = crc.Crc32Xfer;
+ const Crc = crc.@"CRC-32/XFER";
- try testing.expectEqual(@as(u32, 0xbd0be338), Crc32Xfer.hash("123456789"));
+ try testing.expectEqual(@as(u32, 0xbd0be338), Crc.hash("123456789"));
- var c = Crc32Xfer.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u32, 0xbd0be338), c.final());
}
test "CRC-40/GSM" {
- const Crc40Gsm = crc.Crc40Gsm;
+ const Crc = crc.@"CRC-40/GSM";
- try testing.expectEqual(@as(u40, 0xd4164fc646), Crc40Gsm.hash("123456789"));
+ try testing.expectEqual(@as(u40, 0xd4164fc646), Crc.hash("123456789"));
- var c = Crc40Gsm.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u40, 0xd4164fc646), c.final());
}
test "CRC-64/ECMA-182" {
- const Crc64Ecma182 = crc.Crc64Ecma182;
+ const Crc = crc.@"CRC-64/ECMA-182";
- try testing.expectEqual(@as(u64, 0x6c40df5f0b497347), Crc64Ecma182.hash("123456789"));
+ try testing.expectEqual(@as(u64, 0x6c40df5f0b497347), Crc.hash("123456789"));
- var c = Crc64Ecma182.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u64, 0x6c40df5f0b497347), c.final());
}
test "CRC-64/GO-ISO" {
- const Crc64GoIso = crc.Crc64GoIso;
+ const Crc = crc.@"CRC-64/GO-ISO";
- try testing.expectEqual(@as(u64, 0xb90956c775a41001), Crc64GoIso.hash("123456789"));
+ try testing.expectEqual(@as(u64, 0xb90956c775a41001), Crc.hash("123456789"));
- var c = Crc64GoIso.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u64, 0xb90956c775a41001), c.final());
}
test "CRC-64/MS" {
- const Crc64Ms = crc.Crc64Ms;
+ const Crc = crc.@"CRC-64/MS";
- try testing.expectEqual(@as(u64, 0x75d4b74f024eceea), Crc64Ms.hash("123456789"));
+ try testing.expectEqual(@as(u64, 0x75d4b74f024eceea), Crc.hash("123456789"));
- var c = Crc64Ms.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u64, 0x75d4b74f024eceea), c.final());
}
test "CRC-64/REDIS" {
- const Crc64Redis = crc.Crc64Redis;
+ const Crc = crc.@"CRC-64/REDIS";
- try testing.expectEqual(@as(u64, 0xe9c6d914c4b8d9ca), Crc64Redis.hash("123456789"));
+ try testing.expectEqual(@as(u64, 0xe9c6d914c4b8d9ca), Crc.hash("123456789"));
- var c = Crc64Redis.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u64, 0xe9c6d914c4b8d9ca), c.final());
}
test "CRC-64/WE" {
- const Crc64We = crc.Crc64We;
+ const Crc = crc.@"CRC-64/WE";
- try testing.expectEqual(@as(u64, 0x62ec59e3f1a4f00a), Crc64We.hash("123456789"));
+ try testing.expectEqual(@as(u64, 0x62ec59e3f1a4f00a), Crc.hash("123456789"));
- var c = Crc64We.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u64, 0x62ec59e3f1a4f00a), c.final());
}
test "CRC-64/XZ" {
- const Crc64Xz = crc.Crc64Xz;
+ const Crc = crc.@"CRC-64/XZ";
- try testing.expectEqual(@as(u64, 0x995dc9bbdf1939fa), Crc64Xz.hash("123456789"));
+ try testing.expectEqual(@as(u64, 0x995dc9bbdf1939fa), Crc.hash("123456789"));
- var c = Crc64Xz.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u64, 0x995dc9bbdf1939fa), c.final());
}
test "CRC-82/DARC" {
- const Crc82Darc = crc.Crc82Darc;
+ const Crc = crc.@"CRC-82/DARC";
- try testing.expectEqual(@as(u82, 0x09ea83f625023801fd612), Crc82Darc.hash("123456789"));
+ try testing.expectEqual(@as(u82, 0x09ea83f625023801fd612), Crc.hash("123456789"));
- var c = Crc82Darc.init();
+ var c = Crc.init();
c.update("1234");
c.update("56789");
try testing.expectEqual(@as(u82, 0x09ea83f625023801fd612), c.final());
diff --git a/lib/std/hash/xxhash.zig b/lib/std/hash/xxhash.zig
index 107b608006c2f8c23c6ba85077b24304138429b4..27f2701443cc919a9cd2686165ecc8ae087ae002 100644
--- a/lib/std/hash/xxhash.zig
+++ b/lib/std/hash/xxhash.zig
@@ -2,7 +2,6 @@ const std = @import("std");
const builtin = @import("builtin");
const mem = std.mem;
const expectEqual = std.testing.expectEqual;
-const native_endian = builtin.cpu.arch.endian();
const rotl = std.math.rotl;
@@ -421,7 +420,18 @@ pub const XxHash32 = struct {
};
pub const XxHash3 = struct {
+ const block_bytes = 64;
const Block = @Vector(8, u64);
+ const InputBlock = extern struct {
+ raw: [block_bytes]u8,
+ inline fn load(ptr: *const InputBlock) Block {
+ return @bitCast(ptr.raw);
+ }
+ inline fn store(ptr: *InputBlock, val: Block) void {
+ ptr.raw = @bitCast(val);
+ }
+ };
+
const default_secret: [192]u8 = .{
0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
@@ -464,10 +474,6 @@ pub const XxHash3 = struct {
return wide[0] ^ wide[1];
}
- inline fn swap(x: anytype) @TypeOf(x) {
- return if (native_endian == .big) @byteSwap(x) else x;
- }
-
inline fn disableAutoVectorization(x: anytype) void {
if (!@inComptime()) asm volatile (""
:
@@ -476,20 +482,20 @@ pub const XxHash3 = struct {
}
inline fn mix16(seed: u64, input: []const u8, secret: []const u8) u64 {
- const blk: [4]u64 = @bitCast([_][16]u8{ input[0..16].*, secret[0..16].* });
+ const blk: [4]u64 = @bitCast([2][16]u8{ input[0..16].*, secret[0..16].* });
disableAutoVectorization(seed);
return fold(
- swap(blk[0]) ^ (swap(blk[2]) +% seed),
- swap(blk[1]) ^ (swap(blk[3]) -% seed),
+ blk[0] ^ (blk[2] +% seed),
+ blk[1] ^ (blk[3] -% seed),
);
}
- const Accumulator = extern struct {
+ const Accumulator = struct {
consumed: usize = 0,
seed: u64,
- secret: [192]u8 = undefined,
- state: Block = Block{
+ secret: [192]u8,
+ state: Block = .{
XxHash32.prime_3,
XxHash64.prime_1,
XxHash64.prime_2,
@@ -501,33 +507,35 @@ pub const XxHash3 = struct {
},
inline fn init(seed: u64) Accumulator {
- var self = Accumulator{ .seed = seed };
- for (
- std.mem.bytesAsSlice(Block, &self.secret),
- std.mem.bytesAsSlice(Block, &default_secret),
- ) |*dst, src| {
- dst.* = swap(swap(src) +% Block{
- seed, @as(u64, 0) -% seed,
- seed, @as(u64, 0) -% seed,
- seed, @as(u64, 0) -% seed,
- seed, @as(u64, 0) -% seed,
- });
+ const seed_block: Block = .{
+ seed, @as(u64, 0) -% seed,
+ seed, @as(u64, 0) -% seed,
+ seed, @as(u64, 0) -% seed,
+ seed, @as(u64, 0) -% seed,
+ };
+
+ var secret: [192]u8 = undefined;
+ const secret_blocks: []InputBlock = @ptrCast(&secret);
+ const default_secret_blocks: []const InputBlock = @ptrCast(&default_secret);
+ for (secret_blocks, default_secret_blocks) |*dst, *src| {
+ dst.store(src.load() +% seed_block);
}
- return self;
+
+ return .{ .seed = seed, .secret = secret };
}
inline fn round(
noalias state: *Block,
- noalias input_block: *align(1) const Block,
- noalias secret_block: *align(1) const Block,
+ noalias input_block: *const InputBlock,
+ noalias secret_block: *const InputBlock,
) void {
- const data = swap(input_block.*);
- const mixed = data ^ swap(secret_block.*);
+ const data = input_block.load();
+ const mixed = data ^ secret_block.load();
state.* +%= (mixed & @as(Block, @splat(0xffffffff))) *% (mixed >> @splat(32));
state.* +%= @shuffle(u64, data, undefined, [_]i32{ 1, 0, 3, 2, 5, 4, 7, 6 });
}
- fn accumulate(noalias self: *Accumulator, blocks: []align(1) const Block) void {
+ fn accumulate(noalias self: *Accumulator, blocks: []const InputBlock) void {
const secret = std.mem.bytesAsSlice(u64, self.secret[self.consumed * 8 ..]);
for (blocks, secret[0..blocks.len]) |*input_block, *secret_block| {
@prefetch(@as([*]const u8, @ptrCast(input_block)) + 320, .{});
@@ -536,14 +544,14 @@ pub const XxHash3 = struct {
}
fn scramble(self: *Accumulator) void {
- const secret_block: Block = @bitCast(self.secret[192 - @sizeOf(Block) .. 192].*);
+ const secret_block: Block = @bitCast(self.secret[192 - block_bytes .. 192].*);
self.state ^= self.state >> @splat(47);
- self.state ^= swap(secret_block);
+ self.state ^= secret_block;
self.state *%= @as(Block, @splat(XxHash32.prime_1));
}
- fn consume(noalias self: *Accumulator, input_blocks: []align(1) const Block) void {
- const blocks_per_scramble = 1024 / @sizeOf(Block);
+ fn consume(noalias self: *Accumulator, input_blocks: []const InputBlock) void {
+ const blocks_per_scramble = 1024 / block_bytes;
std.debug.assert(self.consumed <= blocks_per_scramble);
var blocks = input_blocks;
@@ -561,12 +569,12 @@ pub const XxHash3 = struct {
self.consumed += blocks.len;
}
- fn digest(noalias self: *Accumulator, total_len: u64, noalias last_block: *align(1) const Block) u64 {
- const secret_block = self.secret[192 - @sizeOf(Block) - 7 ..][0..@sizeOf(Block)];
+ fn digest(noalias self: *Accumulator, total_len: u64, noalias last_block: *const InputBlock) u64 {
+ const secret_block = self.secret[192 - block_bytes - 7 ..][0..block_bytes];
round(&self.state, last_block, @ptrCast(secret_block));
- const merge_block: Block = @bitCast(self.secret[11 .. 11 + @sizeOf(Block)].*);
- self.state ^= swap(merge_block);
+ const merge_block: Block = @bitCast(self.secret[11 .. 11 + block_bytes].*);
+ self.state ^= merge_block;
var result = XxHash64.prime_1 *% total_len;
inline for (0..4) |i| {
@@ -588,7 +596,7 @@ pub const XxHash3 = struct {
if (input.len > 0) return hash3(seed, input, secret);
const flip: [2]u64 = @bitCast(secret[56..72].*);
- const key = swap(flip[0]) ^ swap(flip[1]);
+ const key = flip[0] ^ flip[1];
return avalanche(.h64, seed ^ key);
}
@@ -604,8 +612,8 @@ pub const XxHash3 = struct {
input[input.len / 2],
});
- const key = @as(u64, swap(flip[0]) ^ swap(flip[1])) +% seed;
- return avalanche(.h64, key ^ swap(blk));
+ const key = @as(u64, flip[0] ^ flip[1]) +% seed;
+ return avalanche(.h64, key ^ blk);
}
fn hash8(seed: u64, input: anytype, noalias secret: *const [192]u8) u64 {
@@ -619,8 +627,8 @@ pub const XxHash3 = struct {
});
const mixed = seed ^ (@as(u64, @byteSwap(@as(u32, @truncate(seed)))) << 32);
- const key = (swap(flip[0]) ^ swap(flip[1])) -% mixed;
- const combined = (@as(u64, swap(blk[0])) << 32) +% swap(blk[1]);
+ const key = (flip[0] ^ flip[1]) -% mixed;
+ const combined = (@as(u64, blk[0]) << 32) +% blk[1];
return avalanche(.{ .rrmxmx = input.len }, key ^ combined);
}
@@ -634,8 +642,8 @@ pub const XxHash3 = struct {
input[input.len - 8 ..][0..8].*,
});
- const lo = swap(blk[0]) ^ ((swap(flip[0]) ^ swap(flip[1])) +% seed);
- const hi = swap(blk[1]) ^ ((swap(flip[2]) ^ swap(flip[3])) -% seed);
+ const lo = blk[0] ^ ((flip[0] ^ flip[1]) +% seed);
+ const hi = blk[1] ^ ((flip[2] ^ flip[3]) -% seed);
const combined = @as(u64, input.len) +% @byteSwap(lo) +% hi +% fold(lo, hi);
return avalanche(.h3, combined);
}
@@ -679,11 +687,11 @@ pub const XxHash3 = struct {
@branchHint(.unlikely);
std.debug.assert(input.len >= 240);
- const block_count = ((input.len - 1) / @sizeOf(Block)) * @sizeOf(Block);
- const last_block = input[input.len - @sizeOf(Block) ..][0..@sizeOf(Block)];
+ const block_count = ((input.len - 1) / block_bytes) * block_bytes;
+ const last_block = input[input.len - block_bytes ..][0..block_bytes];
var acc = Accumulator.init(seed);
- acc.consume(std.mem.bytesAsSlice(Block, input[0..block_count]));
+ acc.consume(std.mem.bytesAsSlice(InputBlock, input[0..block_count]));
return acc.digest(input.len, @ptrCast(last_block));
}
@@ -716,21 +724,21 @@ pub const XxHash3 = struct {
@memcpy(self.buffer[self.buffered..], consumable[0..remaining]);
consumable = consumable[remaining..];
- self.accumulator.consume(std.mem.bytesAsSlice(Block, &self.buffer));
+ self.accumulator.consume(std.mem.bytesAsSlice(InputBlock, &self.buffer));
self.buffered = 0;
}
// The input isn't small enough to fit in the buffer. Consume it directly.
if (consumable.len > self.buffer.len) {
- const block_count = ((consumable.len - 1) / @sizeOf(Block)) * @sizeOf(Block);
- self.accumulator.consume(std.mem.bytesAsSlice(Block, consumable[0..block_count]));
+ const block_count = ((consumable.len - 1) / block_bytes) * block_bytes;
+ self.accumulator.consume(std.mem.bytesAsSlice(InputBlock, consumable[0..block_count]));
consumable = consumable[block_count..];
// In case we consume all remaining input, write the last block to end of the buffer
// to populate the last_block_copy in final() similar to hashLong()'s last_block.
@memcpy(
- self.buffer[self.buffer.len - @sizeOf(Block) .. self.buffer.len],
- (consumable.ptr - @sizeOf(Block))[0..@sizeOf(Block)],
+ self.buffer[self.buffer.len - block_bytes .. self.buffer.len],
+ (consumable.ptr - block_bytes)[0..block_bytes],
);
}
@@ -751,16 +759,16 @@ pub const XxHash3 = struct {
// Make a copy of the Accumulator state in case `self` needs to update() / be used later.
var accumulator_copy = self.accumulator;
- var last_block_copy: [@sizeOf(Block)]u8 = undefined;
+ var last_block_copy: [block_bytes]u8 = undefined;
// Digest the last block onthe Accumulator copy.
return accumulator_copy.digest(self.total_len, last_block: {
- if (self.buffered >= @sizeOf(Block)) {
- const block_count = ((self.buffered - 1) / @sizeOf(Block)) * @sizeOf(Block);
- accumulator_copy.consume(std.mem.bytesAsSlice(Block, self.buffer[0..block_count]));
- break :last_block @ptrCast(self.buffer[self.buffered - @sizeOf(Block) ..][0..@sizeOf(Block)]);
+ if (self.buffered >= block_bytes) {
+ const block_count = ((self.buffered - 1) / block_bytes) * block_bytes;
+ accumulator_copy.consume(std.mem.bytesAsSlice(InputBlock, self.buffer[0..block_count]));
+ break :last_block @ptrCast(self.buffer[self.buffered - block_bytes ..][0..block_bytes]);
} else {
- const remaining = @sizeOf(Block) - self.buffered;
+ const remaining = block_bytes - self.buffered;
@memcpy(last_block_copy[0..remaining], self.buffer[self.buffer.len - remaining ..][0..remaining]);
@memcpy(last_block_copy[remaining..][0..self.buffered], self.buffer[0..self.buffered]);
break :last_block @ptrCast(&last_block_copy);
@@ -780,6 +788,7 @@ fn testExpect(comptime H: type, seed: anytype, input: []const u8, expected: u64)
}
test "xxhash3" {
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
const H = XxHash3;
// Non-Seeded Tests
try testExpect(H, 0, "", 0x2d06800538d394c2);
@@ -811,6 +820,7 @@ test "xxhash3" {
}
test "xxhash3 smhasher" {
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
const Test = struct {
fn do() !void {
try expectEqual(verify.smhasher(XxHash3.hash), 0x9a636405);
@@ -822,6 +832,7 @@ test "xxhash3 smhasher" {
}
test "xxhash3 iterative api" {
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
const Test = struct {
fn do() !void {
try verify.iterativeApi(XxHash3);
diff --git a/lib/std/hash_map.zig b/lib/std/hash_map.zig
index 5ba6aadc9ed418611482075e7daf0c6edaf775ea..a6562bc5ea1ab479963b308beae24fb303d98c6d 100644
--- a/lib/std/hash_map.zig
+++ b/lib/std/hash_map.zig
@@ -593,8 +593,8 @@ fn Custom(
fingerprint: FingerPrint = free,
used: u1 = 0,
- const slot_free = @as(u8, @bitCast(Metadata{ .fingerprint = free }));
- const slot_tombstone = @as(u8, @bitCast(Metadata{ .fingerprint = tombstone }));
+ const slot_free: u8 = @bitCast(Metadata{ .fingerprint = free });
+ const slot_tombstone: u8 = @bitCast(Metadata{ .fingerprint = tombstone });
pub fn isUsed(self: Metadata) bool {
return self.used == 1;
diff --git a/lib/std/http/HeadParser.zig b/lib/std/http/HeadParser.zig
index 7b9ca6d2c58f4dce7be24cd4db7e225a1d8bc13a..4c7f1779043b0b0f809cef4f39553fe049e1b53d 100644
--- a/lib/std/http/HeadParser.zig
+++ b/lib/std/http/HeadParser.zig
@@ -116,11 +116,8 @@ pub fn feed(p: *HeadParser, bytes: []const u8) usize {
const chunk = bytes[index..][0..vector_len];
const v: Vector = chunk.*;
- // depends on https://github.com/ziglang/zig/issues/19755
- // const matches_r: BitVector = @bitCast(v == @as(Vector, @splat('\r')));
- // const matches_n: BitVector = @bitCast(v == @as(Vector, @splat('\n')));
- const matches_r: BitVector = @select(u1, v == @as(Vector, @splat('\r')), @as(Vector, @splat(1)), @as(Vector, @splat(0)));
- const matches_n: BitVector = @select(u1, v == @as(Vector, @splat('\n')), @as(Vector, @splat(1)), @as(Vector, @splat(0)));
+ const matches_r: BitVector = @bitCast(v == @as(Vector, @splat('\r')));
+ const matches_n: BitVector = @bitCast(v == @as(Vector, @splat('\n')));
const matches_or: SizeVector = matches_r | matches_n;
const matches = @reduce(.Add, matches_or);
@@ -331,15 +328,15 @@ pub fn feed(p: *HeadParser, bytes: []const u8) usize {
}
inline fn int16(array: *const [2]u8) u16 {
- return @bitCast(array.*);
+ return std.mem.toNative(u16, @bitCast(array.*), .little);
}
inline fn int24(array: *const [3]u8) u24 {
- return @bitCast(array.*);
+ return std.mem.toNative(u24, @bitCast(array.*), .little);
}
inline fn int32(array: *const [4]u8) u32 {
- return @bitCast(array.*);
+ return std.mem.toNative(u32, @bitCast(array.*), .little);
}
inline fn intShift(comptime T: type, x: anytype) T {
diff --git a/lib/std/http/Server.zig b/lib/std/http/Server.zig
index 7820ad6d0dc2db532f2c1f7bebc58cb50bce0a04..3d56f59da31ce69377e8886a62245cc8f6612c7c 100644
--- a/lib/std/http/Server.zig
+++ b/lib/std/http/Server.zig
@@ -726,7 +726,7 @@ pub const WebSocket = struct {
else => @intFromEnum(h1.payload_len),
};
if (len > in.buffer.len) return error.MessageOversize;
- const mask: u32 = @bitCast((try in.takeArray(4)).*);
+ const mask: [4]u8 = (try in.takeArray(4)).*;
const payload = try in.take(len);
// Skip pongs.
@@ -734,11 +734,16 @@ pub const WebSocket = struct {
// The last item may contain a partial word of unused data.
const floored_len = (payload.len / 4) * 4;
- const u32_payload: []align(1) u32 = @ptrCast(payload[0..floored_len]);
- for (u32_payload) |*elem| elem.* ^= mask;
- const mask_bytes: []const u8 = @ptrCast(&mask);
- for (payload[floored_len..], mask_bytes[0 .. payload.len - floored_len]) |*leftover, m|
+
+ const payload_chunks: [][4]u8 = @ptrCast(payload[0..floored_len]);
+ for (payload_chunks) |*chunk| {
+ const mask_i: u32 = @bitCast(mask);
+ const chunk_i: u32 = @bitCast(chunk.*);
+ chunk.* = @bitCast(chunk_i ^ mask_i);
+ }
+ for (payload[floored_len..], mask[0 .. payload.len - floored_len]) |*leftover, m| {
leftover.* ^= m;
+ }
return .{
.opcode = h0.opcode,
diff --git a/lib/std/json/hashmap.zig b/lib/std/json/hashmap.zig
index be4e9bd2dd5a4359c6ed2a0b6be704369fc314e9..7a88f6ea0d3a2ae1d40f2a9a522ebd0bc0ec63f4 100644
--- a/lib/std/json/hashmap.zig
+++ b/lib/std/json/hashmap.zig
@@ -6,20 +6,20 @@ const innerParse = @import("static.zig").innerParse;
const innerParseFromValue = @import("static.zig").innerParseFromValue;
const Value = @import("dynamic.zig").Value;
-/// A thin wrapper around `std.StringArrayHashMapUnmanaged` that implements
+/// A thin wrapper around `std.array_hash_map.String` that implements
/// `jsonParse`, `jsonParseFromValue`, and `jsonStringify`.
/// This is useful when your JSON schema has an object with arbitrary data keys
/// instead of comptime-known struct field names.
pub fn ArrayHashMap(comptime T: type) type {
return struct {
- map: std.StringArrayHashMapUnmanaged(T) = .empty,
+ map: std.array_hash_map.String(T) = .empty,
pub fn deinit(self: *@This(), allocator: Allocator) void {
self.map.deinit(allocator);
}
pub fn jsonParse(allocator: Allocator, source: anytype, options: ParseOptions) !@This() {
- var map: std.StringArrayHashMapUnmanaged(T) = .empty;
+ var map: std.array_hash_map.String(T) = .empty;
errdefer map.deinit(allocator);
if (.object_begin != try source.next()) return error.UnexpectedToken;
@@ -52,7 +52,7 @@ pub fn ArrayHashMap(comptime T: type) type {
pub fn jsonParseFromValue(allocator: Allocator, source: Value, options: ParseOptions) !@This() {
if (source != .object) return error.UnexpectedToken;
- var map: std.StringArrayHashMapUnmanaged(T) = .empty;
+ var map: std.array_hash_map.String(T) = .empty;
errdefer map.deinit(allocator);
var it = source.object.iterator();
diff --git a/lib/std/lang.zig b/lib/std/lang.zig
index 9fdf35ae3fab87b6e70043a9c09a3726576bfd49..21a4fdae87a59afb4a63cbfe106558a0d1a0281d 100644
--- a/lib/std/lang.zig
+++ b/lib/std/lang.zig
@@ -140,7 +140,7 @@ pub const CallingConvention = union(enum(u8)) {
pub const kernel: CallingConvention = switch (builtin.target.cpu.arch) {
.amdgcn => .amdgcn_kernel,
.nvptx, .nvptx64 => .nvptx_kernel,
- .spirv32, .spirv64 => .spirv_kernel,
+ .spirv32, .spirv64 => .{ .spirv_kernel = .{ .x = 1, .y = 1, .z = 1 } },
else => unreachable,
};
@@ -337,11 +337,13 @@ pub const CallingConvention = union(enum(u8)) {
nvptx_device,
nvptx_kernel,
- // Calling conventions for kernels and shaders on the `spirv`, `spirv32`, and `spirv64` architectures.
+ // Calling conventions for kernels and shaders on the `spirv32` and `spirv64` architectures.
spirv_device,
- spirv_kernel,
- spirv_fragment,
spirv_vertex,
+ spirv_kernel: SpirvKernelOptions,
+ spirv_fragment: SpirvFragmentOptions,
+ spirv_task: SpirvKernelOptions,
+ spirv_mesh: SpirvMeshOptions,
// Calling conventions for the `ez80` architecture.
ez80_cet,
@@ -473,6 +475,36 @@ pub const CallingConvention = union(enum(u8)) {
};
};
+ pub const SpirvKernelOptions = struct {
+ x: u32,
+ y: u32,
+ z: u32,
+ };
+
+ pub const SpirvFragmentOptions = struct {
+ pub const DepthAssumption = enum(u2) {
+ none = 0,
+ greater = 1,
+ less = 2,
+ unchanged = 3,
+ };
+
+ pixel_centered_integer: bool = false,
+ depth_assumption: DepthAssumption = .none,
+ };
+
+ pub const SpirvMeshOptions = struct {
+ pub const StageOutput = enum(u2) {
+ output_points = 0,
+ output_lines = 1,
+ output_triangles = 2,
+ };
+
+ stage_output: StageOutput = .output_triangles,
+ max_primitives: u32 = 1,
+ max_vertices: u32 = 3,
+ };
+
/// Returns the array of `std.Target.Cpu.Arch` to which this `CallingConvention` applies.
/// Asserts that `cc` is not `.auto`, `.@"async"`, `.naked`, or `.@"inline"`.
pub fn archs(cc: CallingConvention) []const std.Target.Cpu.Arch {
@@ -535,6 +567,10 @@ pub const AddressSpace = enum(u5) {
/// This address space only addresses the "lookup" ram
lut,
+
+ // Web Assembly
+ externref,
+ funcref,
};
/// This data structure is used by the Zig language code generation and
@@ -578,6 +614,7 @@ pub const Type = union(enum) {
@"anyframe": AnyFrame,
vector: Vector,
enum_literal,
+ spirv: Spirv,
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
@@ -781,6 +818,59 @@ pub const Type = union(enum) {
};
};
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Spirv = union(enum(u2)) {
+ sampler,
+ image: Image,
+ sampled_image: type,
+ runtime_array: type,
+
+ pub const Image = struct {
+ usage: Usage,
+ format: Format,
+ dim: Dimensionality,
+ depth: Depth,
+ access: Access,
+ arrayed: bool,
+ multisampled: bool,
+
+ pub const Usage = union(enum(u2)) {
+ unknown: type,
+ sampled: type,
+ storage: type,
+ };
+
+ pub const Format = enum(u4) {
+ unknown,
+ rgba32f,
+ rgba32i,
+ rgba32u,
+ rgba16f,
+ rgba16i,
+ rgba16u,
+ rgba8unorm,
+ rgba8snorm,
+ rgba8i,
+ rgba8u,
+ r32f,
+ r32i,
+ r32u,
+ };
+
+ pub const Dimensionality = enum(u2) {
+ @"1d",
+ @"2d",
+ @"3d",
+ cube,
+ };
+
+ pub const Depth = enum(u2) { unknown, depth, not_depth };
+
+ pub const Access = enum(u2) { unknown, read_only, write_only, read_write };
+ };
+ };
+
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Opaque = struct {
@@ -914,10 +1004,9 @@ pub const VaListArm = extern struct {
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const VaListHexagon = extern struct {
- __gpr: c_long,
- __fpr: c_long,
- __overflow_arg_area: *anyopaque,
- __reg_save_area: *anyopaque,
+ __current_saved_reg_area_pointer: *anyopaque,
+ __saved_reg_area_end_pointer: *anyopaque,
+ __overflow_area_pointer: *anyopaque,
};
/// This data structure is used by the Zig language code generation and
@@ -933,9 +1022,10 @@ pub const VaListPowerPc = extern struct {
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const VaListS390x = extern struct {
- __current_saved_reg_area_pointer: *anyopaque,
- __saved_reg_area_end_pointer: *anyopaque,
- __overflow_area_pointer: *anyopaque,
+ __gpr: c_long,
+ __fpr: c_long,
+ __overflow_arg_area: *anyopaque,
+ __reg_save_area: *anyopaque,
};
/// This data structure is used by the Zig language code generation and
@@ -1083,11 +1173,12 @@ pub const ExternOptions = struct {
pub const Decoration = union(enum) {
location: u32,
+ flat: u32,
descriptor: Descriptor,
pub const Descriptor = struct {
- binding: u32,
set: u32,
+ binding: u32,
};
};
diff --git a/lib/std/math.zig b/lib/std/math.zig
index 5487e0cb37520ec415f7db1a712c88a8e1f2e9c1..aec6f03ce0d4d8d7b4407c6be5bf241db47b0371 100644
--- a/lib/std/math.zig
+++ b/lib/std/math.zig
@@ -1875,3 +1875,39 @@ test sign {
try testSign();
try comptime testSign();
}
+
+/// Increases the bit width of an integer by copying the most significant bit.
+/// This results in the input and output having the same arithmetic value, when
+/// interpreted as two's complement integers.
+fn signExtend(To: type, n: anytype) To {
+ const From = @TypeOf(n);
+ if (From == u0) return 0;
+ const FromSigned = @Int(.signed, @typeInfo(From).int.bits);
+ const ToSigned = @Int(.signed, @typeInfo(To).int.bits);
+
+ return @bitCast(@as(ToSigned, @as(FromSigned, @bitCast(n))));
+}
+
+test signExtend {
+ const number: u8 = 0x86;
+ try testing.expectEqual(0xff86, signExtend(u16, number));
+
+ try testing.expectEqual(0, signExtend(u1, @as(u0, 0)));
+ try testing.expectEqual(0, signExtend(u16, @as(u0, 0)));
+
+ try testing.expectEqual(0x0000, signExtend(u16, @as(u1, 0b0)));
+ try testing.expectEqual(0xffff, signExtend(u16, @as(u1, 0b1)));
+
+ try testing.expectEqual(0b000, signExtend(u3, @as(u2, 0b00)));
+ try testing.expectEqual(0b001, signExtend(u3, @as(u2, 0b01)));
+ try testing.expectEqual(0b110, signExtend(u3, @as(u2, 0b10)));
+ try testing.expectEqual(0b111, signExtend(u3, @as(u2, 0b11)));
+ try testing.expectEqual(0b0000_0001, signExtend(u8, @as(u2, 0b01)));
+ try testing.expectEqual(0b1111_1110, signExtend(u8, @as(u2, 0b10)));
+
+ try testing.expectEqual(0x0039, signExtend(u16, @as(u8, 0x39)));
+ try testing.expectEqual(0xff93, signExtend(u16, @as(u8, 0x93)));
+
+ try testing.expectEqual(5, signExtend(i32, @as(i8, 5)));
+ try testing.expectEqual(-123, signExtend(i16, @as(i8, -123)));
+}
diff --git a/lib/std/mem.zig b/lib/std/mem.zig
index ba8602e90b458e3425fd03c2d0fd75469483053f..2e0f3cb0ccee44adabf55ff740bd247ad762a5a6 100644
--- a/lib/std/mem.zig
+++ b/lib/std/mem.zig
@@ -1,12 +1,14 @@
-const std = @import("std.zig");
+const mem = @This();
+
const builtin = @import("builtin");
+const native_endian = builtin.cpu.arch.endian();
+
+const std = @import("std.zig");
const debug = std.debug;
const assert = debug.assert;
const math = std.math;
-const mem = @This();
const testing = std.testing;
-const Endian = std.builtin.Endian;
-const native_endian = builtin.cpu.arch.endian();
+const Endian = std.lang.Endian;
/// The standard library currently thoroughly depends on byte size
/// being 8 bits. (see the use of u8 throughout allocation code as
@@ -352,6 +354,7 @@ pub fn zeroes(comptime T: type) T {
.noreturn,
.undefined,
.@"opaque",
+ .spirv,
.frame,
.@"anyframe",
=> {
@@ -1847,18 +1850,18 @@ pub fn readVarPackedInt(
if (@bitSizeOf(T) <= 8) {
// These are the same shifts/masks we perform below, but adds `@truncate`/`@intCast`
// where needed since int is smaller than a byte.
- const value = if (read_size == 1) b: {
- break :b @as(uN, @truncate(read_bytes[0] >> bit_shift));
+ const value: uN = if (read_size == 1) b: {
+ break :b @truncate(read_bytes[0] >> bit_shift);
} else b: {
const i: u1 = @intFromBool(endian == .big);
- const head = @as(uN, @truncate(read_bytes[i] >> bit_shift));
- const tail_shift = @as(Log2N, @intCast(@as(u4, 8) - bit_shift));
- const tail = @as(uN, @truncate(read_bytes[1 - i]));
+ const head: uN = @truncate(read_bytes[i] >> bit_shift);
+ const tail_shift: Log2N = @intCast(@as(u4, 8) - bit_shift);
+ const tail: uN = @truncate(read_bytes[1 - i]);
break :b (tail << tail_shift) | head;
};
switch (signedness) {
- .signed => return @as(T, @intCast((@as(iN, @bitCast(value)) << pad) >> pad)),
- .unsigned => return @as(T, @intCast((@as(uN, @bitCast(value)) << pad) >> pad)),
+ .signed => return @intCast((@as(iN, @bitCast(value)) << pad) >> pad),
+ .unsigned => return @intCast((value << pad) >> pad),
}
}
@@ -1879,8 +1882,8 @@ pub fn readVarPackedInt(
},
}
switch (signedness) {
- .signed => return @as(T, @intCast((@as(iN, @bitCast(int)) << pad) >> pad)),
- .unsigned => return @as(T, @intCast((@as(uN, @bitCast(int)) << pad) >> pad)),
+ .signed => return @intCast((@as(iN, @bitCast(int)) << pad) >> pad),
+ .unsigned => return @intCast((int << pad) >> pad),
}
}
@@ -1895,8 +1898,13 @@ test readVarPackedInt {
/// The bit count of T must be evenly divisible by 8.
/// This function cannot fail and cannot cause undefined behavior.
pub inline fn readInt(comptime T: type, buffer: *const [@divExact(@typeInfo(T).int.bits, 8)]u8, endian: Endian) T {
- const value: T = @bitCast(buffer.*);
- return if (endian == native_endian) value else @byteSwap(value);
+ // Zig's logical bit order aligns with a little-endian byte array, so when reading in big-endian
+ // we must `@byteSwap` the int after we `@bitCast` to it.
+ const little_val: T = @bitCast(buffer.*);
+ return switch (endian) {
+ .little => little_val,
+ .big => @byteSwap(little_val),
+ };
}
test readInt {
@@ -1939,13 +1947,15 @@ fn readPackedIntLittle(comptime T: type, bytes: []const u8, bit_offset: usize) T
// Read by loading a LoadInt, and then follow it up with a 1-byte read
// of the tail if bit_offset pushed us over a byte boundary.
const read_bytes = bytes[bit_offset / 8 ..];
- const val = @as(uN, @truncate(readInt(LoadInt, read_bytes[0..load_size], .little) >> bit_shift));
+ const val: uN = @truncate(readInt(LoadInt, read_bytes[0..load_size], .little) >> bit_shift);
if (bit_shift > load_tail_bits) {
const tail_bits = @as(Log2N, @intCast(bit_shift - load_tail_bits));
const tail_byte = read_bytes[load_size];
const tail_truncated = if (bit_count < 8) @as(uN, @truncate(tail_byte)) else @as(uN, tail_byte);
- return @as(T, @bitCast(val | (tail_truncated << (@as(Log2N, @truncate(bit_count)) -% tail_bits))));
- } else return @as(T, @bitCast(val));
+ return @bitCast(val | (tail_truncated << (@as(Log2N, @truncate(bit_count)) -% tail_bits)));
+ } else {
+ return @bitCast(val);
+ }
}
fn readPackedIntBig(comptime T: type, bytes: []const u8, bit_offset: usize) T {
@@ -1971,8 +1981,10 @@ fn readPackedIntBig(comptime T: type, bytes: []const u8, bit_offset: usize) T {
if (bit_shift > load_tail_bits) {
const tail_bits = @as(Log2N, @intCast(bit_shift - load_tail_bits));
const tail_byte = if (bit_count < 8) @as(uN, @truncate(read_bytes[0])) else @as(uN, read_bytes[0]);
- return @as(T, @bitCast(val | (tail_byte << (@as(Log2N, @truncate(bit_count)) -% tail_bits))));
- } else return @as(T, @bitCast(val));
+ return @bitCast(val | (tail_byte << (@as(Log2N, @truncate(bit_count)) -% tail_bits)));
+ } else {
+ return @bitCast(val);
+ }
}
/// Loads an integer from packed memory.
@@ -2010,7 +2022,12 @@ test "comptime read/write int" {
/// This function always succeeds, has defined behavior for all inputs, but
/// the integer bit width must be divisible by 8.
pub inline fn writeInt(comptime T: type, buffer: *[@divExact(@typeInfo(T).int.bits, 8)]u8, value: T, endian: Endian) void {
- buffer.* = @bitCast(if (endian == native_endian) value else @byteSwap(value));
+ // Zig's logical bit order aligns with a little-endian byte array, so when writing in big-endian
+ // we must `@byteSwap` the int before we `@bitCast` to an array.
+ buffer.* = switch (endian) {
+ .little => @bitCast(value),
+ .big => @bitCast(@byteSwap(value)),
+ };
}
test writeInt {
@@ -2208,10 +2225,10 @@ pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {
/// (Changing their endianness)
pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *align(a.toByteUnits()) S) void {
switch (@typeInfo(S)) {
- .@"struct" => |struct_info| {
- if (struct_info.backing_integer) |Int| {
+ .@"struct" => |@"struct"| {
+ if (@"struct".backing_integer) |Int| {
ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*))));
- } else inline for (struct_info.field_types, struct_info.field_names, struct_info.field_attrs) |f_type, f_name, f_attr| {
+ } else inline for (@"struct".field_types, @"struct".field_names, @"struct".field_attrs) |f_type, f_name, f_attr| {
switch (@typeInfo(f_type)) {
.@"struct" => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),
.@"union", .array => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),
@@ -2219,8 +2236,8 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a
@field(ptr, f_name) = @enumFromInt(@byteSwap(@intFromEnum(@field(ptr, f_name))));
},
.bool => {},
- .float => |float_info| {
- @field(ptr, f_name) = @bitCast(@byteSwap(@as(@Int(.unsigned, float_info.bits), @bitCast(@field(ptr, f_name)))));
+ .float => |float| {
+ @field(ptr, f_name) = @bitCast(@byteSwap(@as(@Int(.unsigned, float.bits), @bitCast(@field(ptr, f_name)))));
},
else => {
@field(ptr, f_name) = @byteSwap(@field(ptr, f_name));
@@ -2228,23 +2245,26 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a
}
}
},
- .@"union" => |union_info| {
- if (union_info.tag_type != null) {
- @compileError("byteSwapAllFields expects an untagged union");
+ .@"union" => |@"union"| if (@"union".backing_integer) |Int| {
+ ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*))));
+ } else {
+ if (@"union".layout != .@"extern") {
+ @compileError("byteSwapAllFields expects a packed or extern union");
}
- const first_size = @bitSizeOf(union_info.field_types[0]);
- inline for (union_info.field_types) |field_type| {
+ const first_size = @bitSizeOf(@"union".field_types[0]);
+ inline for (@"union".field_types) |field_type| {
if (@bitSizeOf(field_type) != first_size) {
@compileError("Unable to byte-swap unions with varying field sizes");
}
}
- const BackingInt = @Int(.unsigned, @bitSizeOf(S));
- ptr.* = @bitCast(@byteSwap(@as(BackingInt, @bitCast(ptr.*))));
+ const FieldInt = @Int(.unsigned, first_size);
+ const field_ptr = &@field(ptr, @"union".field_names[0]);
+ field_ptr.* = @bitCast(@byteSwap(@as(FieldInt, @bitCast(field_ptr.*))));
},
- .array => |info| {
- byteSwapAllElements(info.child, ptr);
+ .array => |array| {
+ byteSwapAllElements(array.child, ptr);
},
else => {
ptr.* = @byteSwap(ptr.*);
@@ -2290,7 +2310,7 @@ test byteSwapAllFields {
.f2 = 0x12345678,
.f3 = .{0x12},
.f4 = true,
- .f5 = @as(f32, @bitCast(@as(u32, 0x4640e400))),
+ .f5 = @bitCast(@as(u32, 0x4640e400)),
.f6 = .{ .f0 = 0x1234 },
};
var k = K{
@@ -2299,7 +2319,7 @@ test byteSwapAllFields {
.f2 = 0x1234,
.f3 = .{0x12},
.f4 = false,
- .f5 = @as(f32, @bitCast(@as(u32, 0x45d42800))),
+ .f5 = @bitCast(@as(u32, 0x45d42800)),
};
var p: P = @bitCast(@as(u32, 0x01234567));
var a: A = A{
@@ -2317,7 +2337,7 @@ test byteSwapAllFields {
.f2 = 0x78563412,
.f3 = .{0x12},
.f4 = true,
- .f5 = @as(f32, @bitCast(@as(u32, 0x00e44046))),
+ .f5 = @bitCast(@as(u32, 0x00e44046)),
.f6 = .{ .f0 = 0x3412 },
}, s);
try std.testing.expectEqual(K{
@@ -2326,7 +2346,7 @@ test byteSwapAllFields {
.f2 = 0x3412,
.f3 = .{0x12},
.f4 = false,
- .f5 = @as(f32, @bitCast(@as(u32, 0x0028d445))),
+ .f5 = @bitCast(@as(u32, 0x0028d445)),
}, k);
try std.testing.expectEqual(@as(P, @bitCast(@as(u32, 0x67452301))), p);
try std.testing.expectEqual(A{
@@ -2347,8 +2367,9 @@ pub fn byteSwapAllElements(comptime Elem: type, slice: []Elem) void {
elem.* = @enumFromInt(@byteSwap(@intFromEnum(elem.*)));
},
.bool => {},
- .float => |float_info| {
- elem.* = @bitCast(@byteSwap(@as(@Int(.unsigned, float_info.bits), @bitCast(elem.*))));
+ .float => |float| {
+ const int_repr: @Int(.unsigned, float.bits) = @bitCast(elem.*);
+ elem.* = @bitCast(@byteSwap(int_repr));
},
else => {
elem.* = @byteSwap(elem.*);
@@ -3869,25 +3890,29 @@ inline fn reverseVector(comptime N: usize, comptime T: type, a: []T) [N]T {
pub fn reverse(comptime T: type, items: []T) void {
var i: usize = 0;
const end = items.len / 2;
- if (use_vectors and
- !@inComptime() and
- @bitSizeOf(T) > 0 and
- std.math.isPowerOfTwo(@bitSizeOf(T)))
- {
- if (std.simd.suggestVectorLength(T)) |simd_size| {
- if (simd_size <= end) {
- const simd_end = end - (simd_size - 1);
- while (i < simd_end) : (i += simd_size) {
- const left_slice = items[i .. i + simd_size];
- const right_slice = items[items.len - i - simd_size .. items.len - i];
- const left_shuffled: [simd_size]T = reverseVector(simd_size, T, left_slice);
- const right_shuffled: [simd_size]T = reverseVector(simd_size, T, right_slice);
+ vec: {
+ if (!use_vectors) break :vec;
+ if (@inComptime()) break :vec;
+ switch (@typeInfo(T)) {
+ .int, .float => {},
+ .pointer => |pointer| if (pointer.size == .slice) break :vec,
+ else => break :vec,
+ }
+ if (@bitSizeOf(T) == 0 or !comptime std.math.isPowerOfTwo(@bitSizeOf(T))) break :vec;
+ const simd_size = std.simd.suggestVectorLength(T) orelse break :vec;
+ if (simd_size > end) break :vec;
- @memcpy(right_slice, &left_shuffled);
- @memcpy(left_slice, &right_shuffled);
- }
- }
+ const simd_end = end - (simd_size - 1);
+ while (i < simd_end) : (i += simd_size) {
+ const left_slice = items[i .. i + simd_size];
+ const right_slice = items[items.len - i - simd_size .. items.len - i];
+
+ const left_shuffled: [simd_size]T = reverseVector(simd_size, T, left_slice);
+ const right_shuffled: [simd_size]T = reverseVector(simd_size, T, right_slice);
+
+ @memcpy(right_slice, &left_shuffled);
+ @memcpy(left_slice, &right_shuffled);
}
}
@@ -5008,8 +5033,8 @@ test "read/write(Var)PackedInt" {
for ([_]PackedType{
~@as(PackedType, 0), // all ones: -1 iN / maxInt uN
@as(PackedType, 0), // all zeros: 0 iN / 0 uN
- @as(PackedType, @bitCast(@as(iPackedType, math.maxInt(iPackedType)))), // maxInt iN
- @as(PackedType, @bitCast(@as(iPackedType, math.minInt(iPackedType)))), // maxInt iN
+ @bitCast(@as(iPackedType, math.maxInt(iPackedType))), // maxInt iN
+ @bitCast(@as(iPackedType, math.minInt(iPackedType))), // maxInt iN
random.int(PackedType), // random
random.int(PackedType), // random
}) |write_value| {
@@ -5129,3 +5154,50 @@ test "read/write(Var)PackedInt" {
}
}
}
+
+pub const PrintError = error{
+ /// As much as possible was written to the buffer, but it was too small to
+ /// fit all the printed bytes.
+ NoSpaceLeft,
+};
+
+/// Render a formatted string into `buffer`. Returns a slice of `buffer`
+/// starting at index 0 containing the result, or `error.NoSpaceLeft` if one or
+/// more bytes were truncated.
+///
+/// See `std.Io.Writer.print`.
+pub fn print(buffer: []u8, comptime format: []const u8, args: anytype) PrintError![]u8 {
+ var w: std.Io.Writer = .fixed(buffer);
+ w.print(format, args) catch |err| switch (err) {
+ error.WriteFailed => return error.NoSpaceLeft,
+ };
+ return w.buffered();
+}
+
+test print {
+ const x: i32 = -1;
+ const y: []const u8 = "hi";
+ var buffer: [64]u8 = undefined;
+ const s = try print(&buffer, "{d}={s}", .{ x, y });
+ try testing.expectEqualStrings("-1=hi", s);
+}
+
+/// Like `print` but returned slice has the provided sentinel.
+pub fn printSentinel(
+ buffer: []u8,
+ comptime format: []const u8,
+ args: anytype,
+ comptime sentinel: u8,
+) PrintError![:sentinel]u8 {
+ const result = try print(buffer, format ++ [1]u8{sentinel}, args);
+ return result[0 .. result.len - 1 :sentinel];
+}
+
+test printSentinel {
+ const x: i32 = -1;
+ const y: []const u8 = "hi";
+ var buffer: [64]u8 = undefined;
+ const s = try printSentinel(&buffer, "{d}={s}", .{ x, y }, 0);
+ try testing.expectEqualStrings("-1=hi", s);
+ try testing.expectEqual(0, s[s.len]);
+}
diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig
index 76e5d11cc46e76cd90aa83601735138367b9d4dd..80341ecc2fa30523ef26bf7f1f68087fea18b925 100644
--- a/lib/std/mem/Allocator.zig
+++ b/lib/std/mem/Allocator.zig
@@ -1,11 +1,12 @@
//! The standard memory allocation interface.
+const Allocator = @This();
+
+const builtin = @import("builtin");
const std = @import("../std.zig");
const assert = std.debug.assert;
const math = std.math;
const mem = std.mem;
-const Allocator = @This();
-const builtin = @import("builtin");
const Alignment = std.mem.Alignment;
pub const Error = error{OutOfMemory};
@@ -444,7 +445,10 @@ pub fn reallocAdvanced(
/// To free a single item, see `destroy`.
pub fn free(self: Allocator, memory: anytype) void {
const slice_info = @typeInfo(@TypeOf(memory)).pointer;
- comptime assert(slice_info.size == .slice);
+ if (slice_info.size != .slice) {
+ // slicing with comptime-known start and end results in *[len]T, which may be free'd
+ comptime assert(slice_info.size == .one and @typeInfo(slice_info.child) == .array);
+ }
const bytes: []u8 = @ptrCast(@constCast(mem.absorbSentinel(memory)));
if (bytes.len == 0) return;
@memset(bytes, undefined);
@@ -471,6 +475,61 @@ pub fn dupeSentinel(
return new_buf[0..m.len :sentinel];
}
+/// Allocates a formatted string which is returned on success.
+///
+/// Returned slice can be deallocated with `free`. If an arena-style allocator
+/// is used instead, such as `std.heap.ArenaAllocator`, then no call to `free`
+/// is necessary.
+///
+/// See `std.Io.Writer.print`.
+pub fn print(a: Allocator, comptime format: []const u8, args: anytype) Error![]u8 {
+ var aw = try std.Io.Writer.Allocating.initCapacity(a, format.len);
+ defer aw.deinit();
+ aw.writer.print(format, args) catch |err| switch (err) {
+ error.WriteFailed => return error.OutOfMemory,
+ };
+ return aw.toOwnedSlice();
+}
+
+test print {
+ const x: i32 = -1;
+ const y: []const u8 = "hi";
+ const a = std.testing.allocator;
+ const s = try print(a, "{d}={s}", .{ x, y });
+ defer free(a, s);
+ try std.testing.expectEqualStrings("-1=hi", s);
+}
+
+/// Like `print` but returned slice has the provided sentinel.
+///
+/// Returned slice can be deallocated with `free`. If an arena-style allocator
+/// is used instead, such as `std.heap.ArenaAllocator`, then no call to `free`
+/// is necessary. Illegal behavior occurs if the returned slice is type-coerced
+/// to a slice without the sentinel and then passed to `free`.
+pub fn printSentinel(
+ a: Allocator,
+ comptime format: []const u8,
+ args: anytype,
+ comptime sentinel: u8,
+) Allocator.Error![:sentinel]u8 {
+ var aw = try std.Io.Writer.Allocating.initCapacity(a, format.len);
+ defer aw.deinit();
+ aw.writer.print(format, args) catch |err| switch (err) {
+ error.WriteFailed => return error.OutOfMemory,
+ };
+ return aw.toOwnedSliceSentinel(sentinel);
+}
+
+test printSentinel {
+ const x: i32 = -1;
+ const y: []const u8 = "hi";
+ const a = std.testing.allocator;
+ const s = try printSentinel(a, "{d}={s}", .{ x, y }, 0);
+ defer free(a, s);
+ try std.testing.expectEqualStrings("-1=hi", s);
+ try std.testing.expectEqual(0, s[s.len]);
+}
+
/// An allocator that always fails to allocate.
pub const failing: Allocator = .{
.ptr = undefined,
diff --git a/lib/std/meta.zig b/lib/std/meta.zig
index 2012f8cafe7c94647ff1bb992d91fc3dc22efc7f..14270ba9d86763f72a5a75eb5f846dee00759954 100644
--- a/lib/std/meta.zig
+++ b/lib/std/meta.zig
@@ -14,31 +14,14 @@ test {
_ = TrailerFlags;
}
-/// Returns the variant of an enum type, `T`, which is named `str`, or `null` if no such variant exists.
+/// Returns the variant of an enum type corresponding to the provided tag name,
+/// or `null` if no such variant exists.
pub fn stringToEnum(comptime T: type, tag_name: []const u8) ?T {
- // Using StaticStringMap here is more performant, but it will start to take too
- // long to compile if the enum is large enough, due to the current limits of comptime
- // performance when doing things like constructing lookup maps at comptime.
- // TODO The '100' here is arbitrary and should be increased when possible:
- // - https://github.com/ziglang/zig/issues/4055
- // - https://github.com/ziglang/zig/issues/3863
- if (@typeInfo(T).@"enum".field_names.len <= 100) {
- return std.StaticStringMap(T).initEnum().get(tag_name);
- } else {
- inline for (@typeInfo(T).@"enum".field_names) |name| {
- if (mem.eql(u8, tag_name, name)) {
- return @field(T, name);
- }
- }
- return null;
- }
+ return std.StaticStringMap(T).initEnum().get(tag_name);
}
test stringToEnum {
- const E1 = enum {
- A,
- B,
- };
+ const E1 = enum { A, B };
try testing.expect(E1.A == stringToEnum(E1, "A").?);
try testing.expect(E1.B == stringToEnum(E1, "B").?);
try testing.expect(null == stringToEnum(E1, "C"));
@@ -516,6 +499,15 @@ test DeclEnum {
try expectEqualEnum(enum {}, DeclEnum(D));
}
+pub fn BareUnion(comptime T: type) type {
+ const u = switch (@typeInfo(T)) {
+ .@"union" => |u| u,
+ else => @compileError("expected union type, found '" ++ @typeName(T) ++ "'"),
+ };
+
+ return @Union(u.layout, null, u.field_names, u.field_types[0..], u.field_attrs[0..]);
+}
+
pub fn Tag(comptime T: type) type {
return switch (@typeInfo(T)) {
.@"enum" => |info| info.tag_type,
@@ -917,6 +909,15 @@ pub inline fn hasUniqueRepresentation(comptime T: type) bool {
return @sizeOf(T) == sum_size;
},
+ .@"union" => |info| {
+ if (info.layout == .@"packed") return @sizeOf(T) * 8 == @bitSizeOf(T);
+ inline for (info.field_types) |field_type| {
+ if (@sizeOf(field_type) != @sizeOf(T)) return false;
+ if (!hasUniqueRepresentation(field_type)) return false;
+ }
+ return true;
+ },
+
.vector => |info| hasUniqueRepresentation(info.child) and
@sizeOf(T) == @sizeOf(info.child) * info.len,
};
@@ -986,6 +987,27 @@ test hasUniqueRepresentation {
try testing.expect(!hasUniqueRepresentation(TestUnion4));
+ const TestUnion5 = extern union {
+ a: u32,
+ b: i32,
+ };
+
+ try testing.expect(hasUniqueRepresentation(TestUnion5));
+
+ const TestUnion6 = packed union(u7) {
+ a: u7,
+ b: i7,
+ };
+
+ try testing.expect(!hasUniqueRepresentation(TestUnion6));
+
+ const TestUnion7 = packed union(u8) {
+ a: u8,
+ b: i8,
+ };
+
+ try testing.expect(hasUniqueRepresentation(TestUnion7));
+
inline for ([_]type{ u8, i16, u32, i64 }) |T| {
try testing.expect(hasUniqueRepresentation(T));
try testing.expect(hasUniqueRepresentation(enum(T) { _ }));
diff --git a/lib/std/multi_array_list.zig b/lib/std/multi_array_list.zig
index 7b99eeb63e1185c0466527b42a99770819a28f46..95404a3288e8459ff334c6e0c0558c71d3d563f6 100644
--- a/lib/std/multi_array_list.zig
+++ b/lib/std/multi_array_list.zig
@@ -44,7 +44,7 @@ pub fn MultiArrayList(comptime T: type) type {
const Elem = switch (@typeInfo(T)) {
.@"struct" => T,
.@"union" => |u| struct {
- pub const Bare = @Union(u.layout, null, u.field_names, u.field_types[0..], u.field_attrs[0..]);
+ pub const Bare = std.meta.BareUnion(T);
pub const Tag =
u.tag_type orelse @compileError("MultiArrayList does not support untagged unions");
tags: Tag,
diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig
index aeaf6f2a53eb961078106775ecb4aad7b89addef..dc22fc6db21bdcf83d929ace73f37594fc0d5982 100644
--- a/lib/std/os/linux.zig
+++ b/lib/std/os/linux.zig
@@ -43,7 +43,7 @@ const arch_bits = switch (native_arch) {
.microblaze, .microblazeel => @import("linux/microblaze.zig"),
.mips, .mipsel => @import("linux/mips.zig"),
.mips64, .mips64el => switch (builtin.abi) {
- .gnuabin32, .muslabin32 => @import("linux/mipsn32.zig"),
+ .gnuabin32, .muslabin32, .abin32 => @import("linux/mipsn32.zig"),
else => @import("linux/mips64.zig"),
},
.or1k => @import("linux/or1k.zig"),
@@ -57,7 +57,7 @@ const arch_bits = switch (native_arch) {
.sparc64 => @import("linux/sparc64.zig"),
.x86 => @import("linux/x86.zig"),
.x86_64 => switch (builtin.abi) {
- .gnux32, .muslx32 => @import("linux/x32.zig"),
+ .gnux32, .muslx32, .x32 => @import("linux/x32.zig"),
else => @import("linux/x86_64.zig"),
},
.xtensa, .xtensaeb => @import("linux/xtensa.zig"),
@@ -80,6 +80,7 @@ pub const restore_rt = syscall_bits.restore_rt;
pub const socketcall = syscall_bits.socketcall;
pub const syscall_pipe = syscall_bits.syscall_pipe;
pub const syscall_fork = syscall_bits.syscall_fork;
+pub const syscall_lseek = syscall_bits.syscall_lseek;
pub fn clone(
func: *const fn (arg: usize) callconv(.c) u8,
@@ -143,7 +144,7 @@ pub const SYS = switch (native_arch) {
.microblaze, .microblazeel => syscalls.Microblaze,
.mips, .mipsel => syscalls.MipsO32,
.mips64, .mips64el => switch (builtin.abi) {
- .gnuabin32, .muslabin32 => syscalls.MipsN32,
+ .gnuabin32, .muslabin32, .abin32 => syscalls.MipsN32,
else => syscalls.MipsN64,
},
.or1k => syscalls.OpenRisc,
@@ -157,7 +158,7 @@ pub const SYS = switch (native_arch) {
.sparc64 => syscalls.Sparc64,
.x86 => syscalls.X86,
.x86_64 => switch (builtin.abi) {
- .gnux32, .muslx32 => syscalls.X32,
+ .gnux32, .muslx32, .x32 => syscalls.X32,
else => syscalls.X64,
},
.xtensa, .xtensaeb => syscalls.Xtensa,
@@ -751,8 +752,8 @@ fn splitValue64(val: i64) [2]u32 {
}
/// Get the errno from a syscall return value. SUCCESS means no error.
-pub fn errno(r: usize) E {
- const signed_r: isize = @bitCast(r);
+pub fn errno(r: u64) E {
+ const signed_r: i32 = @bitCast(@as(u32, @truncate(r)));
const int = if (signed_r > -4096 and signed_r < 0) -signed_r else 0;
return @enumFromInt(int);
}
@@ -1809,7 +1810,7 @@ pub fn fchmodat2(fd: fd_t, path: [*:0]const u8, mode: mode_t, flags: u32) usize
}
/// Can only be called on 32 bit systems. For 64 bit see `lseek`.
-pub fn llseek(fd: fd_t, offset: off_t, result: ?*off_t, whence: u32) usize {
+pub fn llseek(fd: fd_t, offset: off_t, result: ?*off_t, whence: u32) u32 {
// NOTE: The offset parameter splitting is independent from the target
// endianness.
return syscall5(
@@ -1823,8 +1824,17 @@ pub fn llseek(fd: fd_t, offset: off_t, result: ?*off_t, whence: u32) usize {
}
/// Can only be called on 64 bit systems. For 32 bit see `llseek`.
-pub fn lseek(fd: fd_t, offset: off_t, whence: u32) usize {
- return syscall3(.lseek, @as(u32, @bitCast(fd)), @as(u64, @bitCast(offset)), whence);
+pub fn lseek(fd: fd_t, offset: off_t, whence: u32) u64 {
+ return switch (builtin.abi) {
+ .gnuabin32,
+ .muslabin32,
+ .abin32,
+ .gnux32,
+ .muslx32,
+ .x32,
+ => syscall_lseek(fd, offset, whence),
+ else => syscall3(.lseek, @as(u32, @bitCast(fd)), @as(u64, @bitCast(offset)), whence),
+ };
}
pub fn exit(status: i32) noreturn {
@@ -1998,7 +2008,7 @@ pub const F = struct {
const SETLKW = 35;
},
.mips64, .mips64el => switch (native_abi) {
- .gnuabin32, .muslabin32 => struct {
+ .gnuabin32, .muslabin32, .abin32 => struct {
const GETLK = 33;
const SETLK = 34;
const SETLKW = 35;
@@ -3179,7 +3189,7 @@ pub fn tee(src: fd_t, dest: fd_t, len: usize, flags: u32) usize {
}
pub const Sysinfo = switch (native_abi) {
- .gnux32, .muslx32 => extern struct {
+ .gnux32, .muslx32, .x32 => extern struct {
/// Seconds since boot
uptime: i64,
/// 1, 5, and 15 minute load averages
@@ -9450,7 +9460,11 @@ pub const UTIME = struct {
};
// https://github.com/ziglang/zig/issues/4726#issuecomment-2190337877
-pub const timespec = if (native_arch == .hexagon or native_arch == .riscv32) kernel_timespec else extern struct {
+const use_kernel_timespec = native_arch == .hexagon or native_arch == .riscv32 or switch (native_abi) {
+ .gnux32, .muslx32, .x32 => true,
+ else => false,
+};
+pub const timespec = if (use_kernel_timespec) kernel_timespec else extern struct {
sec: isize,
nsec: isize,
};
@@ -10745,11 +10759,11 @@ pub const AUDIT = struct {
.mips => .MIPS,
.mipsel => .MIPSEL,
.mips64 => switch (native_abi) {
- .gnuabin32, .muslabin32 => .MIPS64N32,
+ .gnuabin32, .muslabin32, .abin32 => .MIPS64N32,
else => .MIPS64,
},
.mips64el => switch (native_abi) {
- .gnuabin32, .muslabin32 => .MIPSEL64N32,
+ .gnuabin32, .muslabin32, .abin32 => .MIPSEL64N32,
else => .MIPSEL64,
},
.or1k => .OPENRISC,
diff --git a/lib/std/os/linux/IoUring/test.zig b/lib/std/os/linux/IoUring/test.zig
index add4f30f8512e1c0c470cba0f253a7ff80159cf1..27925c81fb138ec20efbb6bc05acfff5a4a09879 100644
--- a/lib/std/os/linux/IoUring/test.zig
+++ b/lib/std/os/linux/IoUring/test.zig
@@ -526,7 +526,9 @@ test "sendmsg/recvmsg" {
var address_server: linux.sockaddr.in = .{
.port = 0,
- .addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
+ .addr = @as(*align(1) const u32, @ptrCast(
+ &@as([4]u8, .{ 127, 0, 0, 1 }),
+ )).*,
};
const server = try socket(address_server.family, posix.SOCK.DGRAM, 0);
@@ -1028,7 +1030,9 @@ test "shutdown" {
var address: linux.sockaddr.in = .{
.port = 0,
- .addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
+ .addr = @as(*align(1) const u32, @ptrCast(
+ &@as([4]u8, .{ 127, 0, 0, 1 }),
+ )).*,
};
// Socket bound, expect shutdown to work
@@ -1740,7 +1744,9 @@ test "accept multishot" {
var address: linux.sockaddr.in = .{
.port = 0,
- .addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
+ .addr = @as(*align(1) const u32, @ptrCast(
+ &@as([4]u8, .{ 127, 0, 0, 1 }),
+ )).*,
};
const listener_socket = try createListenerSocket(&address);
defer _ = linux.close(listener_socket);
@@ -1842,7 +1848,9 @@ test "accept_direct" {
defer ring.deinit();
var address: linux.sockaddr.in = .{
.port = 0,
- .addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
+ .addr = @as(*align(1) const u32, @ptrCast(
+ &@as([4]u8, .{ 127, 0, 0, 1 }),
+ )).*,
};
// register direct file descriptors
@@ -1931,7 +1939,9 @@ test "accept_multishot_direct" {
var address: linux.sockaddr.in = .{
.port = 0,
- .addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
+ .addr = @as(*align(1) const u32, @ptrCast(
+ &@as([4]u8, .{ 127, 0, 0, 1 }),
+ )).*,
};
var registered_fds: [2]linux.fd_t = @splat(-1);
@@ -2041,7 +2051,9 @@ test "socket_direct/socket_direct_alloc/close_direct" {
// use sockets from registered_fds in connect operation
var address: linux.sockaddr.in = .{
.port = 0,
- .addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
+ .addr = @as(*align(1) const u32, @ptrCast(
+ &@as([4]u8, .{ 127, 0, 0, 1 }),
+ )).*,
};
const listener_socket = try createListenerSocket(&address);
defer _ = linux.close(listener_socket);
@@ -2426,7 +2438,9 @@ test "bind/listen/connect" {
var addr: linux.sockaddr.in = .{
.port = 0,
- .addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
+ .addr = @as(*align(1) const u32, @ptrCast(
+ &@as([4]u8, .{ 127, 0, 0, 1 }),
+ )).*,
};
const proto: u32 = if (addr.family == linux.AF.UNIX) 0 else linux.IPPROTO.TCP;
@@ -2614,7 +2628,9 @@ pub fn createSocketTestHarness(ring: *IoUring) !SocketTestHarness {
// Create a TCP server socket
var address: linux.sockaddr.in = .{
.port = 0,
- .addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
+ .addr = @as(*align(1) const u32, @ptrCast(
+ &@as([4]u8, .{ 127, 0, 0, 1 }),
+ )).*,
};
const listener_socket = try createListenerSocket(&address);
errdefer _ = linux.close(listener_socket);
diff --git a/lib/std/os/linux/mipsn32.zig b/lib/std/os/linux/mipsn32.zig
index 04b240af9fa7631a635024cc7847a62fd691023a..fcaebaa9189e5d005d8026febad952fe29e8ba7d 100644
--- a/lib/std/os/linux/mipsn32.zig
+++ b/lib/std/os/linux/mipsn32.zig
@@ -163,6 +163,25 @@ pub fn syscall_pipe(
: .{ .r1 = true, .r3 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true });
}
+pub fn syscall_lseek(
+ fd: std.os.linux.fd_t,
+ offset: std.os.linux.off_t,
+ whence: u32,
+) u64 {
+ return asm volatile (
+ \\ syscall
+ \\ beq $a3, $zero, 1f
+ \\ blez $v0, 1f
+ \\ dsubu $v0, $zero, $v0
+ \\1:
+ : [ret] "={$2}" (-> u64),
+ : [number] "{$2}" (@intFromEnum(SYS.lseek)),
+ [fd] "{$4}" (@as(u32, @bitCast(fd))),
+ [offset] "{$5}" (@as(u64, @bitCast(offset))),
+ [whence] "{$6}" (whence),
+ : .{ .r1 = true, .r3 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true });
+}
+
pub fn clone() callconv(.naked) u32 {
// __clone(func, stack, flags, arg, ptid, tls, ctid)
// a0, a1, a2, a3, a4, a5, a6
@@ -200,8 +219,8 @@ pub fn clone() callconv(.naked) u32 {
\\ move $fp, $zero
\\ move $ra, $zero
\\
- \\ ld $t9, 0($sp)
- \\ ld $a0, 4($sp)
+ \\ lw $t9, 0($sp)
+ \\ lw $a0, 4($sp)
\\ jalr $t9
\\
\\ move $a0, $v0
diff --git a/lib/std/os/linux/syscalls.zig b/lib/std/os/linux/syscalls.zig
index 226081bf4d6e5942559eef906ee1fb71b8b3a597..4182eb4e46ce497efc9aebba7435835deb8d916c 100644
--- a/lib/std/os/linux/syscalls.zig
+++ b/lib/std/os/linux/syscalls.zig
@@ -1,5 +1,5 @@
// This file is automatically generated by tools/generate_linux_syscalls.zig
-// This list current as of kernel: 7.0.0
+// This list current as of kernel: 7.1.0
pub const X86 = enum(usize) {
restart_syscall = 0,
@@ -9929,7 +9929,6 @@ pub const Hppa64 = enum(usize) {
personality = 136,
setfsuid = 138,
setfsgid = 139,
- llseek = 140,
getdents = 141,
newselect = 142,
flock = 143,
diff --git a/lib/std/os/linux/x32.zig b/lib/std/os/linux/x32.zig
index d26833d9a17bdf40bd76d6477068152fc676dbb2..3b10612786a6d256775c3f3dbe068b1ced5e352b 100644
--- a/lib/std/os/linux/x32.zig
+++ b/lib/std/os/linux/x32.zig
@@ -109,6 +109,20 @@ pub fn syscall6(
: .{ .rcx = true, .r11 = true, .memory = true });
}
+pub fn syscall_lseek(
+ fd: std.os.linux.fd_t,
+ offset: std.os.linux.off_t,
+ whence: u32,
+) u64 {
+ return asm volatile ("syscall"
+ : [ret] "={rax}" (-> u64),
+ : [number] "{rax}" (@intFromEnum(SYS.lseek)),
+ [fd] "{rdi}" (@as(u32, @bitCast(fd))),
+ [offset] "{rsi}" (@as(u64, @bitCast(offset))),
+ [whence] "{rdx}" (whence),
+ : .{ .rcx = true, .r11 = true, .memory = true });
+}
+
pub fn clone() callconv(.naked) u32 {
asm volatile (
\\ movl $0x40000038,%%eax // SYS_clone
@@ -116,7 +130,7 @@ pub fn clone() callconv(.naked) u32 {
\\ mov %%rdx,%%rdi
\\ mov %%r8,%%rdx
\\ mov %%r9,%%r8
- \\ mov 8(%%rsp),%%r10
+ \\ mov 8(%%rsp),%%r10d
\\ mov %%r11,%%r9
\\ and $-16,%%rsi
\\ sub $8,%%rsi
@@ -161,7 +175,7 @@ pub fn restore_rt() callconv(.naked) noreturn {
}
}
-pub const time_t = i32;
+pub const time_t = i64;
pub const VDSO = struct {
pub const CGT_SYM = "__vdso_clock_gettime";
diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig
index cc2dac949e31d6c5a0bda855079f234f0ae7e181..e48ec85fe32bc7af9c7dce101ebf5d2d6a9fbd28 100644
--- a/lib/std/os/uefi.zig
+++ b/lib/std/os/uefi.zig
@@ -218,7 +218,7 @@ pub const TimeCapabilities = extern struct {
pub const FileHandle = *opaque {};
test "GUID formatting" {
- const bytes = [_]u8{ 137, 60, 203, 50, 128, 128, 124, 66, 186, 19, 80, 73, 135, 59, 194, 135 };
+ const bytes: [16]u8 = .{ 137, 60, 203, 50, 128, 128, 124, 66, 186, 19, 80, 73, 135, 59, 194, 135 };
const guid: Guid = @bitCast(bytes);
const str = try std.fmt.allocPrint(std.testing.allocator, "{f}", .{guid});
diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig
index 89105b673602a7c5d13439100a4426082b7c3b0f..7a3c134e2a3416f35aed6cbff592105f0cd95109 100644
--- a/lib/std/os/windows.zig
+++ b/lib/std/os/windows.zig
@@ -4189,19 +4189,11 @@ pub const GUID = extern struct {
Data3: u16,
Data4: [8]u8,
- const hex_offsets = switch (builtin.target.cpu.arch.endian()) {
- .big => [16]u6{
- 0, 2, 4, 6,
- 9, 11, 14, 16,
- 19, 21, 24, 26,
- 28, 30, 32, 34,
- },
- .little => [16]u6{
- 6, 4, 2, 0,
- 11, 9, 16, 14,
- 19, 21, 24, 26,
- 28, 30, 32, 34,
- },
+ const hex_offsets: [16]u6 = .{
+ 6, 4, 2, 0,
+ 11, 9, 16, 14,
+ 19, 21, 24, 26,
+ 28, 30, 32, 34,
};
pub fn parse(s: []const u8) GUID {
@@ -4216,12 +4208,21 @@ pub const GUID = extern struct {
assert(s[13] == '-');
assert(s[18] == '-');
assert(s[23] == '-');
- var bytes: [16]u8 = undefined;
- for (hex_offsets, 0..) |hex_offset, i| {
- bytes[i] = (try std.fmt.charToDigit(s[hex_offset], 16)) << 4 |
- try std.fmt.charToDigit(s[hex_offset + 1], 16);
- }
- return @as(GUID, @bitCast(bytes));
+ var raw1: [4]u8 = undefined;
+ var raw2: [2]u8 = undefined;
+ var raw3: [2]u8 = undefined;
+ var raw4: [8]u8 = undefined;
+ assert((try std.fmt.hexToBytes(&raw1, s[0..8])).len == raw1.len);
+ assert((try std.fmt.hexToBytes(&raw2, s[9..13])).len == raw2.len);
+ assert((try std.fmt.hexToBytes(&raw3, s[14..18])).len == raw3.len);
+ assert((try std.fmt.hexToBytes(raw4[0..2], s[19..23])).len == 2);
+ assert((try std.fmt.hexToBytes(raw4[2..8], s[24..36])).len == 6);
+ return .{
+ .Data1 = @byteSwap(@as(u32, @bitCast(raw1))),
+ .Data2 = @byteSwap(@as(u16, @bitCast(raw2))),
+ .Data3 = @byteSwap(@as(u16, @bitCast(raw3))),
+ .Data4 = raw4,
+ };
}
pub fn format(self: GUID, w: *std.Io.Writer) std.Io.Writer.Error!void {
@@ -4233,28 +4234,28 @@ pub const GUID = extern struct {
self.Data4[2..8],
});
}
-};
-test GUID {
- try std.testing.expectEqual(
- GUID{
+ test parse {
+ const expected: GUID = .{
.Data1 = 0x01234567,
.Data2 = 0x89ab,
.Data3 = 0xef10,
.Data4 = "\x32\x54\x76\x98\xba\xdc\xfe\x91".*,
- },
- GUID.parse("{01234567-89AB-EF10-3254-7698badcfe91}"),
- );
- try std.testing.expectFmt(
- "{01234567-89ab-ef10-3254-7698badcfe91}",
- "{f}",
- .{GUID.parse("{01234567-89AB-EF10-3254-7698badcfe91}")},
- );
- try std.testing.expectFmt(
- "{00000001-0001-0001-0001-000000000001}",
- "{f}",
- .{GUID{ .Data1 = 1, .Data2 = 1, .Data3 = 1, .Data4 = [_]u8{ 0, 1, 0, 0, 0, 0, 0, 1 } }},
- );
+ };
+ try std.testing.expectEqual(expected, GUID.parse("{01234567-89AB-EF10-3254-7698badcfe91}"));
+ }
+
+ test format {
+ const guid0: GUID = .{ .Data1 = 1, .Data2 = 1, .Data3 = 1, .Data4 = .{ 0, 1, 0, 0, 0, 0, 0, 1 } };
+ try std.testing.expectFmt("{00000001-0001-0001-0001-000000000001}", "{f}", .{guid0});
+
+ const guid1: GUID = .parse("{01234567-89AB-EF10-3254-7698badcfe91}");
+ try std.testing.expectFmt("{01234567-89ab-ef10-3254-7698badcfe91}", "{f}", .{guid1});
+ }
+};
+
+test {
+ _ = GUID;
}
pub const COORD = extern struct {
diff --git a/lib/std/pie.zig b/lib/std/pie.zig
index 8d7ac3fa7c447ed7f73a616a982daa321bc87960..0252cde9e8f0161ae5a3767723c3853f94ec82f0 100644
--- a/lib/std/pie.zig
+++ b/lib/std/pie.zig
@@ -162,7 +162,7 @@ inline fn getDynamicSymbol() [*]const elf.Dyn {
:
: .{ .lr = true }),
.mips64, .mips64el => switch (builtin.abi) {
- .gnuabin32, .muslabin32 => asm volatile (
+ .gnuabin32, .muslabin32, .abin32 => asm volatile (
\\ .weak _DYNAMIC
\\ .hidden _DYNAMIC
\\ bal 1f
diff --git a/lib/std/process.zig b/lib/std/process.zig
index bcee558a65eef07afab17b484cc012326bb5004c..f3ef291763d642426770883e886c8a5a50aeae41 100644
--- a/lib/std/process.zig
+++ b/lib/std/process.zig
@@ -315,7 +315,15 @@ pub fn replacePath(io: Io, dir: Io.Dir, options: ReplaceOptions) ReplaceError {
pub const ArgExpansion = enum { expand, no_expand };
/// File name extensions supported natively by `CreateProcess()` on Windows.
-pub const WindowsExtension = enum { bat, cmd, com, exe };
+pub const WindowsExtension = enum {
+ bat,
+ cmd,
+ com,
+ exe,
+
+ /// Length of the longest supported extension (in ASCII characters)
+ pub const max_len = 3;
+};
pub const SpawnError = error{
/// The operating system does not support creating child processes.
diff --git a/lib/std/process/Environ.zig b/lib/std/process/Environ.zig
index bf0408c31ddc4eebf48a08dea54b6391a524e012..a2b2f4110f499171a09ffb42c3d631f7e48faee7 100644
--- a/lib/std/process/Environ.zig
+++ b/lib/std/process/Environ.zig
@@ -101,7 +101,7 @@ pub const Map = struct {
array_hash_map: ArrayHashMap,
allocator: Allocator,
- const ArrayHashMap = std.ArrayHashMapUnmanaged([]const u8, []const u8, EnvNameHashContext, false);
+ const ArrayHashMap = std.array_hash_map.Custom([]const u8, []const u8, EnvNameHashContext, false);
pub const Size = usize;
diff --git a/lib/std/process/Preopens.zig b/lib/std/process/Preopens.zig
index 3baf696ee9a5d95dbf2bed352ea4867e8c3fde8c..6a7337a31e9bcaf207af9d2ab501448a95649cc3 100644
--- a/lib/std/process/Preopens.zig
+++ b/lib/std/process/Preopens.zig
@@ -16,7 +16,7 @@ pub const empty: Preopens = switch (native_os) {
pub const Map = switch (native_os) {
// Indexed by file descriptor number.
- .wasi => std.StringArrayHashMapUnmanaged(void),
+ .wasi => std.array_hash_map.String(void),
else => void,
};
diff --git a/lib/std/sort/pdq.zig b/lib/std/sort/pdq.zig
index 85d3a62c9c5233441edb013b6f6d611d7159b9b9..5b0da14156ae1365f7a677c84453d0b07d84a774 100644
--- a/lib/std/sort/pdq.zig
+++ b/lib/std/sort/pdq.zig
@@ -44,12 +44,11 @@ pub fn pdqContext(a: usize, b: usize, context: anytype) void {
// slices of up to this length get sorted using insertion sort.
const max_insertion = 24;
// number of allowed imbalanced partitions before switching to heap sort.
- const max_limit = std.math.floorPowerOfTwo(usize, b - a) + 1;
+ const max_limit = if (b > a) math.log2_int(usize, b - a) else 0;
// set upper bound on stack memory usage.
const Range = struct { a: usize, b: usize, limit: usize, leftmost: bool };
- const stack_size = math.log2(math.maxInt(usize) + 1);
- var stack: [stack_size]Range = undefined;
+ var stack: [2 * @bitSizeOf(usize)]Range = undefined;
var range = Range{ .a = a, .b = b, .limit = max_limit, .leftmost = true };
var top: usize = 0;
diff --git a/lib/std/spirv.zig b/lib/std/spirv.zig
new file mode 100644
index 0000000000000000000000000000000000000000..6f9fd74967053ec295ad14882d4abda7eedccc18
--- /dev/null
+++ b/lib/std/spirv.zig
@@ -0,0 +1,84 @@
+const std = @import("std.zig");
+
+pub const position_in = @extern(*addrspace(.input) @Vector(4, f32), .{ .name = "position" });
+pub const position_out = @extern(*addrspace(.output) @Vector(4, f32), .{ .name = "position" });
+pub const point_size_in = @extern(*addrspace(.input) f32, .{ .name = "point_size" });
+pub const point_size_out = @extern(*addrspace(.output) f32, .{ .name = "point_size" });
+pub extern const invocation_id: u32 addrspace(.input);
+pub extern const frag_coord: @Vector(4, f32) addrspace(.input);
+pub extern const point_coord: @Vector(2, f32) addrspace(.input);
+// TODO: direct/indirect values
+// pub extern const front_facing: bool addrspace(.input);
+// TODO: runtime array
+// pub extern const sample_mask;
+pub extern var frag_depth: f32 addrspace(.output);
+pub extern const num_workgroups: @Vector(3, u32) addrspace(.input);
+pub extern const workgroup_size: @Vector(3, u32) addrspace(.input);
+pub extern const workgroup_id: @Vector(3, u32) addrspace(.input);
+pub extern const local_invocation_id: @Vector(3, u32) addrspace(.input);
+pub extern const global_invocation_id: @Vector(3, u32) addrspace(.input);
+pub extern const vertex_index: u32 addrspace(.input);
+pub extern const instance_index: u32 addrspace(.input);
+
+pub const Scope = enum(u32) {
+ cross_device = 0,
+ device = 1,
+ workgroup = 2,
+ subgroup = 3,
+ invocation = 4,
+ queue_family = 5,
+ shader_call_khr = 6,
+};
+
+pub const MemorySemantics = packed struct(u32) {
+ _reserved_bit_0: bool = false,
+ acquire: bool = false,
+ release: bool = false,
+ acquire_release: bool = false,
+ sequentially_consistent: bool = false,
+ _reserved_bit_5: bool = false,
+ uniform_memory: bool = false,
+ subgroup_memory: bool = false,
+ workgroup_memory: bool = false,
+ cross_workgroup_memory: bool = false,
+ atomic_counter_memory: bool = false,
+ image_memory: bool = false,
+ output_memory: bool = false,
+ make_available: bool = false,
+ make_visible: bool = false,
+ @"volatile": bool = false,
+ _reserved: u16 = 0,
+
+ pub const none: MemorySemantics = .{};
+};
+
+pub fn controlBarrier(
+ comptime execution: Scope,
+ comptime memory: Scope,
+ comptime semantics: MemorySemantics,
+) void {
+ asm volatile (
+ \\OpControlBarrier %exec %mem %sem
+ :
+ : [exec] "" (@as(u32, @intFromEnum(execution))),
+ [mem] "" (@as(u32, @intFromEnum(memory))),
+ [sem] "" (@as(u32, @bitCast(semantics))),
+ );
+}
+
+pub fn memoryBarrier(comptime memory: Scope, comptime semantics: MemorySemantics) void {
+ asm volatile (
+ \\OpMemoryBarrier %mem %sem
+ :
+ : [mem] "" (@as(u32, @intFromEnum(memory))),
+ [sem] "" (@as(u32, @bitCast(semantics))),
+ );
+}
+
+pub fn workgroupBarrier() void {
+ controlBarrier(
+ .workgroup,
+ .workgroup,
+ .{ .acquire_release = true, .workgroup_memory = true },
+ );
+}
diff --git a/lib/std/start.zig b/lib/std/start.zig
index 6a20adf011ab109115e4365fb9d115ce37d6e0e5..68785b47aed7f36f2bf9dcea941eb12657c7c203 100644
--- a/lib/std/start.zig
+++ b/lib/std/start.zig
@@ -70,7 +70,19 @@ comptime {
// case it's not required to provide an entrypoint such as main.
if (!@hasDecl(root, start_sym_name) and @hasDecl(root, "main")) @export(&wasm_freestanding_start, .{ .name = start_sym_name });
} else switch (native_os) {
- .other, .freestanding, .@"3ds", .psp, .vita => {},
+ .other,
+ .freestanding,
+ .vulkan,
+ .opengl,
+ .opencl,
+
+ .@"3ds",
+ .wiiu,
+
+ .psx,
+ .psp,
+ .vita,
+ => {},
else => if (!@hasDecl(root, start_sym_name)) @export(&_start, .{ .name = start_sym_name }),
}
}
@@ -81,7 +93,7 @@ fn DllMainCRTStartup(
fdwReason: std.os.windows.DWORD,
lpReserved: std.os.windows.LPVOID,
) callconv(.winapi) std.os.windows.BOOL {
- if (!builtin.single_threaded and !builtin.link_libc) {
+ if (!builtin.single_threaded) {
_ = @import("os/windows/tls.zig");
}
@@ -373,7 +385,7 @@ fn _start() callconv(.naked) noreturn {
\\ jalr $t9
,
.mips64, .mips64el => switch (builtin.abi) {
- .gnuabin32, .muslabin32 =>
+ .gnuabin32, .muslabin32, .abin32 =>
\\ move $fp, $zero
\\ bal 1f
\\ .gpword .
diff --git a/lib/std/static_string_map.zig b/lib/std/static_string_map.zig
index f0bfc2adb75cb7b4852d2c0719b8761db0e38cf4..950468fd5162d427c73811c5561e0e020d72b9e6 100644
--- a/lib/std/static_string_map.zig
+++ b/lib/std/static_string_map.zig
@@ -241,7 +241,10 @@ pub fn StaticStringMapWithEql(
return self.kvs.values[self.getIndex(str) orelse return null];
}
- fn getIndex(self: Self, str: []const u8) ?usize {
+ /// Returns the index corresponding to the `str` within the
+ /// generated `kvs`, or `null` if `str` was not found.
+ /// The returned index is unrelated to the input `kvs_list`.
+ pub fn getIndex(self: Self, str: []const u8) ?usize {
const kvs = self.kvs.*;
if (kvs.len == 0)
return null;
@@ -279,6 +282,14 @@ pub fn StaticStringMapWithEql(
};
}
+ /// Returns the index within the generated `kvs` corresponding to the
+ /// key-value pair where key is the longest prefix of `str`, or `null`
+ /// if no such key-value pair was found. The returned index is unrelated
+ /// to the input `kvs_list`.
+ ///
+ /// This is effectively an O(N) algorithm which loops from `max_len` to
+ /// `min_len` and calls `getIndex()` to check all keys with the given
+ /// len.
pub fn getLongestPrefixIndex(self: Self, str: []const u8) ?usize {
if (self.kvs.len == 0)
return null;
@@ -294,11 +305,15 @@ pub fn StaticStringMapWithEql(
return null;
}
+ /// Returns the slice of keys from the generated `kvs`, which may
+ /// be in a different order than the input `kvs_list`.
pub fn keys(self: Self) []const []const u8 {
const kvs = self.kvs.*;
return kvs.keys[0..kvs.len];
}
+ /// Returns the slice of values from the generated `kvs`, which may
+ /// be in a different order than the input `kvs_list`.
pub fn values(self: Self) []const V {
const kvs = self.kvs.*;
return kvs.values[0..kvs.len];
@@ -504,6 +519,20 @@ test "comptime-only value" {
try testing.expect(map.get("d") == null);
}
+test "getIndex" {
+ const slice = [_]TestKV{
+ .{ "longer", .A },
+ .{ "short", .B },
+ };
+ const map = TestMap.initComptime(slice);
+
+ // This index can be different than the index of the "short" KV in `slice`
+ const short_index = map.getIndex("short").?;
+ try testing.expectEqualStrings("short", map.keys()[short_index]);
+ try testing.expectEqual(.B, map.values()[short_index]);
+ try testing.expectEqual(null, map.getIndex("missing"));
+}
+
test "getLongestPrefix" {
const slice = [_]TestKV{
.{ "a", .A },
diff --git a/lib/std/std.zig b/lib/std/std.zig
index 3f2fb1d62d0fb91d048c251c5c9ca569cccd4263..e7c50a946091a47dccf4cf1301d2982189ff8589 100644
--- a/lib/std/std.zig
+++ b/lib/std/std.zig
@@ -81,7 +81,7 @@ pub const elf = @import("elf.zig");
pub const enums = @import("enums.zig");
pub const fmt = @import("fmt.zig");
pub const fs = @import("fs.zig");
-pub const gpu = @import("gpu.zig");
+pub const spirv = @import("spirv.zig");
pub const hash = @import("hash.zig");
pub const hash_map = @import("hash_map.zig");
pub const heap = @import("heap.zig");
diff --git a/lib/std/testing.zig b/lib/std/testing.zig
index 9f00c270d4e59152eeeab8c761de32f2c847109e..46c7fe938b22300c23dcedc3570cb329090d3d3a 100644
--- a/lib/std/testing.zig
+++ b/lib/std/testing.zig
@@ -79,6 +79,7 @@ fn expectEqualInner(comptime T: type, expected: T, actual: T) !void {
switch (@typeInfo(@TypeOf(actual))) {
.noreturn,
.@"opaque",
+ .spirv,
.frame,
.@"anyframe",
=> @compileError("value of type " ++ @typeName(@TypeOf(actual)) ++ " encountered"),
@@ -140,39 +141,45 @@ fn expectEqualInner(comptime T: type, expected: T, actual: T) !void {
try expectEqualSlices(info.child, &expect_array, &actual_array);
},
- .@"struct" => |structType| {
- inline for (structType.field_names) |field_name| {
+ .@"struct" => |@"struct"| {
+ inline for (@"struct".field_names) |field_name| {
try expectEqual(@field(expected, field_name), @field(actual, field_name));
}
},
- .@"union" => |union_info| {
- if (union_info.tag_type == null) {
- const first_size = @bitSizeOf(union_info.field_types[0]);
- inline for (union_info.field_types) |field_type| {
+ .@"union" => |@"union"| if (@"union".backing_integer) |Int| {
+ try expectEqual(@as(Int, @bitCast(expected)), @as(Int, @bitCast(actual)));
+ } else switch (@"union".layout) {
+ .@"packed" => {
+ const Int = @Int(.unsigned, @bitSizeOf(T));
+ try expectEqual(@as(Int, @bitCast(expected)), @as(Int, @bitCast(actual)));
+ },
+ .@"extern" => {
+ const first_size = @bitSizeOf(@"union".field_types[0]);
+ inline for (@"union".field_types) |field_type| {
if (@bitSizeOf(field_type) != first_size) {
- @compileError("Unable to compare untagged unions with varying field sizes for type " ++ @typeName(@TypeOf(actual)));
+ @compileError("Unable to compare extern unions with varying field sizes for type " ++ @typeName(T));
}
}
-
- const BackingInt = @Int(.unsigned, @bitSizeOf(T));
+ const FieldInt = @Int(.unsigned, first_size);
+ const expected_field = @field(expected, @"union".field_names[0]);
+ const actual_field = @field(actual, @"union".field_names[0]);
return expectEqual(
- @as(BackingInt, @bitCast(expected)),
- @as(BackingInt, @bitCast(actual)),
+ @as(FieldInt, @bitCast(expected_field)),
+ @as(FieldInt, @bitCast(actual_field)),
);
- }
-
- const Tag = std.meta.Tag(@TypeOf(expected));
-
- const expectedTag = @as(Tag, expected);
- const actualTag = @as(Tag, actual);
-
- try expectEqual(expectedTag, actualTag);
-
- // we only reach this switch if the tags are equal
- switch (expected) {
- inline else => |val, tag| try expectEqual(val, @field(actual, @tagName(tag))),
- }
+ },
+ .auto => {
+ const Tag = @"union".tag_type orelse @compileError("byteSwapAllFields expects packed, extern, or tagged union");
+
+ try expectEqual(@as(Tag, expected), @as(Tag, actual));
+ switch (expected) {
+ inline else => |expected_payload, tag| {
+ const actual_payload = @field(actual, @tagName(tag));
+ try expectEqual(expected_payload, actual_payload);
+ },
+ }
+ },
},
.optional => {
@@ -737,6 +744,7 @@ fn expectEqualDeepInner(comptime T: type, expected: T, actual: T) error{TestExpe
switch (@typeInfo(@TypeOf(actual))) {
.noreturn,
.@"opaque",
+ .spirv,
.frame,
.@"anyframe",
=> @compileError("value of type " ++ @typeName(@TypeOf(actual)) ++ " encountered"),
diff --git a/lib/std/zig.zig b/lib/std/zig.zig
index 6cd6deecb66f0070411926184fd48929eb6c03f0..05891c582e38646da978177e34a3e8b26ac7f0af 100644
--- a/lib/std/zig.zig
+++ b/lib/std/zig.zig
@@ -774,7 +774,7 @@ pub const EnvVar = enum {
ZIG_VERBOSE_CC,
ZIG_DEBUG_CMD,
ZIG_IS_DETECTING_LIBC_PATHS,
- ZIG_IS_TRYING_TO_NOT_CALL_ITSELF,
+ ZIG_IS_AVOIDING_CALLING_ITSELF,
// C toolchain integration
NIX_CFLAGS_COMPILE,
@@ -996,14 +996,11 @@ pub const EmitArtifact = enum {
docs,
pdb,
h,
- compiler_rt_dyn_lib,
/// If using `Server` to communicate with the compiler, it will place requested artifacts in
/// paths under the output directory, where those paths are named according to this function.
/// Returned string is allocated with `gpa` and owned by the caller.
pub fn cacheName(ea: EmitArtifact, gpa: Allocator, opts: BinNameOptions) Allocator.Error![]const u8 {
- // hack for stage2_x86_64 + coff. See Coff.flush.
- if (ea == .compiler_rt_dyn_lib) return "compiler_rt.dll";
const suffix: []const u8 = switch (ea) {
.bin => return binNameAlloc(gpa, opts),
.@"asm" => ".s",
@@ -1013,7 +1010,6 @@ pub const EmitArtifact = enum {
.docs => "-docs",
.pdb => ".pdb",
.h => ".h",
- .compiler_rt_dyn_lib => unreachable,
};
return std.fmt.allocPrint(gpa, "{s}{s}", .{ opts.root_name, suffix });
}
diff --git a/lib/std/zig/Ast/Render.zig b/lib/std/zig/Ast/Render.zig
index 6c8c0c9143d147b0f2483148f305c7b00c1cf304..8f5b2e2c276f5b8680fb56173154bcbdbf8966e6 100644
--- a/lib/std/zig/Ast/Render.zig
+++ b/lib/std/zig/Ast/Render.zig
@@ -42,7 +42,7 @@ pub const Fixups = struct {
/// These nodes will be replaced with a different node.
replace_nodes_with_node: std.AutoHashMapUnmanaged(Ast.Node.Index, Ast.Node.Index) = .empty,
/// Change all identifier names matching the key to be value instead.
- rename_identifiers: std.StringArrayHashMapUnmanaged([]const u8) = .empty,
+ rename_identifiers: std.array_hash_map.String([]const u8) = .empty,
/// All `@import` builtin calls which refer to a file path will be prefixed
/// with this path.
diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig
index b02f4cc05636a19d0922d93ec32791f2315f64db..4adf7d0232804afe4738add9bf7a5307e2f1cdd3 100644
--- a/lib/std/zig/AstGen.zig
+++ b/lib/std/zig/AstGen.zig
@@ -52,7 +52,7 @@ within_fn: bool = false,
fn_ret_ty: Zir.Inst.Ref = .none,
/// Maps string table indexes to the first `@import` ZIR instruction
/// that uses this string as the operand.
-imports: std.AutoArrayHashMapUnmanaged(Zir.NullTerminatedString, Ast.TokenIndex) = .empty,
+imports: std.array_hash_map.Auto(Zir.NullTerminatedString, Ast.TokenIndex) = .empty,
/// Used for temporary storage when building payloads.
scratch: std.ArrayList(u32) = .empty,
/// Whenever a `ref` instruction is needed, it is created and saved in this
@@ -927,15 +927,14 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
.deref => {
const lhs = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(node).node);
- _ = try gz.addUnNode(.validate_deref, lhs, node);
switch (ri.rl) {
.ref,
.ref_coerced_ty,
.ref_const,
- => return lhs,
+ => return gz.addUnNode(.ref_deref, lhs, node),
else => {
- const result = try gz.addUnNode(.load, lhs, node);
+ const result = try gz.addUnNode(.deref, lhs, node);
return rvalue(gz, ri, result, node);
},
}
@@ -2759,6 +2758,8 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
.mulwrap,
.mul_sat,
.ref,
+ .deref,
+ .ref_deref,
.shl,
.shl_sat,
.shr,
@@ -2932,7 +2933,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
.memcpy,
.memset,
.memmove,
- .validate_deref,
.validate_destructure,
.save_err_ret_index,
.restore_err_ret_index_unconditional,
@@ -3130,7 +3130,7 @@ fn varDecl(
}
const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node.unwrap()) |align_node|
- try expr(gz, scope, coerced_align_ri, align_node)
+ try comptimeExpr(gz, scope, coerced_align_ri, align_node, .@"align")
else
.none;
@@ -3477,7 +3477,7 @@ fn assignDestructureMaybeDecls(
const this_variable_comptime = is_comptime or (is_const and value_is_comptime);
const align_inst: Zir.Inst.Ref = if (full_var_decl.ast.align_node.unwrap()) |align_node|
- try expr(gz, scope, coerced_align_ri, align_node)
+ try comptimeExpr(gz, scope, coerced_align_ri, align_node, .@"align")
else
.none;
@@ -8069,14 +8069,6 @@ fn identifier(
if (std.mem.eql(u8, ident_name_raw, "i0")) {
return astgen.failNode(ident, "signed integer cannot have bit width 0", .{});
}
- if (ident_name_raw[1] == '0') {
- assert(ident_name_raw.len >= 3); // `u0` and `i0` handled
- return astgen.failNode(
- ident,
- "primitive integer type '{s}' has leading zero",
- .{ident_name_raw},
- );
- }
const bit_count = parseBitCount(ident_name_raw[1..]) catch |err| switch (err) {
error.Overflow => return astgen.failNode(
ident,
@@ -8085,6 +8077,14 @@ fn identifier(
),
error.InvalidCharacter => break :int_type,
};
+ if (ident_name_raw[1] == '0') {
+ assert(ident_name_raw.len >= 3); // `u0` and `i0` handled
+ return astgen.failNode(
+ ident,
+ "primitive integer type '{s}' has leading zero",
+ .{ident_name_raw},
+ );
+ }
const result = try gz.add(.{
.tag = .int_type,
.data = .{ .int_type = .{
@@ -9327,6 +9327,16 @@ fn builtinCall(
});
return rvalue(gz, ri, result, node);
},
+ .SpirvType => {
+ const spirv_type_options_ty = try gz.addStdLangValue(node, .spirv_type_options);
+ const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = spirv_type_options_ty } }, params[0], .type);
+ const result = try gz.addExtendedPayload(.reify_spirv_type, Zir.Inst.ReifySpirvType{
+ .src_line = gz.astgen.source_line,
+ .node = node,
+ .operand = operand,
+ });
+ return rvalue(gz, ri, result, node);
+ },
.panic => {
try emitDbgNode(gz, node);
@@ -11153,7 +11163,7 @@ const Scope = struct {
declaring_gz: ?*GenZir,
/// Set of captures used by this namespace.
- captures: std.AutoArrayHashMapUnmanaged(Zir.Inst.Capture, Zir.NullTerminatedString) = .empty,
+ captures: std.array_hash_map.Auto(Zir.Inst.Capture, Zir.NullTerminatedString) = .empty,
fn deinit(self: *Namespace, gpa: Allocator) void {
self.decls.deinit(gpa);
@@ -12846,9 +12856,9 @@ fn scanContainer(
var bfa_state: std.heap.BufferFirstAllocator = .init(&bfa_buf, astgen.gpa);
const bfa = bfa_state.allocator();
- var names: std.AutoArrayHashMapUnmanaged(Zir.NullTerminatedString, NameEntry) = .empty;
- var test_names: std.AutoArrayHashMapUnmanaged(Zir.NullTerminatedString, NameEntry) = .empty;
- var decltest_names: std.AutoArrayHashMapUnmanaged(Zir.NullTerminatedString, NameEntry) = .empty;
+ var names: std.array_hash_map.Auto(Zir.NullTerminatedString, NameEntry) = .empty;
+ var test_names: std.array_hash_map.Auto(Zir.NullTerminatedString, NameEntry) = .empty;
+ var decltest_names: std.array_hash_map.Auto(Zir.NullTerminatedString, NameEntry) = .empty;
defer {
names.deinit(bfa);
test_names.deinit(bfa);
diff --git a/lib/std/zig/AstRlAnnotate.zig b/lib/std/zig/AstRlAnnotate.zig
index a316ef79784f36686b8385bf38020e0263dad247..a9b680c39b2a9e01e967ab33f3b03fe43999392a 100644
--- a/lib/std/zig/AstRlAnnotate.zig
+++ b/lib/std/zig/AstRlAnnotate.zig
@@ -1079,6 +1079,10 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
_ = try astrl.expr(args[3], block, ResultInfo.type_only);
return false;
},
+ .SpirvType => {
+ _ = try astrl.expr(args[0], block, ResultInfo.type_only);
+ return false;
+ },
.Vector => {
_ = try astrl.expr(args[0], block, ResultInfo.type_only);
_ = try astrl.expr(args[1], block, ResultInfo.type_only);
diff --git a/lib/std/zig/AstSmith.zig b/lib/std/zig/AstSmith.zig
index 033556654cee53b3f2203840fb347e9f85dae7d3..87cfc0ccf25a19890d263c9dd8726ec9c209ed2a 100644
--- a/lib/std/zig/AstSmith.zig
+++ b/lib/std/zig/AstSmith.zig
@@ -238,9 +238,6 @@ fn pegToken(a: *AstSmith, tag: Token.Tag) SourceError!void {
switch (lexeme[0]) {
'_', 'a'...'z', 'A'...'Z', '0'...'9' => try a.preservePegEndOfWord(),
- '*' => if (a.tokens_len > 0 and a.source_buf[a.source_len - 1] == '*') {
- try a.addSourceByte(' ');
- },
'.' => if (a.tokens_len > 0 and switch (a.source_buf[a.source_len - 1]) {
'.' => true,
'0'...'9', 'a'...'z', 'A'...'Z' => a.token_tag_buf[a.tokens_len - 1] == .number_literal,
@@ -1810,7 +1807,7 @@ fn pegPrefixTypeOp(a: *AstSmith) SourceError!void {
}
/// SuffixOp
-/// <- LBRACKET Expr (DOT2 (Expr? (COLON Expr)?)?)? RBRACKET
+/// <- LBRACKET Expr (DOT2 Expr? (COLON Expr)?)? RBRACKET
/// / DOT IDENTIFIER
/// / DOTASTERISK
/// / DOTQUESTIONMARK
@@ -1820,12 +1817,14 @@ fn pegSuffixOp(a: *AstSmith) SourceError!void {
try a.pegToken(.l_bracket);
try a.pegExpr();
- const components = a.smith.value(u2);
- if (components >= 1) try a.pegToken(.ellipsis2);
- if (components >= 2) try a.pegExpr();
- if (components >= 3) {
- try a.pegToken(.colon);
- try a.pegExpr();
+ if (a.smith.value(bool)) {
+ try a.pegToken(.ellipsis2);
+ if (a.smith.value(bool))
+ try a.pegExpr();
+ if (a.smith.value(bool)) {
+ try a.pegToken(.colon);
+ try a.pegExpr();
+ }
}
try a.pegToken(.r_bracket);
diff --git a/lib/std/zig/BuiltinFn.zig b/lib/std/zig/BuiltinFn.zig
index 1a8fe743cae34a36a715ae50b6bb9ec859e33b03..4464d1fa46c93a1170238627dc5fd0b03c32048e 100644
--- a/lib/std/zig/BuiltinFn.zig
+++ b/lib/std/zig/BuiltinFn.zig
@@ -114,6 +114,7 @@ pub const Tag = enum {
Struct,
Union,
Enum,
+ SpirvType,
type_info,
type_name,
TypeOf,
@@ -971,6 +972,13 @@ pub const list = list: {
.param_count = 4,
},
},
+ .{
+ "@SpirvType",
+ .{
+ .tag = .SpirvType,
+ .param_count = 1,
+ },
+ },
.{
"@typeInfo",
.{
diff --git a/lib/std/zig/LibCDirs.zig b/lib/std/zig/LibCDirs.zig
index 7ae4061b0d2acd299259acd5bb833a68128860a9..04c61af0bedab6728309db7c00c975ef4229a57d 100644
--- a/lib/std/zig/LibCDirs.zig
+++ b/lib/std/zig/LibCDirs.zig
@@ -282,6 +282,8 @@ fn libCGenericName(target: *const std.Target) [:0]const u8 {
=> return "musl",
.eabi,
.eabihf,
+ .abin32,
+ .x32,
.ilp32,
.android,
.androideabi,
diff --git a/lib/std/zig/LibCInstallation.zig b/lib/std/zig/LibCInstallation.zig
index daf1fb14cb5e502f881348f2dcb118b4b6a6d696..6fa49a0ce985c9115495a16c862e7d6e1a9062d5 100644
--- a/lib/std/zig/LibCInstallation.zig
+++ b/lib/std/zig/LibCInstallation.zig
@@ -46,7 +46,7 @@ pub fn parse(allocator: Allocator, io: Io, libc_file: []const u8, target: *const
const field_names = comptime std.meta.fieldNames(LibCInstallation);
const FoundKey = struct {
found: bool,
- allocated: ?[:0]u8,
+ allocated: ?[]u8,
};
var found_keys: [field_names.len]FoundKey = @splat(.{ .found = false, .allocated = null });
@@ -60,7 +60,7 @@ pub fn parse(allocator: Allocator, io: Io, libc_file: []const u8, target: *const
const contents = try Io.Dir.cwd().readFileAlloc(io, libc_file, allocator, .limited(std.math.maxInt(usize)));
defer allocator.free(contents);
- var it = std.mem.tokenizeScalar(u8, contents, '\n');
+ var it = std.mem.tokenizeAny(u8, contents, "\n\r");
while (it.next()) |line| {
if (line.len == 0 or line[0] == '#') continue;
var line_it = std.mem.splitScalar(u8, line, '=');
@@ -72,7 +72,7 @@ pub fn parse(allocator: Allocator, io: Io, libc_file: []const u8, target: *const
if (value.len == 0) {
@field(self, field_name) = null;
} else {
- found_keys[i].allocated = try allocator.dupeSentinel(u8, value, 0);
+ found_keys[i].allocated = try allocator.dupe(u8, value);
@field(self, field_name) = found_keys[i].allocated;
}
break;
diff --git a/lib/std/zig/Parse.zig b/lib/std/zig/Parse.zig
index c41d5441075e751b7f4b65778ddf0a7b78423e7c..d4c6015131d4c612633e3b87f8da61f0faeaf6a4 100644
--- a/lib/std/zig/Parse.zig
+++ b/lib/std/zig/Parse.zig
@@ -3137,7 +3137,7 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers {
}
/// SuffixOp
-/// <- LBRACKET Expr (DOT2 (Expr? (COLON Expr)?)?)? RBRACKET
+/// <- LBRACKET Expr (DOT2 Expr? (COLON Expr)?)? RBRACKET
/// / DOT IDENTIFIER
/// / DOTASTERISK
/// / DOTQUESTIONMARK
diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig
index b649b7aff06900a27bf19156ae417eeaa5cfd3bf..49897a755f8a08cedc86d421250a887afe03a720 100644
--- a/lib/std/zig/Zir.zig
+++ b/lib/std/zig/Zir.zig
@@ -567,12 +567,21 @@ pub const Inst = struct {
/// Uses the `pl_node` field with payload `Bin`.
merge_error_sets,
/// Turns an R-Value into a const L-Value. In other words, it takes a value,
- /// stores it in a memory location, and returns a const pointer to it. If the value
- /// is `comptime`, the memory location is global static constant data. Otherwise,
- /// the memory location is in the stack frame, local to the scope containing the
- /// instruction.
+ /// stores it in a memory location, and returns a const single-item pointer to it.
+ /// If the value is `comptime`, the memory location is global static constant data.
+ /// Otherwise, the memory location is in the stack frame, local to the scope
+ /// containing the instruction.
/// Uses the `un_tok` union field.
ref,
+ /// Implements the dereference operand (`.*`). Checks that operand is a pointer
+ /// that supports being directly dereferenced.
+ /// Uses the `un_node` union field.
+ deref,
+ /// Emitted when a dereference (`.*`) with a reference result location occurs.
+ /// Checks that operand is a pointer that supports being directly dereferenced
+ /// and returns a single-item pointer to the dereferenced memory location.
+ /// Uses the `un_node` union field.
+ ref_deref,
/// Sends control flow back to the function's callee.
/// Includes an operand as the return value.
/// Includes an AST node source location.
@@ -717,9 +726,6 @@ pub const Inst = struct {
/// - `if (eu) |payload| {...} else |err| {...}`, AST node is the `if`.
/// Uses the `pl_node` union field. Payload is `SwitchBlock`.
switch_block_err_union,
- /// Check that operand type supports the dereference operand (.*).
- /// Uses the `un_node` field.
- validate_deref,
/// Check that the operand's type is an array or tuple with the given number of elements.
/// Uses the `pl_node` field. Payload is `ValidateDestructure`.
validate_destructure,
@@ -1170,6 +1176,8 @@ pub const Inst = struct {
.mulwrap,
.mul_sat,
.ref,
+ .deref,
+ .ref_deref,
.shl,
.shl_sat,
.shr,
@@ -1213,7 +1221,6 @@ pub const Inst = struct {
.switch_block,
.switch_block_ref,
.switch_block_err_union,
- .validate_deref,
.validate_destructure,
.union_init,
.field_type_ref,
@@ -1352,7 +1359,6 @@ pub const Inst = struct {
.atomic_store,
.store_node,
.store_to_inferred_ptr,
- .validate_deref,
.validate_destructure,
.@"export",
.set_runtime_safety,
@@ -1456,6 +1462,8 @@ pub const Inst = struct {
.mulwrap,
.mul_sat,
.ref,
+ .deref,
+ .ref_deref,
.shl,
.shl_sat,
.shr,
@@ -1708,6 +1716,8 @@ pub const Inst = struct {
.merge_error_sets = .pl_node,
.mod_rem = .pl_node,
.ref = .un_tok,
+ .deref = .un_node,
+ .ref_deref = .un_node,
.ret_node = .un_node,
.ret_load = .un_node,
.ret_implicit = .un_tok,
@@ -1744,7 +1754,6 @@ pub const Inst = struct {
.switch_block = .pl_node,
.switch_block_ref = .pl_node,
.switch_block_err_union = .pl_node,
- .validate_deref = .un_node,
.validate_destructure = .pl_node,
.field_type_ref = .pl_node,
.union_init = .pl_node,
@@ -2055,6 +2064,9 @@ pub const Inst = struct {
/// `operand` is payload index to `ReifyEnum`.
/// `small` contains `NameStrategy`.
reify_enum,
+ /// Implements builtin `@SpirvType`.
+ /// `operand` is payload index to `ReifyFn`.
+ reify_spirv_type,
/// Implements the `@cmpxchgStrong` and `@cmpxchgWeak` builtins.
/// `small` 0=>weak 1=>strong
/// `operand` is payload index to `Cmpxchg`.
@@ -3269,6 +3281,14 @@ pub const Inst = struct {
field_values: Ref,
};
+ pub const ReifySpirvType = struct {
+ src_line: u32,
+ /// This node is absolute, because `reify` instructions are tracked across updates, and
+ /// this simplifies the logic for getting source locations for types.
+ node: Ast.Node.Index,
+ operand: Ref,
+ };
+
/// Trailing:
/// 0. multi_cases_len: u32, // If has_multi_cases is set.
/// 1. payload_capture_placeholder: Inst.Index, // If payload_capture_inst_is_placeholder is set.
@@ -3584,6 +3604,7 @@ pub const Inst = struct {
fn_attributes,
container_layout,
enum_mode,
+ spirv_type_options,
// Values
calling_convention_c,
calling_convention_inline,
@@ -4174,6 +4195,8 @@ fn findTrackableInner(
.for_len,
.merge_error_sets,
.ref,
+ .deref,
+ .ref_deref,
.ret_node,
.ret_load,
.ret_implicit,
@@ -4207,7 +4230,6 @@ fn findTrackableInner(
.enum_literal,
.decl_literal,
.decl_literal_no_coerce,
- .validate_deref,
.validate_destructure,
.field_type_ref,
.opt_eu_base_ptr_init,
@@ -4389,6 +4411,7 @@ fn findTrackableInner(
.reify_enum,
.reify_struct,
.reify_union,
+ .reify_spirv_type,
=> return contents.other.append(gpa, inst),
// Type declarations need tracking.
@@ -5181,6 +5204,7 @@ pub fn assertTrackable(zir: Zir, inst_idx: Zir.Inst.Index) void {
.reify_enum,
.reify_struct,
.reify_union,
+ .reify_spirv_type,
=> {}, // tracked in order, as the owner instructions of explicit container types
else => unreachable, // assertion failure; not trackable
},
diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig
index 27a1532aab387624bb127e6ee5f2ad341f989ea8..f780e28f5c4d897d8a920c890c38933ea8f0ee85 100644
--- a/lib/std/zig/llvm/Builder.zig
+++ b/lib/std/zig/llvm/Builder.zig
@@ -21,25 +21,25 @@ data_layout: String,
target_triple: String,
module_asm: std.ArrayList(u8),
-string_map: std.AutoArrayHashMapUnmanaged(void, void),
+string_map: std.array_hash_map.Auto(void, void),
string_indices: std.ArrayList(u32),
string_bytes: std.ArrayList(u8),
-types: std.AutoArrayHashMapUnmanaged(String, Type),
+types: std.array_hash_map.Auto(String, Type),
next_unnamed_type: String,
next_unique_type_id: std.AutoHashMapUnmanaged(String, u32),
-type_map: std.AutoArrayHashMapUnmanaged(void, void),
+type_map: std.array_hash_map.Auto(void, void),
type_items: std.ArrayList(Type.Item),
type_extra: std.ArrayList(u32),
-attributes: std.AutoArrayHashMapUnmanaged(Attribute.Storage, void),
-attributes_map: std.AutoArrayHashMapUnmanaged(void, void),
+attributes: std.array_hash_map.Auto(Attribute.Storage, void),
+attributes_map: std.array_hash_map.Auto(void, void),
attributes_indices: std.ArrayList(u32),
attributes_extra: std.ArrayList(u32),
-function_attributes_set: std.AutoArrayHashMapUnmanaged(FunctionAttributes, void),
+function_attributes_set: std.array_hash_map.Auto(FunctionAttributes, void),
-globals: std.AutoArrayHashMapUnmanaged(StrtabString, Global),
+globals: std.array_hash_map.Auto(StrtabString, Global),
next_unnamed_global: StrtabString,
next_replaced_global: StrtabString,
next_unique_global_id: std.AutoHashMapUnmanaged(StrtabString, u32),
@@ -47,28 +47,28 @@ aliases: std.ArrayList(Alias),
variables: std.ArrayList(Variable),
functions: std.ArrayList(Function),
-strtab_string_map: std.AutoArrayHashMapUnmanaged(void, void),
+strtab_string_map: std.array_hash_map.Auto(void, void),
strtab_string_indices: std.ArrayList(u32),
strtab_string_bytes: std.ArrayList(u8),
-constant_map: std.AutoArrayHashMapUnmanaged(void, void),
+constant_map: std.array_hash_map.Auto(void, void),
constant_items: std.MultiArrayList(Constant.Item),
constant_extra: std.ArrayList(u32),
constant_limbs: std.ArrayList(std.math.big.Limb),
alignment_forward_references: std.ArrayList(Alignment),
-metadata_map: std.AutoArrayHashMapUnmanaged(void, void),
+metadata_map: std.array_hash_map.Auto(void, void),
metadata_items: std.MultiArrayList(Metadata.Item),
metadata_extra: std.ArrayList(u32),
metadata_limbs: std.ArrayList(std.math.big.Limb),
metadata_forward_references: std.ArrayList(Metadata.Optional),
-metadata_named: std.AutoArrayHashMapUnmanaged(String, struct {
+metadata_named: std.array_hash_map.Auto(String, struct {
len: u32,
index: Metadata.Item.ExtraIndex,
}),
-metadata_string_map: std.AutoArrayHashMapUnmanaged(void, void),
+metadata_string_map: std.array_hash_map.Auto(void, void),
metadata_string_indices: std.ArrayList(u32),
metadata_string_bytes: std.ArrayList(u8),
@@ -1633,7 +1633,7 @@ pub const FunctionAttributes = enum(u32) {
pub const Wip = struct {
maps: Maps = .empty,
- const Map = std.AutoArrayHashMapUnmanaged(Attribute.Kind, Attribute.Index);
+ const Map = std.array_hash_map.Auto(Attribute.Kind, Attribute.Index);
const Maps = std.ArrayList(Map);
pub fn deinit(self: *Wip, builder: *const Builder) void {
@@ -1816,7 +1816,7 @@ pub const Linkage = enum(u4) {
}
};
-pub const Preemption = enum {
+pub const Preemption = enum(u2) {
dso_preemptable,
dso_local,
implicit_dso_local,
@@ -2011,7 +2011,7 @@ pub const AddrSpace = enum(u24) {
}
};
-pub const ExternallyInitialized = enum {
+pub const ExternallyInitialized = enum(u1) {
default,
externally_initialized,
@@ -2061,6 +2061,13 @@ pub const Alignment = enum(u6) {
};
}
+ /// Asserts that neither `a` nor `b` is `.default`.
+ pub fn max(a: Alignment, b: Alignment) Alignment {
+ assert(a != .default);
+ assert(b != .default);
+ return @enumFromInt(@max(@intFromEnum(a), @intFromEnum(b)));
+ }
+
pub fn toLlvm(self: Alignment) u6 {
return switch (self) {
.default => 0,
@@ -4314,6 +4321,9 @@ pub const Function = struct {
@"tail call",
@"tail call fast",
trunc,
+ @"trunc nuw",
+ @"trunc nsw",
+ @"trunc nuw nsw",
udiv,
@"udiv exact",
urem,
@@ -4377,7 +4387,10 @@ pub const Function = struct {
};
}
- pub fn toCastOpcode(self: Tag) CastOpcode {
+ /// Does not accept `.@"trunc nuw"`, `.@"trunc nsw"`, or `.@"trunc nuw nsw"`, because
+ /// they do not have distinct `CastOpcode` values, and are instead encoded in bitcode
+ /// using flags on a normal `trunc` operation.
+ fn toCastOpcode(self: Tag) CastOpcode {
return switch (self) {
.trunc => .trunc,
.zext => .zext,
@@ -4572,6 +4585,9 @@ pub const Function = struct {
.sext,
.sitofp,
.trunc,
+ .@"trunc nuw",
+ .@"trunc nsw",
+ .@"trunc nuw nsw",
.uitofp,
.zext,
=> wip.extraData(Cast, instruction.data).type,
@@ -4758,6 +4774,9 @@ pub const Function = struct {
.sext,
.sitofp,
.trunc,
+ .@"trunc nuw",
+ .@"trunc nsw",
+ .@"trunc nuw nsw",
.uitofp,
.zext,
=> function.extraData(Cast, instruction.data).type,
@@ -5235,8 +5254,8 @@ pub const WipFunction = struct {
instructions: std.MultiArrayList(Instruction),
names: std.ArrayList(String),
strip: bool,
- debug_locations: std.AutoArrayHashMapUnmanaged(Instruction.Index, DebugLocation),
- debug_values: std.AutoArrayHashMapUnmanaged(Instruction.Index, void),
+ debug_locations: std.array_hash_map.Auto(Instruction.Index, DebugLocation),
+ debug_values: std.array_hash_map.Auto(Instruction.Index, void),
extra: std.ArrayList(u32),
pub const Cursor = struct { block: Block.Index, instruction: u32 = 0 };
@@ -5975,6 +5994,9 @@ pub const WipFunction = struct {
.sext,
.sitofp,
.trunc,
+ .@"trunc nuw",
+ .@"trunc nsw",
+ .@"trunc nuw nsw",
.uitofp,
.zext,
=> {},
@@ -6583,6 +6605,9 @@ pub const WipFunction = struct {
.sext,
.sitofp,
.trunc,
+ .@"trunc nuw",
+ .@"trunc nsw",
+ .@"trunc nuw nsw",
.uitofp,
.zext,
=> {
@@ -8451,7 +8476,7 @@ pub const Metadata = packed struct(u32) {
const Formatter = struct {
builder: *Builder,
need_comma: bool,
- map: std.AutoArrayHashMapUnmanaged(union(enum) {
+ map: std.array_hash_map.Auto(union(enum) {
metadata: Metadata,
debug_location: DebugLocation.Location,
}, void) = .empty,
@@ -9791,7 +9816,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
}
}
- var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .empty;
+ var attribute_groups: std.array_hash_map.Auto(Attributes, void) = .empty;
defer attribute_groups.deinit(self.gpa);
for (0.., self.functions.items) |function_i, function| {
@@ -9975,6 +10000,9 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
.sext,
.sitofp,
.trunc,
+ .@"trunc nuw",
+ .@"trunc nsw",
+ .@"trunc nuw nsw",
.uitofp,
.zext,
=> |tag| {
@@ -11649,7 +11677,11 @@ fn convTag(
.unneeded => unreachable,
},
.eq => unreachable,
- .gt => .trunc,
+ .gt => switch (signedness) {
+ .unsigned => .@"trunc nuw",
+ .signed => .@"trunc nsw",
+ .unneeded => .trunc,
+ },
},
.pointer => .inttoptr,
else => unreachable,
@@ -13507,7 +13539,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
try type_block.end();
}
- var attributes_set: std.AutoArrayHashMapUnmanaged(struct {
+ var attributes_set: std.array_hash_map.Auto(struct {
attributes: Attributes,
index: u32,
}, void) = .{};
@@ -13743,7 +13775,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
try paramattr_block.end();
}
- var globals: std.AutoArrayHashMapUnmanaged(Global.Index, void) = .empty;
+ var globals: std.array_hash_map.Auto(Global.Index, void) = .empty;
defer globals.deinit(self.gpa);
try globals.ensureUnusedCapacity(
self.gpa,
@@ -13784,7 +13816,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
const ConstantAdapter = struct {
builder: *const Builder,
- globals: *const std.AutoArrayHashMapUnmanaged(Global.Index, void),
+ globals: *const std.array_hash_map.Auto(Global.Index, void),
pub fn get(adapter: @This(), param: anytype) switch (@TypeOf(param)) {
Constant => u32,
@@ -13815,7 +13847,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
// Globals
{
- var section_map: std.AutoArrayHashMapUnmanaged(String, void) = .empty;
+ var section_map: std.array_hash_map.Auto(String, void) = .empty;
defer section_map.deinit(self.gpa);
try section_map.ensureUnusedCapacity(self.gpa, globals.count());
@@ -14962,6 +14994,20 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
.opcode = kind.toCastOpcode(),
});
},
+ .@"trunc nuw",
+ .@"trunc nsw",
+ .@"trunc nuw nsw",
+ => |kind| {
+ const extra = func.extraData(Function.Instruction.Cast, data);
+ try function_block.writeAbbrev(FunctionBlock.TruncNoWrap{
+ .val = adapter.getOffsetValueIndex(extra.val),
+ .type_index = extra.type,
+ .flags = .{
+ .no_unsigned_wrap = kind == .@"trunc nuw" or kind == .@"trunc nuw nsw",
+ .no_signed_wrap = kind == .@"trunc nsw" or kind == .@"trunc nuw nsw",
+ },
+ });
+ },
.@"fcmp false",
.@"fcmp oeq",
.@"fcmp oge",
diff --git a/lib/std/zig/llvm/ir.zig b/lib/std/zig/llvm/ir.zig
index 00c20c3b425a10ea17d09941c5c8ce1b57ac1a39..397ea34b87041fa8223ff8723cb03c87c5a94b6f 100644
--- a/lib/std/zig/llvm/ir.zig
+++ b/lib/std/zig/llvm/ir.zig
@@ -696,6 +696,7 @@ pub const ModuleBlock = struct {
ModuleBlock.FunctionBlock.Select,
ModuleBlock.FunctionBlock.SelectFast,
ModuleBlock.FunctionBlock.Cast,
+ ModuleBlock.FunctionBlock.TruncNoWrap,
ModuleBlock.FunctionBlock.Alloca,
ModuleBlock.FunctionBlock.GetElementPtr,
ModuleBlock.FunctionBlock.ExtractValue,
@@ -1086,6 +1087,24 @@ pub const ModuleBlock = struct {
opcode: CastOpcode,
};
+ pub const TruncNoWrap = struct {
+ pub const Flags = packed struct(u2) {
+ no_unsigned_wrap: bool,
+ no_signed_wrap: bool,
+ };
+ pub const ops = [_]AbbrevOp{
+ .{ .literal = @intFromEnum(ModuleBlock.FunctionBlock.Code.INST_CAST) },
+ ValueAbbrev,
+ .{ .fixed_runtime = Builder.Type },
+ .{ .literal = @intFromEnum(Builder.CastOpcode.trunc) },
+ .{ .fixed = @bitSizeOf(Flags) },
+ };
+
+ val: u32,
+ type_index: Builder.Type,
+ flags: Flags,
+ };
+
pub const Alloca = struct {
pub const Flags = packed struct(u11) {
align_lower: u5,
diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig
index c2ad638832ea8e5944324e98adcd65ec65b6322e..d40d442ce88198297f183a00e586aba3991d09e7 100644
--- a/lib/std/zig/system.zig
+++ b/lib/std/zig/system.zig
@@ -104,7 +104,7 @@ pub fn getExternalExecutor(io: Io, candidate: *const std.Target, options: GetExt
=> .{ .qemu = switch (t) {
.x86 => "qemu-i386",
.x86_64 => switch (candidate.abi) {
- .gnux32, .muslx32 => return bad_result,
+ .gnux32, .muslx32, .x32 => return bad_result,
else => "qemu-x86_64",
},
else => "qemu-" ++ @tagName(t),
@@ -146,7 +146,7 @@ pub fn getExternalExecutor(io: Io, candidate: *const std.Target, options: GetExt
.powerpc64 => "qemu-ppc64",
.powerpc64le => "qemu-ppc64le",
.mips64, .mips64el => switch (candidate.abi) {
- .gnuabin32, .muslabin32 => if (t == .mips64el) "qemu-mipsn32el" else "qemu-mipsn32",
+ .gnuabin32, .muslabin32, .abin32 => if (t == .mips64el) "qemu-mipsn32el" else "qemu-mipsn32",
else => "qemu-" ++ @tagName(t),
},
// TODO: Actually check the SuperH version.
diff --git a/lib/std/zip.zig b/lib/std/zip.zig
index be2a442f3de66e0cb0f912868de26e07fd180d66..3784605d0227653b8424dbc5345ff55a481878b0 100644
--- a/lib/std/zip.zig
+++ b/lib/std/zip.zig
@@ -164,50 +164,6 @@ pub const EndRecord = extern struct {
}
};
-pub const Decompress = struct {
- interface: Reader,
- state: union {
- inflate: flate.Decompress,
- store: *Reader,
- },
-
- pub fn init(reader: *Reader, method: CompressionMethod, buffer: []u8) Reader {
- return switch (method) {
- .store => .{
- .state = .{ .store = reader },
- .interface = .{
- .context = undefined,
- .vtable = &.{ .stream = streamStore },
- .buffer = buffer,
- .end = 0,
- .seek = 0,
- },
- },
- .deflate => .{
- .state = .{ .inflate = .init(reader, .raw) },
- .interface = .{
- .context = undefined,
- .vtable = &.{ .stream = streamDeflate },
- .buffer = buffer,
- .end = 0,
- .seek = 0,
- },
- },
- else => unreachable,
- };
- }
-
- fn streamStore(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!usize {
- const d: *Decompress = @fieldParentPtr("interface", r);
- return d.store.read(w, limit);
- }
-
- fn streamDeflate(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!usize {
- const d: *Decompress = @fieldParentPtr("interface", r);
- return flate.Decompress.read(&d.inflate, w, limit);
- }
-};
-
fn isBadFilename(filename: []const u8) bool {
if (filename.len == 0 or filename[0] == '/')
return true;
@@ -457,15 +413,7 @@ pub const Iterator = struct {
uncompressed_size: u64,
file_offset: u64,
- pub fn extract(
- self: Entry,
- stream: *File.Reader,
- options: ExtractOptions,
- filename_buf: []u8,
- dest: Io.Dir,
- ) !void {
- const io = stream.io;
-
+ pub fn getFilename(self: Entry, stream: *File.Reader, filename_buf: []u8, options: ExtractOptions) ![]u8 {
if (filename_buf.len < self.filename_len)
return error.ZipInsufficientBuffer;
switch (self.compression_method) {
@@ -478,6 +426,25 @@ pub const Iterator = struct {
try stream.interface.readSliceAll(filename);
}
+ if (options.allow_backslashes) {
+ std.mem.replaceScalar(u8, filename, '\\', '/');
+ } else {
+ if (std.mem.findScalar(u8, filename, '\\')) |_|
+ return error.ZipFilenameHasBackslash;
+ }
+
+ if (isBadFilename(filename))
+ return error.ZipBadFilename;
+
+ return filename;
+ }
+
+ pub fn extractTo(self: Entry, stream: *File.Reader, w: *Writer) !void {
+ switch (self.compression_method) {
+ .store, .deflate => {},
+ else => return error.UnsupportedCompressionMethod,
+ }
+
const local_data_header_offset: u64 = local_data_header_offset: {
const local_header = blk: {
try stream.seekTo(self.file_offset);
@@ -540,15 +507,45 @@ pub const Iterator = struct {
@as(u64, local_header.extra_len);
};
- if (options.allow_backslashes) {
- std.mem.replaceScalar(u8, filename, '\\', '/');
- } else {
- if (std.mem.findScalar(u8, filename, '\\')) |_|
- return error.ZipFilenameHasBackslash;
+ const local_data_file_offset: u64 =
+ @as(u64, self.file_offset) +
+ @as(u64, @sizeOf(LocalFileHeader)) +
+ local_data_header_offset;
+ try stream.seekTo(local_data_file_offset);
+
+ // TODO limit based on self.compressed_size
+
+ switch (self.compression_method) {
+ .store => {
+ stream.interface.streamExact64(w, self.uncompressed_size) catch |err| switch (err) {
+ error.ReadFailed => |e| return stream.err orelse e,
+ error.WriteFailed => |e| return e,
+ error.EndOfStream => return error.ZipDecompressTruncated,
+ };
+ },
+ .deflate => {
+ var flate_buffer: [flate.max_window_len]u8 = undefined;
+ var decompress: flate.Decompress = .init(&stream.interface, .raw, &flate_buffer);
+ decompress.reader.streamExact64(w, self.uncompressed_size) catch |err| switch (err) {
+ error.ReadFailed => |e| return decompress.err orelse (stream.err orelse e),
+ error.WriteFailed => |e| return e,
+ error.EndOfStream => return error.ZipDecompressTruncated,
+ };
+ },
+ else => return error.UnsupportedCompressionMethod,
}
+ }
- if (isBadFilename(filename))
- return error.ZipBadFilename;
+ pub fn extract(
+ self: Entry,
+ stream: *File.Reader,
+ options: ExtractOptions,
+ filename_buf: []u8,
+ dest: Io.Dir,
+ ) !void {
+ const io = stream.io;
+
+ const filename = try self.getFilename(stream, filename_buf, options);
// All entries that end in '/' are directories
if (filename[filename.len - 1] == '/') {
@@ -571,33 +568,10 @@ pub const Iterator = struct {
defer out_file.close(io);
var out_file_buffer: [1024]u8 = undefined;
var file_writer = out_file.writer(io, &out_file_buffer);
- const local_data_file_offset: u64 =
- @as(u64, self.file_offset) +
- @as(u64, @sizeOf(LocalFileHeader)) +
- local_data_header_offset;
- try stream.seekTo(local_data_file_offset);
-
- // TODO limit based on self.compressed_size
-
- switch (self.compression_method) {
- .store => {
- stream.interface.streamExact64(&file_writer.interface, self.uncompressed_size) catch |err| switch (err) {
- error.ReadFailed => return stream.err.?,
- error.WriteFailed => return file_writer.err.?,
- error.EndOfStream => return error.ZipDecompressTruncated,
- };
- },
- .deflate => {
- var flate_buffer: [flate.max_window_len]u8 = undefined;
- var decompress: flate.Decompress = .init(&stream.interface, .raw, &flate_buffer);
- decompress.reader.streamExact64(&file_writer.interface, self.uncompressed_size) catch |err| switch (err) {
- error.ReadFailed => return stream.err.?,
- error.WriteFailed => return file_writer.err orelse decompress.err.?,
- error.EndOfStream => return error.ZipDecompressTruncated,
- };
- },
- else => return error.UnsupportedCompressionMethod,
- }
+ self.extractTo(stream, &file_writer.interface) catch |err| switch (err) {
+ error.WriteFailed => |e| return file_writer.err orelse e,
+ else => return err,
+ };
try file_writer.end();
}
};
@@ -664,3 +638,85 @@ pub fn extract(dest: Io.Dir, fr: *File.Reader, options: ExtractOptions) !void {
}
}
}
+
+const testing = std.testing;
+
+test "extractTo" {
+ const io = testing.io;
+ var tmp = testing.tmpDir(.{});
+ defer tmp.cleanup();
+
+ try tmp.dir.writeFile(io, .{
+ .sub_path = "test.zip",
+ .data = @embedFile("zip/testdata/test.zip"),
+ });
+
+ var file = try tmp.dir.openFile(io, "test.zip", .{});
+ defer file.close(io);
+ var read_buf: [512]u8 = undefined;
+ var reader = file.reader(io, &read_buf);
+
+ const Expected = struct {
+ contents: []const u8,
+ compression: CompressionMethod,
+ };
+ const expected_map = std.StaticStringMap(Expected).initComptime(.{
+ .{ "deflate.txt", Expected{ .contents = "aaaaaaaaaaaaaaaaaaaaaaaa\n", .compression = .deflate } },
+ .{ "store.txt", Expected{ .contents = "hello world\n", .compression = .store } },
+ .{ "dir/", Expected{ .contents = "", .compression = .store } },
+ });
+
+ var iter = try Iterator.init(&reader);
+ var num_entries: usize = 0;
+ while (try iter.next()) |entry| {
+ var filename_buf: [256]u8 = undefined;
+ const filename = try entry.getFilename(&reader, &filename_buf, .{});
+ const expected = expected_map.get(filename) orelse {
+ std.debug.print("found unexpected filename: {f}\n", .{std.ascii.hexEscape(filename, .lower)});
+ return error.UnexpectedFilename;
+ };
+ var buf: [256]u8 = undefined;
+ var w: Writer = .fixed(&buf);
+ try entry.extractTo(&reader, &w);
+ try testing.expectEqualStrings(expected.contents, w.buffered());
+ try testing.expectEqual(expected.compression, entry.compression_method);
+ num_entries += 1;
+ }
+ try testing.expectEqual(expected_map.kvs.len, num_entries);
+}
+
+test "output buffers too small" {
+ const io = testing.io;
+ var tmp = testing.tmpDir(.{});
+ defer tmp.cleanup();
+
+ try tmp.dir.writeFile(io, .{
+ .sub_path = "test.zip",
+ .data = @embedFile("zip/testdata/test.zip"),
+ });
+
+ var file = try tmp.dir.openFile(io, "test.zip", .{});
+ defer file.close(io);
+ var read_buf: [512]u8 = undefined;
+ var reader = file.reader(io, &read_buf);
+
+ var iter = try Iterator.init(&reader);
+ var num_entries: usize = 0;
+ while (try iter.next()) |entry| {
+ try testing.expectError(
+ error.ZipInsufficientBuffer,
+ entry.getFilename(&reader, &.{}, .{}),
+ );
+
+ if (entry.uncompressed_size <= 1) continue;
+
+ var buf: [1]u8 = undefined;
+ var w: Writer = .fixed(&buf);
+ try testing.expectError(
+ error.WriteFailed,
+ entry.extractTo(&reader, &w),
+ );
+ num_entries += 1;
+ }
+ try std.testing.expect(num_entries > 0);
+}
diff --git a/lib/std/zip/testdata/test.zip b/lib/std/zip/testdata/test.zip
new file mode 100644
index 0000000000000000000000000000000000000000..48127af3be38d314f7195e3b4aea166ee3a55805
Binary files /dev/null and b/lib/std/zip/testdata/test.zip differ
diff --git a/lib/std/zon/Serializer.zig b/lib/std/zon/Serializer.zig
index c9809e30838f4b790ce1a9e7969dfbc4859ccec9..ec8456bcc964e6724862fce7392a13e01220dc1a 100644
--- a/lib/std/zon/Serializer.zig
+++ b/lib/std/zon/Serializer.zig
@@ -854,6 +854,7 @@ fn canSerializeTypeInner(
.frame,
.@"anyframe",
.@"opaque",
+ .spirv,
=> false,
.@"enum" => |@"enum"| @"enum".mode == .exhaustive,
diff --git a/lib/std/zon/parse.zig b/lib/std/zon/parse.zig
index 49ea45e03420e75bbafce4be577b8b93877f04d2..249dc9b644ce80553568bfd5dfb77291ec6bf60c 100644
--- a/lib/std/zon/parse.zig
+++ b/lib/std/zon/parse.zig
@@ -1173,7 +1173,9 @@ const Parser = struct {
};
fn intFromFloatExact(T: type, value: anytype) ?T {
- if (value > std.math.maxInt(T) or value < std.math.minInt(T)) {
+ const max: @TypeOf(value) = @floatFromInt(std.math.maxInt(T));
+ const min: @TypeOf(value) = @floatFromInt(std.math.minInt(T));
+ if (value > max or value < min) {
return null;
}
@@ -1213,6 +1215,7 @@ fn canParseTypeInner(
.frame,
.@"anyframe",
.@"opaque",
+ .spirv,
.comptime_int,
.comptime_float,
.enum_literal,
@@ -2447,6 +2450,7 @@ test "std.zon intFromFloatExact" {
try std.testing.expectEqual(@as(u8, 10), intFromFloatExact(u8, @as(f32, 10.0)).?);
try std.testing.expectEqual(@as(i8, -123), intFromFloatExact(i8, @as(f64, @as(f64, -123.0))).?);
try std.testing.expectEqual(@as(i16, 45), intFromFloatExact(i16, @as(f128, @as(f128, 45.0))).?);
+ try std.testing.expectEqual(@as(u128, 67), intFromFloatExact(u128, @as(f128, @as(f128, 67.0))).?);
// Out of range
try std.testing.expectEqual(@as(?u4, null), intFromFloatExact(u4, @as(f32, 16.0)));
@@ -2489,6 +2493,10 @@ test "std.zon parse int" {
@as(u65, 36893488147419103231),
try fromSlice(u65, gpa, "368934_881_474191032_31", null, .{}),
);
+ try std.testing.expectEqual(
+ @as(u128, 340282366920938463463374607431768211455),
+ try fromSlice(u128, gpa, "340282366920938463463374607431768211455", null, .{}),
+ );
// Test big integer limits
try std.testing.expectEqual(
diff --git a/lib/zig.h b/lib/zig.h
index 4f8b2da1d7de0ddcbd6d7df8c1b85d563349d7c1..34b56286a508b2707f4498f49612d9d625ee7c86 100644
--- a/lib/zig.h
+++ b/lib/zig.h
@@ -4557,9 +4557,12 @@ static inline void zig_msvc_atomic_store_i128(zig_i128 volatile* obj, zig_i128 a
#include
#endif
+static inline void* zig_e_zig_windows_teb(void) zig_mangled(zig_e_zig_windows_teb, "zig_windows_teb");
+static inline void* zig_e_zig_windows_peb(void) zig_mangled(zig_e_zig_windows_peb, "zig_windows_peb");
+
#if defined(zig_thumb)
-static inline void* zig_windows_teb(void) {
+static inline void* zig_e_zig_windows_teb(void) {
void* teb = 0;
#if defined(zig_msvc)
teb = (void*)_MoveFromCoprocessor(15, 0, 13, 0, 2);
@@ -4571,7 +4574,7 @@ static inline void* zig_windows_teb(void) {
#elif defined(zig_aarch64)
-static inline void* zig_windows_teb(void) {
+static inline void* zig_e_zig_windows_teb(void) {
void* teb = 0;
#if defined(zig_msvc)
teb = (void*)__readx18qword(0x0);
@@ -4583,7 +4586,7 @@ static inline void* zig_windows_teb(void) {
#elif defined(zig_x86_32)
-static inline void* zig_windows_teb(void) {
+static inline void* zig_e_zig_windows_teb(void) {
void* teb = 0;
#if defined(zig_msvc)
teb = (void*)__readfsdword(0x18);
@@ -4593,7 +4596,7 @@ static inline void* zig_windows_teb(void) {
return teb;
}
-static inline void* zig_windows_peb(void) {
+static inline void* zig_e_zig_windows_peb(void) {
void* peb = 0;
#if defined(zig_msvc)
peb = (void*)__readfsdword(0x30);
@@ -4605,7 +4608,7 @@ static inline void* zig_windows_peb(void) {
#elif defined(zig_x86_64)
-static inline void* zig_windows_teb(void) {
+static inline void* zig_e_zig_windows_teb(void) {
void* teb = 0;
#if defined(zig_msvc)
teb = (void*)__readgsqword(0x30);
@@ -4615,7 +4618,7 @@ static inline void* zig_windows_teb(void) {
return teb;
}
-static inline void* zig_windows_peb(void) {
+static inline void* zig_e_zig_windows_peb(void) {
void* peb = 0;
#if defined(zig_msvc)
peb = (void*)__readgsqword(0x60);
@@ -4629,7 +4632,9 @@ static inline void* zig_windows_peb(void) {
#if defined(zig_loongarch)
-static inline void zig_loongarch_cpucfg(uint32_t word, uint32_t* result) {
+static inline void zig_e_zig_loongarch_cpucfg(uint32_t word, uint32_t* result) zig_mangled(zig_e_zig_loongarch_cpucfg, "zig_loongarch_cpucfg");
+
+static inline void zig_e_zig_loongarch_cpucfg(uint32_t word, uint32_t* result) {
#if defined(zig_gnuc_asm)
__asm__("cpucfg %[result], %[word]" : [result] "=r" (result) : [word] "r" (word));
#else
@@ -4639,7 +4644,10 @@ static inline void zig_loongarch_cpucfg(uint32_t word, uint32_t* result) {
#elif defined(zig_x86) && !defined(zig_x86_16)
-static inline void zig_x86_cpuid(uint32_t leaf_id, uint32_t subid, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) {
+static inline void zig_e_zig_x86_cpuid(uint32_t leaf_id, uint32_t subid, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) zig_mangled(zig_e_zig_x86_cpuid, "zig_x86_cpuid");
+static inline uint32_t zig_e_zig_x86_get_xcr0(void) zig_mangled(zig_e_zig_x86_get_xcr0, "zig_x86_get_xcr0");
+
+static inline void zig_e_zig_x86_cpuid(uint32_t leaf_id, uint32_t subid, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) {
#if defined(zig_msvc)
int cpu_info[4];
__cpuidex(cpu_info, leaf_id, subid);
@@ -4657,7 +4665,7 @@ static inline void zig_x86_cpuid(uint32_t leaf_id, uint32_t subid, uint32_t* eax
#endif
}
-static inline uint32_t zig_x86_get_xcr0(void) {
+static inline uint32_t zig_e_zig_x86_get_xcr0(void) {
#if defined(zig_msvc)
return (uint32_t)_xgetbv(0);
#elif defined(zig_gnuc_asm)
diff --git a/src/Air.zig b/src/Air.zig
index fd551de1a5195e3b46c13bd76e42160647104919..baaa70d7e2230274ac91508f4e04e2e7b7ad82d6 100644
--- a/src/Air.zig
+++ b/src/Air.zig
@@ -17,6 +17,7 @@ const print = @import("Air/print.zig");
pub const Legalize = @import("Air/Legalize.zig");
pub const Liveness = @import("Air/Liveness.zig");
+pub const Verify = @import("Air/Verify.zig");
instructions: std.MultiArrayList(Inst).Slice,
/// The meaning of this data is determined by `Inst.Tag` value.
@@ -276,10 +277,50 @@ pub const Inst = struct {
/// Boolean or binary NOT.
/// Uses the `ty_op` field.
not,
- /// Reinterpret the bits of a value as a different type. This is like `@bitCast` but
- /// also supports enums and pointers.
+ /// Implements `@bitCast`.
+ ///
/// Uses the `ty_op` field.
- bitcast,
+ bit_cast,
+ /// Cast a pointer to a different pointer type. The result type is a slice iff the operand
+ /// type is a slice (the length of the slice does not change). All other pointer attributes
+ /// except for the address space may change.
+ ///
+ /// Supports vectors of pointers.
+ ///
+ /// Uses the `ty_op` field.
+ ptr_cast,
+ /// Cast an integer to a pointer (not a slice). Operand type is always `usize`.
+ ///
+ /// Supports vectors of integers.
+ ///
+ /// Uses the `ty_op` field.
+ ptr_from_int,
+ /// Cast a pointer (not a slice) to an integer. Result type is always `usize`.
+ ///
+ /// Supports vectors of pointers.
+ ///
+ /// Uses the `ty_op` field.
+ int_from_ptr,
+ /// Cast an error set `E1` to a different error set `E2`, or cast an error union `E1!T` to
+ /// an error union `E2!T` with the same payload type but a different error set type.
+ ///
+ /// Uses the `ty_op` field.
+ error_cast,
+ /// Cast an integer to an error set type. The integer operand type is unsigned and has bit
+ /// width equal to `zcu.errorSetBits()`.
+ ///
+ /// Uses the `ty_op` field.
+ error_from_int,
+ /// Cast an error set to an integer type. The integer destination type is unsigned and has
+ /// bit width equal to `zcu.errorSetBits()`.
+ ///
+ /// Uses the `ty_op` field.
+ int_from_error,
+ /// Cast an enum value to a tagged union, whose tag type is that enum, and which has no
+ /// payload bits (i.e. all payloads are equivalent to `void`).
+ ///
+ /// Uses the `ty_op` field.
+ union_from_enum,
/// A block runs its body which always ends with a `noreturn` instruction,
/// so the only way to proceed to the code after the `block` is to encounter a `br`
/// that targets this `block`. If the `block` type is `noreturn`,
@@ -589,13 +630,13 @@ pub const Inst = struct {
/// the integer tag type of the enum.
/// See `trunc` for integer truncation.
/// Uses the `ty_op` field.
- intcast,
- /// Like `intcast`, but includes two safety checks:
+ int_cast,
+ /// Like `int_cast`, but includes two safety checks:
/// * triggers a safety panic if the cast truncates bits
/// * triggers a safety panic if the destination type is an exhaustive enum
/// and the operand is not a valid value of this type; i.e. equivalent to
/// a safety check based on `.is_named_enum_value`
- intcast_safe,
+ int_cast_safe,
/// Truncate higher bits from an integer, resulting in an integer type with the same
/// sign but an equal or smaller number of bits.
/// Uses the `ty_op` field.
@@ -918,6 +959,11 @@ pub const Inst = struct {
/// Uses the `ty` field.
c_va_start,
+ /// Implements `.len` field for `@SpirvType(.{ .runtime_array = T })`.
+ /// Result type is always `u32`.
+ /// Uses the `ty_pl` field, payload is `StructField`.
+ spirv_runtime_array_len,
+
/// Implements @workItemId builtin.
/// Result type is always `u32`
/// Uses the `pl_op` field, payload is the dimension to get the work item id for.
@@ -950,7 +996,7 @@ pub const Inst = struct {
/// here is runtime-known, which is usually not allowed for vectors. `Legalize` may emit
/// this instruction when scalarizing vector operations.
///
- /// Uses the `bin_op` field. `lhs` is the vector pointer. `rhs` is the element index. Result
+ /// Uses the `bin_op` field. `lhs` is the vector value. `rhs` is the element index. Result
/// type is the vector element type.
legalize_vec_elem_val,
@@ -1662,12 +1708,19 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
=> return datas[@intFromEnum(inst)].ty_pl.ty.toType(),
.not,
- .bitcast,
+ .bit_cast,
+ .ptr_cast,
+ .ptr_from_int,
+ .int_from_ptr,
+ .error_cast,
+ .error_from_int,
+ .int_from_error,
+ .union_from_enum,
.load,
.fpext,
.fptrunc,
- .intcast,
- .intcast_safe,
+ .int_cast,
+ .int_cast_safe,
.trunc,
.optional_payload,
.optional_payload_ptr,
@@ -1793,6 +1846,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
.work_item_id,
.work_group_size,
.work_group_id,
+ .spirv_runtime_array_len,
=> return .u32,
.legalize_compiler_rt_call => return datas[@intFromEnum(inst)].legalize_compiler_rt_call.func.returnType(),
@@ -1907,7 +1961,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
.add_safe,
.sub_safe,
.mul_safe,
- .intcast_safe,
+ .int_cast_safe,
.int_from_float_safe,
.int_from_float_optimized_safe,
.legalize_vec_store_elem,
@@ -1959,7 +2013,14 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
.shl_sat,
.xor,
.not,
- .bitcast,
+ .bit_cast,
+ .ptr_cast,
+ .ptr_from_int,
+ .int_from_ptr,
+ .error_cast,
+ .error_from_int,
+ .int_from_error,
+ .union_from_enum,
.ret_addr,
.frame_addr,
.clz,
@@ -2003,7 +2064,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
.is_non_err,
.fptrunc,
.fpext,
- .intcast,
+ .int_cast,
.trunc,
.optional_payload,
.optional_payload_ptr,
@@ -2056,6 +2117,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
.work_group_size,
.work_group_id,
.legalize_vec_elem_val,
+ .spirv_runtime_array_len,
=> false,
.is_non_null_ptr, .is_null_ptr, .is_non_err_ptr, .is_err_ptr => air.typeOf(data.un_op, ip).isVolatilePtrIp(ip),
diff --git a/src/Air/Legalize.zig b/src/Air/Legalize.zig
index 5b9c4031a93abe2bd4258a641faf5cea633f8b9c..370666280c21b0d8306888c17fd7a87acd4f8b85 100644
--- a/src/Air/Legalize.zig
+++ b/src/Air/Legalize.zig
@@ -75,13 +75,9 @@ pub const Feature = enum {
scalarize_shl_sat,
scalarize_xor,
scalarize_not,
- /// Scalarize `bitcast` from or to an array or vector type to `bitcast`s of the elements.
- /// This does not apply if `@bitSizeOf(Elem) == 8 * @sizeOf(Elem)`.
- /// When this feature is enabled, all remaining `bitcast`s can be lowered using the old bitcast
- /// semantics (reinterpret memory) instead of the new bitcast semantics (copy logical bits) and
- /// the behavior will be equivalent. However, the behavior of `@bitSize` on arrays must be
- /// changed in `Type.zig` before enabling this feature to conform to the new bitcast semantics.
- scalarize_bitcast,
+ scalarize_ptr_cast,
+ scalarize_ptr_from_int,
+ scalarize_int_from_ptr,
scalarize_clz,
scalarize_ctz,
scalarize_popcount,
@@ -107,8 +103,8 @@ pub const Feature = enum {
scalarize_cmp_vector_optimized,
scalarize_fptrunc,
scalarize_fpext,
- scalarize_intcast,
- scalarize_intcast_safe,
+ scalarize_int_cast,
+ scalarize_int_cast_safe,
scalarize_trunc,
scalarize_int_from_float,
scalarize_int_from_float_optimized,
@@ -122,16 +118,45 @@ pub const Feature = enum {
scalarize_select,
scalarize_mul_add,
+ // Below are several different features for scalarizing `bit_cast` in different scenarios. It is
+ // valid to enable any combination of these features.
+
+ /// Scalarize `bit_cast` where the operand or result type is an array.
+ scalarize_bit_cast_array,
+ /// Scalarize `bit_cast` where either:
+ ///
+ /// * operand type is `@Vector(n, A), but result type is not `@Vector(n, B)`; or
+ /// * result type is `@Vector(n, A), but operand type is not `@Vector(n, B)`
+ ///
+ /// This effectively scalarizes any `bit_cast` to/from a vector, *unless* the operation can be
+ /// performed by bitcasting each vector element and returning a vector of the results.
+ ///
+ /// If this feature is enabled, the following AIR instruction tags may be emitted:
+ /// * `.legalize_vec_elem_val`
+ /// * `.legalize_vec_store_elem`
+ scalarize_bit_cast_vector_non_elementwise,
+ /// Scalarize `bit_cast` where the operand or result type is an array or vector whose element
+ /// type `E` has `@bitSizeOf(E) != 8 * @sizeOf(E)`. These are the cases where the backend may
+ /// need to sign- or zero-extend multiple elements to populate "padding" bits.
+ ///
+ /// Enabling this feature requires changing the behavior of `@bitSize` on arrays in `Type.zig`
+ /// to conform to the new bitcast semantics.
+ ///
+ /// If this feature is enabled, the following AIR instruction tags may be emitted:
+ /// * `.legalize_vec_elem_val`
+ /// * `.legalize_vec_store_elem`
+ scalarize_bit_cast_padded_elems,
+
/// Legalize (shift lhs, (splat rhs)) -> (shift lhs, rhs)
unsplat_shift_rhs,
/// Legalize reduce of a one element vector to a bitcast.
- reduce_one_elem_to_bitcast,
+ reduce_one_elem_to_bit_cast,
/// Legalize splat to a one element vector to a bitcast.
- splat_one_elem_to_bitcast,
+ splat_one_elem_to_bit_cast,
- /// Replace `intcast_safe` with an explicit safety check which `call`s the panic function on failure.
- /// Not compatible with `scalarize_intcast_safe`.
- expand_intcast_safe,
+ /// Replace `int_cast_safe` with an explicit safety check which `call`s the panic function on failure.
+ /// Not compatible with `scalarize_int_cast_safe`.
+ expand_int_cast_safe,
/// Replace `int_from_float_safe` with an explicit safety check which `call`s the panic function on failure.
/// Not compatible with `scalarize_int_from_float_safe`.
expand_int_from_float_safe,
@@ -156,9 +181,9 @@ pub const Feature = enum {
/// Currently assumes little endian and a specific integer layout where the lsb of every integer is the lsb of the
/// first byte of memory until bit pointers know their backing type.
expand_packed_store,
- /// Replace `struct_field_val` of a packed field with a `bitcast` to integer, `shr`, `trunc`, and `bitcast` to field type.
+ /// Replace `struct_field_val` of a packed field with a `bit_cast` to integer, `shr`, `trunc`, and `bit_cast` to field type.
expand_packed_struct_field_val,
- /// Replace `aggregate_init` of a packed struct with a sequence of `shl_exact`, `bitcast`, `intcast`, and `bit_or`.
+ /// Replace `aggregate_init` of a packed struct with a sequence of `shl_exact`, `bit_cast`, `int_cast`, and `bit_or`.
expand_packed_aggregate_init,
/// Replace all arithmetic operations on 16-bit floating-point types with calls to soft-float
@@ -227,7 +252,6 @@ pub const Feature = enum {
.shl_sat => .scalarize_shl_sat,
.xor => .scalarize_xor,
.not => .scalarize_not,
- .bitcast => .scalarize_bitcast,
.clz => .scalarize_clz,
.ctz => .scalarize_ctz,
.popcount => .scalarize_popcount,
@@ -253,8 +277,11 @@ pub const Feature = enum {
.cmp_vector_optimized => .scalarize_cmp_vector_optimized,
.fptrunc => .scalarize_fptrunc,
.fpext => .scalarize_fpext,
- .intcast => .scalarize_intcast,
- .intcast_safe => .scalarize_intcast_safe,
+ .int_cast => .scalarize_int_cast,
+ .int_cast_safe => .scalarize_int_cast_safe,
+ .ptr_cast => .scalarize_ptr_cast,
+ .ptr_from_int => .scalarize_ptr_from_int,
+ .int_from_ptr => .scalarize_int_from_ptr,
.trunc => .scalarize_trunc,
.int_from_float => .scalarize_int_from_float,
.int_from_float_optimized => .scalarize_int_from_float_optimized,
@@ -474,7 +501,10 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
.popcount,
.byte_swap,
.bit_reverse,
- .intcast,
+ .int_cast,
+ .ptr_cast,
+ .ptr_from_int,
+ .int_from_ptr,
.trunc,
=> |air_tag| if (l.features.has(comptime .scalarize(air_tag))) {
const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op;
@@ -548,15 +578,19 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
},
}
},
- .bitcast => if (l.features.has(.scalarize_bitcast)) {
+ .bit_cast => if (l.features.hasAny(&.{
+ .scalarize_bit_cast_array,
+ .scalarize_bit_cast_vector_non_elementwise,
+ .scalarize_bit_cast_padded_elems,
+ })) {
if (try l.scalarizeBitcastBlockPayload(inst)) |payload| {
continue :inst l.replaceInst(inst, .block, payload);
}
},
- .intcast_safe => if (l.features.has(.expand_intcast_safe)) {
- assert(!l.features.has(.scalarize_intcast_safe)); // it doesn't make sense to do both
+ .int_cast_safe => if (l.features.has(.expand_int_cast_safe)) {
+ assert(!l.features.has(.scalarize_int_cast_safe)); // it doesn't make sense to do both
continue :inst l.replaceInst(inst, .block, try l.safeIntcastBlockPayload(inst));
- } else if (l.features.has(.scalarize_intcast_safe)) {
+ } else if (l.features.has(.scalarize_int_cast_safe)) {
const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op;
if (ty_op.ty.toType().isVector(zcu)) {
continue :inst l.replaceInst(inst, .block, try l.scalarizeBlockPayload(inst, .ty_op));
@@ -772,10 +806,10 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
inline .reduce, .reduce_optimized => |air_tag| {
const reduce = l.air_instructions.items(.data)[@intFromEnum(inst)].reduce;
const vector_ty = l.typeOf(reduce.operand);
- if (l.features.has(.reduce_one_elem_to_bitcast)) {
+ if (l.features.has(.reduce_one_elem_to_bit_cast)) {
switch (vector_ty.vectorLen(zcu)) {
0 => unreachable,
- 1 => continue :inst l.replaceInst(inst, .bitcast, .{ .ty_op = .{
+ 1 => continue :inst l.replaceInst(inst, .bit_cast, .{ .ty_op = .{
.ty = .fromType(vector_ty.childType(zcu)),
.operand = reduce.operand,
} }),
@@ -792,11 +826,11 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
.soft_float => unreachable, // the operand is not a scalar
}
},
- .splat => if (l.features.has(.splat_one_elem_to_bitcast)) {
+ .splat => if (l.features.has(.splat_one_elem_to_bit_cast)) {
const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op;
switch (ty_op.ty.toType().vectorLen(zcu)) {
0 => unreachable,
- 1 => continue :inst l.replaceInst(inst, .bitcast, .{ .ty_op = .{
+ 1 => continue :inst l.replaceInst(inst, .bit_cast, .{ .ty_op = .{
.ty = ty_op.ty,
.operand = ty_op.operand,
} }),
@@ -862,7 +896,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
const field_bits = agg_ty.fieldType(field_index, zcu).bitSize(zcu);
if (field_bits == struct_bits) {
// Just bitcast this field.
- continue :inst l.replaceInst(inst, .bitcast, .{ .ty_op = .{
+ continue :inst l.replaceInst(inst, .bit_cast, .{ .ty_op = .{
.ty = .fromType(agg_ty),
.operand = @enumFromInt(l.air_extra.items[ty_pl.payload + field_index]),
} });
@@ -908,6 +942,11 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
.legalize_vec_elem_val,
.legalize_vec_store_elem,
.legalize_compiler_rt_call,
+ .spirv_runtime_array_len,
+ .error_cast,
+ .error_from_int,
+ .int_from_error,
+ .union_from_enum,
=> {},
}
}
@@ -930,7 +969,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, form: Scalariz
if (result_is_array) {
// This is only allowed when legalizing an elementwise bitcast.
- assert(orig.tag == .bitcast);
+ assert(orig.tag == .bit_cast);
assert(form == .ty_op);
}
@@ -1422,35 +1461,94 @@ fn scalarizeBitcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!?
const ty_op = l.air_instructions.items(.data)[@intFromEnum(orig_inst)].ty_op;
const dest_ty = ty_op.ty.toType();
- const dest_legal = switch (dest_ty.zigTypeTag(zcu)) {
- else => true,
- .array, .vector => legal: {
- if (dest_ty.arrayLen(zcu) == 1) break :legal true;
- const dest_elem_ty = dest_ty.childType(zcu);
- break :legal dest_elem_ty.bitSize(zcu) == 8 * dest_elem_ty.abiSize(zcu);
- },
- };
-
const operand_ty = l.typeOf(ty_op.operand);
- const operand_legal = switch (operand_ty.zigTypeTag(zcu)) {
- else => true,
- .array, .vector => legal: {
- if (operand_ty.arrayLen(zcu) == 1) break :legal true;
- const operand_elem_ty = operand_ty.childType(zcu);
- break :legal operand_elem_ty.bitSize(zcu) == 8 * operand_elem_ty.abiSize(zcu);
- },
+
+ // We exit this block only if the scalarization is actually necessary. Otherwise we will return
+ // `null` from within the block.
+ const operand_to_int_ok: bool, const int_to_dest_ok: bool = int_ok: {
+ const operand_tag = operand_ty.zigTypeTag(zcu);
+ const dest_tag = dest_ty.zigTypeTag(zcu);
+
+ if (operand_tag != .array and
+ operand_tag != .vector and
+ dest_tag != .array and
+ dest_tag != .vector)
+ {
+ return null;
+ }
+
+ // We track the validity of 3 different bitcast operations:
+ // * operand -> dest
+ // * operand -> uint
+ // * uint -> dest
+ // If operand->dest turns out to be valid, we don't need to scalarize. Otherwise, knowing
+ // the validity of the other operations helps us lower the scalarization efficiently.
+ var operand_to_dest: bool = true;
+ var operand_to_int: bool = true;
+ var int_to_dest: bool = true;
+
+ if (l.features.has(.scalarize_bit_cast_array)) {
+ if (operand_tag == .array) {
+ operand_to_dest = false;
+ operand_to_int = false;
+ }
+ if (dest_tag == .array) {
+ operand_to_dest = false;
+ int_to_dest = false;
+ }
+ }
+
+ if (l.features.has(.scalarize_bit_cast_vector_non_elementwise)) {
+ if (operand_tag == .vector) operand_to_int = false;
+ if (dest_tag == .vector) int_to_dest = false;
+
+ if (operand_tag == .vector or dest_tag == .vector) {
+ if (operand_tag != .vector or
+ dest_tag != .vector or
+ operand_ty.vectorLen(zcu) != dest_ty.vectorLen(zcu))
+ {
+ operand_to_dest = false;
+ }
+ }
+ }
+
+ if (l.features.has(.scalarize_bit_cast_padded_elems)) {
+ if (operand_tag == .array or operand_tag == .vector) {
+ const elem_ty = operand_ty.childType(zcu);
+ if (elem_ty.bitSize(zcu) != 8 * elem_ty.abiSize(zcu)) {
+ operand_to_int = false;
+ operand_to_dest = false;
+ }
+ }
+ if (dest_tag == .array or dest_tag == .vector) {
+ const elem_ty = dest_ty.childType(zcu);
+ if (elem_ty.bitSize(zcu) != 8 * elem_ty.abiSize(zcu)) {
+ int_to_dest = false;
+ operand_to_dest = false;
+ }
+ }
+ }
+
+ if (operand_to_dest) {
+ return null; // no scalarization needed!
+ }
+
+ // We need a scalarization, but before breaking from the block, check if we can do it
+ // elementwise---if we can, that's preferable to the generic lowering.
+ if ((operand_tag == .array or operand_tag == .vector) and
+ (dest_tag == .array or dest_tag == .vector) and
+ operand_ty.arrayLenIncludingSentinel(zcu) == dest_ty.arrayLenIncludingSentinel(zcu))
+ {
+ // Operand and result types are both arrays/vectors whose element types have the same
+ // bit size, so we can do an elementwise bitcast.
+ return try l.scalarizeBlockPayload(orig_inst, .ty_op);
+ }
+
+ break :int_ok .{ operand_to_int, int_to_dest };
};
- if (dest_legal and operand_legal) return null;
-
- if (!operand_legal and !dest_legal and operand_ty.arrayLen(zcu) == dest_ty.arrayLen(zcu)) {
- // from_ty and to_ty are both arrays or vectors of types with the same bit size,
- // so we can do an elementwise bitcast.
- return try l.scalarizeBlockPayload(orig_inst, .ty_op);
- }
-
- // Fallback path. Our strategy is to use an unsigned integer type as an intermediate
- // "bag of bits" representation which can be manipulated by bitwise operations.
+ // Generic scalarization implementation. Our strategy is to use an unsigned integer type as an
+ // intermediate "bag of bits" representation which can be manipulated by bitwise operations.
const num_bits: u16 = @intCast(dest_ty.bitSize(zcu));
assert(operand_ty.bitSize(zcu) == num_bits);
@@ -1464,11 +1562,17 @@ fn scalarizeBitcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!?
// First, convert `operand_ty` to `uint_ty` (`uN`).
const uint_val: Air.Inst.Ref = uint_val: {
- if (operand_legal) {
+ if (operand_to_int_ok) {
_ = main_block.stealCapacity(19);
break :uint_val main_block.addBitCast(l, uint_ty, ty_op.operand);
}
+ if (operand_ty.arrayLenIncludingSentinel(zcu) == 1) {
+ _ = main_block.stealCapacity(18);
+ const elem = main_block.addBinOp(l, .array_elem_val, ty_op.operand, .zero_usize).toRef();
+ break :uint_val main_block.addBitCast(l, uint_ty, elem);
+ }
+
// %1 = block({
// %2 = alloc(*usize)
// %3 = alloc(*uN)
@@ -1477,8 +1581,8 @@ fn scalarizeBitcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!?
// %6 = loop({
// %7 = load(%2)
// %8 = array_elem_val(orig_operand, %7)
- // %9 = bitcast(uE, %8)
- // %10 = intcast(uN, %9)
+ // %9 = bit_cast(uE, %8)
+ // %10 = int_cast(uN, %9)
// %11 = load(%3)
// %12 = shl_exact(%11, )
// %13 = bit_or(%12, %10)
@@ -1528,7 +1632,7 @@ fn scalarizeBitcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!?
index_val,
).toRef();
const elem_uint = loop.block.addBitCast(l, elem_uint_ty, raw_elem);
- const elem_extended = loop.block.addTyOp(l, .intcast, uint_ty, elem_uint).toRef();
+ const elem_extended = loop.block.addTyOp(l, .int_cast, uint_ty, elem_uint).toRef();
const old_result = loop.block.addTyOp(l, .load, uint_ty, result_ptr).toRef();
const shifted_result = loop.block.addBinOp(l, .shl_exact, old_result, .fromValue(elem_bits_val)).toRef();
const new_result = loop.block.addBinOp(l, .bit_or, shifted_result, elem_extended).toRef();
@@ -1559,10 +1663,23 @@ fn scalarizeBitcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!?
// Now convert `uint_ty` (`uN`) to `dest_ty`.
- if (dest_legal) {
+ if (int_to_dest_ok) {
_ = main_block.stealCapacity(17);
const result = main_block.addBitCast(l, dest_ty, uint_val);
main_block.addBr(l, orig_inst, result);
+ } else if (dest_ty.arrayLenIncludingSentinel(zcu) == 1) {
+ _ = main_block.stealCapacity(16);
+ const elem = main_block.addBitCast(l, dest_ty.childType(zcu), uint_val);
+ const aggregate_init_payload_start = l.air_extra.items.len;
+ try l.air_extra.append(zcu.gpa, @intFromEnum(elem));
+ const result = main_block.add(l, .{
+ .tag = .aggregate_init,
+ .data = .{ .ty_pl = .{
+ .ty = .fromType(dest_ty),
+ .payload = @intCast(aggregate_init_payload_start),
+ } },
+ }).toRef();
+ main_block.addBr(l, orig_inst, result);
} else {
// %1 = alloc(*usize)
// %2 = alloc(*@Vector(N, Result))
@@ -1570,10 +1687,10 @@ fn scalarizeBitcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!?
// %4 = loop({
// %5 = load(%1)
// %6 = mul(%5, )
- // %7 = intcast(uS, %6)
+ // %7 = int_cast(uS, %6)
// %8 = shr(uint_val, %7)
// %9 = trunc(uE, %8)
- // %10 = bitcast(Result, %9)
+ // %10 = bit_cast(Result, %9)
// %11 = legalize_vec_store_elem(%2, %5, %10)
// %12 = cmp_eq(%5, )
// %13 = cond_br(%12, {
@@ -1602,7 +1719,7 @@ fn scalarizeBitcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!?
const index_val = loop.block.addTyOp(l, .load, .usize, index_ptr).toRef();
const bit_offset = loop.block.addBinOp(l, .mul, index_val, .fromValue(try pt.intValue(.usize, elem_bits))).toRef();
- const casted_bit_offset = loop.block.addTyOp(l, .intcast, shift_ty, bit_offset).toRef();
+ const casted_bit_offset = loop.block.addTyOp(l, .int_cast, shift_ty, bit_offset).toRef();
const shifted_uint = loop.block.addBinOp(l, .shr, uint_val, casted_bit_offset).toRef();
const elem_uint = loop.block.addTyOp(l, .trunc, elem_uint_ty, shifted_uint).toRef();
const elem_val = loop.block.addBitCast(l, elem_ty, elem_uint);
@@ -1980,7 +2097,7 @@ fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In
// %5 = call(@panic.invalidEnumValue, [])
// %6 = unreach()
// }, {
- // %7 = intcast(@res_ty, %y)
+ // %7 = int_cast(@res_ty, %y)
// %8 = is_named_enum_value(%7)
// %9 = cond_br(%8, {
// %10 = br(%x, %7)
@@ -2002,7 +2119,7 @@ fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In
// %6 = call(@panic.invalidEnumValue, [])
// %7 = unreach()
// }, {
- // %8 = intcast(@res_ty, %y)
+ // %8 = int_cast(@res_ty, %y)
// %9 = br(%x, %8)
// })
// })
@@ -2055,9 +2172,9 @@ fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In
cur_block = &condbr.else_block;
}
- // Now we know we're in-range, we can intcast:
+ // Now we know we're in-range, we can int_cast:
const cast_inst = cur_block.add(l, .{
- .tag = .intcast,
+ .tag = .int_cast,
.data = .{ .ty_op = .{
.ty = Air.internedToRef(dest_ty.toIntern()),
.operand = operand_ref,
@@ -2228,7 +2345,7 @@ fn safeArithmeticBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, overflow_
// %1 = add_with_overflow(%x, %y)
// %2 = struct_field_val(%1, .@"1")
// %3 = reduce(%2, .@"or")
- // %4 = bitcast(%3, @bool_type)
+ // %4 = bit_cast(%3, @bool_type)
// %5 = cond_br(%4, {
// %6 = call(@panic.integerOverflow, [])
// %7 = unreach()
@@ -2334,7 +2451,7 @@ fn packedLoadBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.Ins
.tag = .load,
.data = .{ .ty_op = .{
.ty = Air.internedToRef(load_ty.toIntern()),
- .operand = res_block.addBitCast(l, load_ptr_ty: {
+ .operand = res_block.addPtrCast(l, load_ptr_ty: {
var load_ptr_info = ptr_info;
load_ptr_info.child = load_ty.toIntern();
load_ptr_info.flags.vector_index = .none;
@@ -2377,23 +2494,17 @@ fn packedStoreBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In
var res_block: Block = .init(&inst_buf);
{
- const backing_ptr_inst = res_block.add(l, .{
- .tag = .bitcast,
- .data = .{ .ty_op = .{
- .ty = Air.internedToRef((load_store_ptr_ty: {
- var load_ptr_info = ptr_info;
- load_ptr_info.child = load_store_ty.toIntern();
- load_ptr_info.flags.vector_index = .none;
- load_ptr_info.packed_offset = .{ .host_size = 0, .bit_offset = 0 };
- break :load_store_ptr_ty try pt.ptrType(load_ptr_info);
- }).toIntern()),
- .operand = orig_bin_op.lhs,
- } },
- });
+ const backing_ptr = res_block.addPtrCast(l, load_store_ptr_ty: {
+ var load_ptr_info = ptr_info;
+ load_ptr_info.child = load_store_ty.toIntern();
+ load_ptr_info.flags.vector_index = .none;
+ load_ptr_info.packed_offset = .{ .host_size = 0, .bit_offset = 0 };
+ break :load_store_ptr_ty try pt.ptrType(load_ptr_info);
+ }, orig_bin_op.lhs);
_ = res_block.add(l, .{
.tag = .store,
.data = .{ .bin_op = .{
- .lhs = backing_ptr_inst.toRef(),
+ .lhs = backing_ptr,
.rhs = res_block.add(l, .{
.tag = .bit_or,
.data = .{ .bin_op = .{
@@ -2404,7 +2515,7 @@ fn packedStoreBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In
.tag = .load,
.data = .{ .ty_op = .{
.ty = Air.internedToRef(load_store_ty.toIntern()),
- .operand = backing_ptr_inst.toRef(),
+ .operand = backing_ptr,
} },
}).toRef(),
.rhs = Air.internedToRef((keep_mask: {
@@ -2433,7 +2544,7 @@ fn packedStoreBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In
.tag = .shl_exact,
.data = .{ .bin_op = .{
.lhs = res_block.add(l, .{
- .tag = .intcast,
+ .tag = .int_cast,
.data = .{ .ty_op = .{
.ty = Air.internedToRef(load_store_ty.toIntern()),
.operand = res_block.addBitCast(l, operand_int_ty, orig_bin_op.rhs),
@@ -2531,7 +2642,7 @@ fn packedAggregateInitBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Erro
const shifted = main_block.addBinOp(l, .shl_exact, cur_uint, field_bit_size_ref).toRef();
const field_as_uint = main_block.addBitCast(l, field_uint_ty, field_val);
- const field_extended = main_block.addTyOp(l, .intcast, uint_ty, field_as_uint).toRef();
+ const field_extended = main_block.addTyOp(l, .int_cast, uint_ty, field_as_uint).toRef();
cur_uint = main_block.addBinOp(l, .bit_or, shifted, field_extended).toRef();
}
@@ -2720,18 +2831,51 @@ const Block = struct {
});
}
- /// Adds a `bitcast` instruction to `b`. This is a thin wrapper that omits the instruction for
+ /// Adds a `bit_cast` instruction to `b`. This is a thin wrapper that omits the instruction for
/// no-op casts.
fn addBitCast(
b: *Block,
l: *Legalize,
- ty: Type,
+ result_ty: Type,
operand: Air.Inst.Ref,
) Air.Inst.Ref {
- if (ty.toIntern() != l.typeOf(operand).toIntern()) return b.add(l, .{
- .tag = .bitcast,
+ const zcu = l.pt.zcu;
+ const operand_ty = l.typeOf(operand);
+ assert(!operand_ty.isPtrAtRuntime(zcu));
+ assert(!operand_ty.isSliceAtRuntime(zcu));
+ assert(!result_ty.isPtrAtRuntime(zcu));
+ assert(!result_ty.isSliceAtRuntime(zcu));
+ if (result_ty.toIntern() != operand_ty.toIntern()) return b.add(l, .{
+ .tag = .bit_cast,
.data = .{ .ty_op = .{
- .ty = Air.internedToRef(ty.toIntern()),
+ .ty = .fromType(result_ty),
+ .operand = operand,
+ } },
+ }).toRef();
+ _ = b.stealCapacity(1);
+ return operand;
+ }
+
+ /// Adds a `ptr_cast` instruction to `b`. This is a thin wrapper that omits the instruction for
+ /// no-op casts.
+ fn addPtrCast(
+ b: *Block,
+ l: *Legalize,
+ result_ty: Type,
+ operand: Air.Inst.Ref,
+ ) Air.Inst.Ref {
+ const zcu = l.pt.zcu;
+ const operand_ty = l.typeOf(operand);
+ if (operand_ty.isSliceAtRuntime(zcu)) {
+ assert(result_ty.isSliceAtRuntime(zcu));
+ } else {
+ assert(operand_ty.isPtrAtRuntime(zcu));
+ assert(result_ty.isPtrAtRuntime(zcu));
+ }
+ if (result_ty.toIntern() != operand_ty.toIntern()) return b.add(l, .{
+ .tag = .ptr_cast,
+ .data = .{ .ty_op = .{
+ .ty = .fromType(result_ty),
.operand = operand,
} },
}).toRef();
@@ -3072,7 +3216,7 @@ fn softFloatFromInt(l: *Legalize, orig_inst: Air.Inst.Index) Error!union(enum) {
var main_block: Block = .init(&inst_buf);
try l.air_instructions.ensureUnusedCapacity(zcu.gpa, inst_buf.len);
- const extended_val = main_block.addTyOp(l, .intcast, extended_ty, ty_op.operand).toRef();
+ const extended_val = main_block.addTyOp(l, .int_cast, extended_ty, ty_op.operand).toRef();
const call_inst = try main_block.addCompilerRtCall(l, func, &.{extended_val});
const casted_result = main_block.addBitCast(l, dest_ty, call_inst.toRef());
main_block.addBr(l, orig_inst, casted_result);
@@ -3099,7 +3243,7 @@ fn softFloatFromInt(l: *Legalize, orig_inst: Air.Inst.Index) Error!union(enum) {
try l.air_instructions.ensureUnusedCapacity(zcu.gpa, inst_buf.len);
const extended_val: Air.Inst.Ref = if (extended_ty.toIntern() != src_ty.toIntern()) ext: {
- break :ext main_block.addTyOp(l, .intcast, extended_ty, ty_op.operand).toRef();
+ break :ext main_block.addTyOp(l, .int_cast, extended_ty, ty_op.operand).toRef();
} else ext: {
_ = main_block.stealCapacity(1);
break :ext ty_op.operand;
@@ -3164,7 +3308,7 @@ fn softIntFromFloat(l: *Legalize, orig_inst: Air.Inst.Index) Error!union(enum) {
try l.air_instructions.ensureUnusedCapacity(zcu.gpa, inst_buf.len);
const call_inst = try main_block.addCompilerRtCall(l, func, &.{ty_op.operand});
- const casted_val = main_block.addTyOp(l, .intcast, dest_ty, call_inst.toRef()).toRef();
+ const casted_val = main_block.addTyOp(l, .int_cast, dest_ty, call_inst.toRef()).toRef();
main_block.addBr(l, orig_inst, casted_val);
return .{ .block_payload = .{ .ty_pl = .{
@@ -3188,7 +3332,7 @@ fn softIntFromFloat(l: *Legalize, orig_inst: Air.Inst.Index) Error!union(enum) {
const bits_val = try pt.intValue(.usize, dest_info.bits);
_ = try main_block.addCompilerRtCall(l, func, &.{ extended_ptr, .fromValue(bits_val), ty_op.operand });
const extended_val = main_block.addTyOp(l, .load, extended_ty, extended_ptr).toRef();
- const result_val = main_block.addTyOp(l, .intcast, dest_ty, extended_val).toRef();
+ const result_val = main_block.addTyOp(l, .int_cast, dest_ty, extended_val).toRef();
main_block.addBr(l, orig_inst, result_val);
return .{ .block_payload = .{ .ty_pl = .{
diff --git a/src/Air/Liveness.zig b/src/Air/Liveness.zig
index 773074a1ce9de7cf019a167d36483db6e3316ec8..ee1c1a2e819fba98a1af5484a2e60a85ed98586b 100644
--- a/src/Air/Liveness.zig
+++ b/src/Air/Liveness.zig
@@ -488,12 +488,19 @@ fn analyzeInst(
=> return analyzeFuncEnd(a, pass, data, inst, .{ .none, .none, .none }),
.not,
- .bitcast,
+ .bit_cast,
+ .ptr_cast,
+ .ptr_from_int,
+ .int_from_ptr,
+ .error_cast,
+ .error_from_int,
+ .int_from_error,
+ .union_from_enum,
.load,
.fpext,
.fptrunc,
- .intcast,
- .intcast_safe,
+ .int_cast,
+ .int_cast_safe,
.trunc,
.optional_payload,
.optional_payload_ptr,
@@ -673,7 +680,7 @@ fn analyzeInst(
const extra = a.air.extraData(Air.UnionInit, inst_datas[@intFromEnum(inst)].ty_pl.payload).data;
return analyzeOperands(a, pass, data, inst, .{ extra.init, .none, .none });
},
- .struct_field_ptr, .struct_field_val => {
+ .struct_field_ptr, .struct_field_val, .spirv_runtime_array_len => {
const extra = a.air.extraData(Air.StructField, inst_datas[@intFromEnum(inst)].ty_pl.payload).data;
return analyzeOperands(a, pass, data, inst, .{ extra.struct_operand, .none, .none });
},
diff --git a/src/Air/Liveness/Verify.zig b/src/Air/Liveness/Verify.zig
index 294a68fc4640072ce924a986e3a6ae0125bf04d4..dbd664db52b56951a8d4de99686ab55cb896d769 100644
--- a/src/Air/Liveness/Verify.zig
+++ b/src/Air/Liveness/Verify.zig
@@ -78,12 +78,19 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
// unary
.not,
- .bitcast,
+ .bit_cast,
+ .ptr_cast,
+ .ptr_from_int,
+ .int_from_ptr,
+ .error_cast,
+ .error_from_int,
+ .int_from_error,
+ .union_from_enum,
.load,
.fpext,
.fptrunc,
- .intcast,
- .intcast_safe,
+ .int_cast,
+ .int_cast_safe,
.trunc,
.optional_payload,
.optional_payload_ptr,
@@ -191,7 +198,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
try self.verifyInstOperands(inst, .{ extra.init, .none, .none });
},
- .struct_field_ptr, .struct_field_val => {
+ .struct_field_ptr, .struct_field_val, .spirv_runtime_array_len => {
const ty_pl = data[@intFromEnum(inst)].ty_pl;
const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
try self.verifyInstOperands(inst, .{ extra.struct_operand, .none, .none });
diff --git a/src/Air/Verify.zig b/src/Air/Verify.zig
new file mode 100644
index 0000000000000000000000000000000000000000..1216ff2f2ee14ffde2ca3e830376a674d95f0cfb
--- /dev/null
+++ b/src/Air/Verify.zig
@@ -0,0 +1,465 @@
+/// Verifies that AIR is valid, in that every instruction has valid operands and types. In compiler
+/// builds with debug extensions, this is run on all AIR, both before `Air.Legalize` is run and (if
+/// it is run) after it.
+///
+/// This verification pass is currently highly incomplete---expand it as needed.
+const Verify = @This();
+
+zcu: *Zcu,
+func_index: InternPool.Index,
+ret_ty: Type,
+air: *const Air,
+cur_inst: Air.Inst.Index,
+
+pub fn run(pt: Zcu.PerThread, func_index: InternPool.Index, air: *const Air) void {
+ if (!@import("build_options").enable_debug_extensions) {
+ // `Air.Verify` is a debugging feature---it should not be used in release builds because it
+ // has little benefit and negatively affects compiler performance.
+ return;
+ }
+
+ const zcu = pt.zcu;
+
+ const func_ty: Type = Value.fromInterned(func_index).typeOf(zcu);
+ const ret_ty = func_ty.fnReturnType(zcu);
+
+ var verify: Verify = .{
+ .zcu = zcu,
+ .func_index = func_index,
+ .ret_ty = ret_ty,
+ .air = air,
+ .cur_inst = undefined, // populated by `body(...)`
+ };
+ verify.body(air.getMainBody()) catch |verify_err| switch (verify_err) {
+ error.VerifyFail => {
+ const ip = &zcu.intern_pool;
+ const func_nav = ip.indexToKey(func_index).func.owner_nav;
+ const func_fqn = ip.getNav(func_nav).fqn.toSlice(ip);
+ log.info("AIR for '{s}':", .{func_fqn});
+ const io = zcu.comp.io;
+ const stderr = io.lockStderr(&.{}, null) catch |err| switch (err) {
+ error.Canceled => return io.recancel(),
+ };
+ defer io.unlockStderr();
+ air.write(&stderr.file_writer.interface, pt, null) catch |err| switch (err) {
+ error.WriteFailed => switch (stderr.file_writer.err.?) {
+ error.Canceled => return io.recancel(),
+ else => {},
+ },
+ };
+ },
+ };
+}
+
+const Error = error{VerifyFail};
+
+fn fail(verify: *Verify, msg: []const u8) Error {
+ const ip = &verify.zcu.intern_pool;
+ const func_nav = ip.indexToKey(verify.func_index).func.owner_nav;
+ const func_fqn = ip.getNav(func_nav).fqn.toSlice(ip);
+ log.err("'{s}', %{d}: {s}", .{ func_fqn, verify.cur_inst, msg });
+ return error.VerifyFail;
+}
+
+fn body(verify: *Verify, body_insts: []const Air.Inst.Index) Error!void {
+ const zcu = verify.zcu;
+ const ip = &zcu.intern_pool;
+ const air = verify.air;
+ const tags = air.instructions.items(.tag);
+ const data = air.instructions.items(.data);
+ for (body_insts, 0..) |inst, body_index| {
+ verify.cur_inst = inst;
+ switch (tags[@intFromEnum(inst)]) {
+ .block => {
+ const block = air.unwrapBlock(inst);
+ try verify.body(block.body);
+ },
+ .dbg_inline_block => {
+ const block = air.unwrapDbgBlock(inst);
+ try verify.body(block.body);
+ },
+ .@"try", .try_cold => {
+ const @"try" = air.unwrapTry(inst);
+ try verify.body(@"try".else_body);
+ },
+ .try_ptr, .try_ptr_cold => {
+ const try_ptr = air.unwrapTryPtr(inst);
+ try verify.body(try_ptr.else_body);
+ },
+ .loop => {
+ const block = air.unwrapBlock(inst);
+ try verify.body(block.body);
+ },
+ .cond_br => {
+ const cond_br = air.unwrapCondBr(inst);
+ try verify.body(cond_br.then_body);
+ try verify.body(cond_br.else_body);
+ },
+ .switch_br, .loop_switch_br => {
+ const switch_br = air.unwrapSwitch(inst);
+ var it = switch_br.iterateCases();
+ while (it.next()) |case| {
+ try verify.body(case.body);
+ }
+ const else_body = it.elseBody();
+ if (else_body.len > 0) {
+ try verify.body(else_body);
+ }
+ },
+ .ret, .ret_safe => {
+ const operand = data[@intFromEnum(inst)].un_op;
+ if (air.typeOf(operand, ip).toIntern() != verify.ret_ty.toIntern()) return verify.fail("bad return type");
+ },
+ .ret_load => {
+ const operand = data[@intFromEnum(inst)].un_op;
+ const ptr_ty = air.typeOf(operand, ip);
+ if (ptr_ty.zigTypeTag(zcu) != .pointer) return verify.fail("operand is not a pointer");
+ if (ptr_ty.ptrSize(zcu) != .one) return verify.fail("pointer size is not '.one'");
+ if (ptr_ty.childType(zcu).toIntern() != verify.ret_ty.toIntern()) return verify.fail("bad return type");
+ },
+
+ .bit_cast => {
+ const ty_op = data[@intFromEnum(inst)].ty_op;
+ const operand_ty = air.typeOf(ty_op.operand, ip);
+ const result_ty = ty_op.ty.toType();
+ // Enums are allowed here even if their backing type is implicit.
+ if (!operand_ty.hasBitRepresentation(zcu) and operand_ty.zigTypeTag(zcu) != .@"enum") {
+ return verify.fail("bad operand type");
+ }
+ if (!result_ty.hasBitRepresentation(zcu) and result_ty.zigTypeTag(zcu) != .@"enum") {
+ return verify.fail("bad result type");
+ }
+ if (operand_ty.isPtrAtRuntime(zcu)) return verify.fail("bad operand type (pointer)");
+ if (result_ty.isPtrAtRuntime(zcu)) return verify.fail("bad result type (pointer)");
+ if (operand_ty.bitSize(zcu) != result_ty.bitSize(zcu)) return verify.fail("bit size mismatch");
+ },
+ .ptr_cast => {
+ const ty_op = data[@intFromEnum(inst)].ty_op;
+ const operand_ty = air.typeOf(ty_op.operand, ip);
+ const result_ty = ty_op.ty.toType();
+ const operand_scalar_ty = operand_ty.scalarType(zcu);
+ const result_scalar_ty = result_ty.scalarType(zcu);
+ if (operand_ty.isSliceAtRuntime(zcu)) {
+ if (!result_ty.isSliceAtRuntime(zcu)) return verify.fail("operand is slice, but result is not");
+ } else {
+ if (!operand_scalar_ty.isPtrAtRuntime(zcu)) return verify.fail("bad operand type");
+ if (!result_scalar_ty.isPtrAtRuntime(zcu)) return verify.fail("operand is pointer, but result is not");
+ if (operand_ty.isVector(zcu) and !result_ty.isVector(zcu)) return verify.fail("operand is vector, but result is not");
+ if (!operand_ty.isVector(zcu) and result_ty.isVector(zcu)) return verify.fail("result is vector, but operand is not");
+ }
+ if (operand_scalar_ty.ptrAddressSpace(zcu) != result_scalar_ty.ptrAddressSpace(zcu)) {
+ return verify.fail("illegal change to address space");
+ }
+ },
+ .ptr_from_int => {
+ const ty_op = data[@intFromEnum(inst)].ty_op;
+ const operand_ty = air.typeOf(ty_op.operand, ip);
+ const result_ty = ty_op.ty.toType();
+ const operand_scalar_ty = operand_ty.scalarType(zcu);
+ const result_scalar_ty = result_ty.scalarType(zcu);
+ if (operand_scalar_ty.toIntern() != .usize_type) return verify.fail("bad operand type");
+ if (!result_scalar_ty.isPtrAtRuntime(zcu)) return verify.fail("bad result type");
+ if (operand_ty.isVector(zcu) and !result_ty.isVector(zcu)) return verify.fail("operand is vector, but result is not");
+ if (!operand_ty.isVector(zcu) and result_ty.isVector(zcu)) return verify.fail("result is vector, but operand is not");
+ },
+ .int_from_ptr => {
+ const ty_op = data[@intFromEnum(inst)].ty_op;
+ const operand_ty = air.typeOf(ty_op.operand, ip);
+ const result_ty = ty_op.ty.toType();
+ const operand_scalar_ty = operand_ty.scalarType(zcu);
+ const result_scalar_ty = result_ty.scalarType(zcu);
+ if (!operand_scalar_ty.isPtrAtRuntime(zcu)) return verify.fail("bad operand type");
+ if (result_scalar_ty.toIntern() != .usize_type) return verify.fail("bad result type");
+ if (operand_ty.isVector(zcu) and !result_ty.isVector(zcu)) return verify.fail("operand is vector, but result is not");
+ if (!operand_ty.isVector(zcu) and result_ty.isVector(zcu)) return verify.fail("result is vector, but operand is not");
+ },
+ .error_cast => {
+ const ty_op = data[@intFromEnum(inst)].ty_op;
+ const operand_ty = air.typeOf(ty_op.operand, ip);
+ const result_ty = ty_op.ty.toType();
+ switch (operand_ty.zigTypeTag(zcu)) {
+ else => return verify.fail("bad operand type"),
+ .error_union => {
+ if (result_ty.zigTypeTag(zcu) != .error_union) {
+ return verify.fail("operand is error union, but result is not");
+ }
+ if (operand_ty.errorUnionPayload(zcu).toIntern() != result_ty.errorUnionPayload(zcu).toIntern()) {
+ return verify.fail("error union payload type differs");
+ }
+ },
+ .error_set => if (result_ty.zigTypeTag(zcu) != .error_set) {
+ return verify.fail("operand is error set, but result is not");
+ },
+ }
+ },
+ .error_from_int => {
+ const ty_op = data[@intFromEnum(inst)].ty_op;
+ const operand_ty = air.typeOf(ty_op.operand, ip);
+ const result_ty = ty_op.ty.toType();
+ if (!operand_ty.isUnsignedInt(zcu)) return verify.fail("bad operand type");
+ if (operand_ty.bitSize(zcu) != zcu.errorSetBits()) return verify.fail("bad operand bit size");
+ if (result_ty.zigTypeTag(zcu) != .error_set) return verify.fail("bad result type");
+ },
+ .int_from_error => {
+ const ty_op = data[@intFromEnum(inst)].ty_op;
+ const operand_ty = air.typeOf(ty_op.operand, ip);
+ const result_ty = ty_op.ty.toType();
+ if (operand_ty.zigTypeTag(zcu) != .error_set) return verify.fail("bad operand type");
+ if (!result_ty.isUnsignedInt(zcu)) return verify.fail("bad result type");
+ if (result_ty.bitSize(zcu) != zcu.errorSetBits()) return verify.fail("bad result bit size");
+ },
+ .union_from_enum => {
+ const ty_op = data[@intFromEnum(inst)].ty_op;
+ const operand_ty = air.typeOf(ty_op.operand, ip);
+ const result_ty = ty_op.ty.toType();
+ if (operand_ty.zigTypeTag(zcu) != .@"enum") return verify.fail("bad operand type");
+ if (result_ty.zigTypeTag(zcu) != .@"union") return verify.fail("bad result type");
+ const union_tag_ty = result_ty.unionTagType(zcu) orelse return verify.fail("union type is not tagged");
+ if (union_tag_ty.toIntern() != operand_ty.toIntern()) return verify.fail("union tag type does not match operand type");
+ },
+
+ .ptr_elem_ptr => {
+ const ty_pl = data[@intFromEnum(inst)].ty_pl;
+ const bin_op = air.extraData(Air.Bin, ty_pl.payload).data;
+ const ptr_ty = air.typeOf(bin_op.lhs, ip);
+ const result_ty = ty_pl.ty.toType();
+ if (ptr_ty.zigTypeTag(zcu) != .pointer) return verify.fail("bad pointer type");
+ if (result_ty.zigTypeTag(zcu) != .pointer) return verify.fail("bad result type");
+ const ptr_info = ptr_ty.ptrInfo(zcu);
+ const result_ptr_info = result_ty.ptrInfo(zcu);
+ if (ptr_info.packed_offset.host_size != 0) return verify.fail("pointer type is bitpacked pointer");
+ if (result_ptr_info.packed_offset.host_size != 0) return verify.fail("result type is bitpacked pointer");
+ },
+
+ .arg,
+ .add,
+ .add_safe,
+ .add_optimized,
+ .add_wrap,
+ .add_sat,
+ .sub,
+ .sub_safe,
+ .sub_optimized,
+ .sub_wrap,
+ .sub_sat,
+ .mul,
+ .mul_safe,
+ .mul_optimized,
+ .mul_wrap,
+ .mul_sat,
+ .div_float,
+ .div_float_optimized,
+ .div_trunc,
+ .div_trunc_optimized,
+ .div_floor,
+ .div_floor_optimized,
+ .div_exact,
+ .div_exact_optimized,
+ .rem,
+ .rem_optimized,
+ .mod,
+ .mod_optimized,
+ .ptr_add,
+ .ptr_sub,
+ .max,
+ .min,
+ .add_with_overflow,
+ .sub_with_overflow,
+ .mul_with_overflow,
+ .shl_with_overflow,
+ .alloc,
+ .inferred_alloc,
+ .inferred_alloc_comptime,
+ .ret_ptr,
+ .assembly,
+ .bit_and,
+ .bit_or,
+ .shr,
+ .shr_exact,
+ .shl,
+ .shl_exact,
+ .shl_sat,
+ .xor,
+ .not,
+ .repeat,
+ .br,
+ .trap,
+ .breakpoint,
+ .ret_addr,
+ .frame_addr,
+ .call,
+ .call_always_tail,
+ .call_never_tail,
+ .call_never_inline,
+ .clz,
+ .ctz,
+ .popcount,
+ .byte_swap,
+ .bit_reverse,
+ .sqrt,
+ .sin,
+ .cos,
+ .tan,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .abs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
+ .neg,
+ .neg_optimized,
+ .cmp_lt,
+ .cmp_lt_optimized,
+ .cmp_lte,
+ .cmp_lte_optimized,
+ .cmp_eq,
+ .cmp_eq_optimized,
+ .cmp_gte,
+ .cmp_gte_optimized,
+ .cmp_gt,
+ .cmp_gt_optimized,
+ .cmp_neq,
+ .cmp_neq_optimized,
+ .cmp_vector,
+ .cmp_vector_optimized,
+ .switch_dispatch,
+ .dbg_stmt,
+ .dbg_empty_stmt,
+ .dbg_var_ptr,
+ .dbg_var_val,
+ .dbg_arg_inline,
+ .is_null,
+ .is_non_null,
+ .is_null_ptr,
+ .is_non_null_ptr,
+ .is_err,
+ .is_non_err,
+ .is_err_ptr,
+ .is_non_err_ptr,
+ .load,
+ .store,
+ .store_safe,
+ .unreach,
+ .fptrunc,
+ .fpext,
+ .int_cast,
+ .int_cast_safe,
+ .trunc,
+ .optional_payload,
+ .optional_payload_ptr,
+ .optional_payload_ptr_set,
+ .wrap_optional,
+ .unwrap_errunion_payload,
+ .unwrap_errunion_err,
+ .unwrap_errunion_payload_ptr,
+ .unwrap_errunion_err_ptr,
+ .errunion_payload_ptr_set,
+ .wrap_errunion_payload,
+ .wrap_errunion_err,
+ .struct_field_ptr,
+ .struct_field_ptr_index_0,
+ .struct_field_ptr_index_1,
+ .struct_field_ptr_index_2,
+ .struct_field_ptr_index_3,
+ .struct_field_val,
+ .set_union_tag,
+ .get_union_tag,
+ .slice,
+ .slice_len,
+ .slice_ptr,
+ .ptr_slice_len_ptr,
+ .ptr_slice_ptr_ptr,
+ .array_elem_val,
+ .slice_elem_val,
+ .slice_elem_ptr,
+ .ptr_elem_val,
+ .array_to_slice,
+ .int_from_float,
+ .int_from_float_optimized,
+ .int_from_float_safe,
+ .int_from_float_optimized_safe,
+ .float_from_int,
+ .reduce,
+ .reduce_optimized,
+ .splat,
+ .shuffle_one,
+ .shuffle_two,
+ .select,
+ .memset,
+ .memset_safe,
+ .memcpy,
+ .memmove,
+ .cmpxchg_weak,
+ .cmpxchg_strong,
+ .atomic_load,
+ .atomic_store_unordered,
+ .atomic_store_monotonic,
+ .atomic_store_release,
+ .atomic_store_seq_cst,
+ .atomic_rmw,
+ .is_named_enum_value,
+ .tag_name,
+ .error_name,
+ .error_set_has_value,
+ .aggregate_init,
+ .union_init,
+ .prefetch,
+ .mul_add,
+ .field_parent_ptr,
+ .wasm_memory_size,
+ .wasm_memory_grow,
+ .cmp_lte_errors_len,
+ .err_return_trace,
+ .set_err_return_trace,
+ .addrspace_cast,
+ .save_err_return_trace_index,
+ .runtime_nav_ptr,
+ .c_va_arg,
+ .c_va_copy,
+ .c_va_end,
+ .c_va_start,
+ .spirv_runtime_array_len,
+ .work_item_id,
+ .work_group_size,
+ .work_group_id,
+ .legalize_vec_store_elem,
+ .legalize_vec_elem_val,
+ .legalize_compiler_rt_call,
+ => {},
+ }
+ if (air.typeOfIndex(inst, ip).isNoReturn(zcu)) {
+ if (body_index == body_insts.len - 1) return;
+
+ // HACK: right now, we emit the safety check for noreturn functions returning in a weird
+ // way, where the `call` instruction is `noreturn` but there are still instructions
+ // following it. We need to figure out a better way to represent that! That safety check
+ // probably just needs to live exclusively in backends; putting AIR instructions after a
+ // call implies that we have e.g. a valid stack at that point, which we can't actually
+ // assume when the user has gotten a function's ABI wrong.
+ switch (tags[@intFromEnum(inst)]) {
+ .call,
+ .call_always_tail,
+ .call_never_tail,
+ .call_never_inline,
+ => continue,
+ else => {},
+ }
+
+ return verify.fail("body contains instructions after noreturn");
+ }
+ }
+ return verify.fail("body does not terminate noreturn");
+}
+
+const std = @import("std");
+const log = std.log.scoped(.air_verify);
+
+const Zcu = @import("../Zcu.zig");
+const InternPool = @import("../InternPool.zig");
+const Air = @import("../Air.zig");
+const Type = @import("../Type.zig");
+const Value = @import("../Value.zig");
diff --git a/src/Air/print.zig b/src/Air/print.zig
index b3739ece3334ede99c3d66164b9fdbd3b7dfec54..39fe184ee492e51ab8b81a227d4dc7fbcc91572c 100644
--- a/src/Air/print.zig
+++ b/src/Air/print.zig
@@ -73,23 +73,19 @@ pub fn writeInst(
}
pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
- const comp = pt.zcu.comp;
- const io = comp.io;
- var buffer: [512]u8 = undefined;
- const stderr = try io.lockStderr(&buffer, null);
- defer io.unlockStderr();
+ var buffer: [4096]u8 = undefined;
+ const stderr = std.debug.lockStderr(&buffer);
+ defer std.debug.unlockStderr();
const w = &stderr.file_writer.interface;
- air.write(w, pt, liveness);
+ air.write(w, pt, liveness) catch return;
}
pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
- const comp = pt.zcu.comp;
- const io = comp.io;
- var buffer: [512]u8 = undefined;
- const stderr = try io.lockStderr(&buffer, null);
- defer io.unlockStderr();
+ var buffer: [4096]u8 = undefined;
+ const stderr = std.debug.lockStderr(&buffer);
+ defer std.debug.unlockStderr();
const w = &stderr.file_writer.interface;
- air.writeInst(w, inst, pt, liveness);
+ air.writeInst(w, inst, pt, liveness) catch return;
}
const Writer = struct {
@@ -232,12 +228,19 @@ const Writer = struct {
.arg => try w.writeArg(s, inst),
.not,
- .bitcast,
+ .bit_cast,
+ .ptr_cast,
+ .ptr_from_int,
+ .int_from_ptr,
+ .error_cast,
+ .error_from_int,
+ .int_from_error,
+ .union_from_enum,
.load,
.fptrunc,
.fpext,
- .intcast,
- .intcast_safe,
+ .int_cast,
+ .int_cast_safe,
.trunc,
.optional_payload,
.optional_payload_ptr,
@@ -306,6 +309,7 @@ const Writer = struct {
.struct_field_ptr => try w.writeStructField(s, inst),
.struct_field_val => try w.writeStructField(s, inst),
+ .spirv_runtime_array_len => try w.writeStructField(s, inst),
.inferred_alloc => @panic("TODO"),
.inferred_alloc_comptime => @panic("TODO"),
.assembly => try w.writeAssembly(s, inst),
diff --git a/src/Compilation.zig b/src/Compilation.zig
index d50586581e3a530b39309573da3dffb933f988ec..2660f74e18f4a4a2efc962c0381141cd159e4a9c 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -87,7 +87,7 @@ link_inputs: []const link.Input,
framework_dirs: []const []const u8,
/// These are only for DLLs dependencies fulfilled by the `.def` files shipped
/// with Zig. Static libraries are provided as `link.Input` values.
-windows_libs: std.StringArrayHashMapUnmanaged(void),
+windows_libs: std.array_hash_map.String(void),
/// The number of items in `windows_libs` which we have already built. All items at or after this
/// index will be built in `performAllTheWork`.
windows_libs_num_done: u32,
@@ -101,18 +101,14 @@ native_system_include_paths: []const []const u8,
/// List of symbols forced as undefined in the symbol table
/// thus forcing their resolution by the linker.
/// Corresponds to `-u ` for ELF/MachO and `/include:` for COFF/PE.
-force_undefined_symbols: std.StringArrayHashMapUnmanaged(void),
+force_undefined_symbols: std.array_hash_map.String(void),
-c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .empty,
-win32_resource_table: if (dev.env.supports(.win32_resource)) std.AutoArrayHashMapUnmanaged(*Win32Resource, void) else struct {
- pub fn keys(_: @This()) [0]void {
- return .{};
- }
- pub fn count(_: @This()) u0 {
- return 0;
- }
+c_objects: std.ArrayList(*CObject) = .empty,
+win32_resources: if (dev.env.supports(.win32_resource)) std.ArrayList(*Win32Resource) else struct {
+ items: [0]*struct {},
+ pub const empty: @This() = .{ .items = .{} };
pub fn deinit(_: @This(), _: Allocator) void {}
-} = .{},
+} = .empty,
link_diags: link.Diags,
link_queue: link.Queue = .empty,
@@ -145,11 +141,11 @@ win32_resource_work_queue: if (dev.env.supports(.win32_resource)) std.Deque(*Win
/// The ErrorMsg memory is owned by the `CObject`, using Compilation's general purpose allocator.
/// This data is accessed by multiple threads and is protected by `mutex`.
-failed_c_objects: std.AutoArrayHashMapUnmanaged(*CObject, *CObject.Diag.Bundle) = .empty,
+failed_c_objects: std.array_hash_map.Auto(*CObject, *CObject.Diag.Bundle) = .empty,
/// The ErrorBundle memory is owned by the `Win32Resource`, using Compilation's general purpose allocator.
/// This data is accessed by multiple threads and is protected by `mutex`.
-failed_win32_resources: if (dev.env.supports(.win32_resource)) std.AutoArrayHashMapUnmanaged(*Win32Resource, ErrorBundle) else struct {
+failed_win32_resources: if (dev.env.supports(.win32_resource)) std.array_hash_map.Auto(*Win32Resource, ErrorBundle) else struct {
pub fn values(_: @This()) [0]void {
return .{};
}
@@ -157,7 +153,7 @@ failed_win32_resources: if (dev.env.supports(.win32_resource)) std.AutoArrayHash
} = .{},
/// Miscellaneous things that can fail.
-misc_failures: std.AutoArrayHashMapUnmanaged(MiscTask, MiscError) = .empty,
+misc_failures: std.array_hash_map.Auto(MiscTask, MiscError) = .empty,
/// When this is `true` it means invoking clang as a sub-process is expected to inherit
/// stdin, stdout, stderr, and if it returns non success, to forward the exit code.
@@ -227,8 +223,6 @@ compiler_rt_lib: ?CrtFile = null,
/// Populated when we build the compiler_rt_obj object. A Job to build this is indicated
/// by setting `queued_jobs.compiler_rt_obj` and resolved before calling linker.flush().
compiler_rt_obj: ?CrtFile = null,
-/// hack for stage2_x86_64 + coff
-compiler_rt_dyn_lib: ?CrtFile = null,
/// Populated when we build the libfuzzer static library. A Job to build this
/// is indicated by setting `queued_jobs.fuzzer_lib` and resolved before
/// calling linker.flush().
@@ -291,8 +285,6 @@ emit_llvm_bc: ?[]const u8,
emit_docs: ?[]const u8,
const QueuedJobs = struct {
- /// hack for stage2_x86_64 + coff
- compiler_rt_dyn_lib: bool = false,
compiler_rt_lib: bool = false,
compiler_rt_obj: bool = false,
ubsan_rt_lib: bool = false,
@@ -865,7 +857,7 @@ pub const TimeReport = struct {
/// a function) all generic instances of this function. It also includes time spent analyzing
/// function bodies if this is a function (generic or otherwise).
/// An entry not existing means the declaration has not been analyzed (so far).
- decl_sema_info: std.AutoArrayHashMapUnmanaged(InternPool.TrackedInst.Index, struct {
+ decl_sema_info: std.array_hash_map.Auto(InternPool.TrackedInst.Index, struct {
ns: u64,
count: u32,
}),
@@ -875,14 +867,14 @@ pub const TimeReport = struct {
/// instances, both of this function itself and of its parent namespace.
/// An entry not existing means the declaration has not been codegenned (so far).
/// Every key in `decl_codegen_ns` is also in `decl_sema_ns`.
- decl_codegen_ns: std.AutoArrayHashMapUnmanaged(InternPool.TrackedInst.Index, u64),
+ decl_codegen_ns: std.array_hash_map.Auto(InternPool.TrackedInst.Index, u64),
/// Key is a ZIR `declaration` instruction which is anything other than a `comptime` decl; value
/// is the number of nanoseconds spent linking it into the binary. As above, this is the total
/// across all generic instances.
/// An entry not existing means the declaration has not been linked (so far).
/// Every key in `decl_link_ns` is also in `decl_sema_ns`.
- decl_link_ns: std.AutoArrayHashMapUnmanaged(InternPool.TrackedInst.Index, u64),
+ decl_link_ns: std.array_hash_map.Auto(InternPool.TrackedInst.Index, u64),
pub fn deinit(tr: *TimeReport, gpa: Allocator) void {
tr.stats = undefined;
@@ -915,21 +907,6 @@ pub const CrtFile = struct {
}
};
-/// Supported languages for "zig clang -x ".
-/// Loosely based on llvm-project/clang/include/clang/Driver/Types.def
-pub const LangToExt = std.StaticStringMap(FileExt).initComptime(.{
- .{ "c", .c },
- .{ "c-header", .h },
- .{ "c++", .cpp },
- .{ "c++-header", .hpp },
- .{ "objective-c", .m },
- .{ "objective-c-header", .hm },
- .{ "objective-c++", .mm },
- .{ "objective-c++-header", .hmm },
- .{ "assembler", .assembly },
- .{ "assembler-with-cpp", .assembly_with_cpp },
-});
-
/// For passing to a C compiler.
pub const CSourceFile = struct {
/// Many C compiler flags are determined by settings contained in the owning Module.
@@ -1068,8 +1045,8 @@ pub const CObject = struct {
}
pub const Bundle = struct {
- file_names: std.AutoArrayHashMapUnmanaged(u32, []const u8) = .empty,
- category_names: std.AutoArrayHashMapUnmanaged(u32, []const u8) = .empty,
+ file_names: std.array_hash_map.Auto(u32, []const u8) = .empty,
+ category_names: std.array_hash_map.Auto(u32, []const u8) = .empty,
diags: []Diag = &.{},
pub fn destroy(bundle: *Bundle, gpa: Allocator) void {
@@ -1122,13 +1099,13 @@ pub const CObject = struct {
var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = &file_reader.interface });
defer bc.deinit();
- var file_names: std.AutoArrayHashMapUnmanaged(u32, []const u8) = .empty;
+ var file_names: std.array_hash_map.Auto(u32, []const u8) = .empty;
errdefer {
for (file_names.values()) |file_name| gpa.free(file_name);
file_names.deinit(gpa);
}
- var category_names: std.AutoArrayHashMapUnmanaged(u32, []const u8) = .empty;
+ var category_names: std.array_hash_map.Auto(u32, []const u8) = .empty;
errdefer {
for (category_names.values()) |category_name| gpa.free(category_name);
category_names.deinit(gpa);
@@ -1604,7 +1581,7 @@ pub const CreateOptions = struct {
/// implementations still do.
lib_directories: []const Cache.Directory = &.{},
rpath_list: []const []const u8 = &[0][]const u8{},
- symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .empty,
+ symbol_wrap_set: std.array_hash_map.String(void) = .empty,
c_source_files: []const CSourceFile = &.{},
rc_source_files: []const RcSourceFile = &.{},
manifest_file: ?[]const u8 = null,
@@ -1683,7 +1660,7 @@ pub const CreateOptions = struct {
skip_linker_dependencies: bool = false,
hash_style: link.File.Lld.Elf.HashStyle = .both,
entry: Entry = .default,
- force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .empty,
+ force_undefined_symbols: std.array_hash_map.String(void) = .empty,
stack_size: ?u64 = null,
image_base: ?u64 = null,
version: ?std.SemanticVersion = null,
@@ -1800,7 +1777,7 @@ fn addModuleTableToCacheHash(
}
}
-const RtStrat = enum { none, lib, obj, zcu, dyn_lib };
+const RtStrat = enum { none, lib, obj, zcu };
pub const CreateDiagnostic = union(enum) {
export_table_import_table_conflict,
@@ -1921,12 +1898,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
};
if (have_zcu and (!need_llvm or use_llvm)) {
if (output_mode == .Obj) break :s .zcu;
- switch (target_util.zigBackend(target, use_llvm)) {
- else => {},
- .stage2_aarch64, .stage2_x86_64 => if (target.ofmt == .coff) {
- break :s if (is_exe_or_dyn_lib and build_options.have_llvm) .dyn_lib else .zcu;
- },
- }
}
if (need_llvm and !build_options.have_llvm) break :s .none; // impossible to build without llvm
if (is_exe_or_dyn_lib) break :s .lib;
@@ -2308,9 +2279,9 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
if (opt_zcu) |zcu| {
// Populate `zcu.module_roots`.
- const pt: Zcu.PerThread = .activate(zcu, .main);
- defer pt.deactivate();
- pt.populateModuleRootTable() catch |err| switch (err) {
+ const active = zcu.acquire();
+ defer active.release();
+ active.pt.populateModuleRootTable() catch |err| switch (err) {
error.OutOfMemory => |e| return e,
error.IllegalZigImport => return diag.fail(.illegal_zig_import),
};
@@ -2476,7 +2447,14 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
},
}
- if (use_llvm) {
+ if (use_llvm and
+ (comp.emit_bin != null or
+ comp.emit_asm != null or
+ comp.emit_llvm_ir != null or
+ comp.emit_llvm_bc != null or
+ comp.verbose_llvm_ir != null or
+ comp.verbose_llvm_bc != null))
+ {
if (opt_zcu) |zcu| {
zcu.llvm_object = try LlvmObject.create(arena, zcu);
}
@@ -2486,8 +2464,10 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
};
errdefer comp.destroy();
+ if (target.ofmt == .c) return comp;
+
// Add a `CObject` for each `c_source_files`.
- try comp.c_object_table.ensureTotalCapacity(gpa, options.c_source_files.len);
+ try comp.c_objects.ensureTotalCapacity(gpa, options.c_source_files.len);
for (options.c_source_files) |c_source_file| {
const c_object = try gpa.create(CObject);
errdefer gpa.destroy(c_object);
@@ -2496,7 +2476,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
.status = .{ .new = {} },
.src = c_source_file,
};
- comp.c_object_table.putAssumeCapacityNoClobber(c_object, {});
+ comp.c_objects.appendAssumeCapacity(c_object);
}
// Add a `Win32Resource` for each `rc_source_files` and one for `manifest_file`.
@@ -2504,7 +2484,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
options.rc_source_files.len + @intFromBool(options.manifest_file != null);
if (win32_resource_count > 0) {
dev.check(.win32_resource);
- try comp.win32_resource_table.ensureTotalCapacity(gpa, win32_resource_count);
+ try comp.win32_resources.ensureTotalCapacity(gpa, win32_resource_count);
for (options.rc_source_files) |rc_source_file| {
const win32_resource = try gpa.create(Win32Resource);
errdefer gpa.destroy(win32_resource);
@@ -2513,7 +2493,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
.status = .{ .new = {} },
.src = .{ .rc = rc_source_file },
};
- comp.win32_resource_table.putAssumeCapacityNoClobber(win32_resource, {});
+ comp.win32_resources.appendAssumeCapacity(win32_resource);
}
if (options.manifest_file) |manifest_path| {
@@ -2524,11 +2504,11 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
.status = .{ .new = {} },
.src = .{ .manifest = manifest_path },
};
- comp.win32_resource_table.putAssumeCapacityNoClobber(win32_resource, {});
+ comp.win32_resources.appendAssumeCapacity(win32_resource);
}
}
- if (comp.emit_bin != null and target.ofmt != .c) {
+ if (comp.emit_bin != null) {
if (!comp.skip_linker_dependencies) {
// If we need to build libc for the target, add work items for it.
// We go through the work queue so that building can be done in parallel.
@@ -2645,11 +2625,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
log.debug("queuing a job to build compiler_rt_obj", .{});
comp.queued_jobs.compiler_rt_obj = true;
},
- .dyn_lib => {
- // hack for stage2_x86_64 + coff
- log.debug("queuing a job to build compiler_rt_dyn_lib", .{});
- comp.queued_jobs.compiler_rt_dyn_lib = true;
- },
}
switch (comp.ubsan_rt_strat) {
@@ -2662,7 +2637,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
log.debug("queuing a job to build ubsan_rt_obj", .{});
comp.queued_jobs.ubsan_rt_obj = true;
},
- .dyn_lib => unreachable, // hack for compiler_rt only
}
switch (comp.zigc_strat) {
@@ -2671,7 +2645,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
log.debug("queuing a job to build libzigc", .{});
comp.queued_jobs.zigc_lib = true;
},
- .obj, .dyn_lib => unreachable, // only available as a static library or inside an existing ZCU
+ .obj => unreachable, // only available as a static library or inside an existing ZCU
}
if (is_exe_or_dyn_lib and comp.config.any_fuzz) {
@@ -2730,7 +2704,6 @@ pub fn destroy(comp: *Compilation) void {
if (comp.zigc_static_lib) |*crt_file| crt_file.deinit(gpa, io);
if (comp.compiler_rt_lib) |*crt_file| crt_file.deinit(gpa, io);
if (comp.compiler_rt_obj) |*crt_file| crt_file.deinit(gpa, io);
- if (comp.compiler_rt_dyn_lib) |*crt_file| crt_file.deinit(gpa, io);
if (comp.fuzzer_lib) |*crt_file| crt_file.deinit(gpa, io);
if (comp.glibc_so_files) |*glibc_file| {
@@ -2749,20 +2722,20 @@ pub fn destroy(comp: *Compilation) void {
openbsd_file.deinit(gpa, io);
}
- for (comp.c_object_table.keys()) |key| {
- key.destroy(gpa, io);
+ for (comp.c_objects.items) |c_object| {
+ c_object.destroy(gpa, io);
}
- comp.c_object_table.deinit(gpa);
+ comp.c_objects.deinit(gpa);
for (comp.failed_c_objects.values()) |bundle| {
bundle.destroy(gpa);
}
comp.failed_c_objects.deinit(gpa);
- for (comp.win32_resource_table.keys()) |key| {
- key.destroy(gpa, io);
+ for (comp.win32_resources.items) |win32_resource| {
+ win32_resource.destroy(gpa, io);
}
- comp.win32_resource_table.deinit(gpa);
+ comp.win32_resources.deinit(gpa);
for (comp.failed_win32_resources.values()) |*value| {
value.deinit(gpa);
@@ -3016,8 +2989,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
// changes. For now, to avoid crashing the linker in this case, don't kick off C object
// updates if we've done prelink already. https://codeberg.org/ziglang/zig/issues/32081
} else {
- try comp.c_object_work_queue.ensureUnusedCapacity(gpa, comp.c_object_table.count());
- for (comp.c_object_table.keys()) |c_object| {
+ try comp.c_object_work_queue.ensureUnusedCapacity(gpa, comp.c_objects.items.len);
+ for (comp.c_objects.items) |c_object| {
comp.c_object_work_queue.pushBackAssumeCapacity(c_object);
try comp.appendFileSystemInput(try .fromUnresolved(arena, comp.dirs, &.{c_object.src.src_path}));
}
@@ -3032,8 +3005,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
// For compiling Win32 resources, we rely on the cache hash system to avoid duplicating work.
// Add a Job for each Win32 resource file.
- try comp.win32_resource_work_queue.ensureUnusedCapacity(gpa, comp.win32_resource_table.count());
- for (comp.win32_resource_table.keys()) |win32_resource| {
+ try comp.win32_resource_work_queue.ensureUnusedCapacity(gpa, comp.win32_resources.items.len);
+ for (comp.win32_resources.items) |win32_resource| {
comp.win32_resource_work_queue.pushBackAssumeCapacity(win32_resource);
switch (win32_resource.src) {
.rc => |f| {
@@ -3044,9 +3017,6 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
}
if (comp.zcu) |zcu| {
- const pt: Zcu.PerThread = .activate(zcu, .main);
- defer pt.deactivate();
-
assert(zcu.cur_analysis_timer == null);
zcu.skip_analysis_this_update = false;
@@ -3099,8 +3069,9 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
try comp.performAllTheWork(main_progress_node, arena);
if (comp.zcu) |zcu| {
- const pt: Zcu.PerThread = .activate(zcu, .main);
- defer pt.deactivate();
+ const active = zcu.acquire();
+ defer active.release();
+ const pt = active.pt;
assert(zcu.cur_analysis_timer == null);
@@ -3142,18 +3113,16 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
return;
}
- if (comp.zcu == null and comp.config.output_mode == .Obj and comp.c_object_table.count() == 1) {
+ if (comp.zcu == null and comp.config.output_mode == .Obj and comp.c_objects.items.len == 1) {
// This is `zig build-obj foo.c`. We can emit asm and LLVM IR/bitcode.
- const c_obj_path = comp.c_object_table.keys()[0].status.success.object_path;
+ const c_obj_path = comp.c_objects.items[0].status.success.object_path;
if (comp.emit_asm) |path| try comp.emitFromCObject(arena, c_obj_path, ".s", path);
if (comp.emit_llvm_ir) |path| try comp.emitFromCObject(arena, c_obj_path, ".ll", path);
if (comp.emit_llvm_bc) |path| try comp.emitFromCObject(arena, c_obj_path, ".bc", path);
}
switch (comp.cache_use) {
- .none, .incremental => {
- try flush(comp, arena, .main);
- },
+ .none, .incremental => try flush(comp, arena),
.whole => |whole| {
if (comp.file_system_inputs) |buf| try man.populateFileSystemInputs(buf);
if (comp.parent_whole_cache) |pwc| {
@@ -3234,7 +3203,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
};
}
- try flush(comp, arena, .main);
+ try flush(comp, arena);
// Calling `flush` may have produced errors, in which case the
// cache manifest must not be written.
@@ -3325,12 +3294,12 @@ pub fn resolveEmitPathFlush(
}
}
-fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id) (Io.Cancelable || Allocator.Error)!void {
+fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error)!void {
const io = comp.io;
+ const tid: Zcu.PerThread.Id = .acquire(io);
+ defer tid.release(io);
if (comp.zcu) |zcu| {
if (zcu.llvm_object) |llvm_object| {
- const pt: Zcu.PerThread = .activate(zcu, tid);
- defer pt.deactivate();
// Emit the ZCU object from LLVM now; it's required to flush the output file.
// If there's an output file, it wants to decide where the LLVM object goes!
@@ -3348,7 +3317,9 @@ fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id) (Io.Cancel
break :p try comp.resolveEmitPathFlush(arena, .temp, llvm_object.out_bin_basename);
} else null;
- llvm_object.emit(pt, .{
+ const active = zcu.activate(tid);
+ defer active.deactivate();
+ llvm_object.emit(active.pt, .{
.pre_ir_path = comp.verbose_llvm_ir,
.pre_bc_path = comp.verbose_llvm_bc,
@@ -3484,14 +3455,14 @@ fn addNonIncrementalStuffToCacheManifest(
try link.hashInputs(man, comp.link_inputs);
- for (comp.c_object_table.keys()) |key| {
- _ = try man.addFile(key.src.src_path, null);
- man.hash.addOptional(key.src.ext);
- man.hash.addListOfBytes(key.src.extra_flags);
+ for (comp.c_objects.items) |c_object| {
+ _ = try man.addFile(c_object.src.src_path, null);
+ man.hash.addOptional(c_object.src.ext);
+ man.hash.addListOfBytes(c_object.src.extra_flags);
}
- for (comp.win32_resource_table.keys()) |key| {
- switch (key.src) {
+ for (comp.win32_resources.items) |win32_resource| {
+ switch (win32_resource.src) {
.rc => |rc_src| {
_ = try man.addFile(rc_src.src_path, null);
man.hash.addListOfBytes(rc_src.extra_flags);
@@ -4066,7 +4037,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {
}
}
if (zcu.skip_analysis_this_update) break :zcu_errors;
- var sorted_failed_analysis: std.AutoArrayHashMapUnmanaged(InternPool.AnalUnit, *Zcu.ErrorMsg).DataList.Slice = s: {
+ var sorted_failed_analysis: std.array_hash_map.Auto(InternPool.AnalUnit, *Zcu.ErrorMsg).DataList.Slice = s: {
const SortOrder = struct {
zcu: *Zcu,
errors: []const *Zcu.ErrorMsg,
@@ -4362,7 +4333,7 @@ pub fn addModuleErrorMsg(
// De-duplicate error notes. The main use case in mind for this is
// too many "note: called from here" notes when eval branch quota is reached.
- var notes: std.ArrayHashMapUnmanaged(ErrorBundle.ErrorMessage, void, ErrorNoteHashContext, true) = .empty;
+ var notes: std.array_hash_map.Custom(ErrorBundle.ErrorMessage, void, ErrorNoteHashContext, true) = .empty;
defer notes.deinit(gpa);
var last_note_loc: ?std.zig.Loc = null;
@@ -4502,33 +4473,25 @@ fn performAllTheWork(
defer if (comp.zcu) |zcu| zcu.codegen_task_pool.cancel(zcu);
if (comp.zcu) |zcu| {
- const pt: Zcu.PerThread = .activate(zcu, .main);
- defer {
- pt.deactivate();
- // Regardless of errors, `comp.zcu` needs to update its generation number.
- zcu.generation += 1;
- }
- try pt.update(main_progress_node, &decl_work_timer);
+ // Regardless of errors, `comp.zcu` needs to update its generation number.
+ defer zcu.generation += 1;
+ const active = zcu.acquire();
+ defer active.release();
+ try active.pt.update(main_progress_node, &decl_work_timer);
}
comp.link_queue.finishZcuQueue(comp);
- // This has to happen after the main semantic analysis loop because it is possible for Sema to
+ // Main thread work is all done, now just wait for all async work.
+ try misc_group.await(io);
+
+ // This has to happen again after the main semantic analysis loop because it is possible for Sema to
// call `addLinkLib` and hence add more items to `comp.windows_libs`.
- for (comp.windows_libs.keys()[comp.windows_libs_num_done..]) |link_lib| {
- mingw.buildImportLib(comp, link_lib) catch |err| {
- // TODO Surface more error details.
- comp.lockAndSetMiscFailure(
- .windows_import_lib,
- "unable to generate DLL import .lib file for {s}: {t}",
- .{ link_lib, err },
- );
- };
- }
+ for (comp.windows_libs.keys()[comp.windows_libs_num_done..]) |lib_name|
+ misc_group.async(io, buildMingwImportLib, .{ comp, lib_name, false, main_progress_node });
comp.windows_libs_num_done = @intCast(comp.windows_libs.count());
-
- // Main thread work is all done, now just wait for all async work.
try misc_group.await(io);
+
comp.link_queue.wait(io);
}
@@ -4587,24 +4550,6 @@ fn dispatchPrelinkWork(comp: *Compilation, main_progress_node: std.Progress.Node
});
}
- // hack for stage2_x86_64 + coff
- if (comp.queued_jobs.compiler_rt_dyn_lib and comp.compiler_rt_dyn_lib == null) {
- prelink_group.async(io, buildRt, .{
- comp,
- "compiler_rt.zig",
- "compiler_rt",
- .Lib,
- .dynamic,
- .compiler_rt,
- main_progress_node,
- RtOptions{
- .checks_valgrind = true,
- .allow_lto = false,
- },
- &comp.compiler_rt_dyn_lib,
- });
- }
-
if (comp.queued_jobs.fuzzer_lib and comp.fuzzer_lib == null) {
prelink_group.async(io, buildRt, .{
comp,
@@ -4748,6 +4693,16 @@ fn dispatchPrelinkWork(comp: *Compilation, main_progress_node: std.Progress.Node
});
}
+ while (comp.windows_libs_num_done < comp.windows_libs.count()) {
+ prelink_group.async(io, buildMingwImportLib, .{
+ comp,
+ comp.windows_libs.keys()[comp.windows_libs_num_done],
+ true,
+ main_progress_node,
+ });
+ comp.windows_libs_num_done += 1;
+ }
+
prelink_group.await(io) catch |err| switch (err) {
error.Canceled => unreachable, // see swapCancelProtection above
};
@@ -4835,7 +4790,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
var buffer: [1024]u8 = undefined;
var tar_file_writer = tar_file.writer(io, &buffer);
- var seen_table: std.AutoArrayHashMapUnmanaged(*Package.Module, []const u8) = .empty;
+ var seen_table: std.array_hash_map.Auto(*Package.Module, []const u8) = .empty;
defer seen_table.deinit(comp.gpa);
try seen_table.put(comp.gpa, zcu.main_mod, comp.root_name);
@@ -5433,6 +5388,39 @@ fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std
}
}
+fn buildMingwImportLib(comp: *Compilation, lib_name: []const u8, is_prelink: bool, prog_node: std.Progress.Node) void {
+ const crt_file_path = mingw.buildImportLib(comp, lib_name, prog_node) catch |err| switch (err) {
+ // TODO: This isn't actually true for self-hosted
+ // In the non-prelink case we will end up putting foo.lib onto the linker line and letting the linker
+ // use its library paths to look for libraries and report any problems.
+ error.DefNotFound => return if (is_prelink) {
+ comp.lockAndSetMiscFailure(
+ .windows_import_lib,
+ "definition not found for required mingw DLL import .lib {s}",
+ .{lib_name},
+ );
+ },
+ // TODO Surface more error details.
+ else => |e| return comp.lockAndSetMiscFailure(
+ .windows_import_lib,
+ "unable to generate mingw DLL import .lib file for {s}: {t}",
+ .{ lib_name, e },
+ ),
+ };
+
+ if (is_prelink)
+ comp.queuePrelinkTasks(&.{.{
+ .load_archive = .{
+ .path = crt_file_path,
+ .must_link = false,
+ },
+ }}) catch |err| comp.lockAndSetMiscFailure(
+ .windows_import_lib,
+ "unable to queue prelink task for mingw import lib {f}: {t}",
+ .{ crt_file_path, err },
+ );
+}
+
fn buildWasiLibcCrtFile(comp: *Compilation, crt_file: wasi_libc.CrtFile, prog_node: std.Progress.Node) void {
if (wasi_libc.buildCrtFile(comp, crt_file, prog_node)) |_| {
comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(crt_file)] = false;
@@ -5596,9 +5584,10 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
c_source_basename[0 .. c_source_basename.len - fs.path.extension(c_source_basename).len];
const target = comp.getTarget();
+ assert(target.ofmt != .c);
const o_ext = target.ofmt.fileExt(target.cpu.arch);
const digest = if (!comp.disable_c_depfile and try man.hit()) man.final() else blk: {
- var argv = std.array_list.Managed([]const u8).init(gpa);
+ var argv: std.array_list.Managed([]const u8) = .init(gpa);
defer argv.deinit();
// In case we are doing passthrough mode, we need to detect -S and -emit-llvm.
@@ -6357,6 +6346,8 @@ fn addCommonCCArgs(
.serenity => try argv.append("__serenity__"),
// Homebrew targets without LLVM support; use communities's preferred macros.
.@"3ds" => try argv.append("-D__3DS__"),
+ .wiiu => try argv.append("-D__WIIU__"),
+ .psx => try argv.append("-D__psx__"),
.psp => try argv.append("-D__PSP__"),
.vita => try argv.append("-D__vita__"),
else => {},
@@ -7059,13 +7050,41 @@ pub const FileExt = enum {
.unknown => "",
};
}
+
+ /// The value accepted by "zig clang -x " and passed to "clang -x ".
+ pub fn toLang(ext: FileExt) ?[]const u8 {
+ return switch (ext) {
+ else => null,
+ .c => "c",
+ .h => "c-header",
+ .cpp => "c++",
+ .hpp => "c++-header",
+ .m => "objective-c",
+ .hm => "objective-c-header",
+ .mm => "objective-c++",
+ .hmm => "objective-c++-header",
+ .assembly => "assembler",
+ .assembly_with_cpp => "assembler-with-cpp",
+ };
+ }
+
+ /// Supported languages for "zig clang -x ".
+ /// Loosely based on llvm-project/clang/include/clang/Driver/Types.def
+ pub const from_lang = std.StaticStringMap(FileExt).initComptime(init: {
+ var init: []const struct { []const u8, FileExt } = &.{};
+ for (std.enums.values(FileExt)) |file_ext| if (file_ext.toLang()) |lang| {
+ init = init ++ .{.{ lang, file_ext }};
+ };
+ break :init init;
+ });
};
pub fn hasObjectExt(filename: []const u8) bool {
return mem.endsWith(u8, filename, ".o") or
mem.endsWith(u8, filename, ".lo") or
mem.endsWith(u8, filename, ".obj") or
- mem.endsWith(u8, filename, ".rmeta");
+ mem.endsWith(u8, filename, ".rmeta") or
+ mem.endsWith(u8, filename, ".spv");
}
pub fn hasStaticLibraryExt(filename: []const u8) bool {
diff --git a/src/InternPool.zig b/src/InternPool.zig
index b32dee237ddd36f81abc2277fe23992cc1380c09..be6e45441e55ec373e533643786528d0abeb310c 100644
--- a/src/InternPool.zig
+++ b/src/InternPool.zig
@@ -41,22 +41,22 @@ tid_shift_32: if (single_threaded) u0 else std.math.Log2Int(u32),
/// * For a `func`, this is the source of the full function signature.
/// These are also invalidated if tracking fails for this instruction.
/// Value is index into `dep_entries` of the first dependency on this hash.
-src_hash_deps: std.AutoArrayHashMapUnmanaged(TrackedInst.Index, DepEntry.Index),
+src_hash_deps: std.array_hash_map.Auto(TrackedInst.Index, DepEntry.Index),
/// Dependencies on the value of a Nav.
/// Value is index into `dep_entries` of the first dependency on this Nav value.
-nav_val_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index),
+nav_val_deps: std.array_hash_map.Auto(Nav.Index, DepEntry.Index),
/// Dependencies on the type of a Nav.
/// Value is index into `dep_entries` of the first dependency on this Nav value.
-nav_ty_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index),
+nav_ty_deps: std.array_hash_map.Auto(Nav.Index, DepEntry.Index),
/// Dependencies on a function's inferred error set. Key is the function body, not the IES.
/// Value is index into `dep_entries` of the first dependency on this function's IES.
-func_ies_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index),
+func_ies_deps: std.array_hash_map.Auto(Index, DepEntry.Index),
/// Dependencies on the resolved layout of a `struct`, `union`, or `enum` type.
/// Value is index into `dep_entries` of the first dependency on this type's layout.
-type_layout_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index),
+type_layout_deps: std.array_hash_map.Auto(Index, DepEntry.Index),
/// Dependencies on the resolved default field values of a `struct` type.
/// Value is index into `dep_entries` of the first dependency on this type's inits.
-struct_defaults_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index),
+struct_defaults_deps: std.array_hash_map.Auto(Index, DepEntry.Index),
/// Dependencies on a Zig or ZON source file. Triggered by `@import`.
/// * For ZON source files, the dependency is invalidated if the file changes at all. The `@import`
/// must be re-analyzed to return the new data structure.
@@ -64,18 +64,18 @@ struct_defaults_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index),
/// (which can only happen because the `.main_struct_inst` got lost). The `@import` must be
/// re-analyzed to return the new type.
/// Value is index into `dep_entries` of the first dependency on this Zig/ZON file.
-source_file_deps: std.AutoArrayHashMapUnmanaged(FileIndex, DepEntry.Index),
+source_file_deps: std.array_hash_map.Auto(FileIndex, DepEntry.Index),
/// Dependencies on an embedded file.
/// Introduced by `@embedFile`; invalidated when the file changes.
/// Value is index into `dep_entries` of the first dependency on this `Zcu.EmbedFile`.
-embed_file_deps: std.AutoArrayHashMapUnmanaged(Zcu.EmbedFile.Index, DepEntry.Index),
+embed_file_deps: std.array_hash_map.Auto(Zcu.EmbedFile.Index, DepEntry.Index),
/// Dependencies on the full set of names in a ZIR namespace.
/// Key refers to a `struct_decl`, `union_decl`, etc.
/// Value is index into `dep_entries` of the first dependency on this namespace.
-namespace_deps: std.AutoArrayHashMapUnmanaged(TrackedInst.Index, DepEntry.Index),
+namespace_deps: std.array_hash_map.Auto(TrackedInst.Index, DepEntry.Index),
/// Dependencies on the (non-)existence of some name in a namespace.
/// Value is index into `dep_entries` of the first dependency on this name.
-namespace_name_deps: std.AutoArrayHashMapUnmanaged(NamespaceNameKey, DepEntry.Index),
+namespace_name_deps: std.array_hash_map.Auto(NamespaceNameKey, DepEntry.Index),
// Dependencies on the value of fields memoized on `Zcu` (`panic_messages` etc).
// If set, these are indices into `dep_entries` of the first dependency on this state.
memoized_state_main_deps: DepEntry.Index.Optional,
@@ -86,7 +86,7 @@ memoized_state_assembly_deps: DepEntry.Index.Optional,
/// Given a `Depender`, points to an entry in `dep_entries` whose `depender`
/// matches. The `next_dependee` field can be used to iterate all such entries
/// and remove them from the corresponding lists.
-first_dependency: std.AutoArrayHashMapUnmanaged(AnalUnit, DepEntry.Index),
+first_dependency: std.array_hash_map.Auto(AnalUnit, DepEntry.Index),
/// Stores dependency information. The hashmaps declared above are used to look
/// up entries in this list as required. This is not stored in `extra` so that
@@ -108,9 +108,9 @@ pub const empty: InternPool = .{
.shards = &.{},
.global_error_set = .empty,
.tid_width = 0,
- .tid_shift_30 = if (single_threaded) 0 else 31,
- .tid_shift_31 = if (single_threaded) 0 else 31,
- .tid_shift_32 = if (single_threaded) 0 else 31,
+ .tid_shift_30 = 0,
+ .tid_shift_31 = 0,
+ .tid_shift_32 = 0,
.src_hash_deps = .empty,
.nav_val_deps = .empty,
.nav_ty_deps = .empty,
@@ -648,15 +648,15 @@ pub const Nav = struct {
fn wrap(unwrapped: Unwrapped, ip: *const InternPool) Nav.Index {
assert(@intFromEnum(unwrapped.tid) <= ip.getTidMask());
- assert(unwrapped.index <= ip.getIndexMask(u32));
- return @enumFromInt(@shlExact(@as(u32, @intFromEnum(unwrapped.tid)), ip.tid_shift_32) |
+ assert(unwrapped.index <= ip.getIndexMask(u30));
+ return @enumFromInt(@shlExact(@as(u32, @intFromEnum(unwrapped.tid)), ip.tid_shift_30) |
unwrapped.index);
}
};
fn unwrap(nav_index: Nav.Index, ip: *const InternPool) Unwrapped {
return .{
- .tid = @enumFromInt(@intFromEnum(nav_index) >> ip.tid_shift_32 & ip.getTidMask()),
- .index = @intFromEnum(nav_index) & ip.getIndexMask(u32),
+ .tid = @enumFromInt(@intFromEnum(nav_index) >> ip.tid_shift_30 & ip.getTidMask()),
+ .index = @intFromEnum(nav_index) & ip.getIndexMask(u30),
};
}
@@ -1587,7 +1587,7 @@ fn getIndexMask(ip: *const InternPool, comptime BackingInt: type) u32 {
return @as(u32, std.math.maxInt(BackingInt)) >> ip.tid_width;
}
-const FieldMap = std.ArrayHashMapUnmanaged(void, void, std.array_hash_map.AutoContext(void), false);
+const FieldMap = std.array_hash_map.Custom(void, void, std.array_hash_map.AutoContext(void), false);
/// An index into `maps` which might be `none`.
pub const OptionalMapIndex = enum(u32) {
@@ -1983,6 +1983,7 @@ pub const Key = union(enum) {
union_type: ContainerType,
opaque_type: ContainerType,
enum_type: ContainerType,
+ spirv_type: SpirvType,
func_type: FuncType,
error_set_type: ErrorSetType,
/// The payload is the function body, either a `func_decl` or `func_instance`.
@@ -2146,6 +2147,15 @@ pub const Key = union(enum) {
};
};
+ pub const SpirvType = extern struct {
+ /// A `spirv_reify` instruction.
+ zir_index: TrackedInst.Index,
+ /// Always 0.
+ padding: u32 = 0,
+ /// A hash of this type's attributes generated by Sema.
+ type_hash: u64,
+ };
+
pub const FuncType = struct {
param_types: Index.Slice,
return_type: Index,
@@ -2583,13 +2593,13 @@ pub const Key = union(enum) {
const KeyTag = @typeInfo(Key).@"union".tag_type.?;
const seed = @intFromEnum(@as(KeyTag, key));
return switch (key) {
- // TODO: assert no padding in these types
inline .ptr_type,
.array_type,
.vector_type,
.opt_type,
.anyframe_type,
.error_union_type,
+ .spirv_type,
.simple_type,
.simple_value,
.opt,
@@ -2599,7 +2609,11 @@ pub const Key = union(enum) {
.enum_tag,
.inferred_error_set_type,
.un,
- => |x| Hash.hash(seed, asBytes(&x)),
+ => |x| {
+ _ = extern struct { is_extern: @TypeOf(x) };
+ comptime assert(std.meta.hasUniqueRepresentation(@TypeOf(x)));
+ return Hash.hash(seed, asBytes(&x));
+ },
.int_type => |x| Hash.hash(seed + @intFromEnum(x.signedness), asBytes(&x.bits)),
@@ -2841,6 +2855,10 @@ pub const Key = union(enum) {
const b_info = b.error_union_type;
return std.meta.eql(a_info, b_info);
},
+ .spirv_type => |a_info| {
+ const b_info = b.spirv_type;
+ return std.meta.eql(a_info, b_info);
+ },
.simple_type => |a_info| {
const b_info = b.simple_type;
return a_info == b_info;
@@ -3130,6 +3148,7 @@ pub const Key = union(enum) {
.simple_type,
.struct_type,
.union_type,
+ .spirv_type,
.opaque_type,
.enum_type,
.tuple_type,
@@ -3877,6 +3896,14 @@ pub fn loadOpaqueType(ip: *const InternPool, index: Index) LoadedOpaqueType {
};
}
+pub fn loadSpirvType(ip: *const InternPool, index: Index) Tag.TypeSpirv {
+ const unwrapped_index = index.unwrap(ip);
+ const item = unwrapped_index.getItem(ip);
+ assert(item.tag == .type_spirv);
+ const extra = extraData(unwrapped_index.getExtra(ip), Tag.TypeSpirv, item.data);
+ return extra;
+}
+
pub const Item = struct {
tag: Tag,
/// The doc comments on the respective Tag explain how to interpret this.
@@ -4146,10 +4173,7 @@ pub const Index = enum(u32) {
const debug_state = InternPool.debug_state;
};
pub fn unwrap(index: Index, ip: *const InternPool) Unwrapped {
- return if (single_threaded) .{
- .tid = .main,
- .index = @intFromEnum(index),
- } else .{
+ return .{
.tid = @enumFromInt(@intFromEnum(index) >> ip.tid_shift_30 & ip.getTidMask()),
.index = @intFromEnum(index) & ip.getIndexMask(u30),
};
@@ -4183,12 +4207,14 @@ pub const Index = enum(u32) {
type_function: struct {
const @"data.flags.has_comptime_bits" = opaque {};
const @"data.flags.has_noalias_bits" = opaque {};
+ const @"data.flags.cc.extraLen()" = opaque {};
const @"data.params_len" = opaque {};
data: *Tag.TypeFunction,
@"trailing.comptime_bits.len": *@"data.flags.has_comptime_bits",
@"trailing.noalias_bits.len": *@"data.flags.has_noalias_bits",
+ @"trailing.cc_bits.len": *@"data.flags.cc.extraLen()",
@"trailing.param_types.len": *@"data.params_len",
- trailing: struct { comptime_bits: []u32, noalias_bits: []u32, param_types: []Index },
+ trailing: struct { comptime_bits: []u32, noalias_bits: []u32, cc_bits: []u32, param_types: []Index },
},
type_tuple: struct {
const @"data.fields_len" = opaque {};
@@ -4214,6 +4240,8 @@ pub const Index = enum(u32) {
type_enum_nonexhaustive: struct { data: *Tag.TypeEnum },
type_opaque: struct { data: *Tag.TypeOpaque },
+ type_spirv: struct { data: *Tag.TypeSpirv },
+
undef: DataIsIndex,
simple_value: void,
ptr_nav: struct { data: *PtrNav },
@@ -4841,6 +4869,10 @@ pub const Tag = enum(u8) {
/// data is extra index of `TypeEnum`.
type_enum_nonexhaustive,
+ /// An spirv type.
+ /// data is index of `TypeSpirv` in extra.
+ type_spirv,
+
/// An opaque type.
/// data is extra index of `TypeOpaque`.
type_opaque,
@@ -5033,9 +5065,9 @@ pub const Tag = enum(u8) {
field_types: []Index,
},
.config = .{
- .@"trailing.type_hash.?" = .@"payload.captures_len == .reified",
- .@"trailing.captures.?" = .@"payload.captures_len != .reified",
- .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)",
+ .@"trailing.type_hash.?" = .@"payload.bits.captures_len == .reified",
+ .@"trailing.captures.?" = .@"payload.bits.captures_len != .reified",
+ .@"trailing.captures.?.len" = .@"@intFromEnum(payload.bits.captures_len)",
.@"trailing.field_names.len" = .@"payload.fields_len",
.@"trailing.field_types.len" = .@"payload.fields_len",
},
@@ -5051,9 +5083,9 @@ pub const Tag = enum(u8) {
field_defaults: []Index,
},
.config = .{
- .@"trailing.type_hash.?" = .@"payload.captures_len == .reified",
- .@"trailing.captures.?" = .@"payload.captures_len != .reified",
- .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)",
+ .@"trailing.type_hash.?" = .@"payload.bits.captures_len == .reified",
+ .@"trailing.captures.?" = .@"payload.bits.captures_len != .reified",
+ .@"trailing.captures.?.len" = .@"@intFromEnum(payload.bits.captures_len)",
.@"trailing.field_names.len" = .@"payload.fields_len",
.@"trailing.field_types.len" = .@"payload.fields_len",
.@"trailing.field_defaults.len" = .@"payload.fields_len",
@@ -5068,9 +5100,9 @@ pub const Tag = enum(u8) {
field_types: []Index,
},
.config = .{
- .@"trailing.type_hash.?" = .@"payload.captures_len == .reified",
- .@"trailing.captures.?" = .@"payload.captures_len != .reified",
- .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)",
+ .@"trailing.type_hash.?" = .@"payload.bits.captures_len == .reified",
+ .@"trailing.captures.?" = .@"payload.bits.captures_len != .reified",
+ .@"trailing.captures.?.len" = .@"@intFromEnum(payload.bits.captures_len)",
.@"trailing.field_types.len" = .@"payload.fields_len",
},
};
@@ -5087,11 +5119,11 @@ pub const Tag = enum(u8) {
field_values: []Index,
},
.config = .{
- .@"trailing.owner_union.?" = .@"payload.captures_len == .generated_union_tag",
- .@"trailing.zir_index.?" = .@"payload.captures_len != .generated_union_tag",
- .@"trailing.type_hash.?" = .@"payload.captures_len == .reified",
- .@"trailing.captures.?" = .@"payload.captures_len != .reified and payload.captures_len != .generated_enum_tag",
- .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)",
+ .@"trailing.owner_union.?" = .@"payload.bits.captures_len == .generated_union_tag",
+ .@"trailing.zir_index.?" = .@"payload.bits.captures_len != .generated_union_tag",
+ .@"trailing.type_hash.?" = .@"payload.bits.captures_len == .reified",
+ .@"trailing.captures.?" = .@"payload.bits.captures_len != .reified and payload.bits.captures_len != .generated_union_tag",
+ .@"trailing.captures.?.len" = .@"@intFromEnum(payload.bits.captures_len)",
.@"trailing.field_names.len" = .@"payload.fields_len",
.@"trailing.field_values.len" = .@"payload.fields_len",
},
@@ -5140,6 +5172,7 @@ pub const Tag = enum(u8) {
.trailing = struct {
param_comptime_bits: ?[]u32,
param_noalias_bits: ?[]u32,
+ param_cc_bits: ?[]u32,
param_type: []Index,
},
.config = .{
@@ -5147,6 +5180,8 @@ pub const Tag = enum(u8) {
.@"trailing.param_comptime_bits.?.len" = .@"(payload.params_len + 31) / 32",
.@"trailing.param_noalias_bits.?" = .@"payload.flags.has_noalias_bits",
.@"trailing.param_noalias_bits.?.len" = .@"(payload.params_len + 31) / 32",
+ .@"trailing.param_cc_bits.?" = .@"payload.flags.cc.extraLen() != 0",
+ .@"trailing.param_cc_bits.?.len" = .@"payload.flags.cc.extraLen()",
.@"trailing.param_type.len" = .@"payload.params_len",
},
},
@@ -5221,16 +5256,17 @@ pub const Tag = enum(u8) {
field_names: []NullTerminatedString,
},
.config = .{
- .@"trailing.owner_union.?" = .@"payload.captures_len == .generated_union_tag",
- .@"trailing.zir_index.?" = .@"payload.captures_len != .generated_union_tag",
- .@"trailing.type_hash.?" = .@"payload.captures_len == .reified",
- .@"trailing.captures.?" = .@"payload.captures_len != .reified and payload.captures_len != .generated_enum_tag",
- .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)",
+ .@"trailing.owner_union.?" = .@"payload.bits.captures_len == .generated_union_tag",
+ .@"trailing.zir_index.?" = .@"payload.bits.captures_len != .generated_union_tag",
+ .@"trailing.type_hash.?" = .@"payload.bits.captures_len == .reified",
+ .@"trailing.captures.?" = .@"payload.bits.captures_len != .reified and payload.bits.captures_len != .generated_union_tag",
+ .@"trailing.captures.?.len" = .@"@intFromEnum(payload.bits.captures_len)",
.@"trailing.field_names.len" = .@"payload.fields_len",
},
},
.type_enum_explicit = enum_explicit_encoding,
.type_enum_nonexhaustive = enum_explicit_encoding,
+ .type_spirv = .{ .summary = .@"{.payload.name%summary#\"}", .payload = Tag.TypeSpirv },
.type_opaque = .{
.summary = .@"{.payload.name%summary#\"}",
.payload = TypeOpaque,
@@ -5375,16 +5411,15 @@ pub const Tag = enum(u8) {
_: u23 = 0,
pub const Source = enum(u1) { builtin, syntax };
- pub const DecorationType = enum(u2) { none, location, descriptor };
+ pub const DecorationType = enum(u2) { none, location, descriptor, flat };
};
pub fn decoration(self: Extern) ?std.lang.ExternOptions.Decoration {
return switch (self.flags.decoration_type) {
.none => null,
- .location => std.lang.ExternOptions.Decoration{
- .location = self.location_or_descriptor_set,
- },
+ .location => std.lang.ExternOptions.Decoration{ .location = self.location_or_descriptor_set },
.descriptor => std.lang.ExternOptions.Decoration{ .descriptor = .{ .set = self.location_or_descriptor_set, .binding = self.descriptor_binding } },
+ .flat => std.lang.ExternOptions.Decoration{ .flat = self.location_or_descriptor_set },
};
}
};
@@ -5688,6 +5723,34 @@ pub const Tag = enum(u8) {
name_nav: Nav.Index.Optional,
namespace: NamespaceIndex,
};
+
+ /// Trailing:
+ /// 0. type_hash: PackedU64
+ pub const TypeSpirv = struct {
+ name: NullTerminatedString,
+ /// The index of the `reify_spirv_type` instruction.
+ zir_index: TrackedInst.Index,
+ /// If tag is `.image`, this is the sampled type or `.none` if `usage` is `.storage`.
+ /// If tag is `.sampled_image`, this is the image type.
+ /// If tag is `.runtime_array`, this is the element type.
+ /// Otherwise this is `.none`.
+ ty: Index,
+ flags: Flags,
+
+ pub const Flags = packed struct(u32) {
+ tag: @typeInfo(std.lang.Type.Spirv).@"union".tag_type.?,
+ // Image type flags
+ usage: @typeInfo(std.lang.Type.Spirv.Image.Usage).@"union".tag_type.?,
+ format: std.lang.Type.Spirv.Image.Format,
+ dim: std.lang.Type.Spirv.Image.Dimensionality,
+ depth: std.lang.Type.Spirv.Image.Depth,
+ access: std.lang.Type.Spirv.Image.Access,
+ is_arrayed: bool,
+ is_multisampled: bool,
+
+ _: u16 = 0,
+ };
+ };
};
/// Differentiates between user-provided and compiler-generated backing types for packed and tagged types.
@@ -5949,13 +6012,7 @@ pub const Alignment = enum(u6) {
return r;
}
- const LlvmBuilderAlignment = std.zig.llvm.Builder.Alignment;
-
- pub fn toLlvm(a: Alignment) LlvmBuilderAlignment {
- return @enumFromInt(@intFromEnum(a));
- }
-
- pub fn fromLlvm(a: LlvmBuilderAlignment) Alignment {
+ pub fn toLlvm(a: Alignment) std.zig.llvm.Builder.Alignment {
return @enumFromInt(@intFromEnum(a));
}
};
@@ -6322,7 +6379,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, io: Io, available_threads: usize) !
}
pub fn deinit(ip: *InternPool, gpa: Allocator, io: Io) void {
- if (debug_state.enable_checks) std.debug.assert(debug_state.intern_pool == null);
+ std.debug.assert(debug_state.intern_pool == null);
ip.src_hash_deps.deinit(gpa);
ip.nav_val_deps.deinit(gpa);
@@ -6367,8 +6424,15 @@ pub fn deinit(ip: *InternPool, gpa: Allocator, io: Io) void {
ip.* = undefined;
}
-pub fn activate(ip: *const InternPool) void {
- if (!debug_state.enable) return;
+pub const Active = struct {
+ prev_ip: if (debug_state.enable) ?*const InternPool else void,
+ pub fn deactivate(active: Active) void {
+ if (!debug_state.enable) return;
+ debug_state.intern_pool = active.prev_ip;
+ }
+};
+pub fn activate(ip: *const InternPool) Active {
+ if (!debug_state.enable) return .{ .prev_ip = {} };
_ = Index.Unwrapped.debug_state;
_ = String.debug_state;
_ = OptionalString.debug_state;
@@ -6378,20 +6442,16 @@ pub fn activate(ip: *const InternPool) void {
_ = TrackedInst.Index.Optional.debug_state;
_ = Nav.Index.debug_state;
_ = Nav.Index.Optional.debug_state;
- if (debug_state.enable_checks) std.debug.assert(debug_state.intern_pool == null);
- debug_state.intern_pool = ip;
-}
-
-pub fn deactivate(ip: *const InternPool) void {
- if (!debug_state.enable) return;
- std.debug.assert(debug_state.intern_pool == ip);
- if (debug_state.enable_checks) debug_state.intern_pool = null;
+ defer debug_state.intern_pool = ip;
+ return .{ .prev_ip = debug_state.intern_pool };
}
/// For debugger access only.
const debug_state = struct {
- const enable = false;
- const enable_checks = enable and !builtin.single_threaded;
+ const enable = switch (builtin.zig_backend) {
+ else => false,
+ .stage2_x86_64 => !builtin.strip_debug_info and build_options.io_mode == .threaded,
+ };
threadlocal var intern_pool: ?*const InternPool = null;
};
@@ -6573,6 +6633,14 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
} },
};
} },
+ .type_spirv => .{ .spirv_type = ns: {
+ const extra_list = unwrapped_index.getExtra(ip);
+ const extra = extraDataTrail(extra_list, Tag.TypeSpirv, data);
+ break :ns .{
+ .zir_index = extra.data.zir_index,
+ .type_hash = extraData(extra_list, PackedU64, extra.end).get(),
+ };
+ } },
.type_opaque => .{ .opaque_type = ns: {
const extra = extraDataTrail(unwrapped_index.getExtra(ip), Tag.TypeOpaque, data);
break :ns .{ .declared = .{
@@ -6918,6 +6986,9 @@ fn extraFuncType(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke
trail_index += 1;
break :b x;
};
+ const cc_extra_len = type_function.data.flags.cc.extraLen();
+ const cc = type_function.data.flags.cc.unpack(extra.view().items(.@"0")[trail_index..][0..cc_extra_len]);
+ trail_index += cc_extra_len;
return .{
.param_types = .{
.tid = tid,
@@ -6927,7 +6998,7 @@ fn extraFuncType(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke
.return_type = type_function.data.return_type,
.comptime_bits = comptime_bits,
.noalias_bits = noalias_bits,
- .cc = type_function.data.flags.cc.unpack(),
+ .cc = cc,
.is_var_args = type_function.data.flags.is_var_args,
.is_noinline = type_function.data.flags.is_noinline,
};
@@ -7345,6 +7416,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key:
.union_type => unreachable, // instead use: getDeclaredUnionType, getReifiedUnionType
.enum_type => unreachable, // instead use: getDeclaredEnumType, getReifiedEnumType, getGeneratedEnumTagType
.opaque_type => unreachable, // instead use: getDeclaredOpaqueType
+ .spirv_type => unreachable, // instead use: getSpirvType
.tuple_type => unreachable, // use getTupleType() instead
.func_type => unreachable, // use getFuncType() instead
@@ -8717,6 +8789,39 @@ pub fn getReifiedEnumType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerT
} };
}
+pub fn getReifiedSpirvType(
+ ip: *InternPool,
+ gpa: Allocator,
+ io: Io,
+ tid: Zcu.PerThread.Id,
+ ini: struct {
+ zir_index: TrackedInst.Index,
+ type_hash: u64,
+ type_spirv: Tag.TypeSpirv,
+ },
+) Allocator.Error!Index {
+ var gop = try ip.getOrPutKey(gpa, io, tid, .{ .spirv_type = .{
+ .zir_index = ini.zir_index,
+ .type_hash = ini.type_hash,
+ } });
+ defer gop.deinit();
+ if (gop == .existing) return gop.existing;
+
+ const local = ip.getLocal(tid);
+ const items = local.getMutableItems(gpa, io);
+ const extra = local.getMutableExtra(gpa, io);
+ try items.ensureUnusedCapacity(1);
+
+ try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeSpirv).@"struct".field_names.len +
+ 2 // type_hash: PackedU64
+ );
+ const extra_index = addExtraAssumeCapacity(extra, ini.type_spirv);
+ _ = addExtraAssumeCapacity(extra, PackedU64.init(ini.type_hash));
+
+ items.appendAssumeCapacity(.{ .tag = .type_spirv, .data = extra_index });
+ return gop.put();
+}
+
pub fn getGeneratedEnumTagType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct {
/// The union type for which this enum is a generated tag.
union_type: Index,
@@ -8992,18 +9097,21 @@ pub fn getFuncType(
// ask if it already exists, and if so, revert the lengths of the mutated
// arrays. This is similar to what `getOrPutTrailingString` does.
const prev_extra_len = extra.mutate.len;
+ const packed_cc: PackedCallingConvention = .pack(key.cc orelse .auto);
+ const cc_extra_len = packed_cc.extraLen();
const params_len: u32 = @intCast(key.param_types.len);
try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeFunction).@"struct".field_names.len +
@intFromBool(key.comptime_bits != 0) +
@intFromBool(key.noalias_bits != 0) +
+ cc_extra_len +
params_len);
const func_type_extra_index = addExtraAssumeCapacity(extra, Tag.TypeFunction{
.params_len = params_len,
.return_type = key.return_type,
.flags = .{
- .cc = .pack(key.cc orelse .auto),
+ .cc = packed_cc,
.is_var_args = key.is_var_args,
.has_comptime_bits = key.comptime_bits != 0,
.has_noalias_bits = key.noalias_bits != 0,
@@ -9013,6 +9121,18 @@ pub fn getFuncType(
if (key.comptime_bits != 0) extra.appendAssumeCapacity(.{key.comptime_bits});
if (key.noalias_bits != 0) extra.appendAssumeCapacity(.{key.noalias_bits});
+ if (key.cc) |cc| switch (cc) {
+ .spirv_kernel, .spirv_task => |kernel| extra.appendSliceAssumeCapacity(.{&.{
+ kernel.x,
+ kernel.y,
+ kernel.z,
+ }}),
+ .spirv_mesh => |mesh| extra.appendSliceAssumeCapacity(.{&.{
+ mesh.max_primitives,
+ mesh.max_vertices,
+ }}),
+ else => {},
+ };
extra.appendSliceAssumeCapacity(.{@ptrCast(key.param_types)});
errdefer extra.mutate.len = prev_extra_len;
@@ -9077,7 +9197,8 @@ pub fn getExtern(
}) catch unreachable; // capacity asserted above
const decoration_type, const location_or_descriptor_set, const descriptor_binding = if (key.decoration) |decoration| switch (decoration) {
.location => |location| .{ Tag.Extern.Flags.DecorationType.location, location, undefined },
- .descriptor => |descriptor| .{ Tag.Extern.Flags.DecorationType.descriptor, descriptor.binding, descriptor.set },
+ .flat => |location| .{ Tag.Extern.Flags.DecorationType.flat, location, undefined },
+ .descriptor => |descriptor| .{ Tag.Extern.Flags.DecorationType.descriptor, descriptor.set, descriptor.binding },
} else .{ Tag.Extern.Flags.DecorationType.none, undefined, undefined };
const extra_index = addExtraAssumeCapacity(extra, Tag.Extern{
.ty = key.ty,
@@ -9810,6 +9931,7 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 {
Tag.TypeStructPacked.Bits,
Tag.TypeUnionPacked.Bits,
Tag.TypeEnum.Bits,
+ Tag.TypeSpirv.Flags,
=> @bitCast(@field(item, field_name)),
else => @compileError("bad field type: " ++ @typeName(field_type)),
@@ -9877,6 +9999,7 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat
Tag.TypeStructPacked.Bits,
Tag.TypeUnionPacked.Bits,
Tag.TypeEnum.Bits,
+ Tag.TypeSpirv.Flags,
=> @bitCast(extra_item),
else => @compileError("bad field type: " ++ @typeName(field_type)),
@@ -9930,6 +10053,11 @@ pub fn childType(ip: *const InternPool, i: Index) Index {
.vector_type => |vector_type| vector_type.child,
.array_type => |array_type| array_type.child,
.opt_type, .anyframe_type => |child| child,
+ .spirv_type => blk: {
+ const info = ip.loadSpirvType(i);
+ assert(info.flags.tag == .runtime_array);
+ break :blk info.ty;
+ },
else => unreachable,
};
}
@@ -10583,6 +10711,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo
.type_optional => 0,
.type_anyframe => 0,
.type_error_union => @sizeOf(Key.ErrorUnionType),
+ .type_spirv => @sizeOf(Tag.TypeSpirv) + @sizeOf(PackedU64),
.type_anyerror_union => 0,
.type_error_set => b: {
const info = extraData(extra_list, Tag.ErrorSet, data);
@@ -10597,6 +10726,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo
const info = extraData(extra_list, Tag.TypeFunction, data);
break :b @sizeOf(Tag.TypeFunction) +
(@sizeOf(Index) * info.params_len) +
+ (@as(u32, 4) * info.flags.cc.extraLen()) +
(@as(u32, 4) * @intFromBool(info.flags.has_comptime_bits)) +
(@as(u32, 4) * @intFromBool(info.flags.has_noalias_bits));
},
@@ -10860,6 +10990,7 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void {
.type_enum_explicit,
.type_enum_nonexhaustive,
.type_opaque,
+ .type_spirv,
.undef,
.ptr_nav,
.ptr_comptime_alloc,
@@ -10931,7 +11062,7 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator,
defer arena_allocator.deinit();
const arena = arena_allocator.allocator();
- var instances: std.AutoArrayHashMapUnmanaged(Index, std.ArrayList(Index)) = .empty;
+ var instances: std.array_hash_map.Auto(Index, std.ArrayList(Index)) = .empty;
for (ip.locals, 0..) |*local, tid| {
const items = local.shared.items.view().slice();
const extra_list = local.shared.extra;
@@ -11598,6 +11729,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
.type_enum_explicit,
.type_enum_nonexhaustive,
.type_opaque,
+ .type_spirv,
=> .type_type,
.undef,
@@ -11955,6 +12087,8 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.lang.TypeId {
.type_opaque,
=> .@"opaque",
+ .type_spirv => .spirv,
+
.type_function => .@"fn",
// values, not types
@@ -12462,12 +12596,35 @@ const PackedCallingConvention = packed struct(u18) {
.incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0),
.extra = @intFromEnum(pl.save),
},
+ std.lang.CallingConvention.SpirvKernelOptions => .{
+ .tag = tag,
+ .incoming_stack_alignment = .none,
+ .extra = 0,
+ },
+ std.lang.CallingConvention.SpirvFragmentOptions => .{
+ .tag = tag,
+ .incoming_stack_alignment = .none,
+ .extra = @as(u4, @intFromEnum(pl.depth_assumption)) << 1 | @intFromBool(pl.pixel_centered_integer),
+ },
+ std.lang.CallingConvention.SpirvMeshOptions => .{
+ .tag = tag,
+ .incoming_stack_alignment = .none,
+ .extra = @intFromEnum(pl.stage_output),
+ },
else => comptime unreachable,
},
};
}
- fn unpack(cc: PackedCallingConvention) std.lang.CallingConvention {
+ fn extraLen(cc: PackedCallingConvention) u2 {
+ return switch (cc.tag) {
+ .spirv_kernel, .spirv_task => 3,
+ .spirv_mesh => 2,
+ else => 0,
+ };
+ }
+
+ fn unpack(cc: PackedCallingConvention, trailing: []const u32) std.lang.CallingConvention {
return switch (cc.tag) {
inline else => |tag| @unionInit(
std.lang.CallingConvention,
@@ -12505,6 +12662,20 @@ const PackedCallingConvention = packed struct(u18) {
.incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(),
.save = @enumFromInt(cc.extra),
},
+ std.lang.CallingConvention.SpirvKernelOptions => .{
+ .x = trailing[0],
+ .y = trailing[1],
+ .z = trailing[2],
+ },
+ std.lang.CallingConvention.SpirvFragmentOptions => .{
+ .pixel_centered_integer = @bitCast(@as(u1, @truncate(cc.extra))),
+ .depth_assumption = @enumFromInt(@as(u2, @truncate(cc.extra >> 1))),
+ },
+ std.lang.CallingConvention.SpirvMeshOptions => .{
+ .stage_output = @enumFromInt(cc.extra),
+ .max_primitives = trailing[0],
+ .max_vertices = trailing[1],
+ },
else => comptime unreachable,
},
),
diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig
index d5e0c3e615c687b775852f65a9d1df9393ec852e..20e19cdaa7ad2e55b9ddb07f490df1ffdaa26eea 100644
--- a/src/Package/Fetch.zig
+++ b/src/Package/Fetch.zig
@@ -162,9 +162,9 @@ pub const JobQueue = struct {
/// Both non-lazy and lazy dependencies are always fetched.
all,
};
- pub const Table = std.AutoArrayHashMapUnmanaged(Package.Hash, *Fetch);
- pub const UnlazySet = std.AutoArrayHashMapUnmanaged(Package.Hash, void);
- pub const ForkSet = std.ArrayHashMapUnmanaged(Fork, void, Fork.Context, false);
+ pub const Table = std.array_hash_map.Auto(Package.Hash, *Fetch);
+ pub const UnlazySet = std.array_hash_map.Auto(Package.Hash, void);
+ pub const ForkSet = std.array_hash_map.Custom(Fork, void, Fork.Context, false);
pub const Fork = struct {
path: Cache.Path,
@@ -1725,7 +1725,7 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute
// Track directories which had any files deleted from them so that empty directories
// can be deleted.
- var sus_dirs: std.StringArrayHashMapUnmanaged(void) = .empty;
+ var sus_dirs: std.array_hash_map.String(void) = .empty;
defer sus_dirs.deinit(gpa);
var walker = try root_dir.walk(gpa);
@@ -2002,7 +2002,7 @@ fn normalizePath(bytes: []u8) void {
}
const Filter = struct {
- include_paths: std.StringArrayHashMapUnmanaged(void) = .empty,
+ include_paths: std.array_hash_map.String(void) = .empty,
/// sub_path is relative to the package root.
pub fn includePath(self: *const Filter, sub_path: []const u8) bool {
diff --git a/src/Package/Manifest.zig b/src/Package/Manifest.zig
index 05ca2a31c25d6939bc190f19b79cc9d53bea2647..849fc742ec5c7b5be02a2895f54f99fece02b2ff 100644
--- a/src/Package/Manifest.zig
+++ b/src/Package/Manifest.zig
@@ -42,9 +42,9 @@ name: []const u8,
id: u32,
version: std.SemanticVersion,
version_node: Ast.Node.Index,
-dependencies: std.StringArrayHashMapUnmanaged(Dependency),
+dependencies: std.array_hash_map.String(Dependency),
dependencies_node: Ast.Node.OptionalIndex,
-paths: std.StringArrayHashMapUnmanaged(void),
+paths: std.array_hash_map.String(void),
minimum_zig_version: ?std.SemanticVersion,
errors: []ErrorMessage,
@@ -144,9 +144,9 @@ const Parse = struct {
id: u32,
version: std.SemanticVersion,
version_node: Ast.Node.Index,
- dependencies: std.StringArrayHashMapUnmanaged(Dependency),
+ dependencies: std.array_hash_map.String(Dependency),
dependencies_node: Ast.Node.OptionalIndex,
- paths: std.StringArrayHashMapUnmanaged(void),
+ paths: std.array_hash_map.String(void),
allow_missing_paths_field: bool,
minimum_zig_version: ?std.SemanticVersion,
diff --git a/src/Package/Module.zig b/src/Package/Module.zig
index 9241293d1dd480b1d9046c26e2d419a6874d2556..0c7e4166adf7d6c290cbb330bb12857c1cf21d90 100644
--- a/src/Package/Module.zig
+++ b/src/Package/Module.zig
@@ -35,11 +35,11 @@ cc_argv: []const []const u8,
structured_cfg: bool,
no_builtin: bool,
-pub const Deps = std.StringArrayHashMapUnmanaged(*Module);
+pub const Deps = std.array_hash_map.String(*Module);
pub const Tree = struct {
/// Each `Package` exposes a `Module` with build.zig as its root source file.
- build_module_table: std.AutoArrayHashMapUnmanaged(MultiHashHexDigest, *Module),
+ build_module_table: std.array_hash_map.Auto(MultiHashHexDigest, *Module),
};
pub const CreateOptions = struct {
diff --git a/src/RangeSet.zig b/src/RangeSet.zig
index 34597062027bf7c04667575ed43c719ac48eeeb5..3033e8510394cbef68b815601f4eea545fb4feae 100644
--- a/src/RangeSet.zig
+++ b/src/RangeSet.zig
@@ -1,6 +1,6 @@
const RangeSet = @This();
-ranges: std.ArrayList(Range),
+ranges: std.MultiArrayList(Range),
pub const Range = struct {
first: Value,
@@ -20,17 +20,21 @@ pub fn ensureUnusedCapacity(self: *RangeSet, allocator: Allocator, additional_co
}
pub fn addAssumeCapacity(set: *RangeSet, new: Range, ty: Type, zcu: *Zcu) ?LazySrcLoc {
- assert(new.first.typeOf(zcu).eql(ty, zcu));
- assert(new.last.typeOf(zcu).eql(ty, zcu));
+ assert(new.first.typeOf(zcu).eql(ty));
+ assert(new.last.typeOf(zcu).eql(ty));
+ assert(new.first.compareScalar(.lte, new.last, ty, zcu));
- for (set.ranges.items) |range| {
- if (new.last.compareScalar(.gte, range.first, ty, zcu) and
- new.first.compareScalar(.lte, range.last, ty, zcu))
- {
- return range.src; // They overlap.
- }
+ const idx = std.sort.lowerBound(Value, set.ranges.items(.last), @as(SearchCtx, .{
+ .val = new.first,
+ .zcu = zcu,
+ }), compare);
+
+ if (idx != set.ranges.len and // `new.first` is *not* greater than all `old.last`
+ new.last.compareScalar(.gte, set.ranges.items(.first)[idx], ty, zcu))
+ {
+ return set.ranges.items(.src)[idx]; // `new` overlaps with existing range.
}
- set.ranges.appendAssumeCapacity(new);
+ set.ranges.insertAssumeCapacity(idx, new);
return null;
}
@@ -39,15 +43,6 @@ pub fn add(set: *RangeSet, allocator: Allocator, new: Range, ty: Type, zcu: *Zcu
return set.addAssumeCapacity(new, ty, zcu);
}
-const SortCtx = struct {
- ty: Type,
- zcu: *Zcu,
-};
-/// Assumes a and b do not overlap
-fn lessThan(ctx: SortCtx, a: Range, b: Range) bool {
- return a.first.compareScalar(.lt, b.first, ctx.ty, ctx.zcu);
-}
-
pub fn spans(
set: *RangeSet,
allocator: Allocator,
@@ -56,37 +51,38 @@ pub fn spans(
ty: Type,
zcu: *Zcu,
) Allocator.Error!bool {
- assert(first.typeOf(zcu).eql(ty, zcu));
- assert(last.typeOf(zcu).eql(ty, zcu));
- if (set.ranges.items.len == 0) return false;
+ assert(first.typeOf(zcu).eql(ty));
+ assert(last.typeOf(zcu).eql(ty));
+ if (set.ranges.len == 0) return false;
- std.mem.sort(Range, set.ranges.items, SortCtx{ .ty = ty, .zcu = zcu }, lessThan);
+ assert(std.sort.isSorted(Value, set.ranges.items(.first), @as(SortCtx, .{ .ty = ty, .zcu = zcu }), lessThan));
+ assert(std.sort.isSorted(Value, set.ranges.items(.last), @as(SortCtx, .{ .ty = ty, .zcu = zcu }), lessThan));
- if (!set.ranges.items[0].first.eql(first, ty, zcu) or
- !set.ranges.items[set.ranges.items.len - 1].last.eql(last, ty, zcu))
+ if (!set.ranges.items(.first)[0].eql(first, ty, zcu) or
+ !set.ranges.items(.last)[set.ranges.len - 1].eql(last, ty, zcu))
{
return false;
}
const limbs = try allocator.alloc(
- std.math.big.Limb,
- std.math.big.int.calcTwosCompLimbCount(ty.intInfo(zcu).bits),
+ math.big.Limb,
+ math.big.int.calcTwosCompLimbCount(ty.intInfo(zcu).bits),
);
defer allocator.free(limbs);
- var counter: std.math.big.int.Mutable = .init(limbs, 0);
+ var counter: math.big.int.Mutable = .init(limbs, 0);
var space: InternPool.Key.Int.Storage.BigIntSpace = undefined;
// look for gaps
- for (set.ranges.items[1..], 0..) |cur, i| {
- // i starts counting from the second item.
- const prev = set.ranges.items[i];
-
- // prev.last + 1 == cur.first
- counter.copy(prev.last.toBigInt(&space, zcu));
+ for (
+ set.ranges.items(.first)[1..],
+ set.ranges.items(.last)[0 .. set.ranges.len - 1],
+ ) |cur_first, prev_last| {
+ // prev_last + 1 == cur_first
+ counter.copy(prev_last.toBigInt(&space, zcu));
counter.addScalar(counter.toConst(), 1);
- const cur_start_int = cur.first.toBigInt(&space, zcu);
+ const cur_start_int = cur_first.toBigInt(&space, zcu);
if (!cur_start_int.eql(counter.toConst())) {
return false;
}
@@ -95,7 +91,24 @@ pub fn spans(
return true;
}
+const SearchCtx = struct {
+ val: Value,
+ zcu: *const Zcu,
+};
+fn compare(ctx: SearchCtx, other: Value) math.Order {
+ return ctx.val.order(other, ctx.zcu);
+}
+
+const SortCtx = struct {
+ ty: Type,
+ zcu: *Zcu,
+};
+fn lessThan(ctx: SortCtx, a: Value, b: Value) bool {
+ return a.compareScalar(.lt, b, ctx.ty, ctx.zcu);
+}
+
const std = @import("std");
+const math = std.math;
const assert = std.debug.assert;
const Allocator = std.mem.Allocator;
diff --git a/src/Sema.zig b/src/Sema.zig
index 0d8a40ae9d808c4b6e60e4015bc73c002a0eba5e..08510f58975ced08aeb2416f5d1530c0fa724c6c 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -88,7 +88,7 @@ err: ?*Zcu.ErrorMsg = null,
/// The temporary arena is used for the memory of the `InferredAlloc` values
/// here so the values can be dropped without any cleanup.
-unresolved_inferred_allocs: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, InferredAlloc) = .empty,
+unresolved_inferred_allocs: std.array_hash_map.Auto(Air.Inst.Index, InferredAlloc) = .empty,
/// Links every pointer derived from a base `alloc` back to that `alloc`. Used
/// to detect comptime-known `const`s.
@@ -119,13 +119,13 @@ exports: std.ArrayList(Zcu.Export) = .empty,
/// All references registered so far by this `Sema`. This is a temporary duplicate
/// of data stored in `Zcu.all_references`. It exists to avoid adding references to
/// a given `AnalUnit` multiple times.
-references: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .empty,
-type_references: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .empty,
+references: std.array_hash_map.Auto(AnalUnit, void) = .empty,
+type_references: std.array_hash_map.Auto(InternPool.Index, void) = .empty,
/// All dependencies registered so far by this `Sema`. This is a temporary duplicate
/// of the main dependency data. It exists to avoid adding dependencies to a given
/// `AnalUnit` multiple times.
-dependencies: std.AutoArrayHashMapUnmanaged(InternPool.Dependee, void) = .empty,
+dependencies: std.array_hash_map.Auto(InternPool.Dependee, void) = .empty,
/// Whether memoization of this call is permitted. Operations with side effects global
/// to the `Sema`, such as `@setEvalBranchQuota`, set this to `false`. It is observed
@@ -212,11 +212,11 @@ pub const InferredErrorSet = struct {
/// are returned from any dependent functions.
errors: NameMap = .{},
/// Other inferred error sets which this inferred error set should include.
- inferred_error_sets: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .empty,
+ inferred_error_sets: std.array_hash_map.Auto(InternPool.Index, void) = .empty,
/// The regular error set created by resolving this inferred error set.
resolved: InternPool.Index = .none,
- pub const NameMap = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void);
+ pub const NameMap = std.array_hash_map.Auto(InternPool.NullTerminatedString, void);
pub fn addErrorSet(
self: *InferredErrorSet,
@@ -583,16 +583,6 @@ pub const Block = struct {
});
}
- fn addBitCast(block: *Block, ty: Type, operand: Air.Inst.Ref) Allocator.Error!Air.Inst.Ref {
- return block.addInst(.{
- .tag = .bitcast,
- .data = .{ .ty_op = .{
- .ty = Air.internedToRef(ty.toIntern()),
- .operand = operand,
- } },
- });
- }
-
fn addNoOp(block: *Block, tag: Air.Inst.Tag) error{OutOfMemory}!Air.Inst.Ref {
return block.addInst(.{
.tag = tag,
@@ -1241,6 +1231,8 @@ fn analyzeBodyInner(
.optional_type => try sema.zirOptionalType(block, inst),
.ptr_type => try sema.zirPtrType(block, inst),
.ref => try sema.zirRef(block, inst),
+ .deref => try sema.zirDeref(block, inst),
+ .ref_deref => try sema.zirRefDeref(block, inst),
.shr => try sema.zirShr(block, inst, .shr),
.shr_exact => try sema.zirShr(block, inst, .shr_exact),
.slice_end => try sema.zirSliceEnd(block, inst),
@@ -1434,6 +1426,7 @@ fn analyzeBodyInner(
.reify_struct => try sema.zirReifyStruct( block, extended, inst),
.reify_union => try sema.zirReifyUnion( block, extended, inst),
.reify_enum => try sema.zirReifyEnum( block, extended, inst),
+ .reify_spirv_type => try sema.zirReifySpirvType( block, extended, inst),
// zig fmt: on
.set_float_mode => {
@@ -1442,9 +1435,7 @@ fn analyzeBodyInner(
continue;
},
.breakpoint => {
- if (!block.isComptime()) {
- _ = try block.addNoOp(.breakpoint);
- }
+ try sema.zirBreakpoint(block, extended);
i += 1;
continue;
},
@@ -1567,11 +1558,6 @@ fn analyzeBodyInner(
i += 1;
continue;
},
- .validate_deref => {
- try sema.zirValidateDeref(block, inst);
- i += 1;
- continue;
- },
.validate_destructure => {
try sema.zirValidateDestructure(block, inst);
i += 1;
@@ -3083,6 +3069,79 @@ fn zirRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
return sema.analyzeRef(block, block.tokenOffset(inst_data.src_tok), operand, .none);
}
+fn zirDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
+ const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
+ const src = block.nodeOffset(inst_data.src_node);
+ const ptr_src = block.src(.{ .node_offset_deref_ptr = inst_data.src_node });
+ const operand = sema.resolveInst(inst_data.operand);
+
+ try sema.validateDeref(block, src, operand, sema.typeOf(operand));
+
+ return sema.analyzeLoad(block, src, operand, ptr_src);
+}
+
+fn zirRefDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
+ const pt = sema.pt;
+ const zcu = pt.zcu;
+ const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
+ const src = block.nodeOffset(inst_data.src_node);
+ const operand = sema.resolveInst(inst_data.operand);
+ const operand_ty = sema.typeOf(operand);
+
+ try sema.validateDeref(block, src, operand, operand_ty);
+
+ const ptr_info = operand_ty.ptrInfo(zcu);
+ return switch (ptr_info.flags.size) {
+ .many, .slice => unreachable, // cannot be dereferenced
+ .c => single_ptr: {
+ const single_ptr_ty = try pt.ptrType(p: {
+ var p = ptr_info;
+ p.flags.size = .one;
+ p.flags.is_allowzero = false;
+ break :p p;
+ });
+ // https://github.com/ziglang/zig/issues/6597
+ if (sema.resolveValue(operand)) |operand_val| {
+ if (!operand_val.isNull(zcu)) {
+ break :single_ptr .fromValue(try pt.getCoerced(operand_val, single_ptr_ty));
+ }
+ }
+ if (block.wantSafety()) {
+ const is_non_null = try block.addUnOp(.is_non_null, operand);
+ try sema.addSafetyCheck(block, src, is_non_null, .unwrap_null);
+ }
+ const single_ptr = try block.addTyOp(.ptr_cast, single_ptr_ty, operand);
+ try sema.checkKnownAllocPtr(block, operand, single_ptr);
+ break :single_ptr single_ptr;
+ },
+ .one => operand,
+ };
+}
+
+fn validateDeref(
+ sema: *Sema,
+ block: *Block,
+ src: LazySrcLoc,
+ ref: Air.Inst.Ref,
+ ty: Type,
+) CompileError!void {
+ const pt = sema.pt;
+ const zcu = pt.zcu;
+ if (ty.zigTypeTag(zcu) != .pointer) {
+ return sema.fail(block, src, "cannot dereference non-pointer type '{f}'", .{ty.fmt(pt)});
+ } else switch (ty.ptrSize(zcu)) {
+ .one, .c => {},
+ .many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{f}'", .{ty.fmt(pt)}),
+ .slice => return sema.fail(block, src, "index syntax required for slice type '{f}'", .{ty.fmt(pt)}),
+ }
+ if (sema.resolveValue(ref)) |val| {
+ // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal.
+ if (val.isUndef(zcu) and ty.childType(zcu).classify(zcu) != .one_possible_value) {
+ return sema.fail(block, src, "cannot dereference undefined value", .{});
+ }
+ }
+}
+
fn zirEnsureResultUsed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
const operand = sema.resolveInst(inst_data.operand);
@@ -3517,7 +3576,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,
.{ .elem = idx_val.toUnsignedInt(zcu) },
};
},
- .bitcast => .{
+ .ptr_cast => .{
tmp_air.instructions.items(.data)[@intFromEnum(air_ptr)].ty_op.operand,
.same_addr,
},
@@ -3660,7 +3719,7 @@ fn finishResolveComptimeKnownAllocPtr(
// This instruction has type `alloc_ty`, meaning we can rewrite the `alloc` AIR instruction to
// this one to drop the side effect. We also need to rewrite the stores; we'll turn them to this
// too because it doesn't really matter what they become.
- const nop_inst: Air.Inst = .{ .tag = .bitcast, .data = .{ .ty_op = .{
+ const nop_inst: Air.Inst = .{ .tag = .ptr_from_int, .data = .{ .ty_op = .{
.ty = .fromIntern(alloc_ty.toIntern()),
.operand = .zero_usize,
} } };
@@ -3710,7 +3769,7 @@ fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Ai
return Air.internedToRef((try sema.pt.getCoerced(val, const_ptr_ty)).toIntern());
}
- return block.addBitCast(const_ptr_ty, alloc);
+ return block.addTyOp(.ptr_cast, const_ptr_ty, alloc);
}
fn zirAllocInferredComptime(
@@ -4607,30 +4666,6 @@ fn zirValidatePtrArrayInit(
}
}
-fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
- const pt = sema.pt;
- const zcu = pt.zcu;
- const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
- const src = block.nodeOffset(inst_data.src_node);
- const operand = sema.resolveInst(inst_data.operand);
- const operand_ty = sema.typeOf(operand);
-
- if (operand_ty.zigTypeTag(zcu) != .pointer) {
- return sema.fail(block, src, "cannot dereference non-pointer type '{f}'", .{operand_ty.fmt(pt)});
- } else switch (operand_ty.ptrSize(zcu)) {
- .one, .c => {},
- .many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{f}'", .{operand_ty.fmt(pt)}),
- .slice => return sema.fail(block, src, "index syntax required for slice type '{f}'", .{operand_ty.fmt(pt)}),
- }
-
- if (sema.resolveValue(operand)) |val| {
- // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal.
- if (val.isUndef(zcu) and operand_ty.childType(zcu).classify(zcu) != .one_possible_value) {
- return sema.fail(block, src, "cannot dereference undefined value", .{});
- }
- }
-}
-
fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
const pt = sema.pt;
const zcu = pt.zcu;
@@ -5081,6 +5116,14 @@ fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
_ = try block.addNoOp(.trap);
}
+fn zirBreakpoint(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
+ const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
+ const src = block.nodeOffset(src_node);
+ if (block.isComptime())
+ return sema.fail(block, src, "encountered @breakpoint at comptime", .{});
+ _ = try block.addNoOp(.breakpoint);
+}
+
fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const pt = sema.pt;
const zcu = pt.zcu;
@@ -5244,33 +5287,51 @@ fn resolveBlockBody(
return sema.resolveAnalyzedBlock(parent_block, src, child_block, merges, need_debug_scope);
} else |err| switch (err) {
error.ComptimeBreak => {
+ const break_inst = sema.comptime_break_inst;
+ const break_data = sema.code.instructions.items(.data)[@intFromEnum(break_inst)].@"break";
+ const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data;
+ const breaks_to_body = extra.block_inst == body_inst;
+
// Comptime control flow is happening, however child_block may still contain
// runtime instructions which need to be copied to the parent block.
if (need_debug_scope and child_block.instructions.items.len > 0) {
- // We need a runtime block for scoping reasons.
- _ = try child_block.addBr(merges.block_inst, .void_value);
+ // We need a runtime block for scoping reasons. The break
+ // operand may have been produced by a runtime instruction
+ // inside `child_blocks`.
+ const operand = sema.resolveInst(break_data.operand);
+ const operand_ty = sema.typeOf(operand);
+ _ = try child_block.addBr(merges.block_inst, operand);
try parent_block.instructions.append(sema.gpa, merges.block_inst);
try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Block).@"struct".field_names.len +
child_block.instructions.items.len);
sema.air_instructions.items(.data)[@intFromEnum(merges.block_inst)] = .{ .ty_pl = .{
- .ty = .void_type,
+ .ty = Air.internedToRef(operand_ty.toIntern()),
.payload = sema.addExtraAssumeCapacity(Air.Block{
.body_len = @intCast(child_block.instructions.items.len),
}),
} };
sema.air_extra.appendSliceAssumeCapacity(@ptrCast(child_block.instructions.items));
+
+ // The block result now holds the operand value, so we remap
+ // the operand such that an enclosing scope which resolves
+ // it picks up the block result rather than the internal
+ // block instruction.
+ if (break_data.operand.toIndex()) |operand_zir| {
+ sema.inst_map.putAssumeCapacity(operand_zir, merges.block_inst.toRef());
+ }
+ if (breaks_to_body) {
+ return merges.block_inst.toRef();
+ } else {
+ return error.ComptimeBreak;
+ }
} else {
// We can copy instructions directly to the parent block.
try parent_block.instructions.appendSlice(sema.gpa, child_block.instructions.items);
- }
-
- const break_inst = sema.comptime_break_inst;
- const break_data = sema.code.instructions.items(.data)[@intFromEnum(break_inst)].@"break";
- const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data;
- if (extra.block_inst == body_inst) {
- return sema.resolveInst(break_data.operand);
- } else {
- return error.ComptimeBreak;
+ if (breaks_to_body) {
+ return sema.resolveInst(break_data.operand);
+ } else {
+ return error.ComptimeBreak;
+ }
}
},
else => |e| return e,
@@ -5455,7 +5516,7 @@ fn resolveAnalyzedBlock(
const br_operand = sema.air_instructions.items(.data)[@intFromEnum(br)].br.operand;
const br_operand_src = src;
const br_operand_ty = sema.typeOf(br_operand);
- if (br_operand_ty.eql(resolved_ty, zcu)) {
+ if (br_operand_ty.eql(resolved_ty)) {
// No type coercion needed.
continue;
}
@@ -6415,22 +6476,6 @@ const CallArgsInfo = union(enum) {
const uncoerced_arg: Air.Inst.Ref = switch (cai) {
inline .resolved, .call_builtin => |resolved| resolved.args[arg_index],
.zir_call => |zir_call| arg_val: {
- const has_bound_arg = zir_call.bound_arg != .none;
- if (arg_index == 0 and has_bound_arg) {
- break :arg_val zir_call.bound_arg;
- }
- const real_arg_idx = arg_index - @intFromBool(has_bound_arg);
-
- const arg_body = if (real_arg_idx == 0) blk: {
- const start = zir_call.num_args;
- const end = @intFromEnum(zir_call.args_body[0]);
- break :blk zir_call.args_body[start..end];
- } else blk: {
- const start = @intFromEnum(zir_call.args_body[real_arg_idx - 1]);
- const end = @intFromEnum(zir_call.args_body[real_arg_idx]);
- break :blk zir_call.args_body[start..end];
- };
-
// Generate args to comptime params in comptime block
const parent_comptime = block.comptime_reason;
defer block.comptime_reason = parent_comptime;
@@ -6452,11 +6497,27 @@ const CallArgsInfo = union(enum) {
};
}
}
- // Give the arg its result type
- const provide_param_ty: Type = maybe_param_ty orelse .generic_poison;
- sema.inst_map.putAssumeCapacity(zir_call.call_inst, Air.internedToRef(provide_param_ty.toIntern()));
- // Resolve the arg!
- const uncoerced_arg = try sema.resolveInlineBody(block, arg_body, zir_call.call_inst);
+
+ const has_bound_arg = zir_call.bound_arg != .none;
+ const uncoerced_arg = if (arg_index == 0 and has_bound_arg) zir_call.bound_arg else arg: {
+ const real_arg_idx = arg_index - @intFromBool(has_bound_arg);
+
+ const arg_body = if (real_arg_idx == 0) blk: {
+ const start = zir_call.num_args;
+ const end = @intFromEnum(zir_call.args_body[0]);
+ break :blk zir_call.args_body[start..end];
+ } else blk: {
+ const start = @intFromEnum(zir_call.args_body[real_arg_idx - 1]);
+ const end = @intFromEnum(zir_call.args_body[real_arg_idx]);
+ break :blk zir_call.args_body[start..end];
+ };
+
+ // Give the arg its result type
+ const provide_param_ty: Type = maybe_param_ty orelse .generic_poison;
+ sema.inst_map.putAssumeCapacity(zir_call.call_inst, Air.internedToRef(provide_param_ty.toIntern()));
+ // Resolve the arg!
+ break :arg try sema.resolveInlineBody(block, arg_body, zir_call.call_inst);
+ };
if (block.isComptime() and !try sema.isComptimeKnown(uncoerced_arg)) {
return sema.failWithNeededComptime(block, cai.argSrc(block, arg_index), null);
@@ -7277,7 +7338,7 @@ fn analyzeCall(
if (resolved_ty == .none) break :r result_raw;
// TODO: mutate in place the previous instruction if possible
// rather than adding a bitcast instruction.
- break :r try block.addBitCast(.fromInterned(resolved_ty), result_raw);
+ break :r try block.addTyOp(.error_cast, .fromInterned(resolved_ty), result_raw);
};
if (block.isComptime()) {
@@ -7583,7 +7644,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
}
try sema.requireRuntimeBlock(block, src, operand_src);
- return block.addBitCast(err_int_ty, operand);
+ return block.addTyOp(.int_from_error, err_int_ty, operand);
}
fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
@@ -7621,13 +7682,7 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
const ok = try block.addBinOp(.bit_and, is_lte_len, is_non_zero);
try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
}
- return block.addInst(.{
- .tag = .bitcast,
- .data = .{ .ty_op = .{
- .ty = .anyerror_type,
- .operand = operand,
- } },
- });
+ return block.addTyOp(.error_from_int, .anyerror, operand);
}
fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -7810,7 +7865,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
}
try sema.requireRuntimeBlock(block, src, operand_src);
- return block.addBitCast(int_tag_ty, enum_tag);
+ return block.addTyOp(.bit_cast, int_tag_ty, enum_tag);
}
fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -7869,9 +7924,9 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
try sema.requireRuntimeBlock(block, src, operand_src);
if (block.wantSafety()) {
try sema.preparePanicId(src, .invalid_enum_value);
- return block.addTyOp(.intcast_safe, dest_ty, operand);
+ return block.addTyOp(.int_cast_safe, dest_ty, operand);
}
- return block.addTyOp(.intcast, dest_ty, operand);
+ return block.addTyOp(.int_cast, dest_ty, operand);
}
/// Pointer in, pointer out.
@@ -7913,12 +7968,10 @@ fn analyzeOptionalPayloadPtr(
}
const child_type = opt_type.optionalChild(zcu);
- const child_pointer = try pt.ptrType(.{
- .child = child_type.toIntern(),
- .flags = .{
- .is_const = optional_ptr_ty.isConstPtr(zcu),
- .address_space = optional_ptr_ty.ptrAddressSpace(zcu),
- },
+ const child_pointer = try pt.ptrType(info: {
+ var new = optional_ptr_ty.ptrInfo(zcu);
+ new.child = child_type.toIntern();
+ break :info new;
});
if (try sema.resolveDefinedValue(block, src, optional_ptr)) |ptr_val| {
@@ -8592,6 +8645,7 @@ fn checkReturnTypeAndCallConv(
) CompileError!void {
const pt = sema.pt;
const zcu = pt.zcu;
+ const target = zcu.getTarget();
if (opt_varargs_src) |varargs_src| {
try sema.checkCallConvSupportsVarArgs(block, varargs_src, @"callconv");
}
@@ -8653,6 +8707,32 @@ fn checkReturnTypeAndCallConv(
.@"inline" => if (is_noinline) {
return sema.fail(block, callconv_src, "'noinline' function cannot have calling convention 'inline'", .{});
},
+ .spirv_fragment => |fragment| {
+ if (fragment.pixel_centered_integer and target.os.tag != .opengl) {
+ return sema.fail(block, callconv_src, "'pixel_centered_integer' is not supported on this target", .{});
+ }
+ },
+ .spirv_kernel => |kernel| {
+ if (kernel.x == 0 or kernel.y == 0 or kernel.z == 0) {
+ return sema.fail(block, callconv_src, "kernel workgroup dimensions must be at least 1", .{});
+ }
+ },
+ .spirv_task => |task| {
+ if (task.x == 0 or task.y == 0 or task.z == 0) {
+ return sema.fail(block, callconv_src, "kernel workgroup dimensions must be at least 1", .{});
+ }
+ if (!target.cpu.has(.spirv, .mesh_shading_ext)) {
+ return sema.fail(block, callconv_src, "calling convention '{t}' requires the 'mesh_shading_ext' feature", .{@"callconv"});
+ }
+ },
+ .spirv_mesh => |mesh| {
+ if (mesh.max_vertices == 0 or mesh.max_primitives == 0) {
+ return sema.fail(block, callconv_src, "mesh shader 'max_vertices' and 'max_primitives' must be at least 1", .{});
+ }
+ if (!target.cpu.has(.spirv, .mesh_shading_ext)) {
+ return sema.fail(block, callconv_src, "calling convention '{t}' requires the 'mesh_shading_ext' feature", .{@"callconv"});
+ }
+ },
else => {},
}
switch (zcu.callconvSupported(@"callconv")) {
@@ -8763,6 +8843,8 @@ fn callConvIsCallable(cc: std.lang.CallingConvention.Tag) bool {
.spirv_kernel,
.spirv_fragment,
.spirv_vertex,
+ .spirv_task,
+ .spirv_mesh,
=> false,
else => true,
@@ -8791,7 +8873,7 @@ fn checkMergeAllowed(sema: *Sema, block: *Block, src: LazySrcLoc, peer_ty: Type)
try sema.errNote(runtime_src, msg, "runtime control flow here", .{});
const backend = target_util.zigBackend(target, zcu.comp.config.use_llvm);
- try sema.errNote(src, msg, "pointers with address space '{s}' cannot be returned from a branch on target {s}-{s} by compiler backend {s}", .{
+ try sema.errNote(src, msg, "pointers with address space '{s}' cannot be returned from a branch on target '{s}-{s}' by compiler backend '{s}'", .{
@tagName(as),
@tagName(target.cpu.arch.family()),
@tagName(target.os.tag),
@@ -9083,7 +9165,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), ptr_src);
try sema.validateRuntimeValue(block, ptr_src, operand);
try sema.checkLogicalPtrOperation(block, ptr_src, ptr_ty);
- return block.addBitCast(dest_ty, operand);
+ return block.addTyOp(.int_from_ptr, dest_ty, operand);
}
fn zirFieldPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -9232,7 +9314,7 @@ fn intCast(
break :ok all_in_range;
} else ok: {
const zero_inst = Air.internedToRef((try pt.intValue(operand_ty, 0)).toIntern());
- const is_in_range = try block.addBinOp(.cmp_lte, operand, zero_inst);
+ const is_in_range = try block.addBinOp(.cmp_eq, operand, zero_inst);
break :ok is_in_range;
};
try sema.addSafetyCheck(block, src, ok, .integer_out_of_bounds);
@@ -9245,9 +9327,9 @@ fn intCast(
try sema.requireRuntimeBlock(block, src, operand_src);
if (block.wantSafety()) {
try sema.preparePanicId(src, .integer_out_of_bounds);
- return block.addTyOp(.intcast_safe, dest_ty, operand);
+ return block.addTyOp(.int_cast_safe, dest_ty, operand);
}
- return block.addTyOp(.intcast, dest_ty, operand);
+ return block.addTyOp(.int_cast, dest_ty, operand);
}
fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -9261,156 +9343,53 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@bitCast");
const operand = sema.resolveInst(extra.rhs);
const operand_ty = sema.typeOf(operand);
- switch (dest_ty.zigTypeTag(zcu)) {
- .@"anyframe",
- .comptime_float,
- .comptime_int,
- .enum_literal,
- .error_set,
- .error_union,
- .@"fn",
- .frame,
- .noreturn,
- .null,
- .@"opaque",
- .optional,
- .type,
- .undefined,
- .void,
- => return sema.fail(block, src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)}),
- .@"enum" => {
- const msg = msg: {
- const msg = try sema.errMsg(src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)});
- errdefer msg.destroy(sema.gpa);
- switch (operand_ty.zigTypeTag(zcu)) {
- .int, .comptime_int => try sema.errNote(src, msg, "use @enumFromInt to cast from '{f}'", .{operand_ty.fmt(pt)}),
- else => {},
- }
-
- break :msg msg;
- };
- return sema.failWithOwnedErrorMsg(block, msg);
- },
-
- .pointer => {
- const msg = msg: {
- const msg = try sema.errMsg(src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)});
- errdefer msg.destroy(sema.gpa);
- switch (operand_ty.zigTypeTag(zcu)) {
- .int, .comptime_int => try sema.errNote(src, msg, "use @ptrFromInt to cast from '{f}'", .{operand_ty.fmt(pt)}),
- .pointer => try sema.errNote(src, msg, "use @ptrCast to cast from '{f}'", .{operand_ty.fmt(pt)}),
- else => {},
- }
-
- break :msg msg;
- };
- return sema.failWithOwnedErrorMsg(block, msg);
- },
- .@"struct", .@"union" => if (dest_ty.containerLayout(zcu) == .auto) {
- const container = switch (dest_ty.zigTypeTag(zcu)) {
- .@"struct" => "struct",
- .@"union" => "union",
- else => unreachable,
- };
- return sema.fail(block, src, "cannot @bitCast to '{f}'; {s} does not have a guaranteed in-memory layout", .{
- dest_ty.fmt(pt), container,
- });
- },
- .array => {
- const elem_ty = dest_ty.childType(zcu);
- if (!elem_ty.hasWellDefinedLayout(zcu)) {
- const msg = msg: {
- const msg = try sema.errMsg(src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)});
- errdefer msg.destroy(sema.gpa);
- try sema.errNote(src, msg, "array element type '{f}' does not have a guaranteed in-memory layout", .{elem_ty.fmt(pt)});
- break :msg msg;
- };
- return sema.failWithOwnedErrorMsg(block, msg);
+ // Check for pointers before checking `hasBitRepresentation` so we can emit a better message for slices.
+ switch (dest_ty.scalarType(zcu).zigTypeTag(zcu)) {
+ .pointer, .optional => return sema.failWithOwnedErrorMsg(block, msg: {
+ const msg = try sema.errMsg(src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)});
+ errdefer msg.destroy(sema.gpa);
+ switch (operand_ty.zigTypeTag(zcu)) {
+ .int, .comptime_int => try sema.errNote(src, msg, "use @ptrFromInt to cast from '{f}'", .{operand_ty.fmt(pt)}),
+ .pointer => try sema.errNote(src, msg, "use @ptrCast to cast from '{f}'", .{operand_ty.fmt(pt)}),
+ else => {},
}
- },
-
- .bool,
- .float,
- .int,
- .vector,
- => {},
- }
- switch (operand_ty.zigTypeTag(zcu)) {
- .@"anyframe",
- .comptime_float,
- .comptime_int,
- .enum_literal,
- .error_set,
- .error_union,
- .@"fn",
- .frame,
- .noreturn,
- .null,
- .@"opaque",
- .optional,
- .type,
- .undefined,
- .void,
- => return sema.fail(block, operand_src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)}),
- .@"enum" => {
- const msg = msg: {
- const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)});
- errdefer msg.destroy(sema.gpa);
- switch (dest_ty.zigTypeTag(zcu)) {
- .int, .comptime_int => try sema.errNote(operand_src, msg, "use @intFromEnum to cast to '{f}'", .{dest_ty.fmt(pt)}),
- else => {},
- }
-
- break :msg msg;
- };
- return sema.failWithOwnedErrorMsg(block, msg);
+ break :msg msg;
+ }),
+ .array => switch (dest_ty.arrayBase(zcu)[0].zigTypeTag(zcu)) {
+ .pointer, .optional => return sema.fail(block, src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)}),
+ else => {},
},
- .pointer => {
- const msg = msg: {
- const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)});
- errdefer msg.destroy(sema.gpa);
- switch (dest_ty.zigTypeTag(zcu)) {
- .int, .comptime_int => try sema.errNote(operand_src, msg, "use @intFromPtr to cast to '{f}'", .{dest_ty.fmt(pt)}),
- .pointer => try sema.errNote(operand_src, msg, "use @ptrCast to cast to '{f}'", .{dest_ty.fmt(pt)}),
- else => {},
- }
+ else => {},
+ }
+ if (!dest_ty.hasBitRepresentation(zcu)) {
+ return sema.fail(block, src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)});
+ }
- break :msg msg;
- };
- return sema.failWithOwnedErrorMsg(block, msg);
- },
- .@"struct", .@"union" => if (operand_ty.containerLayout(zcu) == .auto) {
- const container = switch (operand_ty.zigTypeTag(zcu)) {
- .@"struct" => "struct",
- .@"union" => "union",
- else => unreachable,
- };
- return sema.fail(block, operand_src, "cannot @bitCast from '{f}'; {s} does not have a guaranteed in-memory layout", .{
- operand_ty.fmt(pt), container,
- });
- },
- .array => {
- const elem_ty = operand_ty.childType(zcu);
- if (!elem_ty.hasWellDefinedLayout(zcu)) {
- const msg = msg: {
- const msg = try sema.errMsg(src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)});
- errdefer msg.destroy(sema.gpa);
- try sema.errNote(src, msg, "array element type '{f}' does not have a guaranteed in-memory layout", .{elem_ty.fmt(pt)});
- break :msg msg;
- };
- return sema.failWithOwnedErrorMsg(block, msg);
+ // Check for pointers before checking `hasBitRepresentation` so we can emit a better message for slices.
+ switch (operand_ty.scalarType(zcu).zigTypeTag(zcu)) {
+ .pointer, .optional => return sema.failWithOwnedErrorMsg(block, msg: {
+ const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)});
+ errdefer msg.destroy(sema.gpa);
+ switch (dest_ty.zigTypeTag(zcu)) {
+ .int, .comptime_int => try sema.errNote(operand_src, msg, "use @intFromPtr to cast to '{f}'", .{dest_ty.fmt(pt)}),
+ .pointer => try sema.errNote(operand_src, msg, "use @ptrCast to cast to '{f}'", .{dest_ty.fmt(pt)}),
+ else => {},
}
+ break :msg msg;
+ }),
+ .array => switch (operand_ty.arrayBase(zcu)[0].zigTypeTag(zcu)) {
+ .pointer, .optional => return sema.fail(block, operand_src, "cannot @bitCast from '{f}'", .{dest_ty.fmt(pt)}),
+ else => {},
},
-
- .bool,
- .float,
- .int,
- .vector,
- => {},
+ else => {},
}
- return sema.bitCast(block, dest_ty, operand, block.nodeOffset(inst_data.src_node), operand_src);
+ if (!operand_ty.hasBitRepresentation(zcu)) {
+ return sema.fail(block, operand_src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)});
+ }
+
+ return sema.bitCast(block, dest_ty, operand, block.nodeOffset(inst_data.src_node));
}
fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -9780,7 +9759,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
const maybe_switch_ref: ?Air.Inst.Ref = ref: {
// make err capture (i.e. switch operand) available to switch prong bodies
- sema.inst_map.putAssumeCapacityNoClobber(inst, raw_switch_operand);
+ sema.inst_map.putAssumeCapacity(inst, raw_switch_operand);
defer assert(sema.inst_map.remove(inst));
break :ref try sema.analyzeSwitchBlock(block, &switch_block, raw_switch_operand, false, merges, inst, &zir_switch, &validated_switch);
};
@@ -10839,7 +10818,7 @@ fn finishSwitchBr(
const ValidatedSwitchBlock = struct {
seen_enum_fields: []const ?LazySrcLoc,
seen_errors: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc),
- seen_ranges: []const RangeSet.Range,
+ seen_ranges: std.MultiArrayList(RangeSet.Range).Slice,
true_src: ?LazySrcLoc,
false_src: ?LazySrcLoc,
void_src: ?LazySrcLoc,
@@ -10874,7 +10853,7 @@ const ValidatedSwitchBlock = struct {
error_names: InternPool.NullTerminatedString.Slice,
seen_enum_fields: []const ?LazySrcLoc,
seen_errors: *const std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc),
- seen_ranges: []const RangeSet.Range,
+ seen_ranges: std.MultiArrayList(RangeSet.Range).Slice,
seen_true: bool,
seen_false: bool,
seen_void: bool,
@@ -10911,13 +10890,13 @@ const ValidatedSwitchBlock = struct {
else => unreachable,
};
while (it.next_idx < it.seen_ranges.len and
- cur_val.eql(it.seen_ranges[it.next_idx].first, int_ty, zcu))
+ cur_val.eql(it.seen_ranges.items(.first)[it.next_idx], int_ty, zcu))
{
defer it.next_idx += 1;
const incr = try arith.incrementDefinedInt(
sema,
int_ty,
- it.seen_ranges[it.next_idx].last,
+ it.seen_ranges.items(.last)[it.next_idx],
);
if (incr.overflow) {
it.next_val = null;
@@ -11405,7 +11384,7 @@ fn validateSwitchBlock(
return .{
.seen_enum_fields = seen_enum_fields,
.seen_errors = seen_errors,
- .seen_ranges = range_set.ranges.items,
+ .seen_ranges = range_set.ranges.slice(),
.true_src = true_src,
.false_src = false_src,
.void_src = void_src,
@@ -11955,11 +11934,17 @@ fn analyzeSwitchCaptures(
.@"inline" => unreachable, // handled above
.has_ranges => unreachable, // not possible for error set
.special => {
- if (else_err_ty) |err_ty| {
- break :payload_ref try sema.bitCast(case_block, err_ty, loaded_operand, operand_src, null);
- } else {
+ const capture_err_ty = else_err_ty orelse {
try sema.analyzeUnreachable(case_block, operand_src, false);
break :payload_ref .unreachable_value;
+ };
+ if (sema.resolveValue(loaded_operand)) |err_val| {
+ break :payload_ref .fromIntern(try pt.intern(.{ .err = .{
+ .ty = capture_err_ty.toIntern(),
+ .name = zcu.intern_pool.indexToKey(err_val.toIntern()).err.name,
+ } }));
+ } else {
+ break :payload_ref try case_block.addTyOp(.error_cast, capture_err_ty, loaded_operand);
}
},
.item_refs => |item_refs| {
@@ -11969,8 +11954,15 @@ fn analyzeSwitchCaptures(
const item_val = sema.resolveValue(item_ref).?;
names.putAssumeCapacityNoClobber(item_val.getErrorName(zcu).unwrap().?, {});
}
- const narrowed_ty = try pt.errorSetFromUnsortedNames(names.keys());
- break :payload_ref try sema.bitCast(case_block, narrowed_ty, loaded_operand, operand_src, null);
+ const capture_err_ty = try pt.errorSetFromUnsortedNames(names.keys());
+ if (sema.resolveValue(loaded_operand)) |err_val| {
+ break :payload_ref .fromIntern(try pt.intern(.{ .err = .{
+ .ty = capture_err_ty.toIntern(),
+ .name = zcu.intern_pool.indexToKey(err_val.toIntern()).err.name,
+ } }));
+ } else {
+ break :payload_ref try case_block.addTyOp(.error_cast, capture_err_ty, loaded_operand);
+ }
},
}
}
@@ -12020,15 +12012,12 @@ fn resolveSwitchPayloadCaptureTaggedUnion(
const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
const payload_ref: Air.Inst.Ref = payload_ref: {
if (capture_by_ref) {
- const operand_ptr_info = sema.typeOf(loaded_operand).ptrInfo(zcu);
- const ptr_field_ty = try pt.ptrType(.{
- .child = field_ty.toIntern(),
- .flags = .{
- .is_const = operand_ptr_info.flags.is_const,
- .is_volatile = operand_ptr_info.flags.is_volatile,
- .address_space = operand_ptr_info.flags.address_space,
- },
- });
+ const ptr_field_ty = try sema.typeOf(loaded_operand).fieldPtrType(field_index, pt);
+ if (try sema.resolveDefinedValue(case_block, operand_src, loaded_operand)) |op_ptr_val| {
+ if (op_ptr_val.isUndef(zcu)) break :payload_ref try pt.undefRef(ptr_field_ty);
+ const field_ptr_val = try op_ptr_val.ptrField(field_index, pt);
+ break :payload_ref .fromValue(try pt.getCoerced(field_ptr_val, ptr_field_ty));
+ }
break :payload_ref try case_block.addStructFieldPtr(loaded_operand, field_index, ptr_field_ty);
}
if (try sema.resolveDefinedValue(case_block, operand_src, loaded_operand)) |union_val| {
@@ -12083,7 +12072,7 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
// PTR! This will also allow us to emit simpler code.
const same_types = for (field_indices[1..]) |field_idx| {
const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]);
- if (!field_ty.eql(first_field_ty, zcu)) break false;
+ if (!field_ty.eql(first_field_ty)) break false;
} else true;
const capture_ty: Type = capture_ty: {
@@ -12188,40 +12177,9 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
return case_block.addStructFieldVal(loaded_operand, first_field_index, capture_ty);
}
- // We may have to emit a switch block which coerces the operand to the capture type.
- // If we can, try to avoid that using in-memory coercions.
- const first_non_imc = in_mem: {
- for (field_indices, 0..) |field_idx, i| {
- const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]);
- if (.ok != try sema.coerceInMemoryAllowed(case_block, capture_ty, field_ty, false, zcu.getTarget(), .unneeded, .unneeded, null)) {
- break :in_mem i;
- }
- }
- // All fields are in-memory coercible to the resolved type!
- // Just take the first field and bitcast the result.
- const uncoerced = try case_block.addStructFieldVal(loaded_operand, first_field_index, first_field_ty);
- return case_block.addBitCast(capture_ty, uncoerced);
- };
-
// By-val capture with heterogeneous types which are not all in-memory coercible to
// the resolved capture type. We finally have to fall back to the ugly method.
- // However, let's first track which operands are in-memory coercible. There may well
- // be several, and we can squash all of these cases into the same switch prong using
- // a simple bitcast. We'll make this the 'else' prong.
-
- var in_mem_coercible: std.bit_set.Dynamic = try .initFull(sema.arena, field_indices.len);
- in_mem_coercible.unset(first_non_imc);
- {
- const next = first_non_imc + 1;
- for (field_indices[next..], next..) |field_idx, i| {
- const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]);
- if (.ok != try sema.coerceInMemoryAllowed(case_block, capture_ty, field_ty, false, zcu.getTarget(), .unneeded, .unneeded, null)) {
- in_mem_coercible.unset(i);
- }
- }
- }
-
const capture_block_inst = try case_block.addInstAsIndex(.{
.tag = .block,
.data = .{
@@ -12232,23 +12190,19 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
},
});
- const prong_count = field_indices.len - in_mem_coercible.count();
-
- const estimated_extra = prong_count * 6 + (prong_count / 10); // 2 for Case, 1 item, probably 3 insts; plus hints
+ const estimated_extra = field_indices.len * 6 + (field_indices.len / 10); // 2 for Case, 1 item, probably 3 insts; plus hints
var cases_extra = try std.ArrayList(u32).initCapacity(gpa, estimated_extra);
defer cases_extra.deinit(gpa);
{
// All branch hints are `.none`, so just add zero elems.
comptime assert(@intFromEnum(std.lang.BranchHint.none) == 0);
- const need_elems = std.math.divCeil(usize, prong_count + 1, 10) catch unreachable;
+ const need_elems = std.math.divCeil(usize, field_indices.len + 1, 10) catch unreachable;
try cases_extra.appendNTimes(gpa, 0, need_elems);
}
{
- // Non-bitcast cases
- var it = in_mem_coercible.iterator(.{ .kind = .unset });
- while (it.next()) |idx| {
+ for (field_indices, item_refs, 0..) |field_index, item, item_index| {
var coerce_block = case_block.makeSubBlock();
defer coerce_block.instructions.deinit(sema.gpa);
@@ -12257,13 +12211,12 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
.offset = .{ .switch_case_item = .{
.switch_node_offset = switch_node_offset,
.case_idx = capture_src.offset.switch_capture.case_idx,
- .item_idx = .{ .kind = .single, .value = @intCast(idx) },
+ .item_idx = .{ .kind = .single, .value = @intCast(item_index) },
} },
};
- const field_idx = field_indices[idx];
- const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]);
- const uncoerced = try coerce_block.addStructFieldVal(loaded_operand, field_idx, field_ty);
+ const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
+ const uncoerced = try coerce_block.addStructFieldVal(loaded_operand, field_index, field_ty);
const coerced = try sema.coerce(&coerce_block, capture_ty, uncoerced, case_src);
_ = try coerce_block.addBr(capture_block_inst, coerced);
@@ -12275,24 +12228,16 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
.ranges_len = 0,
.body_len = @intCast(coerce_block.instructions.items.len),
}));
- cases_extra.appendAssumeCapacity(@intFromEnum(item_refs[idx])); // item
+ cases_extra.appendAssumeCapacity(@intFromEnum(item)); // item
cases_extra.appendSliceAssumeCapacity(@ptrCast(coerce_block.instructions.items)); // body
}
}
const else_body_len = len: {
- // 'else' prong uses a bitcast
- var coerce_block = case_block.makeSubBlock();
- defer coerce_block.instructions.deinit(sema.gpa);
-
- const first_imc_item_idx = in_mem_coercible.findFirstSet().?;
- const first_imc_field_idx = field_indices[first_imc_item_idx];
- const first_imc_field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[first_imc_field_idx]);
- const uncoerced = try coerce_block.addStructFieldVal(loaded_operand, first_imc_field_idx, first_imc_field_ty);
- const coerced = try coerce_block.addBitCast(capture_ty, uncoerced);
- _ = try coerce_block.addBr(capture_block_inst, coerced);
-
- try cases_extra.appendSlice(gpa, @ptrCast(coerce_block.instructions.items));
- break :len coerce_block.instructions.items.len;
+ // 'else' prong is unreachable
+ const result_index: Air.Inst.Index = @enumFromInt(sema.air_instructions.len);
+ try sema.air_instructions.append(gpa, .{ .tag = .unreach, .data = .{ .no_op = {} } });
+ try cases_extra.append(gpa, @intFromEnum(result_index));
+ break :len 1;
};
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr).@"struct".field_names.len +
@@ -12307,7 +12252,7 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
.pl_op = .{
.operand = undefined, // set by switch below
.payload = sema.addExtraAssumeCapacity(Air.SwitchBr{
- .cases_len = @intCast(prong_count),
+ .cases_len = @intCast(field_indices.len),
.else_body_len = @intCast(else_body_len),
}),
},
@@ -12417,7 +12362,7 @@ fn resolveSwitchItem(
// being switched on if their prong body is `=> comptime unreachable,`.
switch (try sema.coerceInMemoryAllowedErrorSets(block, item_ty, uncoerced_ty, item_src, item_src)) {
.ok => if (sema.resolveValue(uncoerced)) |uncoerced_val| {
- break :item_ref try sema.coerceInMemory(uncoerced_val, item_ty);
+ break :item_ref .fromValue(try pt.getCoerced(uncoerced_val, item_ty));
},
.missing_error => if (prong_is_comptime_unreach) {
break :item_ref uncoerced;
@@ -13323,8 +13268,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
defer trash_block.instructions.deinit(sema.gpa);
const instructions = [_]Air.Inst.Ref{
- try trash_block.addBitCast(lhs_info.elem_type, .void_value),
- try trash_block.addBitCast(rhs_info.elem_type, .void_value),
+ try trash_block.addTyOp(.bit_cast, lhs_info.elem_type, .void_value),
+ try trash_block.addTyOp(.bit_cast, rhs_info.elem_type, .void_value),
};
break :t try sema.resolvePeerTypes(block, src, &instructions, .{
.override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
@@ -13416,7 +13361,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
while (elem_i < lhs_len) : (elem_i += 1) {
const lhs_elem_i = elem_i;
const elem_default_val: ?Value = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, zcu) else null;
- const elem_val = elem_default_val orelse try lhs_sub_val.elemValue(pt, lhs_elem_i);
+ const elem_val = elem_default_val orelse
+ if (lhs_sub_val.isUndef(zcu)) try pt.undefValue(resolved_elem_ty) else try lhs_sub_val.elemValue(pt, lhs_elem_i);
const operand_src = block.src(.{ .array_cat_lhs = .{
.array_cat_offset = inst_data.src_node,
.elem_index = elem_i,
@@ -13428,7 +13374,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
while (elem_i < result_len) : (elem_i += 1) {
const rhs_elem_i = elem_i - lhs_len;
const elem_default_val: ?Value = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, zcu) else null;
- const elem_val = elem_default_val orelse try rhs_sub_val.elemValue(pt, rhs_elem_i);
+ const elem_val = elem_default_val orelse
+ if (rhs_sub_val.isUndef(zcu)) try pt.undefValue(resolved_elem_ty) else try rhs_sub_val.elemValue(pt, rhs_elem_i);
const operand_src = block.src(.{ .array_cat_rhs = .{
.array_cat_offset = inst_data.src_node,
.elem_index = @intCast(rhs_elem_i),
@@ -13479,7 +13426,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
});
const many_ty = slice_ty.slicePtrFieldType(zcu);
- const many_alloc = try block.addBitCast(many_ty, mutable_alloc);
+ const many_alloc = try block.addTyOp(.ptr_cast, many_ty, mutable_alloc);
// lhs_dest_slice = dest[0..lhs.len]
if (lhs_len > 0) {
@@ -13528,7 +13475,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store);
}
- return block.addBitCast(constant_alloc_ty, mutable_alloc);
+ return block.addTyOp(.ptr_cast, constant_alloc_ty, mutable_alloc);
}
var elem_i: u32 = 0;
@@ -13561,7 +13508,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store);
}
- return block.addBitCast(constant_alloc_ty, mutable_alloc);
+ return block.addTyOp(.ptr_cast, constant_alloc_ty, mutable_alloc);
}
const element_refs = try sema.arena.alloc(Air.Inst.Ref, result_len);
@@ -14844,8 +14791,8 @@ fn analyzeArithmetic(
try sema.requireRuntimeBlock(block, src, runtime_src);
try sema.checkLogicalPtrOperation(block, src, lhs_ty);
try sema.checkLogicalPtrOperation(block, src, rhs_ty);
- const lhs_int = try block.addBitCast(.usize, lhs);
- const rhs_int = try block.addBitCast(.usize, rhs);
+ const lhs_int = try block.addTyOp(.int_from_ptr, .usize, lhs);
+ const rhs_int = try block.addTyOp(.int_from_ptr, .usize, rhs);
const address = try block.addBinOp(.sub_wrap, lhs_int, rhs_int);
return try block.addBinOp(.div_exact, address, try pt.intRef(.usize, elem_size));
}
@@ -15113,15 +15060,76 @@ fn zirAsm(
break :out_ty sema.typeOf(inst).childType(zcu);
}
};
- if (!out_ty.hasWellDefinedLayout(zcu)) {
- return sema.failWithOwnedErrorMsg(block, msg: {
- const msg = try sema.errMsg(output_src, "invalid inline assembly output type; '{f}' does not have a guaranteed in-memory layout", .{
- out_ty.fmt(pt),
- });
+ switch (out_ty.zigTypeTag(zcu)) {
+ .int, .float, .bool, .vector => {},
+
+ .pointer => if (out_ty.isSlice(zcu)) return sema.failWithOwnedErrorMsg(block, msg: {
+ const msg = try sema.errMsg(output_src, "invalid inline assembly output type '{f}'", .{out_ty.fmt(pt)});
errdefer msg.destroy(gpa);
- try sema.addDeclaredHereNote(msg, out_ty);
+ try sema.errNote(output_src, msg, "consider separate outputs for 'ptr' and 'len'", .{});
break :msg msg;
- });
+ }),
+
+ .optional => if (!out_ty.isPtrLikeOptional(zcu)) {
+ return sema.fail(block, output_src, "invalid inline assembly output type '{f}'", .{out_ty.fmt(pt)});
+ },
+
+ .@"enum" => switch (ip.loadEnumType(out_ty.toIntern()).int_tag_mode) {
+ .explicit => {},
+ .auto => return sema.failWithOwnedErrorMsg(block, msg: {
+ const msg = try sema.errMsg(output_src, "invalid inline assembly output type '{f}'", .{out_ty.fmt(pt)});
+ errdefer msg.destroy(gpa);
+ try sema.errNote(out_ty.srcLoc(zcu), msg, "integer tag type of enum is inferred", .{});
+ try sema.errNote(out_ty.srcLoc(zcu), msg, "consider explicitly specifying the integer tag type", .{});
+ break :msg msg;
+ }),
+ },
+
+ .@"struct" => switch (out_ty.containerLayout(zcu)) {
+ .@"packed" => {},
+ .auto, .@"extern" => return sema.failWithOwnedErrorMsg(block, msg: {
+ const msg = try sema.errMsg(output_src, "invalid inline assembly output type '{f}'", .{out_ty.fmt(pt)});
+ errdefer msg.destroy(gpa);
+ try sema.errNote(output_src, msg, "struct types cannot be passed to inline assembly", .{});
+ try sema.addDeclaredHereNote(msg, out_ty);
+ break :msg msg;
+ }),
+ },
+
+ .@"union" => switch (out_ty.containerLayout(zcu)) {
+ .@"packed" => {},
+ .auto, .@"extern" => return sema.failWithOwnedErrorMsg(block, msg: {
+ const msg = try sema.errMsg(output_src, "invalid inline assembly output type '{f}'", .{out_ty.fmt(pt)});
+ errdefer msg.destroy(gpa);
+ try sema.errNote(output_src, msg, "union types cannot be passed to inline assembly", .{});
+ try sema.addDeclaredHereNote(msg, out_ty);
+ break :msg msg;
+ }),
+ },
+
+ .array => return sema.failWithOwnedErrorMsg(block, msg: {
+ const msg = try sema.errMsg(output_src, "invalid inline assembly output type '{f}'", .{out_ty.fmt(pt)});
+ errdefer msg.destroy(gpa);
+ try sema.errNote(output_src, msg, "array types cannot be passed to inline assembly", .{});
+ break :msg msg;
+ }),
+
+ .void,
+ .type,
+ .noreturn,
+ .comptime_float,
+ .comptime_int,
+ .undefined,
+ .null,
+ .error_union,
+ .error_set,
+ .@"fn",
+ .@"opaque",
+ .frame,
+ .@"anyframe",
+ .enum_literal,
+ .spirv,
+ => return sema.fail(block, output_src, "invalid inline assembly output type '{f}'", .{out_ty.fmt(pt)}),
}
const constraint = sema.code.nullTerminatedString(output.data.constraint);
@@ -15292,7 +15300,7 @@ fn zirCmpEq(
if (lhs_ty_tag == .type and rhs_ty_tag == .type) {
const lhs_as_type = try sema.analyzeAsType(block, lhs_src, .type, lhs);
const rhs_as_type = try sema.analyzeAsType(block, rhs_src, .type, rhs);
- return if (lhs_as_type.eql(rhs_as_type, zcu) == (op == .eq)) .bool_true else .bool_false;
+ return if (lhs_as_type.eql(rhs_as_type) == (op == .eq)) .bool_true else .bool_false;
}
return sema.analyzeCmp(block, src, lhs, rhs, op, lhs_src, rhs_src, true);
}
@@ -15525,36 +15533,13 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0);
const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand);
- switch (operand_ty.zigTypeTag(zcu)) {
- .@"fn",
- .noreturn,
- .undefined,
- .null,
- .@"opaque",
- .type,
- .enum_literal,
- .comptime_float,
- .comptime_int,
- => return sema.fail(block, operand_src, "no size available for type '{f}'", .{operand_ty.fmt(pt)}),
-
- .void,
- => return .zero,
-
- .bool,
- .int,
- .float,
- .pointer,
- .array,
- .@"struct",
- .optional,
- .error_union,
- .error_set,
- .@"enum",
- .@"union",
- .vector,
- .frame,
- .@"anyframe",
- => {},
+ if (!operand_ty.hasBitRepresentation(zcu) and
+ // TODO: allow these types too for now because this is used in some places. We need to
+ // figure out whether we think errors and auto-enums have bit representations!
+ operand_ty.zigTypeTag(zcu) != .error_set and
+ operand_ty.zigTypeTag(zcu) != .@"enum")
+ {
+ return sema.fail(block, operand_src, "no bit size available for type '{f}'", .{operand_ty.fmt(pt)});
}
try sema.ensureLayoutResolved(operand_ty, operand_src, .size_of);
return .fromValue(try pt.intValue(.comptime_int, operand_ty.bitSize(zcu)));
@@ -16834,6 +16819,43 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.val = (try pt.aggregateValue(type_opaque_ty, &field_values)).toIntern(),
})));
},
+ .spirv => {
+ const spirv_info = ip.loadSpirvType(ty.toIntern());
+ const spirv_union_ty = try sema.getStdLangType(src, .@"Type.Spirv");
+ const spirv_tag_ty = spirv_union_ty.unionTagType(zcu).?;
+ const spirv_tag_val = try pt.enumValueFieldIndex(spirv_tag_ty, @intFromEnum(spirv_info.flags.tag));
+ const spirv_payload_val: Value = switch (spirv_info.flags.tag) {
+ .sampler => .void,
+ .sampled_image, .runtime_array => .fromInterned(spirv_info.ty),
+ .image => image: {
+ const image_ty = try sema.getStdLangType(src, .@"Type.Spirv.Image");
+ const usage_union_ty = try sema.getStdLangType(src, .@"Type.Spirv.Image.Usage");
+ const format_ty = try sema.getStdLangType(src, .@"Type.Spirv.Image.Format");
+ const dim_ty = try sema.getStdLangType(src, .@"Type.Spirv.Image.Dimensionality");
+ const depth_ty = try sema.getStdLangType(src, .@"Type.Spirv.Image.Depth");
+ const access_ty = try sema.getStdLangType(src, .@"Type.Spirv.Image.Access");
+ const usage_tag_ty = usage_union_ty.unionTagType(zcu).?;
+ const usage_tag_val = try pt.enumValueFieldIndex(usage_tag_ty, @intFromEnum(spirv_info.flags.usage));
+ const usage_val = try pt.unionValue(usage_union_ty, usage_tag_val, .fromInterned(spirv_info.ty));
+ const image_field_vals = [_]InternPool.Index{
+ usage_val.toIntern(),
+ (try pt.enumValueFieldIndex(format_ty, @intFromEnum(spirv_info.flags.format))).toIntern(),
+ (try pt.enumValueFieldIndex(dim_ty, @intFromEnum(spirv_info.flags.dim))).toIntern(),
+ (try pt.enumValueFieldIndex(depth_ty, @intFromEnum(spirv_info.flags.depth))).toIntern(),
+ (try pt.enumValueFieldIndex(access_ty, @intFromEnum(spirv_info.flags.access))).toIntern(),
+ Value.makeBool(spirv_info.flags.is_arrayed).toIntern(),
+ Value.makeBool(spirv_info.flags.is_multisampled).toIntern(),
+ };
+ break :image try pt.aggregateValue(image_ty, &image_field_vals);
+ },
+ };
+ const spirv_val = try pt.unionValue(spirv_union_ty, spirv_tag_val, spirv_payload_val);
+ return Air.internedToRef((try pt.internUnion(.{
+ .ty = type_info_ty.toIntern(),
+ .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.lang.TypeId.spirv))).toIntern(),
+ .val = spirv_val.toIntern(),
+ })));
+ },
.frame => return sema.failWithUseOfAsync(block, src),
.@"anyframe" => return sema.failWithUseOfAsync(block, src),
}
@@ -17523,15 +17545,10 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
const is_cold = sema.branch_hint == .cold;
const operand_ty = sema.typeOf(operand);
- const ptr_info = operand_ty.ptrInfo(zcu);
- const res_ty = try pt.ptrType(.{
- .child = err_union_ty.errorUnionPayload(zcu).toIntern(),
- .flags = .{
- .is_const = ptr_info.flags.is_const,
- .is_volatile = ptr_info.flags.is_volatile,
- .is_allowzero = ptr_info.flags.is_allowzero,
- .address_space = ptr_info.flags.address_space,
- },
+ const res_ty = try pt.ptrType(info: {
+ var new = operand_ty.ptrInfo(zcu);
+ new.child = err_union_ty.errorUnionPayload(zcu).toIntern();
+ break :info new;
});
const res_ty_ref = Air.internedToRef(res_ty.toIntern());
try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.TryPtr).@"struct".field_names.len +
@@ -18004,6 +18021,12 @@ fn analyzeRet(
try inlining.merges.results.append(sema.gpa, operand);
try inlining.merges.br_list.append(sema.gpa, br_inst.toIndex().?);
try inlining.merges.src_locs.append(sema.gpa, operand_src);
+ var body_block = block;
+ while (body_block.parent) |parent| body_block = parent;
+ if (body_block.runtime_cond == null and body_block.runtime_loop == null) {
+ body_block.runtime_cond = block.runtime_cond orelse block.runtime_loop;
+ body_block.runtime_loop = block.runtime_loop;
+ }
} else {
try sema.validateRuntimeValue(block, operand_src, operand);
const ret_tag: Air.Inst.Tag = if (block.wantSafety()) .ret_safe else .ret;
@@ -18098,13 +18121,19 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
} else 0;
if (host_size != 0) {
+ try sema.ensureLayoutResolved(elem_ty, elem_ty_src, .bit_ptr_child);
+ if (elem_ty.unpackable(zcu)) |reason| return sema.failWithOwnedErrorMsg(block, msg: {
+ const msg = try sema.errMsg(elem_ty_src, "bit-pointer cannot refer to value of type '{f}'", .{elem_ty.fmt(pt)});
+ errdefer msg.destroy(sema.gpa);
+ try sema.explainWhyTypeIsUnpackable(msg, elem_ty_src, reason);
+ break :msg msg;
+ });
+ const elem_bit_size = elem_ty.bitSize(zcu);
if (bit_offset >= host_size * 8) {
return sema.fail(block, bitoffset_src, "packed type '{f}' at bit offset {d} starts {d} bits after the end of a {d} byte host integer", .{
elem_ty.fmt(pt), bit_offset, bit_offset - host_size * 8, host_size,
});
}
- try sema.ensureLayoutResolved(elem_ty, elem_ty_src, .bit_ptr_child);
- const elem_bit_size = elem_ty.bitSize(zcu);
if (elem_bit_size > host_size * 8 - bit_offset) {
return sema.fail(block, bitoffset_src, "packed type '{f}' at bit offset {d} ends {d} bits after the end of a {d} byte host integer", .{
elem_ty.fmt(pt), bit_offset, elem_bit_size - (host_size * 8 - bit_offset), host_size,
@@ -18120,15 +18149,6 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
return sema.fail(block, elem_ty_src, "indexable pointer to opaque type '{f}' not allowed", .{elem_ty.fmt(pt)});
}
- if (host_size != 0) {
- if (elem_ty.unpackable(zcu)) |reason| return sema.failWithOwnedErrorMsg(block, msg: {
- const msg = try sema.errMsg(elem_ty_src, "bit-pointer cannot refer to value of type '{f}'", .{elem_ty.fmt(pt)});
- errdefer msg.destroy(sema.gpa);
- try sema.explainWhyTypeIsUnpackable(msg, elem_ty_src, reason);
- break :msg msg;
- });
- }
-
const ty = try pt.ptrType(.{
.child = elem_ty.toIntern(),
.sentinel = sentinel,
@@ -18298,7 +18318,7 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
const payload = try sema.coerce(block, field_ty, sema.resolveInst(extra.init), payload_src);
if (union_ty.containerLayout(zcu) == .@"packed") {
- return sema.bitCast(block, union_ty, payload, block.nodeOffset(inst_data.src_node), payload_src);
+ return sema.bitCast(block, union_ty, payload, block.nodeOffset(inst_data.src_node));
}
if (sema.resolveValue(payload)) |payload_val| {
@@ -18435,7 +18455,7 @@ fn zirStructInit(
const init_inst = try sema.coerce(block, field_ty, uncoerced_init_inst, field_src);
if (resolved_ty.containerLayout(zcu) == .@"packed") {
- const union_val = try sema.bitCast(block, resolved_ty, init_inst, src, field_src);
+ const union_val = try sema.bitCast(block, resolved_ty, init_inst, src);
const result_val = try sema.coerce(block, result_ty, union_val, src);
if (is_ref) {
return sema.analyzeRef(block, src, result_val, .none);
@@ -18599,20 +18619,15 @@ fn finishStructInit(
},
.@"packed" => {
const buf = try sema.arena.alloc(u8, @intCast((struct_ty.bitSize(zcu) + 7) / 8));
+ @memset(buf, 0);
var bit_offset: u16 = 0;
for (field_inits) |field_init| {
const field_val = sema.resolveValue(field_init).?;
- field_val.writeToPackedMemory(zcu, buf, bit_offset) catch |err| switch (err) {
- error.ReinterpretDeclRef => unreachable, // bitpack fields cannot be pointers
- error.OutOfMemory => |e| return e,
- };
+ field_val.writeToPackedMemory(zcu, buf, bit_offset);
bit_offset += @intCast(field_val.typeOf(zcu).bitSize(zcu));
}
assert(bit_offset == struct_ty.bitSize(zcu));
- const struct_val = Value.readFromPackedMemory(struct_ty, pt, buf, 0, sema.arena) catch |err| switch (err) {
- error.IllDefinedMemoryLayout => unreachable, // bitpacks have well-defined layout
- error.OutOfMemory => |e| return e,
- };
+ const struct_val: Value = try .readFromPackedMemory(struct_ty, pt, buf, 0);
const final_val_ref = try sema.coerce(block, result_ty, .fromValue(struct_val), init_src);
return sema.addConstantMaybeRef(sema.resolveValue(final_val_ref).?, is_ref);
},
@@ -18748,6 +18763,18 @@ fn structInitAnon(
break :rs runtime_index;
};
+ // A field can't be `comptime` if it references a `comptime var` but the aggregate can still be comptime-known.
+ // Replace these fields with `.none` only for generating the type.
+ const values_no_comptime = if (!any_values) values else blk: {
+ const new_values = try sema.arena.alloc(InternPool.Index, types.len);
+ for (values, new_values) |val, *new_val| {
+ if (val != .none and Value.fromInterned(val).canMutateComptimeVarState(zcu)) {
+ new_val.* = .none;
+ } else new_val.* = val;
+ }
+ break :blk new_values;
+ };
+
// We treat anonymous struct types as reified types, because there are similarities: they have
// no captures, and instead use a form of structural equivalence which we can easy represent by
// hashing the field names/types/values. They also perform layout resolution immediately. These
@@ -18756,7 +18783,7 @@ fn structInitAnon(
const type_hash: u64 = hash: {
var hasher = std.hash.Wyhash.init(0);
hasher.update(std.mem.sliceAsBytes(types));
- hasher.update(std.mem.sliceAsBytes(values));
+ hasher.update(std.mem.sliceAsBytes(values_no_comptime));
hasher.update(std.mem.sliceAsBytes(names));
break :hash hasher.final();
};
@@ -18780,9 +18807,9 @@ fn structInitAnon(
@memcpy(wip.field_names.get(ip), names);
@memcpy(wip.field_types.get(ip), types);
if (any_values) {
- @memcpy(wip.field_values.get(ip), values);
+ @memcpy(wip.field_values.get(ip), values_no_comptime);
@memset(wip.field_is_comptime_bits.getAll(ip), 0);
- for (values, 0..) |val, field_index| {
+ for (values_no_comptime, 0..) |val, field_index| {
if (val == .none) continue;
const bit_bag_index = field_index / 32;
const mask = @as(u32, 1) << @intCast(field_index % 32);
@@ -18810,6 +18837,15 @@ fn structInitAnon(
return sema.addConstantMaybeRef(struct_val, is_ref);
};
+ for (values, 0..) |field_val, i| {
+ if (field_val == .none) continue; // runtime-known
+ const field_src = block.src(.{ .init_elem = .{
+ .init_node_offset = src.offset.node_offset.x,
+ .elem_index = @intCast(i),
+ } });
+ try sema.validateRuntimeValue(block, field_src, .fromIntern(field_val));
+ }
+
if (is_ref) {
const target = zcu.getTarget();
const alloc_ty = try pt.ptrType(.{
@@ -19066,13 +19102,11 @@ fn arrayInitAnon(
.values = values_no_comptime,
}));
- const runtime_src = opt_runtime_src orelse {
+ _ = opt_runtime_src orelse {
const tuple_val = try pt.aggregateValue(tuple_ty, values);
return sema.addConstantMaybeRef(tuple_val, is_ref);
};
- try sema.requireRuntimeBlock(block, src, runtime_src);
-
for (operands, 0..) |operand, i| {
const operand_src = block.src(.{ .init_elem = .{
.init_node_offset = src.offset.node_offset.x,
@@ -19287,7 +19321,7 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
}
return Air.internedToRef((try pt.aggregateValue(dest_ty, new_elems)).toIntern());
}
- return block.addBitCast(dest_ty, operand);
+ return block.addTyOp(.bit_cast, dest_ty, operand);
}
fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -20449,6 +20483,303 @@ fn zirReifyEnum(
}
}
+fn zirReifySpirvType(
+ sema: *Sema,
+ block: *Block,
+ extended: Zir.Inst.Extended.InstData,
+ inst: Zir.Inst.Index,
+) CompileError!Air.Inst.Ref {
+ const pt = sema.pt;
+ const zcu = pt.zcu;
+ const comp = zcu.comp;
+ const gpa = comp.gpa;
+ const io = comp.io;
+ const ip = &zcu.intern_pool;
+ const target = zcu.getTarget();
+
+ const extra = sema.code.extraData(Zir.Inst.ReifySpirvType, extended.operand).data;
+ const tracked_inst = try block.trackZir(inst);
+ const src: LazySrcLoc = .{
+ .base_node_inst = tracked_inst,
+ .offset = .nodeOffset(.zero),
+ };
+ const operand_src: LazySrcLoc = .{
+ .base_node_inst = tracked_inst,
+ .offset = .{ .node_offset_builtin_call_arg = .{
+ .builtin_call_node = .zero,
+ .arg_index = 0,
+ } },
+ };
+
+ if (!target.cpu.arch.isSpirV()) {
+ return sema.fail(
+ block,
+ src,
+ "builtin @SpirvType is only available when targeting SPIR-V; targeted CPU architecture is {t}",
+ .{target.cpu.arch},
+ );
+ }
+
+ const spirv_type_options_ty = try sema.getStdLangType(operand_src, .@"Type.Spirv");
+ const operand_uncoerced = sema.resolveInst(extra.operand);
+ const operand_coerced = try sema.coerce(block, spirv_type_options_ty, operand_uncoerced, operand_src);
+ const operand_val = try sema.resolveConstDefinedValue(block, operand_src, operand_coerced, .{ .simple = .type });
+ const union_val = ip.indexToKey(operand_val.toIntern()).un;
+
+ if (try sema.anyUndef(block, operand_src, .fromInterned(union_val.val))) {
+ return sema.failWithUseOfUndef(block, operand_src, null);
+ }
+
+ // TODO: use a longer hash!
+ var hasher = std.hash.Wyhash.init(0);
+ std.hash.autoHash(&hasher, union_val.tag);
+
+ const name = try ip.getOrPutStringFmt(
+ gpa,
+ io,
+ pt.tid,
+ "{f}__SpirvType_{d}",
+ .{ block.type_name_ctx.fmt(ip), @intFromEnum(inst) },
+ .no_embedded_nulls,
+ );
+ const tag = try sema.interpretStdLangType(block, src, .fromInterned(union_val.tag), @typeInfo(std.lang.Type.Spirv).@"union".tag_type.?);
+ const ip_data: InternPool.Tag.TypeSpirv = switch (tag) {
+ .sampler => .{
+ .name = name,
+ .zir_index = tracked_inst,
+ .ty = .none,
+ .flags = .{
+ .tag = .sampler,
+ .usage = .unknown,
+ .format = .unknown,
+ .dim = .@"1d",
+ .depth = .unknown,
+ .access = .unknown,
+ .is_arrayed = false,
+ .is_multisampled = false,
+ },
+ },
+ .image => ip_data: {
+ const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
+ const usage_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
+ ip,
+ try ip.getOrPutString(gpa, io, pt.tid, "usage", .no_embedded_nulls),
+ ).?);
+ const format_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
+ ip,
+ try ip.getOrPutString(gpa, io, pt.tid, "format", .no_embedded_nulls),
+ ).?);
+ const dim_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
+ ip,
+ try ip.getOrPutString(gpa, io, pt.tid, "dim", .no_embedded_nulls),
+ ).?);
+ const depth_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
+ ip,
+ try ip.getOrPutString(gpa, io, pt.tid, "depth", .no_embedded_nulls),
+ ).?);
+ const access_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
+ ip,
+ try ip.getOrPutString(gpa, io, pt.tid, "access", .no_embedded_nulls),
+ ).?);
+ const arrayed_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
+ ip,
+ try ip.getOrPutString(gpa, io, pt.tid, "arrayed", .no_embedded_nulls),
+ ).?);
+ const multisampled_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
+ ip,
+ try ip.getOrPutString(gpa, io, pt.tid, "multisampled", .no_embedded_nulls),
+ ).?);
+ const format = try sema.interpretStdLangType(block, operand_src, format_val, std.lang.Type.Spirv.Image.Format);
+ const dim = try sema.interpretStdLangType(block, operand_src, dim_val, std.lang.Type.Spirv.Image.Dimensionality);
+ const depth = try sema.interpretStdLangType(block, operand_src, depth_val, std.lang.Type.Spirv.Image.Depth);
+ const access = try sema.interpretStdLangType(block, operand_src, access_val, std.lang.Type.Spirv.Image.Access);
+
+ switch (target.os.tag) {
+ .opencl => if (access == .unknown) {
+ return sema.fail(block, operand_src, "'access' field must be specified under the 'opencl' os", .{});
+ },
+ else => if (access != .unknown) {
+ return sema.fail(block, operand_src, "access qualifier '.{t}' is only valid under the 'opencl' os", .{access});
+ },
+ }
+
+ const arrayed = try sema.interpretStdLangType(block, operand_src, arrayed_val, bool);
+ const multisampled = try sema.interpretStdLangType(block, operand_src, multisampled_val, bool);
+
+ const usage_tag_val = usage_val.unionTag(zcu).?;
+ const usage_tag = try sema.interpretStdLangType(block, operand_src, usage_tag_val, @typeInfo(std.lang.Type.Spirv.Image.Usage).@"union".tag_type.?);
+
+ switch (target.os.tag) {
+ .vulkan => {
+ if (usage_tag == .unknown) {
+ return sema.fail(
+ block,
+ operand_src,
+ "'usage' must be '.sampled' or '.storage' under the 'vulkan' os (Sampled == 0 is forbidden)",
+ .{},
+ );
+ }
+ },
+ .opencl => {
+ if (usage_tag != .unknown) {
+ return sema.fail(block, operand_src, "'usage' must be '.unknown' under the 'opencl' os", .{});
+ }
+ if (multisampled) {
+ return sema.fail(block, operand_src, "'multisampled' must be 'false' under the 'opencl' os", .{});
+ }
+ if (format != .unknown) {
+ return sema.fail(block, operand_src, "'format' must be '.unknown' under the 'opencl' os", .{});
+ }
+ if (dim == .cube) {
+ return sema.fail(block, operand_src, "'dim' '.cube' is not allowed under the 'opencl' os", .{});
+ }
+ if (arrayed and dim != .@"1d" and dim != .@"2d") {
+ return sema.fail(block, operand_src, "'arrayed' may only be 'true' when 'dim' is '.1d' or '.2d' under the 'opencl' os", .{});
+ }
+ },
+ else => {},
+ }
+
+ std.hash.autoHash(&hasher, usage_tag);
+ std.hash.autoHash(&hasher, format);
+ std.hash.autoHash(&hasher, dim);
+ std.hash.autoHash(&hasher, depth);
+ std.hash.autoHash(&hasher, access);
+ std.hash.autoHash(&hasher, arrayed);
+ std.hash.autoHash(&hasher, multisampled);
+
+ break :ip_data .{
+ .name = name,
+ .zir_index = tracked_inst,
+ .ty = blk: {
+ const sampled_type = usage_val.unionPayload(zcu).toType();
+ std.hash.autoHash(&hasher, sampled_type.toIntern());
+
+ if (target.os.tag != .opencl and sampled_type.toIntern() == .void_type) {
+ return sema.fail(block, operand_src, "'void' type for '{t}' field is only valid under the 'opencl' os", .{usage_tag});
+ }
+ if (target.os.tag == .opencl and sampled_type.toIntern() != .void_type) {
+ return sema.fail(block, operand_src, "'{t}' field type must be 'void' under the 'opencl' os", .{usage_tag});
+ }
+
+ if (sampled_type.toIntern() != .void_type and
+ (!sampled_type.hasRuntimeBits(zcu) or (!sampled_type.isRuntimeFloat() and !sampled_type.isInt(zcu))))
+ {
+ return sema.fail(block, operand_src, "invalid '{t}' field value '{f}'", .{ usage_tag, sampled_type.fmt(pt) });
+ }
+
+ if (target.os.tag == .vulkan) {
+ const ok = (sampled_type.isRuntimeFloat() and sampled_type.bitSize(zcu) == 32) or
+ (sampled_type.isInt(zcu) and (sampled_type.bitSize(zcu) == 32 or sampled_type.bitSize(zcu) == 64));
+ if (!ok) {
+ return sema.fail(
+ block,
+ operand_src,
+ "'{t}' field value must be a 32-bit int, 64-bit int or 32-bit float under the 'vulkan' os",
+ .{usage_tag},
+ );
+ }
+
+ if (format != .unknown) {
+ const format_kind: enum { float, sint, uint } = switch (format) {
+ .rgba32f, .rgba16f, .rgba8unorm, .rgba8snorm, .r32f => .float,
+ .rgba32i, .rgba16i, .rgba8i, .r32i => .sint,
+ .rgba32u, .rgba16u, .rgba8u, .r32u => .uint,
+ .unknown => unreachable,
+ };
+ const matches = switch (format_kind) {
+ .float => sampled_type.isRuntimeFloat(),
+ .sint => sampled_type.isInt(zcu) and sampled_type.intInfo(zcu).signedness == .signed,
+ .uint => sampled_type.isInt(zcu) and sampled_type.intInfo(zcu).signedness == .unsigned,
+ };
+ if (!matches) {
+ return sema.fail(
+ block,
+ operand_src,
+ "image 'format' '.{t}' does not match '{t}' type '{f}' under the 'vulkan' os",
+ .{ format, usage_tag, sampled_type.fmt(pt) },
+ );
+ }
+ }
+ }
+
+ break :blk sampled_type.toIntern();
+ },
+ .flags = .{
+ .tag = .image,
+ .usage = usage_tag,
+ .format = format,
+ .dim = dim,
+ .depth = depth,
+ .access = access,
+ .is_arrayed = arrayed,
+ .is_multisampled = multisampled,
+ },
+ };
+ },
+ .sampled_image => blk: {
+ const image_ty = Value.fromInterned(union_val.val).toType();
+ if (image_ty.zigTypeTag(zcu) != .spirv or ip.loadSpirvType(image_ty.toIntern()).flags.tag != .image) {
+ return sema.fail(block, operand_src, "'sampled_image' element must be an @SpirvType image, found '{f}'", .{image_ty.fmt(pt)});
+ }
+ const image_info = ip.loadSpirvType(image_ty.toIntern()).flags;
+ if (image_info.usage != .sampled) {
+ return sema.fail(block, operand_src, "'sampled_image' element must be an image with 'usage = .sampled'", .{});
+ }
+ std.hash.autoHash(&hasher, union_val.val);
+ break :blk .{
+ .name = name,
+ .zir_index = tracked_inst,
+ .ty = union_val.val,
+ .flags = .{
+ .tag = tag,
+ .usage = .unknown,
+ .format = .unknown,
+ .dim = .@"1d",
+ .depth = .unknown,
+ .access = .unknown,
+ .is_arrayed = false,
+ .is_multisampled = false,
+ },
+ };
+ },
+ .runtime_array => blk: {
+ const elem_ty = Value.fromInterned(union_val.val).toType();
+ if (elem_ty.toIntern() == .void_type) {
+ return sema.fail(block, operand_src, "'runtime_array' element type must not be 'void'", .{});
+ }
+ if (target.os.tag == .vulkan and
+ elem_ty.zigTypeTag(zcu) == .spirv and
+ ip.loadSpirvType(elem_ty.toIntern()).flags.tag == .runtime_array)
+ {
+ return sema.fail(block, operand_src, "'runtime_array' of 'runtime_array' is not allowed under the 'vulkan' os", .{});
+ }
+ std.hash.autoHash(&hasher, union_val.val);
+ break :blk .{
+ .name = name,
+ .zir_index = tracked_inst,
+ .ty = union_val.val,
+ .flags = .{
+ .tag = tag,
+ .usage = .unknown,
+ .format = .unknown,
+ .dim = .@"1d",
+ .depth = .unknown,
+ .access = .unknown,
+ .is_arrayed = false,
+ .is_multisampled = false,
+ },
+ };
+ },
+ };
+
+ return .fromIntern(try ip.getReifiedSpirvType(gpa, io, pt.tid, .{
+ .zir_index = tracked_inst,
+ .type_hash = hasher.final(),
+ .type_spirv = ip_data,
+ }));
+}
+
fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref {
const pt = sema.pt;
const va_list_ty = try sema.getStdLangType(src, .VaList);
@@ -20845,7 +21176,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment);
}
}
- return block.addBitCast(dest_ty, operand_coerced);
+ return block.addTyOp(.ptr_from_int, dest_ty, operand_coerced);
}
fn ptrFromIntVal(
@@ -21044,7 +21375,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
.error_union => try block.addTyOp(.unwrap_errunion_err, operand_err_ty, operand),
else => unreachable,
};
- const err_int_inst = try block.addBitCast(err_int_ty, err_code_inst);
+ const err_int_inst = try block.addTyOp(.int_from_error, err_int_ty, err_code_inst);
if (dest_tag == .error_union) {
const zero_err = try pt.intRef(err_int_ty, 0);
const is_zero = try block.addBinOp(.cmp_eq, err_int_inst, zero_err);
@@ -21064,10 +21395,10 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
}
if (operand_tag == .error_set and dest_tag == .error_union) {
- const err_val = try block.addBitCast(dest_err_ty, operand);
+ const err_val = try block.addTyOp(.error_cast, dest_err_ty, operand);
return block.addTyOp(.wrap_errunion_err, dest_ty, err_val);
} else {
- return block.addBitCast(dest_ty, operand);
+ return block.addTyOp(.error_cast, dest_ty, operand);
}
}
@@ -21615,7 +21946,7 @@ fn ptrCastFull(
// `operand_ptr` converted to an integer, for safety checks.
const operand_ptr_int: Air.Inst.Ref = if (need_null_check or need_align_check) i: {
assert(need_operand_ptr);
- break :i try block.addBitCast(.usize, operand_ptr);
+ break :i try block.addTyOp(.int_from_ptr, .usize, operand_ptr);
} else .none;
if (need_null_check) {
@@ -21642,8 +21973,8 @@ fn ptrCastFull(
if (dest_info.flags.size == .slice) {
if (src_info.flags.size == .slice and !flags.addrspace_cast and !slice_needs_len_change) {
- // Fast path: just bitcast!
- return block.addBitCast(dest_ty, operand);
+ // Fast path: just pointer cast!
+ return block.addTyOp(.ptr_cast, dest_ty, operand);
}
// We need to deconstruct the slice (if applicable) and reconstruct it.
@@ -21701,7 +22032,7 @@ fn ptrCastFull(
else => unreachable,
};
const coerced_ptr = if (operand_ptr_ty.toIntern() != want_ptr_ty.toIntern()) ptr: {
- break :ptr try block.addBitCast(want_ptr_ty, operand_ptr);
+ break :ptr try block.addTyOp(.ptr_cast, want_ptr_ty, operand_ptr);
} else operand_ptr;
return block.addInst(.{
@@ -21716,12 +22047,11 @@ fn ptrCastFull(
});
} else {
assert(need_operand_ptr);
- // We just need to bitcast the pointer, if necessary.
- // It might not be necessary, since we might have just needed the `addrspace_cast`.
+ // We just need a ptr_cast, if even that (we might only have needed the `addrspace_cast`).
const result = if (sema.typeOf(operand_ptr).toIntern() == dest_ty.toIntern())
operand_ptr
else
- try block.addBitCast(dest_ty, operand_ptr);
+ try block.addTyOp(.ptr_cast, dest_ty, operand_ptr);
try sema.checkKnownAllocPtr(block, operand, result);
return result;
@@ -21757,7 +22087,7 @@ fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
}
try sema.requireRuntimeBlock(block, src, null);
- const new_ptr = try block.addBitCast(dest_ty, operand);
+ const new_ptr = try block.addTyOp(.ptr_cast, dest_ty, operand);
try sema.checkKnownAllocPtr(block, operand, new_ptr);
return new_ptr;
}
@@ -23859,7 +24189,7 @@ fn analyzeMinMax(
// where we have refined the range, so we should be doing an intcast.
assert(intermediate_scalar_ty.zigTypeTag(zcu) == .int);
assert(result_scalar_ty.zigTypeTag(zcu) == .int);
- return block.addTyOp(.intcast, result_ty, cur_result);
+ return block.addTyOp(.int_cast, result_ty, cur_result);
}
fn upgradeToArrayPtr(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, len: u64) !Air.Inst.Ref {
@@ -23889,7 +24219,7 @@ fn upgradeToArrayPtr(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, len: u64) !A
try block.addTyOp(.slice_ptr, ptr_ty.slicePtrFieldType(zcu), ptr)
else
ptr;
- return block.addBitCast(new_ty, non_slice_ptr);
+ return block.addTyOp(.ptr_cast, new_ty, non_slice_ptr);
}
fn zirMemcpy(
@@ -24635,6 +24965,13 @@ fn zirBuiltinExtern(
.pcrel => if (options.visibility == .default) return sema.fail(block, options_src, "cannot require a pc-relative relocation to a symbol with default visibility", .{}),
}
+ if (options.decoration) |decoration| switch (decoration) {
+ .flat => if (ptr_info.flags.address_space != .input) {
+ return sema.fail(block, options_src, "'flat' decoration requires 'input' address space", .{});
+ },
+ .location, .descriptor => {},
+ };
+
// TODO: error for threadlocal functions, non-const functions, etc
const extern_val = try pt.getExtern(.{
@@ -24680,7 +25017,7 @@ fn zirBuiltinExtern(
const casted_ptr_val = try pt.getCoerced(uncasted_ptr_val, result_ptr_ty);
return Air.internedToRef(casted_ptr_val.toIntern());
} else {
- return block.addBitCast(result_ptr_ty, uncasted_ptr);
+ return block.addTyOp(.ptr_cast, result_ptr_ty, uncasted_ptr);
}
}
@@ -24760,6 +25097,7 @@ fn zirStdLangValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
.fn_attributes, => .@"Type.Fn.Attributes",
.container_layout => .@"Type.ContainerLayout",
.enum_mode => .@"Type.Enum.Mode",
+ .spirv_type_options => .@"Type.Spirv",
// zig fmt: on
// Values are handled here.
@@ -24957,6 +25295,7 @@ fn explainWhyTypeIsComptime(
.void,
.@"enum",
.@"opaque",
+ .spirv,
.pointer,
=> unreachable, // not comptime-only
@@ -25043,6 +25382,7 @@ pub fn explainWhyTypeIsNotExtern(
.noreturn => try sema.errNote(src_loc, msg, "'noreturn' is only allowed as a return type", .{}),
.@"opaque",
+ .spirv,
.bool,
.float,
.@"anyframe",
@@ -25123,7 +25463,7 @@ pub fn explainWhyTypeIsNotExtern(
.param_ty => try sema.errNote(src_loc, msg, "arrays are not allowed as a parameter type", .{}),
else => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.childType(zcu), .element),
},
- .vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.childType(zcu), .element),
+ .vector => try sema.errNote(src_loc, msg, "vectors have no guaranteed in-memory representation", .{}),
.optional => try sema.errNote(src_loc, msg, "non-pointer optionals have no guaranteed in-memory representation", .{}),
}
}
@@ -25391,7 +25731,7 @@ fn addSafetyCheckSentinelMismatch(
.address_space = ptr_info.flags.address_space,
},
});
- const many_ptr = try parent_block.addBitCast(many_ptr_ty, ptr);
+ const many_ptr = try parent_block.addTyOp(.ptr_cast, many_ptr_ty, ptr);
break :s try parent_block.addBinOp(.ptr_elem_val, many_ptr, sentinel_index);
},
.many => unreachable,
@@ -25458,17 +25798,21 @@ fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.Simple
fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
sema.branch_count += 1;
if (sema.branch_count > sema.branch_quota) {
- const msg = try sema.errMsg(
- src,
- "evaluation exceeded {d} backwards branches",
- .{sema.branch_quota},
- );
- try sema.errNote(
- src,
- msg,
- "use @setEvalBranchQuota() to raise the branch limit from {d}",
- .{sema.branch_quota},
- );
+ const msg = msg: {
+ const msg = try sema.errMsg(
+ src,
+ "evaluation exceeded {d} backwards branches",
+ .{sema.branch_quota},
+ );
+ errdefer msg.destroy(sema.gpa);
+ try sema.errNote(
+ src,
+ msg,
+ "use @setEvalBranchQuota() to raise the branch limit from {d}",
+ .{sema.branch_quota},
+ );
+ break :msg msg;
+ };
return sema.failWithOwnedErrorMsg(block, msg);
}
}
@@ -25483,9 +25827,13 @@ fn fieldPtrLoad(
) CompileError!Air.Inst.Ref {
const pt = sema.pt;
const zcu = pt.zcu;
+ const ip = &zcu.intern_pool;
const object_ptr_ty = sema.typeOf(object_ptr);
assert(object_ptr_ty.zigTypeTag(zcu) == .pointer);
const pointee_ty = object_ptr_ty.childType(zcu);
+ if (pointee_ty.isSpirvRuntimeArray(zcu) and field_name.eqlSlice("len", ip)) {
+ return sema.analyzeSpirvRuntimeArrayLen(block, src, object_ptr, field_name_src);
+ }
try sema.ensureLayoutResolved(pointee_ty, src, .ptr_access);
if (try pointee_ty.onePossibleValue(pt)) |opv| {
const object: Air.Inst.Ref = .fromValue(opv);
@@ -25675,11 +26023,123 @@ fn fieldVal(
} else {
return sema.unionFieldVal(block, src, object, field_name, field_name_src, inner_ty);
},
+ .spirv => if (inner_ty.isSpirvRuntimeArray(zcu) and field_name.eqlSlice("len", ip)) {
+ if (!is_pointer_to) {
+ return sema.fail(
+ block,
+ src,
+ "accessing 'len' field on a SPIR-V runtime_array requires a pointer to the array field",
+ .{},
+ );
+ }
+ return sema.analyzeSpirvRuntimeArrayLen(block, src, object, field_name_src);
+ },
else => {},
}
return sema.failWithInvalidFieldAccess(block, src, object_ty, field_name);
}
+fn analyzeSpirvRuntimeArrayLen(
+ sema: *Sema,
+ block: *Block,
+ src: LazySrcLoc,
+ runtime_array_ptr: Air.Inst.Ref,
+ src_for_err: LazySrcLoc,
+) CompileError!Air.Inst.Ref {
+ const pt = sema.pt;
+ const zcu = pt.zcu;
+ const ip = &zcu.intern_pool;
+
+ const struct_operand: Air.Inst.Ref, const field_index: u32 = sf: {
+ if (runtime_array_ptr.toIndex()) |inst| {
+ const tag = sema.air_instructions.items(.tag)[@intFromEnum(inst)];
+ const data = sema.air_instructions.items(.data)[@intFromEnum(inst)];
+ switch (tag) {
+ .struct_field_ptr => {
+ const extra = sema.getTmpAir().extraData(Air.StructField, data.ty_pl.payload).data;
+ break :sf .{ extra.struct_operand, extra.field_index };
+ },
+ .struct_field_ptr_index_0 => break :sf .{ data.ty_op.operand, 0 },
+ .struct_field_ptr_index_1 => break :sf .{ data.ty_op.operand, 1 },
+ .struct_field_ptr_index_2 => break :sf .{ data.ty_op.operand, 2 },
+ .struct_field_ptr_index_3 => break :sf .{ data.ty_op.operand, 3 },
+ else => {},
+ }
+ }
+
+ const ptr_val = sema.resolveValue(runtime_array_ptr) orelse return sema.fail(
+ block,
+ src_for_err,
+ "'len' field on a SPIR-V runtime_array requires direct struct field access",
+ .{},
+ );
+ const ptr_key = ip.indexToKey(ptr_val.toIntern()).ptr;
+ if (ptr_key.base_addr == .field and ptr_key.byte_offset == 0) {
+ const field = ptr_key.base_addr.field;
+ break :sf .{ .fromIntern(field.base), @intCast(field.index) };
+ }
+
+ const parent_ty: Type = switch (ptr_key.base_addr) {
+ .nav => |nav| .fromInterned(ip.getNav(nav).resolved.?.type),
+ .uav => |uav| .fromInterned(ip.typeOf(uav.val)),
+ .comptime_alloc,
+ .comptime_field,
+ .eu_payload,
+ .opt_payload,
+ .arr_elem,
+ .field,
+ .int,
+ => return sema.fail(
+ block,
+ src_for_err,
+ "'len' field on a SPIR-V runtime_array requires direct struct field access",
+ .{},
+ ),
+ };
+ if (parent_ty.zigTypeTag(zcu) != .@"struct") return sema.fail(
+ block,
+ src_for_err,
+ "'len' field on a SPIR-V runtime_array requires the array to be a struct field",
+ .{},
+ );
+
+ const field_ptr_info = ip.indexToKey(ptr_key.ty).ptr_type;
+ const rtarr_ty_ip = field_ptr_info.child;
+ const struct_obj = ip.loadStructType(parent_ty.toIntern());
+ const field_idx: u32 = for (struct_obj.field_types.get(ip), 0..) |field_ty_ip, i| {
+ if (field_ty_ip == rtarr_ty_ip and
+ struct_obj.field_offsets.get(ip)[i] == ptr_key.byte_offset)
+ {
+ break @intCast(i);
+ }
+ } else unreachable;
+ const struct_ptr_ty = try pt.ptrType(.{
+ .child = parent_ty.toIntern(),
+ .flags = field_ptr_info.flags,
+ });
+ const struct_ptr_val = try sema.ptrSubtract(
+ block,
+ src_for_err,
+ ptr_val,
+ ptr_key.byte_offset,
+ struct_ptr_ty,
+ );
+ break :sf .{ .fromIntern(struct_ptr_val.toIntern()), field_idx };
+ };
+
+ try sema.requireRuntimeBlock(block, src, null);
+ return block.addInst(.{
+ .tag = .spirv_runtime_array_len,
+ .data = .{ .ty_pl = .{
+ .ty = .u32_type,
+ .payload = try sema.addExtra(Air.StructField{
+ .struct_operand = struct_operand,
+ .field_index = field_index,
+ }),
+ } },
+ });
+}
+
fn fieldPtr(
sema: *Sema,
block: *Block,
@@ -25748,7 +26208,7 @@ fn fieldPtr(
},
.packed_offset = ptr_ptr_info.packed_offset,
});
- return sema.bitCast(block, result_ty, object_ptr, src, null);
+ return block.addTyOp(.ptr_cast, result_ty, object_ptr);
} else {
return sema.fail(
block,
@@ -25767,17 +26227,7 @@ fn fieldPtr(
const attr_ptr_ty = if (is_pointer_to) object_ty else object_ptr_ty;
if (field_name.eqlSlice("ptr", ip)) {
- const slice_ptr_ty = inner_ty.slicePtrFieldType(zcu);
-
- const result_ty = try pt.ptrType(.{
- .child = slice_ptr_ty.toIntern(),
- .flags = .{
- .is_const = !attr_ptr_ty.ptrIsMutable(zcu),
- .is_volatile = attr_ptr_ty.isVolatilePtr(zcu),
- .address_space = attr_ptr_ty.ptrAddressSpace(zcu),
- },
- });
-
+ const result_ty = try attr_ptr_ty.fieldPtrType(Value.slice_ptr_index, pt);
if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {
return Air.internedToRef((try val.ptrField(Value.slice_ptr_index, pt)).toIntern());
}
@@ -25787,15 +26237,7 @@ fn fieldPtr(
try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr);
return field_ptr;
} else if (field_name.eqlSlice("len", ip)) {
- const result_ty = try pt.ptrType(.{
- .child = .usize_type,
- .flags = .{
- .is_const = !attr_ptr_ty.ptrIsMutable(zcu),
- .is_volatile = attr_ptr_ty.isVolatilePtr(zcu),
- .address_space = attr_ptr_ty.ptrAddressSpace(zcu),
- },
- });
-
+ const result_ty = try attr_ptr_ty.fieldPtrType(Value.slice_len_index, pt);
if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {
return Air.internedToRef((try val.ptrField(Value.slice_len_index, pt)).toIntern());
}
@@ -25954,23 +26396,21 @@ fn fieldCallBind(
.@"struct" => {
if (zcu.typeToStruct(concrete_ty)) |struct_type| {
const field_index = struct_type.nameIndex(ip, field_name) orelse break :find_field;
- const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
-
- return sema.finishFieldCallBind(block, src, ptr_ty, field_ty, field_index, object_ptr);
+ return sema.finishFieldCallBind(block, src, ptr_ty, field_index, object_ptr);
} else if (concrete_ty.isTuple(zcu)) {
if (field_name.eqlSlice("len", ip)) {
return .{ .direct = try pt.intRef(.usize, concrete_ty.structFieldCount(zcu)) };
}
if (field_name.toUnsigned(ip)) |field_index| {
if (field_index >= concrete_ty.structFieldCount(zcu)) break :find_field;
- return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.fieldType(field_index, zcu), field_index, object_ptr);
+ return sema.finishFieldCallBind(block, src, ptr_ty, field_index, object_ptr);
}
} else {
const max = concrete_ty.structFieldCount(zcu);
for (0..max) |i_usize| {
const i: u32 = @intCast(i_usize);
if (field_name == concrete_ty.structFieldName(i, zcu).unwrap().?) {
- return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.fieldType(i, zcu), i, object_ptr);
+ return sema.finishFieldCallBind(block, src, ptr_ty, i, object_ptr);
}
}
}
@@ -26007,7 +26447,7 @@ fn fieldCallBind(
(first_param_type.zigTypeTag(zcu) == .pointer and
(first_param_type.ptrSize(zcu) == .one or
first_param_type.ptrSize(zcu) == .c) and
- first_param_type.childType(zcu).eql(concrete_ty, zcu)))
+ first_param_type.childType(zcu).eql(concrete_ty)))
{
// Note that if the param type is generic poison, we know that it must
// specifically be `anytype` since it's the first parameter, meaning we
@@ -26018,7 +26458,7 @@ fn fieldCallBind(
.func_inst = decl_val,
.arg0_inst = object_ptr,
} };
- } else if (first_param_type.eql(concrete_ty, zcu)) {
+ } else if (first_param_type.eql(concrete_ty)) {
const deref = try sema.analyzeLoad(block, src, object_ptr, src);
return .{ .method = .{
.func_inst = decl_val,
@@ -26026,7 +26466,7 @@ fn fieldCallBind(
} };
} else if (first_param_type.zigTypeTag(zcu) == .optional) {
const child = first_param_type.optionalChild(zcu);
- if (child.eql(concrete_ty, zcu)) {
+ if (child.eql(concrete_ty)) {
const deref = try sema.analyzeLoad(block, src, object_ptr, src);
return .{ .method = .{
.func_inst = decl_val,
@@ -26034,7 +26474,7 @@ fn fieldCallBind(
} };
} else if (child.zigTypeTag(zcu) == .pointer and
child.ptrSize(zcu) == .one and
- child.childType(zcu).eql(concrete_ty, zcu))
+ child.childType(zcu).eql(concrete_ty))
{
return .{ .method = .{
.func_inst = decl_val,
@@ -26042,7 +26482,7 @@ fn fieldCallBind(
} };
}
} else if (first_param_type.zigTypeTag(zcu) == .error_union and
- first_param_type.errorUnionPayload(zcu).eql(concrete_ty, zcu))
+ first_param_type.errorUnionPayload(zcu).eql(concrete_ty))
{
const deref = try sema.analyzeLoad(block, src, object_ptr, src);
return .{ .method = .{
@@ -26086,19 +26526,12 @@ fn finishFieldCallBind(
block: *Block,
src: LazySrcLoc,
ptr_ty: Type,
- field_ty: Type,
field_index: u32,
object_ptr: Air.Inst.Ref,
) CompileError!ResolvedFieldCallee {
const pt = sema.pt;
const zcu = pt.zcu;
- const ptr_field_ty = try pt.ptrType(.{
- .child = field_ty.toIntern(),
- .flags = .{
- .is_const = !ptr_ty.ptrIsMutable(zcu),
- .address_space = ptr_ty.ptrAddressSpace(zcu),
- },
- });
+ const ptr_field_ty = try ptr_ty.fieldPtrType(field_index, pt);
const container_ty = ptr_ty.childType(zcu);
if (container_ty.zigTypeTag(zcu) == .@"struct") {
@@ -26484,16 +26917,13 @@ fn unionFieldVal(
break :msg msg;
});
},
- .@"extern" => if (try sema.bitCastVal(union_val, field_ty, 0, 0, 0)) |field_val| {
+ .@"extern" => if (try sema.castMemory(union_val, field_ty, 0)) |field_val| {
return .fromValue(field_val);
} else {
// Runtime-known due to a pointer-to-integer conversion.
},
.@"packed" => {
- const field_val = try sema.bitCastVal(union_val, field_ty, 0, union_ty.bitSize(zcu), 0) orelse {
- unreachable; // `null` is only possible if the input value contains a pointer, which a packed union cannot.
- };
- return .fromValue(field_val);
+ return .fromValue(try sema.bitCastVal(union_val, field_ty));
},
}
}
@@ -26540,6 +26970,7 @@ fn elemPtr(
.vector => try sema.elemPtrVector(block, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init),
.array => try sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety),
.@"struct" => try sema.tupleElemPtr(block, src, indexable_ptr, elem_index, elem_index_src),
+ .spirv => try sema.elemPtrSpirvRuntimeArray(block, indexable_ptr, elem_index),
else => {
const indexable = try sema.analyzeLoad(block, indexable_ptr_src, indexable_ptr, indexable_ptr_src);
try sema.ensureLayoutResolved(sema.typeOf(indexable).childType(zcu), src, .ptr_access);
@@ -26584,16 +27015,14 @@ fn elemPtrOneLayerOnly(
return .fromValue(try ptr_val.ptrElem(index, pt));
}
- try sema.checkLogicalPtrOperation(block, src, indexable_ty);
-
const result_ty = try indexable_ty.elemPtrType(maybe_index, pt);
- try sema.validateRuntimeElemAccess(block, elem_index_src, result_ty, indexable_ty, indexable_src);
+ try sema.validateRuntimeElemAccess(block, elem_index_src, result_ty, indexable_src);
try sema.validateRuntimeValue(block, indexable_src, indexable);
if (child_ty.abiSize(zcu) == 0) {
// zero-bit child type; just bitcast the pointer
- return block.addBitCast(result_ty, indexable);
+ return block.addTyOp(.ptr_cast, result_ty, indexable);
}
return block.addPtrElemPtr(indexable, elem_index, result_ty);
@@ -26651,7 +27080,7 @@ fn elemVal(
return sema.analyzeLoad(block, src, .fromValue(elem_ptr_val), indexable_src);
}
- try sema.validateRuntimeElemAccess(block, elem_index_src, child_ty, indexable_ty, src);
+ try sema.validateRuntimeElemAccess(block, elem_index_src, child_ty, src);
switch (child_ty.classify(zcu)) {
.runtime => {},
.one_possible_value => return .fromValue((try child_ty.onePossibleValue(pt)).?),
@@ -26700,11 +27129,9 @@ fn validateRuntimeElemAccess(
block: *Block,
elem_index_src: LazySrcLoc,
elem_ty: Type,
- parent_ty: Type,
parent_src: LazySrcLoc,
) CompileError!void {
- const pt = sema.pt;
- const zcu = pt.zcu;
+ const zcu = sema.pt.zcu;
if (elem_ty.comptimeOnly(zcu)) {
const msg = msg: {
@@ -26721,14 +27148,6 @@ fn validateRuntimeElemAccess(
};
return sema.failWithOwnedErrorMsg(block, msg);
}
-
- if (zcu.intern_pool.indexToKey(parent_ty.toIntern()) == .ptr_type) {
- const target = zcu.getTarget();
- const as = parent_ty.ptrAddressSpace(zcu);
- if (target_util.shouldBlockPointerOps(target, as)) {
- return sema.fail(block, elem_index_src, "cannot access element of logical pointer '{f}'", .{parent_ty.fmt(pt)});
- }
- }
}
/// Validates `elem_index`, and returns a pointer to that field using `structFieldPtrByIndex`.
@@ -26799,7 +27218,7 @@ fn tupleField(
return Air.internedToRef((try tuple_val.fieldValue(pt, field_index)).toIntern());
}
- try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);
+ try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_src);
return block.addStructFieldVal(tuple, field_index, field_ty);
}
@@ -26854,7 +27273,7 @@ fn elemValArray(
if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
}
- try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, array_ty, array_src);
+ try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, array_src);
try sema.validateRuntimeValue(block, array_src, array);
if (oob_safety and block.wantSafety()) {
@@ -26900,68 +27319,52 @@ fn elemPtrVector(
}
const elem_ty = vector_ty.childType(zcu);
- const elem_bits = elem_ty.bitSize(zcu);
- // Exiting this block means the operation is a runtime one.
- const elem_ptr_ty: Type = if (elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits)) elem_ptr_ty: {
- // Use a packed pointer (i.e. vector_index != 0)
- const vector_ptr_info = vector_ptr_ty.ptrInfo(zcu);
- const elem_ptr_ty = try pt.ptrType(.{
- .child = elem_ty.toIntern(),
- .flags = .{
- .size = .one,
- .alignment = vector_ptr_info.flags.alignment,
- .is_const = vector_ptr_info.flags.is_const,
- .is_volatile = vector_ptr_info.flags.is_volatile,
- .is_allowzero = vector_ptr_info.flags.is_allowzero,
- .address_space = vector_ptr_info.flags.address_space,
- .vector_index = @enumFromInt(index),
- },
- .packed_offset = .{
- .host_size = @intCast(vector_len),
- .bit_offset = 0,
- },
- });
- if (maybe_vector_ptr_val) |ptr_val| {
- if (ptr_val.isUndef(zcu)) return pt.undefRef(elem_ptr_ty);
- return .fromValue(try pt.getCoerced(ptr_val, elem_ptr_ty));
- }
- break :elem_ptr_ty elem_ptr_ty;
- } else elem_ptr_ty: {
- // Use a normal pointer (i.e. vector_index == 0)
- const vector_ptr_info = vector_ptr_ty.ptrInfo(zcu);
- const elem_ptr_ty = try pt.ptrType(.{
- .child = elem_ty.toIntern(),
- .flags = .{
- .size = .one,
- // TODO: this logic was ported from old code, but it's bogus. This entire block will
- // go away when https://github.com/ziglang/zig/issues/24061 is implemented anyway.
- .alignment = switch (vector_ptr_info.flags.alignment) {
- .none => .none,
- else => |vec_align| switch (index * elem_ty.abiSize(zcu)) {
- 0 => vec_align,
- else => |byte_offset| .minStrict(vec_align, .fromLog2Units(@ctz(byte_offset))),
- },
- },
- .is_const = vector_ptr_info.flags.is_const,
- .is_volatile = vector_ptr_info.flags.is_volatile,
- .is_allowzero = vector_ptr_info.flags.is_allowzero,
- .address_space = vector_ptr_info.flags.address_space,
- },
- });
- if (maybe_vector_ptr_val) |ptr_val| {
- if (ptr_val.isUndef(zcu)) return pt.undefRef(elem_ptr_ty);
- const bit_offset = index * @divExact(elem_ty.bitSize(zcu), 8);
- return .fromValue(try ptr_val.getOffsetPtr(bit_offset, elem_ptr_ty, pt));
- }
- break :elem_ptr_ty elem_ptr_ty;
- };
+
+ const vector_ptr_info = vector_ptr_ty.ptrInfo(zcu);
+ const elem_ptr_ty = try pt.ptrType(.{
+ .child = elem_ty.toIntern(),
+ .flags = .{
+ .size = .one,
+ .alignment = vector_ptr_info.flags.alignment,
+ .is_const = vector_ptr_info.flags.is_const,
+ .is_volatile = vector_ptr_info.flags.is_volatile,
+ .is_allowzero = vector_ptr_info.flags.is_allowzero,
+ .address_space = vector_ptr_info.flags.address_space,
+ .vector_index = @enumFromInt(index),
+ },
+ .packed_offset = .{
+ .host_size = @intCast(vector_len),
+ .bit_offset = 0,
+ },
+ });
+
+ if (maybe_vector_ptr_val) |ptr_val| {
+ if (ptr_val.isUndef(zcu)) return pt.undefRef(elem_ptr_ty);
+ return .fromValue(try pt.getCoerced(ptr_val, elem_ptr_ty));
+ }
if (!init) {
- try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, vector_ty, vector_ptr_src);
+ try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, vector_ptr_src);
try sema.validateRuntimeValue(block, vector_ptr_src, vector_ptr);
}
- return block.addPtrElemPtr(vector_ptr, elem_index, elem_ptr_ty);
+ return block.addTyOp(.ptr_cast, elem_ptr_ty, vector_ptr);
+}
+
+fn elemPtrSpirvRuntimeArray(
+ sema: *Sema,
+ block: *Block,
+ array_ptr: Air.Inst.Ref,
+ elem_index: Air.Inst.Ref,
+) CompileError!Air.Inst.Ref {
+ const pt = sema.pt;
+ const zcu = pt.zcu;
+ const array_ptr_ty = sema.typeOf(array_ptr);
+ assert(array_ptr_ty.ptrSize(zcu) == .one);
+ const array_ty = array_ptr_ty.childType(zcu);
+ assert(array_ty.isSpirvRuntimeArray(zcu));
+ const elem_ptr_ty = try array_ptr_ty.elemPtrType(null, pt);
+ return block.addPtrElemPtr(array_ptr, elem_index, elem_ptr_ty);
}
/// Asserts that the layout of the array is already resolved.
@@ -27014,7 +27417,7 @@ fn elemPtrArray(
}
if (!init) {
- try sema.validateRuntimeElemAccess(block, elem_index_src, array_ty.childType(zcu), array_ty, array_ptr_src);
+ try sema.validateRuntimeElemAccess(block, elem_index_src, array_ty.childType(zcu), array_ptr_src);
try sema.validateRuntimeValue(block, array_ptr_src, array_ptr);
}
@@ -27027,7 +27430,7 @@ fn elemPtrArray(
if (array_ty.childType(zcu).abiSize(zcu) == 0) {
// zero-bit child type; just bitcast the pointer
- return block.addBitCast(elem_ptr_ty, array_ptr);
+ return block.addTyOp(.ptr_cast, elem_ptr_ty, array_ptr);
}
return block.addPtrElemPtr(array_ptr, elem_index, elem_ptr_ty);
@@ -27077,7 +27480,7 @@ fn elemValSlice(
if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
- try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, slice_ty, slice_src);
+ try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, slice_src);
try sema.validateRuntimeValue(block, slice_src, slice);
if (oob_safety and block.wantSafety()) {
@@ -27137,7 +27540,7 @@ fn elemPtrSlice(
}
}
- try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ptr_ty, slice_ty, slice_src);
+ try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ptr_ty, slice_src);
try sema.validateRuntimeValue(block, slice_src, slice);
if (oob_safety and block.wantSafety()) {
@@ -27153,7 +27556,7 @@ fn elemPtrSlice(
if (elem_ty.abiSize(zcu) == 0) {
// zero-bit child type; just extract the pointer and bitcast it
const slice_ptr = try block.addTyOp(.slice_ptr, slice_ty.slicePtrFieldType(zcu), slice);
- return block.addBitCast(elem_ptr_ty, slice_ptr);
+ return block.addTyOp(.ptr_cast, elem_ptr_ty, slice_ptr);
}
return block.addSliceElemPtr(slice, elem_index, elem_ptr_ty);
}
@@ -27228,7 +27631,7 @@ fn coerceExtra(
try sema.ensureLayoutResolved(dest_ty, inst_src, .coerce);
// If the types are the same, we can return the operand.
- if (dest_ty.eql(inst_ty, zcu))
+ if (dest_ty.eql(inst_ty))
return inst;
const maybe_inst_val = sema.resolveValue(inst);
@@ -27236,12 +27639,31 @@ fn coerceExtra(
var in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src, maybe_inst_val);
if (in_memory_result == .ok) {
if (maybe_inst_val) |val| {
- return sema.coerceInMemory(val, dest_ty);
+ return .fromValue(try pt.getCoerced(val, dest_ty));
}
- try sema.requireRuntimeBlock(block, inst_src, null);
- const new_val = try block.addBitCast(dest_ty, inst);
- try sema.checkKnownAllocPtr(block, inst, new_val);
- return new_val;
+ const coerced: Air.Inst.Ref = switch (in_memory_result.ok) {
+ .none => coerced: {
+ const @"addrspace" = target_util.defaultAddressSpace(zcu.getTarget(), .local);
+ const src_ptr_ty = try pt.ptrType(.{
+ .child = inst_ty.toIntern(),
+ .flags = .{ .size = .one, .address_space = @"addrspace" },
+ });
+ const dest_ptr_ty = try pt.ptrType(.{
+ .child = dest_ty.toIntern(),
+ .flags = .{ .size = .one, .address_space = @"addrspace" },
+ });
+ const ptr = try block.addTy(.alloc, src_ptr_ty);
+ _ = try block.addBinOp(.store_safe, ptr, inst);
+ const casted_ptr = try block.addTyOp(.ptr_cast, dest_ptr_ty, ptr);
+ break :coerced try block.addTyOp(.load, dest_ty, casted_ptr);
+ },
+ .same_type => unreachable, // we checked for equal types just above
+ .bit_cast => try block.addTyOp(.bit_cast, dest_ty, inst),
+ .ptr_cast => try block.addTyOp(.ptr_cast, dest_ty, inst),
+ .error_cast => try block.addTyOp(.error_cast, dest_ty, inst),
+ };
+ try sema.checkKnownAllocPtr(block, inst, coerced);
+ return coerced;
}
switch (dest_ty.zigTypeTag(zcu)) {
@@ -27355,8 +27777,8 @@ fn coerceExtra(
if (dest_info.sentinel != .none) {
if (array_ty.sentinel(zcu)) |inst_sent| {
- if (Air.internedToRef(dest_info.sentinel) !=
- try sema.coerceInMemory(inst_sent, dst_elem_type))
+ if (dest_info.sentinel !=
+ (try pt.getCoerced(inst_sent, dst_elem_type)).toIntern())
{
in_memory_result = .{ .ptr_sentinel = .{
.actual = inst_sent,
@@ -27550,8 +27972,8 @@ fn coerceExtra(
}
if (dest_info.sentinel == .none or inst_info.sentinel == .none or
- Air.internedToRef(dest_info.sentinel) !=
- try sema.coerceInMemory(Value.fromInterned(inst_info.sentinel), .fromInterned(dest_info.child)))
+ dest_info.sentinel !=
+ (try pt.getCoerced(.fromInterned(inst_info.sentinel), .fromInterned(dest_info.child))).toIntern())
break :p;
const slice_ptr = try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty);
@@ -27600,7 +28022,7 @@ fn coerceExtra(
(dst_info.signedness == .signed and dst_info.bits > src_info.bits))
{
try sema.requireRuntimeBlock(block, inst_src, null);
- return block.addTyOp(.intcast, dest_ty, inst);
+ return block.addTyOp(.int_cast, dest_ty, inst);
}
},
else => {},
@@ -27862,16 +28284,8 @@ fn coerceExtra(
return sema.failWithOwnedErrorMsg(block, msg);
}
-fn coerceInMemory(
- sema: *Sema,
- val: Value,
- dst_ty: Type,
-) CompileError!Air.Inst.Ref {
- return Air.internedToRef((try sema.pt.getCoerced(val, dst_ty)).toIntern());
-}
-
const InMemoryCoercionResult = union(enum) {
- ok,
+ ok: Strategy,
no_match: Pair,
int_not_coercible: Int,
comptime_int_not_coercible: TypeValuePair,
@@ -27907,6 +28321,21 @@ const InMemoryCoercionResult = union(enum) {
double_ptr_to_anyopaque: Pair,
slice_to_anyopaque: Pair,
+ const Strategy = enum {
+ /// There isn't a special strategy for this particular coercion---we'll just need to
+ /// reinterpret the bytes in memory.
+ none,
+
+ /// The source and destination types are equal, so no explicit cast operation is necessary.
+ same_type,
+ /// The coercion can be lowered to `Air.Inst.Tag.bit_cast`.
+ bit_cast,
+ /// The coercion can be lowered to `Air.Inst.Tag.ptr_cast`.
+ ptr_cast,
+ /// The coercion can be lowered to `Air.Inst.Tag.error_cast`.
+ error_cast,
+ };
+
const Pair = struct {
actual: Type,
wanted: Type,
@@ -28279,8 +28708,8 @@ pub fn coerceInMemoryAllowed(
assert(val.typeOf(zcu).toIntern() == src_ty.toIntern());
}
- if (dest_ty.eql(src_ty, zcu))
- return .ok;
+ if (dest_ty.eql(src_ty))
+ return .{ .ok = .same_type };
const dest_tag = dest_ty.zigTypeTag(zcu);
const src_tag = src_ty.zigTypeTag(zcu);
@@ -28293,7 +28722,7 @@ pub fn coerceInMemoryAllowed(
if (dest_info.signedness == src_info.signedness and
dest_info.bits == src_info.bits)
{
- return .ok;
+ return .{ .ok = .bit_cast };
}
if ((src_info.signedness == dest_info.signedness and dest_info.bits < src_info.bits) or
@@ -28301,7 +28730,7 @@ pub fn coerceInMemoryAllowed(
(dest_info.signedness == .signed and src_info.signedness == .unsigned and dest_info.bits <= src_info.bits) or
(dest_info.signedness == .unsigned and src_info.signedness == .signed))
{
- return InMemoryCoercionResult{ .int_not_coercible = .{
+ return .{ .int_not_coercible = .{
.actual_signedness = src_info.signedness,
.wanted_signedness = dest_info.signedness,
.actual_bits = src_info.bits,
@@ -28324,7 +28753,7 @@ pub fn coerceInMemoryAllowed(
const dest_bits = dest_ty.floatBits(target);
const src_bits = src_ty.floatBits(target);
if (dest_bits == src_bits) {
- return .ok;
+ return .{ .ok = .bit_cast };
}
}
@@ -28347,24 +28776,38 @@ pub fn coerceInMemoryAllowed(
if (dest_tag == .error_union and src_tag == .error_union) {
const dest_payload = dest_ty.errorUnionPayload(zcu);
const src_payload = src_ty.errorUnionPayload(zcu);
- const child = try sema.coerceInMemoryAllowed(block, dest_payload, src_payload, dest_is_mut, target, dest_src, src_src, null);
- if (child != .ok) {
- return .{ .error_union_payload = .{
- .child = try child.dupe(sema.arena),
+ const payload_strat = switch (try sema.coerceInMemoryAllowed(block, dest_payload, src_payload, dest_is_mut, target, dest_src, src_src, null)) {
+ .ok => |strat| strat,
+ else => |payload_result| return .{ .error_union_payload = .{
+ .child = try payload_result.dupe(sema.arena),
.actual = src_payload,
.wanted = dest_payload,
- } };
+ } },
+ };
+ switch (try sema.coerceInMemoryAllowed(block, dest_ty.errorUnionSet(zcu), src_ty.errorUnionSet(zcu), dest_is_mut, target, dest_src, src_src, null)) {
+ .ok => {},
+ else => |err_set_result| return err_set_result,
}
- return try sema.coerceInMemoryAllowed(block, dest_ty.errorUnionSet(zcu), src_ty.errorUnionSet(zcu), dest_is_mut, target, dest_src, src_src, null);
+ return switch (payload_strat) {
+ .same_type => .{ .ok = .error_cast },
+ else => .{ .ok = .none },
+ };
}
// Error Sets
if (dest_tag == .error_set and src_tag == .error_set) {
- const res1 = try sema.coerceInMemoryAllowedErrorSets(block, dest_ty, src_ty, dest_src, src_src);
- if (!dest_is_mut or res1 != .ok) return res1;
- // src -> dest is okay, but `dest_is_mut`, so it needs to be allowed in the other direction.
- const res2 = try sema.coerceInMemoryAllowedErrorSets(block, src_ty, dest_ty, src_src, dest_src);
- return res2;
+ switch (try sema.coerceInMemoryAllowedErrorSets(block, dest_ty, src_ty, dest_src, src_src)) {
+ .ok => |strat| assert(strat == .error_cast),
+ else => |result| return result,
+ }
+ if (dest_is_mut) {
+ // src -> dest is okay, but `dest_is_mut`, so it needs to be allowed in the other direction.
+ switch (try sema.coerceInMemoryAllowedErrorSets(block, src_ty, dest_ty, src_src, dest_src)) {
+ .ok => |strat| assert(strat == .error_cast),
+ else => |result| return result,
+ }
+ }
+ return .{ .ok = .error_cast };
}
// Arrays
@@ -28379,9 +28822,9 @@ pub fn coerceInMemoryAllowed(
}
const child = try sema.coerceInMemoryAllowed(block, dest_info.elem_type, src_info.elem_type, dest_is_mut, target, dest_src, src_src, null);
- switch (child) {
- .ok => {},
- .no_match => return child,
+ const child_strat = switch (child) {
+ .ok => |strat| strat,
+ .no_match => |no_match| return .{ .no_match = no_match },
else => {
return .{ .array_elem = .{
.child = try child.dupe(sema.arena),
@@ -28389,7 +28832,7 @@ pub fn coerceInMemoryAllowed(
.wanted = dest_info.elem_type,
} };
},
- }
+ };
const ok_sent = (dest_info.sentinel == null and src_info.sentinel == null) or
(src_info.sentinel != null and
dest_info.sentinel != null and
@@ -28405,7 +28848,10 @@ pub fn coerceInMemoryAllowed(
.ty = dest_info.elem_type,
} };
}
- return .ok;
+ return .{ .ok = switch (child_strat) {
+ .bit_cast => .bit_cast,
+ else => .none,
+ } };
}
// Vectors
@@ -28421,16 +28867,18 @@ pub fn coerceInMemoryAllowed(
const dest_elem_ty = dest_ty.scalarType(zcu);
const src_elem_ty = src_ty.scalarType(zcu);
- const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src, null);
- if (child != .ok) {
- return .{ .vector_elem = .{
- .child = try child.dupe(sema.arena),
+ switch (try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src, null)) {
+ .ok => |child_strat| return .{ .ok = switch (child_strat) {
+ .bit_cast => .bit_cast,
+ .ptr_cast => .ptr_cast,
+ else => .none,
+ } },
+ else => |child_result| return .{ .vector_elem = .{
+ .child = try child_result.dupe(sema.arena),
.actual = src_elem_ty,
.wanted = dest_elem_ty,
- } };
+ } },
}
-
- return .ok;
}
// Optionals
@@ -28454,7 +28902,7 @@ pub fn coerceInMemoryAllowed(
} };
}
- return .ok;
+ return .{ .ok = .none };
}
// Tuples (with in-memory-coercible fields)
@@ -28468,7 +28916,7 @@ pub fn coerceInMemoryAllowed(
const field = try sema.coerceInMemoryAllowed(block, dest_field_ty, src_field_ty, dest_is_mut, target, dest_src, src_src, null);
if (field != .ok) break :tuple;
}
- return .ok;
+ return .{ .ok = .none };
}
return .{ .no_match = .{
@@ -28491,13 +28939,13 @@ fn coerceInMemoryAllowedErrorSets(
const ip = &zcu.intern_pool;
const dest_set: InternPool.Key.ErrorSetType = err_set: switch (dest_ty.toIntern()) {
- .anyerror_type => return .ok,
+ .anyerror_type => return .{ .ok = .error_cast },
.adhoc_inferred_error_set_type => {
// We are trying to coerce an error set to the current function's
// inferred error set.
const dst_ies = sema.fn_ret_ty_ies.?;
try dst_ies.addErrorSet(src_ty, ip, sema.arena);
- return .ok;
+ return .{ .ok = .error_cast };
},
else => |err_set_ty| switch (ip.indexToKey(err_set_ty)) {
.inferred_error_set_type => |func_index| {
@@ -28506,7 +28954,7 @@ fn coerceInMemoryAllowedErrorSets(
// We are trying to coerce an error set to the current function's
// inferred error set.
try dst_ies.addErrorSet(src_ty, ip, sema.arena);
- return .ok;
+ return .{ .ok = .error_cast };
}
}
try sema.ensureFuncIesResolved(block, dest_src, func_index);
@@ -28545,7 +28993,7 @@ fn coerceInMemoryAllowedErrorSets(
) };
}
- return .ok;
+ return .{ .ok = .error_cast };
}
fn coerceInMemoryAllowedFns(
@@ -28662,7 +29110,7 @@ fn coerceInMemoryAllowedFns(
}
}
- return .ok;
+ return .{ .ok = .none };
}
fn callconvCoerceAllowed(
@@ -28676,10 +29124,10 @@ fn callconvCoerceAllowed(
switch (src_cc) {
inline else => |src_data, tag| {
const dest_data = @field(dest_cc, @tagName(tag));
- if (@TypeOf(src_data) != void) {
+ if (@TypeOf(src_data) != void and @hasField(@TypeOf(src_data), "incoming_stack_alignment")) {
const default_stack_align = target.stackAlignment();
const src_stack_align = src_data.incoming_stack_alignment orelse default_stack_align;
- const dest_stack_align = src_data.incoming_stack_alignment orelse default_stack_align;
+ const dest_stack_align = dest_data.incoming_stack_alignment orelse default_stack_align;
if (dest_stack_align < src_stack_align) return false;
}
switch (@TypeOf(src_data)) {
@@ -28705,6 +29153,10 @@ fn callconvCoerceAllowed(
std.lang.CallingConvention.ShInterruptOptions => {
if (src_data.save != dest_data.save) return false;
},
+ std.lang.CallingConvention.SpirvKernelOptions,
+ std.lang.CallingConvention.SpirvFragmentOptions,
+ std.lang.CallingConvention.SpirvMeshOptions,
+ => {},
else => comptime unreachable,
}
},
@@ -28735,7 +29187,7 @@ fn coerceInMemoryAllowedPtrs(
const ok_ptr_size = src_info.flags.size == dest_info.flags.size or
src_info.flags.size == .c or dest_info.flags.size == .c;
if (!ok_ptr_size) {
- return InMemoryCoercionResult{ .ptr_size = .{
+ return .{ .ptr_size = .{
.actual = src_info.flags.size,
.wanted = dest_info.flags.size,
} };
@@ -28871,14 +29323,14 @@ fn coerceInMemoryAllowedPtrs(
break :a dest_child.abiAlignment(zcu);
} else dest_info.flags.alignment;
if (dest_align.compare(if (dest_is_mut) .neq else .gt, src_align)) {
- return InMemoryCoercionResult{ .ptr_alignment = .{
+ return .{ .ptr_alignment = .{
.actual = src_align,
.wanted = dest_align,
} };
}
}
- return .ok;
+ return .{ .ok = .ptr_cast };
}
fn coerceVarArgParam(
@@ -29182,7 +29634,6 @@ fn bitCast(
dest_ty: Type,
inst: Air.Inst.Ref,
inst_src: LazySrcLoc,
- operand_src: ?LazySrcLoc,
) CompileError!Air.Inst.Ref {
const pt = sema.pt;
const zcu = pt.zcu;
@@ -29191,6 +29642,11 @@ fn bitCast(
old_ty.assertHasLayout(zcu);
try sema.ensureLayoutResolved(dest_ty, inst_src, .init);
+ assert(old_ty.hasBitRepresentation(zcu));
+ assert(dest_ty.hasBitRepresentation(zcu));
+ assert(old_ty.scalarType(zcu).zigTypeTag(zcu) != .pointer);
+ assert(dest_ty.scalarType(zcu).zigTypeTag(zcu) != .pointer);
+
const dest_bits = dest_ty.bitSize(zcu);
const old_bits = old_ty.bitSize(zcu);
@@ -29204,20 +29660,30 @@ fn bitCast(
}
if (sema.resolveValue(inst)) |val| {
- if (val.isUndef(zcu))
- return pt.undefRef(dest_ty);
- if (old_ty.zigTypeTag(zcu) == .error_set and dest_ty.zigTypeTag(zcu) == .error_set) {
- // Special case: we sometimes call `bitCast` on error set values, but they
- // don't have a well-defined layout, so we can't use `bitCastVal` on them.
- return Air.internedToRef((try pt.getCoerced(val, dest_ty)).toIntern());
- }
- if (try sema.bitCastVal(val, dest_ty, 0, 0, 0)) |result_val| {
- return Air.internedToRef(result_val.toIntern());
- }
+ return .fromValue(try sema.bitCastVal(val, dest_ty));
}
- try sema.requireRuntimeBlock(block, inst_src, operand_src);
try sema.validateRuntimeValue(block, inst_src, inst);
- return block.addBitCast(dest_ty, inst);
+ return block.addTyOp(.bit_cast, dest_ty, inst);
+}
+
+/// Supports only types which `@bitCast` supports, so pointers are *not* supported.
+pub fn bitCastVal(
+ sema: *Sema,
+ val: Value,
+ dest_ty: Type,
+) Allocator.Error!Value {
+ const pt = sema.pt;
+ const zcu = pt.zcu;
+ const bit_size = dest_ty.bitSize(zcu);
+ assert(val.typeOf(zcu).bitSize(zcu) == bit_size);
+ if (val.isUndef(zcu)) {
+ return pt.undefValue(dest_ty);
+ } else {
+ const buf = try sema.arena.alloc(u8, @intCast((bit_size + 7) / 8));
+ @memset(buf, 0);
+ val.writeToPackedMemory(zcu, buf, 0);
+ return .readFromPackedMemory(dest_ty, pt, buf, 0);
+ }
}
fn coerceArrayPtrToSlice(
@@ -29334,14 +29800,17 @@ fn coerceCompatiblePtrs(
);
}
try sema.requireRuntimeBlock(block, inst_src, null);
- const inst_allows_zero = inst_ty.zigTypeTag(zcu) != .pointer or inst_ty.ptrAllowsZero(zcu);
- if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero(zcu)) {
+ const maybe_zero: bool = switch (inst_ty.toIntern()) {
+ .usize_type, .isize_type => true,
+ else => inst_ty.ptrAllowsZero(zcu),
+ };
+ if (block.wantSafety() and maybe_zero and !dest_ty.ptrAllowsZero(zcu)) {
try sema.checkLogicalPtrOperation(block, inst_src, inst_ty);
const actual_ptr = if (inst_ty.isSlice(zcu))
try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty)
else
inst;
- const ptr_int = try block.addBitCast(.usize, actual_ptr);
+ const ptr_int = try block.addTyOp(.int_from_ptr, .usize, actual_ptr);
const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize);
const ok = if (inst_ty.isSlice(zcu)) ok: {
const len = try sema.analyzeSliceLen(block, inst_src, inst);
@@ -29350,7 +29819,14 @@ fn coerceCompatiblePtrs(
} else is_non_zero;
try sema.addSafetyCheck(block, inst_src, ok, .cast_to_null);
}
- const new_ptr = try sema.bitCast(block, dest_ty, inst, inst_src, null);
+ const new_ptr: Air.Inst.Ref = switch (inst_ty.toIntern()) {
+ .usize_type => try block.addTyOp(.ptr_from_int, dest_ty, inst),
+ .isize_type => new_ptr: {
+ const usize_inst = try block.addTyOp(.bit_cast, .usize, inst);
+ break :new_ptr try block.addTyOp(.ptr_from_int, dest_ty, usize_inst);
+ },
+ else => try block.addTyOp(.ptr_cast, dest_ty, inst),
+ };
try sema.checkKnownAllocPtr(block, inst, new_ptr);
return new_ptr;
}
@@ -29447,7 +29923,7 @@ fn coerceEnumToUnion(
return .fromValue(opv);
} else {
// The union layout is just the tag, so we can bitcast the enum straight to the union.
- return block.addBitCast(union_ty, enum_tag);
+ return block.addTyOp(.union_from_enum, union_ty, enum_tag);
}
}
@@ -29496,18 +29972,6 @@ fn coerceArrayLike(
const inst_ty = sema.typeOf(inst);
const target = zcu.getTarget();
- // try coercion of the whole array
- const in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src, null);
- if (in_memory_result == .ok) {
- if (sema.resolveValue(inst)) |inst_val| {
- // These types share the same comptime value representation.
- return sema.coerceInMemory(inst_val, dest_ty);
- }
- try sema.requireRuntimeBlock(block, inst_src, null);
- return block.addBitCast(dest_ty, inst);
- }
-
- // otherwise, try element by element
const inst_len = inst_ty.arrayLen(zcu);
const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen(zcu));
if (dest_len != inst_len) {
@@ -29534,7 +29998,7 @@ fn coerceArrayLike(
(dst_info.signedness == .signed and dst_info.bits > src_info.bits))
{
try sema.requireRuntimeBlock(block, inst_src, null);
- return block.addTyOp(.intcast, dest_ty, inst);
+ return block.addTyOp(.int_cast, dest_ty, inst);
}
},
.float => if (inst_elem_ty.isRuntimeFloat()) {
@@ -30061,7 +30525,7 @@ fn analyzeRef(
// Cast to the constant pointer type. We do this directly rather than going via `coerce` to
// avoid errors in the `block.isComptime()` case.
- return block.addBitCast(ptr_type, alloc);
+ return block.addTyOp(.ptr_cast, ptr_type, alloc);
}
fn analyzeLoad(
@@ -30104,6 +30568,11 @@ fn analyzeLoad(
break :msg msg;
});
+ // https://github.com/ziglang/zig/issues/6597
+ if (block.wantSafety() and ptr_ty.isCPtr(zcu)) {
+ const is_non_null = try block.addUnOp(.is_non_null, ptr);
+ try sema.addSafetyCheck(block, src, is_non_null, .unwrap_null);
+ }
return block.addTyOp(.load, elem_ty, ptr);
}
@@ -30808,7 +31277,7 @@ fn analyzeSlice(
const opt_new_ptr_val = sema.resolveValue(new_ptr);
const new_ptr_val = opt_new_ptr_val orelse {
- const result = try block.addBitCast(return_ty, new_ptr);
+ const result = try block.addTyOp(.ptr_cast, return_ty, new_ptr);
if (block.wantSafety()) {
// requirement: slicing C ptr is non-null
if (ptr_ptr_child_ty.isCPtr(zcu)) {
@@ -31496,7 +31965,7 @@ const PeerResolveStrategy = enum {
fn select(ty: Type, zcu: *Zcu) PeerResolveStrategy {
return switch (ty.zigTypeTag(zcu)) {
- .type, .void, .bool, .@"opaque", .frame, .@"anyframe" => .exact,
+ .type, .void, .bool, .@"opaque", .spirv, .frame, .@"anyframe" => .exact,
.noreturn, .undefined => .unknown,
.null => .nullable,
.comptime_int => .comptime_int,
@@ -31793,7 +32262,7 @@ fn resolvePeerTypesInner(
.nullable => {
for (peer_tys, 0..) |opt_ty, i| {
const ty = opt_ty orelse continue;
- if (!ty.eql(.null, zcu)) return .{ .conflict = .{
+ if (!ty.eql(.null)) return .{ .conflict = .{
.peer_idx_a = strat_reason,
.peer_idx_b = i,
} };
@@ -31881,7 +32350,7 @@ fn resolvePeerTypesInner(
} };
const peer_elem_ty = ty.childType(zcu);
- if (!peer_elem_ty.eql(elem_ty, zcu)) coerce: {
+ if (!peer_elem_ty.eql(elem_ty)) coerce: {
const peer_elem_coerces_to_elem =
try sema.coerceInMemoryAllowed(block, elem_ty, peer_elem_ty, false, zcu.getTarget(), src, src, null);
if (peer_elem_coerces_to_elem == .ok) {
@@ -32462,11 +32931,11 @@ fn resolvePeerTypesInner(
.@"enum" => switch (ty.zigTypeTag(zcu)) {
.enum_literal => {},
.@"enum" => {
- if (!ty.eql(cur_ty, zcu)) return generic_err;
+ if (!ty.eql(cur_ty)) return generic_err;
},
.@"union" => {
const tag_ty = ty.unionTagTypeHypothetical(zcu);
- if (!tag_ty.eql(cur_ty, zcu)) return generic_err;
+ if (!tag_ty.eql(cur_ty)) return generic_err;
opt_cur_ty = ty;
cur_ty_idx = i;
},
@@ -32476,10 +32945,10 @@ fn resolvePeerTypesInner(
.enum_literal => {},
.@"enum" => {
const cur_tag_ty = cur_ty.unionTagTypeHypothetical(zcu);
- if (!ty.eql(cur_tag_ty, zcu)) return generic_err;
+ if (!ty.eql(cur_tag_ty)) return generic_err;
},
.@"union" => {
- if (!ty.eql(cur_ty, zcu)) return generic_err;
+ if (!ty.eql(cur_ty)) return generic_err;
},
else => unreachable,
},
@@ -32612,7 +33081,7 @@ fn resolvePeerTypesInner(
.comptime_float, .comptime_int, .int => {},
.float => {
if (opt_cur_ty) |cur_ty| {
- if (cur_ty.eql(ty, zcu)) continue;
+ if (cur_ty.eql(ty)) continue;
// Recreate the type so we eliminate any c_longdouble
const bits = @max(cur_ty.floatBits(target), ty.floatBits(target));
opt_cur_ty = switch (bits) {
@@ -32787,7 +33256,7 @@ fn resolvePeerTypesInner(
for (peer_tys, 0..) |opt_ty, i| {
const ty = opt_ty orelse continue;
if (expect_ty) |expect| {
- if (!ty.eql(expect, zcu)) return .{ .conflict = .{
+ if (!ty.eql(expect)) return .{ .conflict = .{
.peer_idx_a = first_idx,
.peer_idx_b = i,
} };
@@ -32853,7 +33322,7 @@ fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike {
};
const elem_ty = ty.fieldType(0, zcu);
for (1..field_count) |i| {
- if (!ty.fieldType(i, zcu).eql(elem_ty, zcu)) {
+ if (!ty.fieldType(i, zcu).eql(elem_ty)) {
return null;
}
}
@@ -32873,6 +33342,7 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
const msg = try sema.errMsg(src, "type '{f}' does not support indexing", .{ty.fmt(pt)});
errdefer msg.destroy(sema.gpa);
try sema.errNote(src, msg, "operand must be an array, slice, tuple, or vector", .{});
+ try sema.addDeclaredHereNote(msg, ty);
break :msg msg;
};
return sema.failWithOwnedErrorMsg(block, msg);
@@ -33839,8 +34309,8 @@ pub fn flushExports(sema: *Sema) !void {
}
}
-pub const bitCastVal = @import("Sema/bitcast.zig").bitCast;
-pub const bitCastSpliceVal = @import("Sema/bitcast.zig").bitCastSplice;
+pub const castMemory = @import("Sema/reinterpret.zig").castMemory;
+pub const spliceMemory = @import("Sema/reinterpret.zig").spliceMemory;
const loadComptimePtr = @import("Sema/comptime_ptr_access.zig").loadComptimePtr;
const ComptimeLoadResult = @import("Sema/comptime_ptr_access.zig").ComptimeLoadResult;
diff --git a/src/Sema/LowerZon.zig b/src/Sema/LowerZon.zig
index 0ba12a8813477ce26016c34443c2ea3825630740..f807043d8ecd7bbf6c628feb877d25c92212d08c 100644
--- a/src/Sema/LowerZon.zig
+++ b/src/Sema/LowerZon.zig
@@ -244,6 +244,7 @@ fn checkTypeInner(
.frame,
.@"anyframe",
.@"opaque",
+ .spirv,
=> return self.failUnsupportedResultType(ty, null),
.pointer => {
@@ -408,6 +409,7 @@ fn lowerExprKnownResTyInner(
.error_set,
.@"fn",
.@"opaque",
+ .spirv,
.frame,
.@"anyframe",
.void,
@@ -813,20 +815,15 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool
.@"packed" => result: {
const arena = self.sema.arena;
const buf = try arena.alloc(u8, @intCast((res_ty.bitSize(zcu) + 7) / 8));
+ @memset(buf, 0);
var bit_offset: u16 = 0;
for (field_values) |field_ip| {
const field_val: Value = .fromInterned(field_ip);
- field_val.writeToPackedMemory(zcu, buf, bit_offset) catch |err| switch (err) {
- error.ReinterpretDeclRef => unreachable, // bitpack fields cannot be pointers
- error.OutOfMemory => |e| return e,
- };
+ field_val.writeToPackedMemory(zcu, buf, bit_offset);
bit_offset += @intCast(field_val.typeOf(zcu).bitSize(zcu));
}
assert(bit_offset == res_ty.bitSize(zcu));
- break :result Value.readFromPackedMemory(res_ty, pt, buf, 0, arena) catch |err| switch (err) {
- error.IllDefinedMemoryLayout => unreachable, // bitpacks have well-defined layout
- error.OutOfMemory => |e| return e,
- };
+ break :result try .readFromPackedMemory(res_ty, pt, buf, 0);
},
};
return result.toIntern();
@@ -979,9 +976,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
};
const result: Value = switch (union_info.layout) {
.auto, .@"extern" => try pt.unionValue(res_ty, tag, val),
- .@"packed" => try self.sema.bitCastVal(val, res_ty, 0, 0, 0) orelse {
- unreachable; // `null` is only possible if the input value contains a pointer, which a packed union cannot.
- },
+ .@"packed" => try self.sema.bitCastVal(val, res_ty),
};
return result.toIntern();
}
diff --git a/src/Sema/bitcast.zig b/src/Sema/bitcast.zig
deleted file mode 100644
index 40a29e183bd4324aedc297ab1cba278c987e63fa..0000000000000000000000000000000000000000
--- a/src/Sema/bitcast.zig
+++ /dev/null
@@ -1,773 +0,0 @@
-//! This file contains logic for bit-casting arbitrary values at comptime, including splicing
-//! bits together for comptime stores of bit-pointers. The strategy is to "flatten" values to
-//! a sequence of values in *packed* memory, and then unflatten through a combination of special
-//! cases (particularly for pointers and `undefined` values) and in-memory buffer reinterprets.
-//!
-//! This is a little awkward on big-endian targets, as non-packed datastructures (e.g. `extern struct`)
-//! have their fields reversed when represented as packed memory on such targets.
-
-/// If `host_bits` is `0`, attempts to convert the memory at offset
-/// `byte_offset` into `val` to a non-packed value of type `dest_ty`,
-/// ignoring `bit_offset`.
-///
-/// Otherwise, `byte_offset` is an offset in bytes into `val` to a
-/// non-packed value consisting of `host_bits` bits. A value of type
-/// `dest_ty` will be interpreted at a packed offset of `bit_offset`
-/// into this value.
-///
-/// Returns `null` if the operation must be performed at runtime.
-pub fn bitCast(
- sema: *Sema,
- val: Value,
- dest_ty: Type,
- byte_offset: u64,
- host_bits: u64,
- bit_offset: u64,
-) CompileError!?Value {
- return bitCastInner(sema, val, dest_ty, byte_offset, host_bits, bit_offset) catch |err| switch (err) {
- error.ReinterpretDeclRef => return null,
- error.IllDefinedMemoryLayout => unreachable,
- error.Unimplemented => @panic("unimplemented bitcast"),
- else => |e| return e,
- };
-}
-
-/// Uses bitcasting to splice the value `splice_val` into `val`,
-/// replacing overlapping bits and returning the modified value.
-///
-/// If `host_bits` is `0`, splices `splice_val` at an offset
-/// `byte_offset` bytes into the virtual memory of `val`, ignoring
-/// `bit_offset`.
-///
-/// Otherwise, `byte_offset` is an offset into bytes into `val` to
-/// a non-packed value consisting of `host_bits` bits. The value
-/// `splice_val` will be placed at a packed offset of `bit_offset`
-/// into this value.
-pub fn bitCastSplice(
- sema: *Sema,
- val: Value,
- splice_val: Value,
- byte_offset: u64,
- host_bits: u64,
- bit_offset: u64,
-) CompileError!?Value {
- return bitCastSpliceInner(sema, val, splice_val, byte_offset, host_bits, bit_offset) catch |err| switch (err) {
- error.ReinterpretDeclRef => return null,
- error.IllDefinedMemoryLayout => unreachable,
- error.Unimplemented => @panic("unimplemented bitcast"),
- else => |e| return e,
- };
-}
-
-const BitCastError = CompileError || error{ ReinterpretDeclRef, IllDefinedMemoryLayout, Unimplemented };
-
-fn bitCastInner(
- sema: *Sema,
- val: Value,
- dest_ty: Type,
- byte_offset: u64,
- host_bits: u64,
- bit_offset: u64,
-) BitCastError!Value {
- const pt = sema.pt;
- const zcu = pt.zcu;
- const endian = zcu.getTarget().cpu.arch.endian();
-
- if (dest_ty.toIntern() == val.typeOf(zcu).toIntern() and bit_offset == 0) {
- return val;
- }
-
- const val_ty = val.typeOf(zcu);
-
- val_ty.assertHasLayout(zcu);
- dest_ty.assertHasLayout(zcu);
-
- assert(val_ty.hasWellDefinedLayout(zcu));
-
- const abi_pad_bits, const host_pad_bits = if (host_bits > 0)
- .{ val_ty.abiSize(zcu) * 8 - host_bits, host_bits - val_ty.bitSize(zcu) }
- else
- .{ val_ty.abiSize(zcu) * 8 - val_ty.bitSize(zcu), 0 };
-
- const skip_bits = switch (endian) {
- .little => bit_offset + byte_offset * 8,
- .big => if (host_bits > 0)
- val_ty.abiSize(zcu) * 8 - byte_offset * 8 - host_bits + bit_offset
- else
- val_ty.abiSize(zcu) * 8 - byte_offset * 8 - dest_ty.bitSize(zcu),
- };
-
- var unpack: UnpackValueBits = .{
- .pt = sema.pt,
- .arena = sema.arena,
- .skip_bits = skip_bits,
- .remaining_bits = dest_ty.bitSize(zcu),
- .unpacked = std.array_list.Managed(InternPool.Index).init(sema.arena),
- };
- switch (endian) {
- .little => {
- try unpack.add(val);
- try unpack.padding(abi_pad_bits);
- },
- .big => {
- try unpack.padding(abi_pad_bits);
- try unpack.add(val);
- },
- }
- try unpack.padding(host_pad_bits);
-
- var pack: PackValueBits = .{
- .pt = sema.pt,
- .arena = sema.arena,
- .unpacked = unpack.unpacked.items,
- };
- return pack.get(dest_ty);
-}
-
-fn bitCastSpliceInner(
- sema: *Sema,
- val: Value,
- splice_val: Value,
- byte_offset: u64,
- host_bits: u64,
- bit_offset: u64,
-) BitCastError!Value {
- const pt = sema.pt;
- const zcu = pt.zcu;
- const endian = zcu.getTarget().cpu.arch.endian();
- const val_ty = val.typeOf(zcu);
- const splice_val_ty = splice_val.typeOf(zcu);
-
- val_ty.assertHasLayout(zcu);
- splice_val_ty.assertHasLayout(zcu);
-
- const splice_bits = splice_val_ty.bitSize(zcu);
-
- const splice_offset = switch (endian) {
- .little => bit_offset + byte_offset * 8,
- .big => if (host_bits > 0)
- val_ty.abiSize(zcu) * 8 - byte_offset * 8 - host_bits + bit_offset
- else
- val_ty.abiSize(zcu) * 8 - byte_offset * 8 - splice_bits,
- };
-
- assert(splice_offset + splice_bits <= val_ty.abiSize(zcu) * 8);
-
- const abi_pad_bits, const host_pad_bits = if (host_bits > 0)
- .{ val_ty.abiSize(zcu) * 8 - host_bits, host_bits - val_ty.bitSize(zcu) }
- else
- .{ val_ty.abiSize(zcu) * 8 - val_ty.bitSize(zcu), 0 };
-
- var unpack: UnpackValueBits = .{
- .pt = pt,
- .arena = sema.arena,
- .skip_bits = 0,
- .remaining_bits = splice_offset,
- .unpacked = std.array_list.Managed(InternPool.Index).init(sema.arena),
- };
- switch (endian) {
- .little => {
- try unpack.add(val);
- try unpack.padding(abi_pad_bits);
- },
- .big => {
- try unpack.padding(abi_pad_bits);
- try unpack.add(val);
- },
- }
- try unpack.padding(host_pad_bits);
-
- unpack.remaining_bits = splice_bits;
- try unpack.add(splice_val);
-
- unpack.skip_bits = splice_offset + splice_bits;
- unpack.remaining_bits = val_ty.abiSize(zcu) * 8 - splice_offset - splice_bits;
- switch (endian) {
- .little => {
- try unpack.add(val);
- try unpack.padding(abi_pad_bits);
- },
- .big => {
- try unpack.padding(abi_pad_bits);
- try unpack.add(val);
- },
- }
- try unpack.padding(host_pad_bits);
-
- var pack: PackValueBits = .{
- .pt = pt,
- .arena = sema.arena,
- .unpacked = unpack.unpacked.items,
- };
- switch (endian) {
- .little => {},
- .big => try pack.padding(abi_pad_bits),
- }
- return pack.get(val_ty);
-}
-
-/// Recurses through struct fields, array elements, etc, to get a sequence of "primitive" values
-/// which are bit-packed in memory to represent a single value. `unpacked` represents a series
-/// of values in *packed* memory - therefore, on big-endian targets, the first element of this
-/// list contains bits from the *final* byte of the value.
-const UnpackValueBits = struct {
- pt: Zcu.PerThread,
- arena: Allocator,
- skip_bits: u64,
- remaining_bits: u64,
- extra_bits: u64 = undefined,
- unpacked: std.array_list.Managed(InternPool.Index),
-
- fn add(unpack: *UnpackValueBits, val: Value) BitCastError!void {
- const pt = unpack.pt;
- const zcu = pt.zcu;
- const endian = zcu.getTarget().cpu.arch.endian();
- const ip = &zcu.intern_pool;
-
- if (unpack.remaining_bits == 0) {
- return;
- }
-
- const ty = val.typeOf(zcu);
- const bit_size = ty.bitSize(zcu);
-
- if (unpack.skip_bits >= bit_size) {
- unpack.skip_bits -= bit_size;
- return;
- }
-
- switch (ip.indexToKey(val.toIntern())) {
- .int_type,
- .ptr_type,
- .array_type,
- .vector_type,
- .opt_type,
- .anyframe_type,
- .error_union_type,
- .simple_type,
- .struct_type,
- .tuple_type,
- .union_type,
- .opaque_type,
- .enum_type,
- .func_type,
- .error_set_type,
- .inferred_error_set_type,
- .@"extern",
- .func,
- .err,
- .error_union,
- .enum_literal,
- .slice,
- .memoized_call,
- => unreachable, // ill-defined layout or not real values
-
- .undef,
- .int,
- .enum_tag,
- .simple_value,
- .float,
- .ptr,
- .opt,
- => try unpack.primitive(val),
-
- .bitpack => |bitpack| try unpack.primitive(.fromInterned(bitpack.backing_int_val)),
-
- .aggregate => switch (ty.zigTypeTag(zcu)) {
- .vector => {
- const len: usize = @intCast(ty.arrayLen(zcu));
- for (0..len) |i| {
- // We reverse vector elements in packed memory on BE targets.
- const real_idx = switch (endian) {
- .little => i,
- .big => len - i - 1,
- };
- const elem_val = try val.elemValue(pt, real_idx);
- try unpack.add(elem_val);
- }
- },
- .array => {
- // Each element is padded up to its ABI size. Padding bits are undefined.
- // The final element does not have trailing padding.
- // Elements are reversed in packed memory on BE targets.
- const elem_ty = ty.childType(zcu);
- const pad_bits = elem_ty.abiSize(zcu) * 8 - elem_ty.bitSize(zcu);
- const len = ty.arrayLen(zcu);
- const maybe_sent = ty.sentinel(zcu);
-
- if (endian == .big) if (maybe_sent) |s| {
- try unpack.add(s);
- if (len != 0) try unpack.padding(pad_bits);
- };
-
- for (0..@intCast(len)) |i| {
- // We reverse array elements in packed memory on BE targets.
- const real_idx = switch (endian) {
- .little => i,
- .big => len - i - 1,
- };
- const elem_val = try val.elemValue(pt, @intCast(real_idx));
- try unpack.add(elem_val);
- if (i != len - 1) try unpack.padding(pad_bits);
- }
-
- if (endian == .little) if (maybe_sent) |s| {
- if (len != 0) try unpack.padding(pad_bits);
- try unpack.add(s);
- };
- },
- .@"struct" => switch (ty.containerLayout(zcu)) {
- .auto => unreachable, // ill-defined layout
- .@"extern" => switch (endian) {
- .little => {
- var cur_bit_off: u64 = 0;
- var it = zcu.typeToStruct(ty).?.iterateRuntimeOrder(ip);
- while (it.next()) |field_idx| {
- const want_bit_off = ty.structFieldOffset(field_idx, zcu) * 8;
- const pad_bits = want_bit_off - cur_bit_off;
- const field_val = try val.fieldValue(pt, field_idx);
- try unpack.padding(pad_bits);
- try unpack.add(field_val);
- cur_bit_off = want_bit_off + field_val.typeOf(zcu).bitSize(zcu);
- }
- // Add trailing padding bits.
- try unpack.padding(bit_size - cur_bit_off);
- },
- .big => {
- var cur_bit_off: u64 = bit_size;
- var it = zcu.typeToStruct(ty).?.iterateRuntimeOrderReverse(ip);
- while (it.next()) |field_idx| {
- const field_val = try val.fieldValue(pt, field_idx);
- const field_ty = field_val.typeOf(zcu);
- const want_bit_off = ty.structFieldOffset(field_idx, zcu) * 8 + field_ty.bitSize(zcu);
- const pad_bits = cur_bit_off - want_bit_off;
- try unpack.padding(pad_bits);
- try unpack.add(field_val);
- cur_bit_off = want_bit_off - field_ty.bitSize(zcu);
- }
- assert(cur_bit_off == 0);
- },
- },
- .@"packed" => {
- // Just add all fields in order. There are no padding bits.
- // This is identical between LE and BE targets.
- for (0..ty.structFieldCount(zcu)) |i| {
- const field_val = try val.fieldValue(pt, i);
- try unpack.add(field_val);
- }
- },
- },
- else => unreachable,
- },
-
- .un => |un| {
- // We actually don't care about the tag here!
- // Instead, we just need to write the payload value, plus any necessary padding.
- // This correctly handles the case where `tag == .none`, since the payload is then
- // either an integer or a byte array, both of which we can unpack.
- const payload_val = Value.fromInterned(un.val);
- const pad_bits = bit_size - payload_val.typeOf(zcu).bitSize(zcu);
- if (endian == .little or ty.containerLayout(zcu) == .@"packed") {
- try unpack.add(payload_val);
- try unpack.padding(pad_bits);
- } else {
- try unpack.padding(pad_bits);
- try unpack.add(payload_val);
- }
- },
- }
- }
-
- fn padding(unpack: *UnpackValueBits, pad_bits: u64) BitCastError!void {
- if (pad_bits == 0) return;
- const pt = unpack.pt;
- // Figure out how many full bytes and leftover bits there are.
- const bytes = pad_bits / 8;
- const bits = pad_bits % 8;
- // Add undef u8 values for the bytes...
- const undef_u8 = try pt.undefValue(Type.u8);
- for (0..@intCast(bytes)) |_| {
- try unpack.primitive(undef_u8);
- }
- // ...and an undef int for the leftover bits.
- if (bits == 0) return;
- const bits_ty = try pt.intType(.unsigned, @intCast(bits));
- const bits_val = try pt.undefValue(bits_ty);
- try unpack.primitive(bits_val);
- }
-
- fn primitive(unpack: *UnpackValueBits, val: Value) BitCastError!void {
- const pt = unpack.pt;
- const zcu = pt.zcu;
-
- if (unpack.remaining_bits == 0) {
- return;
- }
-
- const ty = val.typeOf(pt.zcu);
- const bit_size = ty.bitSize(zcu);
-
- // Note that this skips all zero-bit types.
- if (unpack.skip_bits >= bit_size) {
- unpack.skip_bits -= bit_size;
- return;
- }
-
- if (unpack.skip_bits > 0) {
- const skip = unpack.skip_bits;
- unpack.skip_bits = 0;
- return unpack.splitPrimitive(val, skip, bit_size - skip);
- }
-
- if (unpack.remaining_bits < bit_size) {
- return unpack.splitPrimitive(val, 0, unpack.remaining_bits);
- }
-
- unpack.remaining_bits -|= bit_size;
-
- try unpack.unpacked.append(val.toIntern());
- }
-
- fn splitPrimitive(unpack: *UnpackValueBits, val: Value, bit_offset: u64, bit_count: u64) BitCastError!void {
- const pt = unpack.pt;
- const zcu = pt.zcu;
- const ty = val.typeOf(pt.zcu);
-
- const val_bits = ty.bitSize(zcu);
- assert(bit_offset + bit_count <= val_bits);
-
- switch (pt.zcu.intern_pool.indexToKey(val.toIntern())) {
- // In the `ptr` case, this will return `error.ReinterpretDeclRef`
- // if we're trying to split a non-integer pointer value.
- .int, .float, .enum_tag, .ptr, .opt => {
- // This @intCast is okay because no primitive can exceed the size of a u16.
- const int_ty = try unpack.pt.intType(.unsigned, @intCast(bit_count));
- const buf = try unpack.arena.alloc(u8, @intCast((val_bits + 7) / 8));
- try val.writeToPackedMemory(zcu, buf, 0);
- const sub_val = try Value.readFromPackedMemory(int_ty, unpack.pt, buf, @intCast(bit_offset), unpack.arena);
- try unpack.primitive(sub_val);
- },
- .undef => try unpack.padding(bit_count),
- // The only values here with runtime bits are `true` and `false.
- // These are both 1 bit, so will never need truncating.
- .simple_value => unreachable,
- else => unreachable, // zero-bit or not primitives
- }
- }
-};
-
-/// Given a sequence of bit-packed values in packed memory (see `UnpackValueBits`),
-/// reconstructs a value of an arbitrary type, with correct handling of `undefined`
-/// values and of pointers which align in virtual memory.
-const PackValueBits = struct {
- pt: Zcu.PerThread,
- arena: Allocator,
- bit_offset: u64 = 0,
- unpacked: []const InternPool.Index,
-
- fn get(pack: *PackValueBits, ty: Type) BitCastError!Value {
- const pt = pack.pt;
- const zcu = pt.zcu;
- const endian = zcu.getTarget().cpu.arch.endian();
- const ip = &zcu.intern_pool;
- const arena = pack.arena;
- switch (ty.zigTypeTag(zcu)) {
- .vector => {
- // Elements are bit-packed.
- const len = ty.arrayLen(zcu);
- const elem_ty = ty.childType(zcu);
- const elems = try arena.alloc(InternPool.Index, @intCast(len));
- // We reverse vector elements in packed memory on BE targets.
- switch (endian) {
- .little => for (elems) |*elem| {
- elem.* = (try pack.get(elem_ty)).toIntern();
- },
- .big => {
- var i = elems.len;
- while (i > 0) {
- i -= 1;
- elems[i] = (try pack.get(elem_ty)).toIntern();
- }
- },
- }
- return pt.aggregateValue(ty, elems);
- },
- .array => {
- // Each element is padded up to its ABI size. The final element does not have trailing padding.
- const len = ty.arrayLen(zcu);
- const elem_ty = ty.childType(zcu);
- const maybe_sent = ty.sentinel(zcu);
- const pad_bits = elem_ty.abiSize(zcu) * 8 - elem_ty.bitSize(zcu);
- const elems = try arena.alloc(InternPool.Index, @intCast(len));
-
- if (endian == .big and maybe_sent != null) {
- // TODO: validate sentinel was preserved!
- try pack.padding(elem_ty.bitSize(zcu));
- if (len != 0) try pack.padding(pad_bits);
- }
-
- for (0..elems.len) |i| {
- const real_idx = switch (endian) {
- .little => i,
- .big => len - i - 1,
- };
- elems[@intCast(real_idx)] = (try pack.get(elem_ty)).toIntern();
- if (i != len - 1) try pack.padding(pad_bits);
- }
-
- if (endian == .little and maybe_sent != null) {
- // TODO: validate sentinel was preserved!
- if (len != 0) try pack.padding(pad_bits);
- try pack.padding(elem_ty.bitSize(zcu));
- }
-
- return pt.aggregateValue(ty, elems);
- },
- .@"struct" => switch (ty.containerLayout(zcu)) {
- .auto => unreachable, // ill-defined layout
- .@"extern" => {
- const elems = try arena.alloc(InternPool.Index, ty.structFieldCount(zcu));
- @memset(elems, .none);
- switch (endian) {
- .little => {
- var cur_bit_off: u64 = 0;
- var it = zcu.typeToStruct(ty).?.iterateRuntimeOrder(ip);
- while (it.next()) |field_idx| {
- const want_bit_off = ty.structFieldOffset(field_idx, zcu) * 8;
- try pack.padding(want_bit_off - cur_bit_off);
- const field_ty = ty.fieldType(field_idx, zcu);
- elems[field_idx] = (try pack.get(field_ty)).toIntern();
- cur_bit_off = want_bit_off + field_ty.bitSize(zcu);
- }
- try pack.padding(ty.bitSize(zcu) - cur_bit_off);
- },
- .big => {
- var cur_bit_off: u64 = ty.bitSize(zcu);
- var it = zcu.typeToStruct(ty).?.iterateRuntimeOrderReverse(ip);
- while (it.next()) |field_idx| {
- const field_ty = ty.fieldType(field_idx, zcu);
- const want_bit_off = ty.structFieldOffset(field_idx, zcu) * 8 + field_ty.bitSize(zcu);
- try pack.padding(cur_bit_off - want_bit_off);
- elems[field_idx] = (try pack.get(field_ty)).toIntern();
- cur_bit_off = want_bit_off - field_ty.bitSize(zcu);
- }
- assert(cur_bit_off == 0);
- },
- }
- // Any fields which do not have runtime bits should be OPV or comptime fields.
- // Fill those values now.
- for (elems, 0..) |*elem, field_idx| {
- if (elem.* != .none) continue;
- const val = (try ty.structFieldValueComptime(pt, field_idx)).?;
- elem.* = val.toIntern();
- }
- return pt.aggregateValue(ty, elems);
- },
- .@"packed" => {
- const backing_int_val = try pack.primitive(ty.bitpackBackingInt(zcu));
- if (backing_int_val.isUndef(zcu)) return pt.undefValue(ty);
- return pt.bitpackValue(ty, backing_int_val);
- },
- },
- .@"union" => switch (ty.containerLayout(zcu)) {
- .auto => unreachable, // ill-defined layout
- .@"extern" => {
- // We will attempt to read as the backing representation. If this emits
- // `error.ReinterpretDeclRef`, we will try each union field, preferring larger ones.
- // We will also attempt smaller fields when we get `undefined`, as if some bits are
- // defined we want to include them.
- // TODO: this is very very bad. We need a more sophisticated union representation.
-
- const prev_unpacked = pack.unpacked;
- const prev_bit_offset = pack.bit_offset;
-
- const backing_ty = try ty.externUnionBackingType(pt);
-
- backing: {
- const backing_val = pack.get(backing_ty) catch |err| switch (err) {
- error.ReinterpretDeclRef => {
- pack.unpacked = prev_unpacked;
- pack.bit_offset = prev_bit_offset;
- break :backing;
- },
- else => |e| return e,
- };
- if (backing_val.isUndef(zcu)) {
- pack.unpacked = prev_unpacked;
- pack.bit_offset = prev_bit_offset;
- break :backing;
- }
- return Value.fromInterned(try pt.internUnion(.{
- .ty = ty.toIntern(),
- .tag = .none,
- .val = backing_val.toIntern(),
- }));
- }
-
- const field_order = try pack.arena.alloc(u32, ty.unionTagTypeHypothetical(zcu).enumFieldCount(zcu));
- for (field_order, 0..) |*f, i| f.* = @intCast(i);
- // Sort `field_order` to put the fields with the largest bit sizes first.
- const SizeSortCtx = struct {
- zcu: *Zcu,
- field_types: []const InternPool.Index,
- fn lessThan(ctx: @This(), a_idx: u32, b_idx: u32) bool {
- const a_ty = Type.fromInterned(ctx.field_types[a_idx]);
- const b_ty = Type.fromInterned(ctx.field_types[b_idx]);
- return a_ty.bitSize(ctx.zcu) > b_ty.bitSize(ctx.zcu);
- }
- };
- std.mem.sortUnstable(u32, field_order, SizeSortCtx{
- .zcu = zcu,
- .field_types = zcu.typeToUnion(ty).?.field_types.get(ip),
- }, SizeSortCtx.lessThan);
-
- const padding_after = endian == .little or ty.containerLayout(zcu) == .@"packed";
-
- for (field_order) |field_idx| {
- const field_ty = Type.fromInterned(zcu.typeToUnion(ty).?.field_types.get(ip)[field_idx]);
- const pad_bits = ty.bitSize(zcu) - field_ty.bitSize(zcu);
- if (!padding_after) try pack.padding(pad_bits);
- const field_val = pack.get(field_ty) catch |err| switch (err) {
- error.ReinterpretDeclRef => {
- pack.unpacked = prev_unpacked;
- pack.bit_offset = prev_bit_offset;
- continue;
- },
- else => |e| return e,
- };
- if (padding_after) try pack.padding(pad_bits);
- if (field_val.isUndef(zcu)) {
- pack.unpacked = prev_unpacked;
- pack.bit_offset = prev_bit_offset;
- continue;
- }
- const tag_val = try pt.enumValueFieldIndex(ty.unionTagTypeHypothetical(zcu), field_idx);
- return Value.fromInterned(try pt.internUnion(.{
- .ty = ty.toIntern(),
- .tag = tag_val.toIntern(),
- .val = field_val.toIntern(),
- }));
- }
-
- // No field could represent the value. Just do whatever happens when we try to read
- // the backing type - either `undefined` or `error.ReinterpretDeclRef`.
- const backing_val = try pack.get(backing_ty);
- return Value.fromInterned(try pt.internUnion(.{
- .ty = ty.toIntern(),
- .tag = .none,
- .val = backing_val.toIntern(),
- }));
- },
- .@"packed" => {
- const backing_int_val = try pack.primitive(ty.bitpackBackingInt(zcu));
- if (backing_int_val.isUndef(zcu)) return pt.undefValue(ty);
- return pt.bitpackValue(ty, backing_int_val);
- },
- },
- else => return pack.primitive(ty),
- }
- }
-
- fn padding(pack: *PackValueBits, pad_bits: u64) BitCastError!void {
- _ = pack.prepareBits(pad_bits);
- }
-
- fn primitive(pack: *PackValueBits, want_ty: Type) BitCastError!Value {
- const pt = pack.pt;
- const zcu = pt.zcu;
-
- if (try want_ty.onePossibleValue(pt)) |opv| return opv;
-
- const vals, const bit_offset = pack.prepareBits(want_ty.bitSize(zcu));
-
- for (vals) |val| {
- if (!Value.fromInterned(val).isUndef(zcu)) break;
- } else {
- // All bits of the value are `undefined`.
- return pt.undefValue(want_ty);
- }
-
- // TODO: we need to decide how to handle partially-undef values here.
- // Currently, a value with some undefined bits becomes `0xAA` so that we
- // preserve the well-defined bits, because we can't currently represent
- // a partially-undefined primitive (e.g. an int with some undef bits).
- // In future, we probably want to take one of these two routes:
- // * Define that if any bits are `undefined`, the entire value is `undefined`.
- // This is a major breaking change, and probably a footgun.
- // * Introduce tracking for partially-undef values at comptime.
- // This would complicate a lot of operations in Sema, such as basic
- // arithmetic.
- // This design complexity is tracked by #19634.
-
- ptr_cast: {
- if (vals.len != 1) break :ptr_cast;
- const val = Value.fromInterned(vals[0]);
- if (!val.typeOf(zcu).isPtrAtRuntime(zcu)) break :ptr_cast;
- if (!want_ty.isPtrAtRuntime(zcu)) break :ptr_cast;
- return pt.getCoerced(val, want_ty);
- }
-
- // Reinterpret via an in-memory buffer.
-
- var buf_bits: u64 = 0;
- for (vals) |ip_val| {
- const val = Value.fromInterned(ip_val);
- const ty = val.typeOf(pt.zcu);
- buf_bits += ty.bitSize(zcu);
- }
-
- const buf = try pack.arena.alloc(u8, @intCast((buf_bits + 7) / 8));
- // We will skip writing undefined values, so mark the buffer as `0xAA` so we get "undefined" bits.
- @memset(buf, 0xAA);
- var cur_bit_off: usize = 0;
- for (vals) |ip_val| {
- const val = Value.fromInterned(ip_val);
- const ty = val.typeOf(zcu);
- if (!val.isUndef(zcu)) {
- try val.writeToPackedMemory(zcu, buf, cur_bit_off);
- }
- cur_bit_off += @intCast(ty.bitSize(zcu));
- }
-
- return Value.readFromPackedMemory(want_ty, pt, buf, @intCast(bit_offset), pack.arena);
- }
-
- fn prepareBits(pack: *PackValueBits, need_bits: u64) struct { []const InternPool.Index, u64 } {
- if (need_bits == 0) return .{ &.{}, 0 };
-
- const pt = pack.pt;
- const zcu = pt.zcu;
-
- var bits: u64 = 0;
- var len: usize = 0;
- while (bits < pack.bit_offset + need_bits) {
- bits += Value.fromInterned(pack.unpacked[len]).typeOf(pt.zcu).bitSize(zcu);
- len += 1;
- }
-
- const result_vals = pack.unpacked[0..len];
- const result_offset = pack.bit_offset;
-
- const extra_bits = bits - pack.bit_offset - need_bits;
- if (extra_bits == 0) {
- pack.unpacked = pack.unpacked[len..];
- pack.bit_offset = 0;
- } else {
- pack.unpacked = pack.unpacked[len - 1 ..];
- pack.bit_offset = Value.fromInterned(pack.unpacked[0]).typeOf(pt.zcu).bitSize(zcu) - extra_bits;
- }
-
- return .{ result_vals, result_offset };
- }
-};
-
-const std = @import("std");
-const Allocator = std.mem.Allocator;
-const assert = std.debug.assert;
-
-const Sema = @import("../Sema.zig");
-const Zcu = @import("../Zcu.zig");
-const InternPool = @import("../InternPool.zig");
-const Type = @import("../Type.zig");
-const Value = @import("../Value.zig");
-const CompileError = Zcu.CompileError;
diff --git a/src/Sema/comptime_ptr_access.zig b/src/Sema/comptime_ptr_access.zig
index 396cbc0d5ae96fa8731550410217bd1da25070db..4df8dafbe03bddd71ca212af1cf1ebebfdfe1e04 100644
--- a/src/Sema/comptime_ptr_access.zig
+++ b/src/Sema/comptime_ptr_access.zig
@@ -14,27 +14,46 @@ pub const ComptimeLoadResult = union(enum) {
pub fn loadComptimePtr(sema: *Sema, block: *Block, src: LazySrcLoc, ptr: Value) !ComptimeLoadResult {
const pt = sema.pt;
const zcu = pt.zcu;
+
const ptr_info = ptr.typeOf(pt.zcu).ptrInfo(pt.zcu);
- // TODO: host size for vectors is terrible
- const host_bits = switch (ptr_info.flags.vector_index) {
- .none => ptr_info.packed_offset.host_size * 8,
- else => ptr_info.packed_offset.host_size * Type.fromInterned(ptr_info.child).bitSize(zcu),
- };
- const bit_offset = if (host_bits != 0) bit_offset: {
- const child_bits = Type.fromInterned(ptr_info.child).bitSize(zcu);
- const bit_offset = ptr_info.packed_offset.bit_offset + switch (ptr_info.flags.vector_index) {
- .none => 0,
- else => |idx| switch (pt.zcu.getTarget().cpu.arch.endian()) {
- .little => child_bits * @intFromEnum(idx),
- .big => host_bits - child_bits * (@intFromEnum(idx) + 1), // element order reversed on big endian
- },
- };
- if (child_bits + bit_offset > host_bits) {
+ const elem_ty: Type = .fromInterned(ptr_info.child);
+ const host_size = ptr_info.packed_offset.host_size;
+
+ if (host_size == 0) {
+ return loadComptimePtrInner(sema, block, src, ptr, elem_ty, 0);
+ }
+
+ assert(elem_ty.hasBitRepresentation(zcu));
+ if (ptr_info.flags.vector_index == .none) {
+ if (ptr_info.packed_offset.bit_offset + elem_ty.bitSize(zcu) > host_size * 8) {
return .exceeds_host_size;
}
- break :bit_offset bit_offset;
- } else 0;
- return loadComptimePtrInner(sema, block, src, ptr, bit_offset, host_bits, Type.fromInterned(ptr_info.child), 0);
+ const load_ty: Type = try pt.intType(.unsigned, host_size * 8);
+ const backing_int_mv = switch (try loadComptimePtrInner(sema, block, src, ptr, load_ty, 0)) {
+ else => |result| return result,
+ .success => |mv| mv,
+ };
+ const backing_int_val = try backing_int_mv.intern(pt, sema.arena);
+ const buf = try sema.arena.alloc(u8, host_size);
+ @memset(buf, 0);
+ backing_int_val.writeToPackedMemory(zcu, buf, 0);
+ const result_val: Value = try .readFromPackedMemory(elem_ty, pt, buf, ptr_info.packed_offset.bit_offset);
+ return .{ .success = .{ .interned = result_val.toIntern() } };
+ }
+ if (@intFromEnum(ptr_info.flags.vector_index) >= host_size) {
+ return .exceeds_host_size;
+ }
+ const load_ty: Type = try pt.vectorType(.{
+ .len = host_size,
+ .child = elem_ty.toIntern(),
+ });
+ const vector_mv = switch (try loadComptimePtrInner(sema, block, src, ptr, load_ty, 0)) {
+ else => |result| return result,
+ .success => |mv| mv,
+ };
+ const vector_val = try vector_mv.intern(pt, sema.arena);
+ const result_val = try vector_val.elemValue(pt, @intFromEnum(ptr_info.flags.vector_index));
+ return .{ .success = .{ .interned = result_val.toIntern() } };
}
pub const ComptimeStoreResult = union(enum) {
@@ -52,7 +71,8 @@ pub const ComptimeStoreResult = union(enum) {
};
/// Perform a comptime load of value `store_val` to a pointer.
-/// The pointer's type is ignored.
+///
+/// Asserts that the type of `store_val` equals the element type of the pointer type.
pub fn storeComptimePtr(
sema: *Sema,
block: *Block,
@@ -62,42 +82,84 @@ pub fn storeComptimePtr(
) !ComptimeStoreResult {
const pt = sema.pt;
const zcu = pt.zcu;
- const ptr_info = ptr.typeOf(zcu).ptrInfo(zcu);
- assert(store_val.typeOf(zcu).toIntern() == ptr_info.child);
- {
- const store_ty: Type = .fromInterned(ptr_info.child);
- if (!store_ty.comptimeOnly(zcu) and !store_ty.hasRuntimeBits(zcu)) {
- // zero-bit store; nothing to do
- return .success;
- }
+ const ptr_info = ptr.typeOf(pt.zcu).ptrInfo(pt.zcu);
+ const elem_ty: Type = .fromInterned(ptr_info.child);
+ const host_size = ptr_info.packed_offset.host_size;
+ assert(store_val.typeOf(zcu).toIntern() == elem_ty.toIntern());
+
+ if (host_size == 0) {
+ return storeComptimePtrInner(sema, block, src, ptr, store_val);
}
- // TODO: host size for vectors is terrible
- const host_bits = switch (ptr_info.flags.vector_index) {
- .none => ptr_info.packed_offset.host_size * 8,
- else => ptr_info.packed_offset.host_size * Type.fromInterned(ptr_info.child).bitSize(zcu),
- };
- const bit_offset = ptr_info.packed_offset.bit_offset + switch (ptr_info.flags.vector_index) {
- .none => 0,
- else => |idx| switch (zcu.getTarget().cpu.arch.endian()) {
- .little => Type.fromInterned(ptr_info.child).bitSize(zcu) * @intFromEnum(idx),
- .big => host_bits - Type.fromInterned(ptr_info.child).bitSize(zcu) * (@intFromEnum(idx) + 1), // element order reversed on big endian
- },
- };
- const pseudo_store_ty = if (host_bits > 0) t: {
- const need_bits = Type.fromInterned(ptr_info.child).bitSize(zcu);
- if (need_bits + bit_offset > host_bits) {
+ assert(elem_ty.hasBitRepresentation(zcu));
+ if (ptr_info.flags.vector_index == .none) {
+ if (ptr_info.packed_offset.bit_offset + elem_ty.bitSize(zcu) > host_size * 8) {
return .exceeds_host_size;
}
- break :t try sema.pt.intType(.unsigned, @intCast(host_bits));
- } else Type.fromInterned(ptr_info.child);
+ const backing_ty: Type = try pt.intType(.unsigned, host_size * 8);
+ const backing_int_mv = switch (try loadComptimePtrInner(sema, block, src, ptr, backing_ty, 0)) {
+ .success => |mv| mv,
+ .runtime_load => return .runtime_store,
+ inline else => |payload, tag| return @unionInit(ComptimeStoreResult, @tagName(tag), payload),
+ };
+ const old_backing_int_val = try backing_int_mv.intern(pt, sema.arena);
+ const buf = try sema.arena.alloc(u8, host_size);
+ @memset(buf, 0);
+ old_backing_int_val.writeToPackedMemory(zcu, buf, 0);
+ // Write the new element...
+ store_val.writeToPackedMemory(zcu, buf, ptr_info.packed_offset.bit_offset);
+ // ...then read the resulting backing integer value...
+ const new_backing_int_val: Value = try .readFromPackedMemory(backing_ty, pt, buf, 0);
+ // ...and store that back into memory
+ return storeComptimePtrInner(sema, block, src, ptr, new_backing_int_val);
+ }
- const strat = try prepareComptimePtrStore(sema, block, src, ptr, pseudo_store_ty, 0);
+ if (@intFromEnum(ptr_info.flags.vector_index) >= host_size) {
+ return .exceeds_host_size;
+ }
+ const vec_ty: Type = try pt.vectorType(.{
+ .len = host_size,
+ .child = elem_ty.toIntern(),
+ });
+ const vector_mv = switch (try loadComptimePtrInner(sema, block, src, ptr, vec_ty, 0)) {
+ .success => |mv| mv,
+ .runtime_load => return .runtime_store,
+ inline else => |payload, tag| return @unionInit(ComptimeStoreResult, @tagName(tag), payload),
+ };
+ const old_vector_val = try vector_mv.intern(pt, sema.arena);
+ const elems_buf = try sema.arena.alloc(InternPool.Index, host_size);
+ for (elems_buf, 0..) |*elem, elem_index| {
+ const elem_val = try old_vector_val.elemValue(pt, elem_index);
+ elem.* = elem_val.toIntern();
+ }
+ elems_buf[@intFromEnum(ptr_info.flags.vector_index)] = store_val.toIntern();
+ const new_vector_val = try pt.aggregateValue(vec_ty, elems_buf);
+ return storeComptimePtrInner(sema, block, src, ptr, new_vector_val);
+}
+
+/// Like `storeComptimePtr`, except ignores the type of `ptr`, instead treating it as a single-item
+/// pointer to `store_val.typeOf(zcu)`.
+fn storeComptimePtrInner(
+ sema: *Sema,
+ block: *Block,
+ src: LazySrcLoc,
+ ptr: Value,
+ store_val: Value,
+) !ComptimeStoreResult {
+ const pt = sema.pt;
+ const zcu = pt.zcu;
+ const store_ty = store_val.typeOf(zcu);
+
+ if (store_ty.classify(zcu) == .one_possible_value) {
+ // zero-bit store; nothing to do
+ return .success;
+ }
+
+ const strat = try prepareComptimePtrStore(sema, block, src, ptr, store_ty, 0);
// Propagate errors and handle comptime fields.
switch (strat) {
- .direct, .index, .flat_index, .reinterpret => {},
.comptime_field => {
// To "store" to a comptime field, just perform a load of the field
// and see if the store value matches.
@@ -125,79 +187,60 @@ pub fn storeComptimePtr(
.inactive_union_field => return .inactive_union_field,
.needed_well_defined => |ty| return .{ .needed_well_defined = ty },
.out_of_bounds => |ty| return .{ .out_of_bounds = ty },
- }
-
- // Check the store is not inside a runtime condition
- try checkComptimeVarStore(sema, block, src, strat.alloc());
- if (host_bits == 0) {
- // We can attempt a direct store depending on the strategy.
- switch (strat) {
- .direct => |direct| {
- const want_ty = direct.val.typeOf(zcu);
- const coerced_store_val = try pt.getCoerced(store_val, want_ty);
- direct.val.* = .{ .interned = coerced_store_val.toIntern() };
- return .success;
- },
- .index => |index| {
- const want_ty = index.val.typeOf(zcu).childType(zcu);
- const coerced_store_val = try pt.getCoerced(store_val, want_ty);
- try index.val.setElem(pt, sema.arena, @intCast(index.elem_index), .{ .interned = coerced_store_val.toIntern() });
- return .success;
- },
- .flat_index => |flat| {
- const store_elems = store_val.typeOf(zcu).arrayBase(zcu)[1];
- const flat_elems = try sema.arena.alloc(InternPool.Index, @intCast(store_elems));
- {
- var next_idx: u64 = 0;
- var skip: u64 = 0;
- try flattenArray(sema, .{ .interned = store_val.toIntern() }, &skip, &next_idx, flat_elems);
- }
- for (flat_elems, 0..) |elem, idx| {
- // TODO: recursiveIndex in a loop does a lot of redundant work!
- // Better would be to gather all the store targets into an array.
- var index: u64 = flat.flat_elem_index + idx;
- const val_ptr, const final_idx = (try recursiveIndex(sema, flat.val, &index)).?;
- try val_ptr.setElem(pt, sema.arena, @intCast(final_idx), .{ .interned = elem });
- }
- return .success;
- },
- .reinterpret => {},
- else => unreachable,
- }
- }
-
- // Either there is a bit offset, or the strategy required reinterpreting.
- // Therefore, we must perform a bitcast.
+ .direct => |direct| {
+ try checkComptimeVarStore(sema, block, src, direct.alloc);
+ const want_ty = direct.val.typeOf(zcu);
+ const coerced_store_val = try pt.getCoerced(store_val, want_ty);
+ direct.val.* = .{ .interned = coerced_store_val.toIntern() };
+ return .success;
+ },
- const val_ptr: *MutableValue, const byte_offset: u64 = switch (strat) {
- .direct => |direct| .{ direct.val, 0 },
- .index => |index| .{
- index.val,
- index.elem_index * index.val.typeOf(zcu).childType(zcu).abiSize(zcu),
+ .index => |index| {
+ try checkComptimeVarStore(sema, block, src, index.alloc);
+ const want_ty = index.val.typeOf(zcu).childType(zcu);
+ const coerced_store_val = try pt.getCoerced(store_val, want_ty);
+ try index.val.setElem(pt, sema.arena, @intCast(index.elem_index), .{ .interned = coerced_store_val.toIntern() });
+ return .success;
},
- .flat_index => |flat| .{ flat.val, flat.flat_elem_index * flat.val.typeOf(zcu).arrayBase(zcu)[0].abiSize(zcu) },
- .reinterpret => |reinterpret| .{ reinterpret.val, reinterpret.byte_offset },
- else => unreachable,
- };
- if (!val_ptr.typeOf(zcu).hasWellDefinedLayout(zcu)) {
- return .{ .needed_well_defined = val_ptr.typeOf(zcu) };
- }
+ .flat_index => |flat| {
+ try checkComptimeVarStore(sema, block, src, flat.alloc);
+ const store_elems = store_val.typeOf(zcu).arrayBase(zcu)[1];
+ const flat_elems = try sema.arena.alloc(InternPool.Index, @intCast(store_elems));
+ {
+ var next_idx: u64 = 0;
+ var skip: u64 = 0;
+ try flattenArray(sema, .{ .interned = store_val.toIntern() }, &skip, &next_idx, flat_elems);
+ }
+ for (flat_elems, 0..) |elem, idx| {
+ // TODO: recursiveIndex in a loop does a lot of redundant work!
+ // Better would be to gather all the store targets into an array.
+ var index: u64 = flat.flat_elem_index + idx;
+ const val_ptr, const final_idx = (try recursiveIndex(sema, flat.val, &index)).?;
+ try val_ptr.setElem(pt, sema.arena, @intCast(final_idx), .{ .interned = elem });
+ }
+ return .success;
+ },
- if (!store_val.typeOf(zcu).hasWellDefinedLayout(zcu)) {
- return .{ .needed_well_defined = store_val.typeOf(zcu) };
+ .reinterpret => |reinterpret| {
+ try checkComptimeVarStore(sema, block, src, reinterpret.alloc);
+ if (!reinterpret.val.typeOf(zcu).hasWellDefinedLayout(zcu)) {
+ return .{ .needed_well_defined = reinterpret.val.typeOf(zcu) };
+ }
+ if (!store_ty.hasWellDefinedLayout(zcu)) {
+ return .{ .needed_well_defined = store_ty };
+ }
+ const old_val = try reinterpret.val.intern(pt, sema.arena);
+ const new_val = try sema.spliceMemory(
+ old_val,
+ store_val,
+ reinterpret.byte_offset,
+ ) orelse return .runtime_store;
+ reinterpret.val.* = .{ .interned = new_val.toIntern() };
+ return .success;
+ },
}
-
- const new_val = try sema.bitCastSpliceVal(
- try val_ptr.intern(pt, sema.arena),
- store_val,
- byte_offset,
- host_bits,
- bit_offset,
- ) orelse return .runtime_store;
- val_ptr.* = .{ .interned = new_val.toIntern() };
- return .success;
}
/// Perform a comptime load of type `load_ty` from a pointer.
@@ -207,8 +250,6 @@ fn loadComptimePtrInner(
block: *Block,
src: LazySrcLoc,
ptr_val: Value,
- bit_offset: u64,
- host_bits: u64,
load_ty: Type,
/// If `load_ty` is an array, this is the number of array elements to skip
/// before `load_ty`. Otherwise, it is ignored and may be `undefined`.
@@ -244,7 +285,7 @@ fn loadComptimePtrInner(
.eu_payload => |base_ptr_ip| val: {
const base_ptr = Value.fromInterned(base_ptr_ip);
const base_ty = base_ptr.typeOf(zcu).childType(zcu);
- switch (try loadComptimePtrInner(sema, block, src, base_ptr, 0, 0, base_ty, undefined)) {
+ switch (try loadComptimePtrInner(sema, block, src, base_ptr, base_ty, undefined)) {
.success => |eu_val| switch (eu_val.unpackErrorUnion(zcu)) {
.undef => return .undef,
.err => |err| return .{ .err_payload = err },
@@ -256,7 +297,7 @@ fn loadComptimePtrInner(
.opt_payload => |base_ptr_ip| val: {
const base_ptr = Value.fromInterned(base_ptr_ip);
const base_ty = base_ptr.typeOf(zcu).childType(zcu);
- switch (try loadComptimePtrInner(sema, block, src, base_ptr, 0, 0, base_ty, undefined)) {
+ switch (try loadComptimePtrInner(sema, block, src, base_ptr, base_ty, undefined)) {
.success => |eu_val| switch (eu_val.unpackOptional(zcu)) {
.undef => return .undef,
.null => return .null_payload,
@@ -283,7 +324,7 @@ fn loadComptimePtrInner(
.child = base_ty.toIntern(),
});
- switch (try loadComptimePtrInner(sema, block, src, base_ptr, 0, 0, want_ty, base_index.index)) {
+ switch (try loadComptimePtrInner(sema, block, src, base_ptr, want_ty, base_index.index)) {
.success => |arr_val| break :val arr_val,
else => |err| return err,
}
@@ -293,7 +334,7 @@ fn loadComptimePtrInner(
const base_ty = base_ptr.typeOf(zcu).childType(zcu);
// Field of a slice, or of an auto-layout struct or union.
- const agg_val = switch (try loadComptimePtrInner(sema, block, src, base_ptr, 0, 0, base_ty, undefined)) {
+ const agg_val = switch (try loadComptimePtrInner(sema, block, src, base_ptr, base_ty, undefined)) {
.success => |val| val,
else => |err| return err,
};
@@ -324,7 +365,7 @@ fn loadComptimePtrInner(
},
};
- if (ptr.byte_offset == 0 and host_bits == 0) {
+ if (ptr.byte_offset == 0) {
if (load_ty.zigTypeTag(zcu) != .array or array_offset == 0) {
if (.ok == try sema.coerceInMemoryAllowed(
block,
@@ -343,8 +384,6 @@ fn loadComptimePtrInner(
}
restructure_array: {
- if (host_bits != 0) break :restructure_array;
-
// We might also be changing the length of an array, or restructuring it.
// e.g. [1][2][3]T -> [3][2]T.
// This case is important because it's permitted for types with ill-defined layouts.
@@ -402,7 +441,7 @@ fn loadComptimePtrInner(
cur_offset += load_ty.childType(zcu).abiSize(zcu) * array_offset;
}
- const need_bytes = if (host_bits > 0) (host_bits + 7) / 8 else load_ty.abiSize(zcu);
+ const need_bytes = load_ty.abiSize(zcu);
if (cur_offset + need_bytes > cur_val.typeOf(zcu).abiSize(zcu)) {
return .{ .out_of_bounds = cur_val.typeOf(zcu) };
@@ -422,6 +461,7 @@ fn loadComptimePtrInner(
.undefined,
.enum_literal,
.@"opaque",
+ .spirv,
.@"fn",
.error_union,
=> unreachable, // ill-defined layout
@@ -452,7 +492,7 @@ fn loadComptimePtrInner(
},
.@"struct" => switch (cur_ty.containerLayout(zcu)) {
.auto => unreachable, // ill-defined layout
- .@"packed" => break, // let the bitcast logic handle this
+ .@"packed" => break, // let the memory reinterpret logic handle this
.@"extern" => for (0..cur_ty.structFieldCount(zcu)) |field_idx| {
const start_off = cur_ty.structFieldOffset(field_idx, zcu);
const end_off = start_off + cur_ty.fieldType(field_idx, zcu).abiSize(zcu);
@@ -465,9 +505,9 @@ fn loadComptimePtrInner(
},
.@"union" => switch (cur_ty.containerLayout(zcu)) {
.auto => unreachable, // ill-defined layout
- .@"packed" => break, // let the bitcast logic handle this
+ .@"packed" => break, // let the memory reinterpret logic handle this
.@"extern" => {
- // TODO: we have to let bitcast logic handle this for now.
+ // TODO: we have to let the memory reinterpret logic handle this for now.
// Otherwise, we might traverse into a union field which doesn't allow pointers.
// Figure out a solution!
if (true) break;
@@ -494,27 +534,13 @@ fn loadComptimePtrInner(
// Fast path: check again if we're now at the type we want to load.
// If so, just return the loaded value.
- if (cur_offset == 0 and host_bits == 0 and cur_val.typeOf(zcu).toIntern() == load_ty.toIntern()) {
+ if (cur_offset == 0 and cur_val.typeOf(zcu).toIntern() == load_ty.toIntern()) {
return .{ .success = cur_val };
}
- var bitcast_src_val = try cur_val.intern(sema.pt, sema.arena);
-
- if (host_bits != 0) {
- const src_bit_size = bitcast_src_val.typeOf(zcu).bitSize(zcu);
- if (src_bit_size > host_bits) {
- const truncate_ty = try pt.intType(.unsigned, @intCast(host_bits));
- bitcast_src_val = try pt.getCoerced(bitcast_src_val, truncate_ty);
- }
- }
-
- const result_val = try sema.bitCastVal(
- bitcast_src_val,
- load_ty,
- cur_offset,
- host_bits,
- bit_offset,
- ) orelse return .runtime_load;
+ // Otherwise, use the memory reinterpretation logic to pull out the bytes we need.
+ const reinterpret_val = try cur_val.intern(pt, sema.arena);
+ const result_val = try sema.castMemory(reinterpret_val, load_ty, cur_offset) orelse return .runtime_load;
return .{ .success = .{ .interned = result_val.toIntern() } };
}
@@ -545,7 +571,7 @@ const ComptimeStoreStrategy = union(enum) {
val: *MutableValue,
flat_elem_index: u64,
},
- /// This value should be reinterpreted using bitcast logic to perform the
+ /// This value should be reinterpreted using `Sema.spliceMemory` to perform
/// store. Only returned if `store_ty` and the type of `val` both have
/// well-defined layouts.
reinterpret: struct {
@@ -854,6 +880,7 @@ fn prepareComptimePtrStore(
.undefined,
.enum_literal,
.@"opaque",
+ .spirv,
.@"fn",
.error_union,
=> unreachable, // ill-defined layout
@@ -884,7 +911,7 @@ fn prepareComptimePtrStore(
},
.@"struct" => switch (cur_ty.containerLayout(zcu)) {
.auto => unreachable, // ill-defined layout
- .@"packed" => break, // let the bitcast logic handle this
+ .@"packed" => break, // let the memory reinterp logic handle this
.@"extern" => for (0..cur_ty.structFieldCount(zcu)) |field_idx| {
const start_off = cur_ty.structFieldOffset(field_idx, zcu);
const end_off = start_off + cur_ty.fieldType(field_idx, zcu).abiSize(zcu);
@@ -897,9 +924,9 @@ fn prepareComptimePtrStore(
},
.@"union" => switch (cur_ty.containerLayout(zcu)) {
.auto => unreachable, // ill-defined layout
- .@"packed" => break, // let the bitcast logic handle this
+ .@"packed" => break, // let the memory reinterp logic handle this
.@"extern" => {
- // TODO: we have to let bitcast logic handle this for now.
+ // TODO: we have to let the memory reinterp logic handle this for now.
// Otherwise, we might traverse into a union field which doesn't allow pointers.
// Figure out a solution!
if (true) break;
diff --git a/src/Sema/reinterpret.zig b/src/Sema/reinterpret.zig
new file mode 100644
index 0000000000000000000000000000000000000000..21a5bad1abd72afc1a6c8982e9caadd1825ea824
--- /dev/null
+++ b/src/Sema/reinterpret.zig
@@ -0,0 +1,576 @@
+//! This file contains logic for bit-casting arbitrary values at comptime, including splicing
+//! bits together for comptime stores of bit-pointers. The strategy is to "flatten" values to
+//! a sequence of values in *packed* memory, and then unflatten through a combination of special
+//! cases (particularly for pointers and `undefined` values) and in-memory buffer reinterprets.
+//!
+//! This is a little awkward on big-endian targets, as non-packed datastructures (e.g. `extern struct`)
+//! have their fields reversed when represented as packed memory on such targets.
+
+/// If `host_bits` is `0`, attempts to convert the memory at offset
+/// `byte_offset` into `val` to a non-packed value of type `dest_ty`,
+/// ignoring `bit_offset`.
+///
+/// Otherwise, `byte_offset` is an offset in bytes into `val` to a
+/// non-packed value consisting of `host_bits` bits. A value of type
+/// `dest_ty` will be interpreted at a packed offset of `bit_offset`
+/// into this value.
+///
+/// Returns `null` if the operation must be performed at runtime.
+pub fn castMemory(
+ sema: *Sema,
+ val: Value,
+ dest_ty: Type,
+ byte_offset: u64,
+) CompileError!?Value {
+ const pt = sema.pt;
+ const zcu = pt.zcu;
+
+ const val_ty = val.typeOf(zcu);
+
+ if (dest_ty.toIntern() == val_ty.toIntern()) {
+ assert(byte_offset == 0);
+ return val;
+ }
+
+ val_ty.assertHasLayout(zcu);
+ dest_ty.assertHasLayout(zcu);
+
+ var unpack: UnpackValueBytes = .{
+ .pt = pt,
+ .arena = sema.arena,
+ .skip_bytes = byte_offset,
+ .remaining_bytes = dest_ty.abiSize(zcu),
+ .unpacked = .init(sema.arena),
+ };
+ unpack.add(val) catch |err| switch (err) {
+ error.ReinterpretDeclRef => return null,
+ error.OutOfMemory => |e| return e,
+ };
+
+ var pack: PackValueBytes = .{
+ .pt = pt,
+ .arena = sema.arena,
+ .unpacked = unpack.unpacked.items,
+ };
+ return pack.get(dest_ty) catch |err| switch (err) {
+ error.ReinterpretDeclRef => return null,
+ error.OutOfMemory => |e| return e,
+ };
+}
+
+/// Splice the value `splice_val` into `val` at the given `byte_offset`, replacing overlapping bits
+/// and returning the modified value.
+pub fn spliceMemory(
+ sema: *Sema,
+ val: Value,
+ splice_val: Value,
+ byte_offset: u64,
+) CompileError!?Value {
+ const pt = sema.pt;
+ const zcu = pt.zcu;
+ const val_ty = val.typeOf(zcu);
+ const splice_val_ty = splice_val.typeOf(zcu);
+
+ val_ty.assertHasLayout(zcu);
+ splice_val_ty.assertHasLayout(zcu);
+
+ var unpack: UnpackValueBytes = .{
+ .pt = pt,
+ .arena = sema.arena,
+ .skip_bytes = 0,
+ .remaining_bytes = byte_offset,
+ .unpacked = .init(sema.arena),
+ };
+ unpack.add(val) catch |err| switch (err) {
+ error.ReinterpretDeclRef => return null,
+ error.OutOfMemory => |e| return e,
+ };
+
+ const splice_len = splice_val_ty.abiSize(zcu);
+
+ unpack.remaining_bytes = splice_len;
+ unpack.add(splice_val) catch |err| switch (err) {
+ error.ReinterpretDeclRef => return null,
+ error.OutOfMemory => |e| return e,
+ };
+
+ unpack.skip_bytes = byte_offset + splice_len;
+ unpack.remaining_bytes = val_ty.abiSize(zcu) * 8 - byte_offset - splice_len;
+ unpack.add(val) catch |err| switch (err) {
+ error.ReinterpretDeclRef => return null,
+ error.OutOfMemory => |e| return e,
+ };
+
+ var pack: PackValueBytes = .{
+ .pt = pt,
+ .arena = sema.arena,
+ .unpacked = unpack.unpacked.items,
+ };
+ return pack.get(val_ty) catch |err| switch (err) {
+ error.ReinterpretDeclRef => return null,
+ error.OutOfMemory => |e| return e,
+ };
+}
+
+/// Recurses through struct fields, array elements, etc, to get a sequence of "primitive" values
+/// which are bit-packed in memory to represent a single value. `unpacked` represents a series
+/// of values in *packed* memory - therefore, on big-endian targets, the first element of this
+/// list contains bits from the *final* byte of the value.
+const UnpackValueBytes = struct {
+ pt: Zcu.PerThread,
+ arena: Allocator,
+ skip_bytes: u64,
+ remaining_bytes: u64,
+ unpacked: std.array_list.Managed(InternPool.Index),
+
+ fn add(unpack: *UnpackValueBytes, val: Value) (error{ReinterpretDeclRef} || Allocator.Error)!void {
+ const pt = unpack.pt;
+ const zcu = pt.zcu;
+ const ip = &zcu.intern_pool;
+
+ if (unpack.remaining_bytes == 0) {
+ return;
+ }
+
+ const ty = val.typeOf(zcu);
+ const size = ty.abiSize(zcu);
+
+ if (unpack.skip_bytes >= size) {
+ unpack.skip_bytes -= size;
+ return;
+ }
+
+ switch (ip.indexToKey(val.toIntern())) {
+ .int_type,
+ .ptr_type,
+ .array_type,
+ .vector_type,
+ .opt_type,
+ .anyframe_type,
+ .error_union_type,
+ .simple_type,
+ .struct_type,
+ .tuple_type,
+ .union_type,
+ .opaque_type,
+ .spirv_type,
+ .enum_type,
+ .func_type,
+ .error_set_type,
+ .inferred_error_set_type,
+ .@"extern",
+ .func,
+ .err,
+ .error_union,
+ .enum_literal,
+ .slice,
+ .memoized_call,
+ => unreachable, // ill-defined layout or not real values
+
+ .undef,
+ .int,
+ .enum_tag,
+ .simple_value,
+ .float,
+ .ptr,
+ .opt,
+ => try unpack.primitive(val),
+
+ .bitpack => |bitpack| try unpack.primitive(.fromInterned(bitpack.backing_int_val)),
+
+ .aggregate => switch (ty.zigTypeTag(zcu)) {
+ .vector => unreachable, // ill-defined layout
+ .array => {
+ for (0..@intCast(ty.arrayLen(zcu))) |elem_index| {
+ const elem_val = try val.elemValue(pt, @intCast(elem_index));
+ try unpack.add(elem_val);
+ }
+ if (ty.sentinel(zcu)) |s| {
+ try unpack.add(s);
+ }
+ },
+ .@"struct" => switch (ty.containerLayout(zcu)) {
+ .auto => unreachable, // ill-defined layout
+ .@"packed" => unreachable, // uses `.bitpack`, not `.aggregate`
+ .@"extern" => {
+ var it = ip.loadStructType(ty.toIntern()).iterateRuntimeOrder(ip);
+ var offset: u64 = 0;
+ while (it.next()) |field_index| {
+ const pad_bytes = ty.structFieldOffset(field_index, zcu) - offset;
+ const field_val = try val.fieldValue(pt, field_index);
+ try unpack.padding(pad_bytes);
+ try unpack.add(field_val);
+ offset += pad_bytes + field_val.typeOf(zcu).abiSize(zcu);
+ }
+ try unpack.padding(size - offset);
+ },
+ },
+ else => unreachable,
+ },
+
+ .un => |un| {
+ const payload_val = Value.fromInterned(un.val);
+ const pad_bytes = size - payload_val.typeOf(zcu).abiSize(zcu);
+ try unpack.add(payload_val);
+ try unpack.padding(pad_bytes);
+ },
+ }
+ }
+
+ fn padding(unpack: *UnpackValueBytes, num_bytes: u64) Allocator.Error!void {
+ if (num_bytes == 0) return;
+ const undef_u8 = try unpack.pt.undefValue(Type.u8);
+ for (0..@intCast(num_bytes)) |_| {
+ unpack.primitive(undef_u8) catch |err| switch (err) {
+ error.OutOfMemory => |e| return e,
+ error.ReinterpretDeclRef => unreachable,
+ };
+ }
+ }
+
+ fn primitive(unpack: *UnpackValueBytes, val: Value) (error{ReinterpretDeclRef} || Allocator.Error)!void {
+ const pt = unpack.pt;
+ const zcu = pt.zcu;
+
+ if (unpack.remaining_bytes == 0) {
+ return;
+ }
+
+ const ty = val.typeOf(pt.zcu);
+ const size = ty.abiSize(zcu);
+
+ if (unpack.skip_bytes >= size) {
+ unpack.skip_bytes -= size;
+ return;
+ }
+
+ if (unpack.skip_bytes > 0) {
+ const offset = unpack.skip_bytes;
+ unpack.skip_bytes = 0;
+ return unpack.splitPrimitive(val, offset, @min(size - offset, unpack.remaining_bytes));
+ }
+
+ if (unpack.remaining_bytes < size) {
+ return unpack.splitPrimitive(val, 0, unpack.remaining_bytes);
+ }
+
+ unpack.remaining_bytes -= size;
+ try unpack.unpacked.append(val.toIntern());
+ }
+
+ fn splitPrimitive(unpack: *UnpackValueBytes, val: Value, offset: u64, len: u64) (error{ReinterpretDeclRef} || Allocator.Error)!void {
+ const pt = unpack.pt;
+ const zcu = pt.zcu;
+ const ty = val.typeOf(pt.zcu);
+
+ assert(offset + len <= ty.abiSize(zcu));
+
+ try unpack.unpacked.ensureUnusedCapacity(@intCast(len));
+ unpack.remaining_bytes -= len;
+
+ switch (pt.zcu.intern_pool.indexToKey(val.toIntern())) {
+ // In the `ptr` case, this will return `error.ReinterpretDeclRef`
+ // if we're trying to split a non-integer pointer value.
+ .int, .float, .enum_tag, .ptr, .opt => {
+ const buf = try unpack.arena.alloc(u8, @intCast(ty.abiSize(zcu)));
+ val.writeToMemory(zcu, buf) catch |err| switch (err) {
+ error.IllDefinedMemoryLayout => unreachable,
+ else => |e| return e,
+ };
+ for (buf[@intCast(offset)..][0..@intCast(len)]) |byte_raw| {
+ const byte_val = try pt.intValue(.u8, byte_raw);
+ unpack.unpacked.appendAssumeCapacity(byte_val.toIntern());
+ }
+ },
+ .undef => {
+ const undef_u8 = try pt.undefValue(.u8);
+ for (0..@intCast(len)) |_| {
+ unpack.unpacked.appendAssumeCapacity(undef_u8.toIntern());
+ }
+ },
+ // The only values here with runtime bits are `true` and `false`.
+ // These are both 1 byte, so will never need splitting.
+ .simple_value => unreachable,
+ else => unreachable, // zero-bit or not primitives
+ }
+ }
+};
+
+/// Given a sequence of bit-packed values in packed memory (see `UnpackValueBytes`),
+/// reconstructs a value of an arbitrary type, with correct handling of `undefined`
+/// values and of pointers which align in virtual memory.
+const PackValueBytes = struct {
+ pt: Zcu.PerThread,
+ arena: Allocator,
+ byte_offset: u64 = 0,
+ unpacked: []const InternPool.Index,
+
+ fn get(pack: *PackValueBytes, ty: Type) (Allocator.Error || error{ReinterpretDeclRef})!Value {
+ const pt = pack.pt;
+ const zcu = pt.zcu;
+ const ip = &zcu.intern_pool;
+ const arena = pack.arena;
+ switch (ty.zigTypeTag(zcu)) {
+ .vector => unreachable, // ill-defined layout
+ .array => {
+ // Each element is padded up to its ABI size. The final element does not have trailing padding.
+ const elem_ty = ty.childType(zcu);
+ const elems = try arena.alloc(InternPool.Index, @intCast(ty.arrayLen(zcu)));
+
+ for (elems) |*elem| {
+ elem.* = (try pack.get(elem_ty)).toIntern();
+ }
+
+ if (ty.sentinel(zcu)) |s| {
+ _ = s; // TODO: validate sentinel was preserved!
+ pack.padding(elem_ty.abiSize(zcu));
+ }
+
+ return pt.aggregateValue(ty, elems);
+ },
+ .@"struct" => switch (ty.containerLayout(zcu)) {
+ .auto => unreachable, // ill-defined layout
+ .@"extern" => {
+ const elems = try arena.alloc(InternPool.Index, ty.structFieldCount(zcu));
+ @memset(elems, .none);
+ var offset: u64 = 0;
+ var it = ip.loadStructType(ty.toIntern()).iterateRuntimeOrder(ip);
+ while (it.next()) |field_index| {
+ const field_ty = ty.fieldType(field_index, zcu);
+ const pad_bytes = ty.structFieldOffset(field_index, zcu) - offset;
+ pack.padding(pad_bytes);
+ elems[field_index] = (try pack.get(field_ty)).toIntern();
+ offset += pad_bytes + field_ty.abiSize(zcu);
+ }
+ pack.padding(ty.abiSize(zcu) - offset);
+ // Any fields which do not have runtime bits should be OPV or comptime fields.
+ // Fill those values now.
+ for (elems, 0..) |*elem, field_index| {
+ if (elem.* != .none) continue;
+ const val = (try ty.structFieldValueComptime(pt, field_index)).?;
+ elem.* = val.toIntern();
+ }
+ return pt.aggregateValue(ty, elems);
+ },
+ .@"packed" => {
+ const backing_int_val = try pack.primitive(ty.bitpackBackingInt(zcu));
+ if (backing_int_val.isUndef(zcu)) return pt.undefValue(ty);
+ return pt.bitpackValue(ty, backing_int_val);
+ },
+ },
+ .@"union" => switch (ty.containerLayout(zcu)) {
+ .auto => unreachable, // ill-defined layout
+ .@"extern" => {
+ // We will attempt to read as the backing representation. If this emits
+ // `error.ReinterpretDeclRef`, we will try each union field, preferring larger ones.
+ // We will also attempt smaller fields when we get `undefined`, as if some bits are
+ // defined we want to include them.
+ // TODO: this is very very bad. We need a more sophisticated union representation.
+
+ const prev_unpacked = pack.unpacked;
+ const prev_byte_offset = pack.byte_offset;
+
+ const backing_ty = try ty.externUnionBackingType(pt);
+
+ const backing_result: enum { undef, reinterpret_decl_ref } = backing: {
+ const backing_val = pack.get(backing_ty) catch |err| switch (err) {
+ error.ReinterpretDeclRef => break :backing .reinterpret_decl_ref,
+ else => |e| return e,
+ };
+ if (backing_val.isUndef(zcu)) break :backing .undef;
+ return .fromInterned(try pt.internUnion(.{
+ .ty = ty.toIntern(),
+ .tag = .none,
+ .val = backing_val.toIntern(),
+ }));
+ };
+
+ const field_order = try pack.arena.alloc(u32, ty.unionTagTypeHypothetical(zcu).enumFieldCount(zcu));
+ for (field_order, 0..) |*f, i| f.* = @intCast(i);
+ // Sort `field_order` to put the fields with the largest ABI sizes first.
+ const SizeSortCtx = struct {
+ zcu: *const Zcu,
+ field_types: []const InternPool.Index,
+ fn lessThan(ctx: @This(), a_idx: u32, b_idx: u32) bool {
+ const a_ty: Type = .fromInterned(ctx.field_types[a_idx]);
+ const b_ty: Type = .fromInterned(ctx.field_types[b_idx]);
+ return a_ty.abiSize(ctx.zcu) > b_ty.abiSize(ctx.zcu);
+ }
+ };
+ std.mem.sortUnstable(u32, field_order, SizeSortCtx{
+ .zcu = zcu,
+ .field_types = zcu.typeToUnion(ty).?.field_types.get(ip),
+ }, SizeSortCtx.lessThan);
+
+ for (field_order) |field_index| {
+ pack.unpacked = prev_unpacked;
+ pack.byte_offset = prev_byte_offset;
+ const field_ty = ty.fieldType(field_index, zcu);
+ const field_val = pack.get(field_ty) catch |err| switch (err) {
+ error.ReinterpretDeclRef => continue,
+ else => |e| return e,
+ };
+ if (field_val.isUndef(zcu)) continue;
+ pack.padding(ty.abiSize(zcu) - field_ty.abiSize(zcu));
+ const tag_val = try pt.enumValueFieldIndex(ty.unionTagTypeHypothetical(zcu), field_index);
+ return pt.unionValue(ty, tag_val, field_val);
+ }
+
+ // No field could represent the value. Just do whatever happens when we try to read
+ // the backing type - either `undefined` or `error.ReinterpretDeclRef`.
+ switch (backing_result) {
+ .undef => return pt.undefValue(ty),
+ .reinterpret_decl_ref => return error.ReinterpretDeclRef,
+ }
+ },
+ .@"packed" => {
+ const backing_int_val = try pack.primitive(ty.bitpackBackingInt(zcu));
+ if (backing_int_val.isUndef(zcu)) return pt.undefValue(ty);
+ return pt.bitpackValue(ty, backing_int_val);
+ },
+ },
+ .@"enum" => {
+ const tag_int_val = try pack.primitive(ty.intTagType(zcu));
+ if (tag_int_val.isUndef(zcu)) return pt.undefValue(ty);
+ return pt.enumValue(ty, tag_int_val.toIntern());
+ },
+ else => return pack.primitive(ty),
+ }
+ }
+
+ fn padding(pack: *PackValueBytes, num_bytes: u64) void {
+ _ = pack.prepareBytes(num_bytes);
+ }
+
+ fn primitive(pack: *PackValueBytes, want_ty: Type) (Allocator.Error || error{ReinterpretDeclRef})!Value {
+ const pt = pack.pt;
+ const zcu = pt.zcu;
+
+ if (try want_ty.onePossibleValue(pt)) |opv| return opv;
+
+ const vals, const byte_offset = pack.prepareBytes(want_ty.abiSize(zcu));
+
+ for (vals) |val| {
+ if (!Value.fromInterned(val).isUndef(zcu)) break;
+ } else {
+ // All bits of the value are `undefined`.
+ return pt.undefValue(want_ty);
+ }
+
+ // TODO: we need to decide how to handle partially-undef values here.
+ // Currently, a value with some undefined bits becomes `0xAA` so that we
+ // preserve the well-defined bits, because we can't currently represent
+ // a partially-undefined primitive (e.g. an int with some undef bits).
+ // In future, we probably want to take one of these two routes:
+ // * Define that if any bits are `undefined`, the entire value is `undefined`.
+ // This is a major breaking change, and probably a footgun.
+ // * Introduce tracking for partially-undef values at comptime.
+ // This would complicate a lot of operations in Sema, such as basic
+ // arithmetic.
+ // This design complexity is tracked by #19634.
+
+ if (vals.len == 1 and
+ want_ty.isPtrAtRuntime(zcu) and
+ Value.fromInterned(vals[0]).typeOf(zcu).isPtrAtRuntime(zcu))
+ {
+ return pt.getCoerced(.fromInterned(vals[0]), want_ty);
+ }
+
+ // Reinterpret via an in-memory buffer.
+
+ var buf_len: u64 = 0;
+ for (vals) |ip_val| {
+ const val: Value = .fromInterned(ip_val);
+ buf_len += val.typeOf(zcu).abiSize(zcu);
+ }
+
+ const buf = try pack.arena.alloc(u8, @intCast(buf_len));
+ {
+ var offset: usize = 0;
+ for (vals) |ip_val| {
+ const val: Value = .fromInterned(ip_val);
+ const ty = val.typeOf(zcu);
+ const size = ty.abiSize(zcu);
+ if (val.isUndef(zcu)) {
+ @memset(buf[offset..][0..@intCast(size)], 0xAA);
+ } else {
+ val.writeToMemory(zcu, buf[offset..][0..@intCast(size)]) catch |err| switch (err) {
+ error.IllDefinedMemoryLayout => unreachable,
+ else => |e| return e,
+ };
+ }
+ offset += @intCast(size);
+ }
+ }
+ const bytes = buf[@intCast(byte_offset)..];
+
+ const target = zcu.getTarget();
+ const endian = target.cpu.arch.endian();
+ switch (want_ty.zigTypeTag(zcu)) {
+ .bool => return .makeBool(bytes[0] != 0),
+ .int => return .readIntFromMemory(want_ty, pt, bytes, pack.arena),
+ .float => switch (want_ty.floatBits(target)) {
+ 16 => return pt.floatValue(want_ty, @as(f16, @bitCast(std.mem.readInt(u16, bytes[0..2], endian)))),
+ 32 => return pt.floatValue(want_ty, @as(f32, @bitCast(std.mem.readInt(u32, bytes[0..4], endian)))),
+ 64 => return pt.floatValue(want_ty, @as(f64, @bitCast(std.mem.readInt(u64, bytes[0..8], endian)))),
+ 80 => return pt.floatValue(want_ty, @as(f80, @bitCast(std.mem.readInt(u80, bytes[0..10], endian)))),
+ 128 => return pt.floatValue(want_ty, @as(f128, @bitCast(std.mem.readInt(u128, bytes[0..16], endian)))),
+ else => unreachable,
+ },
+ .pointer => {
+ assert(!want_ty.isSlice(zcu));
+ const ptr_addr = std.mem.readVarInt(u64, bytes[0..@intCast(want_ty.abiSize(zcu))], endian);
+ return pt.ptrIntValue(want_ty, ptr_addr);
+ },
+ .optional => {
+ assert(want_ty.isPtrLikeOptional(zcu));
+ const ptr_ty = want_ty.optionalChild(zcu);
+ const ptr_addr = std.mem.readVarInt(u64, bytes[0..@intCast(want_ty.abiSize(zcu))], endian);
+ return .fromInterned(try pt.intern(.{ .opt = .{
+ .ty = want_ty.toIntern(),
+ .val = if (ptr_addr == 0) .none else (try pt.ptrIntValue(ptr_ty, ptr_addr)).toIntern(),
+ } }));
+ },
+ else => unreachable,
+ }
+ }
+
+ fn prepareBytes(pack: *PackValueBytes, need_bytes: u64) struct { []const InternPool.Index, u64 } {
+ if (need_bytes == 0) return .{ &.{}, 0 };
+
+ const pt = pack.pt;
+ const zcu = pt.zcu;
+
+ var bytes: u64 = 0;
+ var len: usize = 0;
+ while (bytes < pack.byte_offset + need_bytes) {
+ bytes += Value.fromInterned(pack.unpacked[len]).typeOf(zcu).abiSize(zcu);
+ len += 1;
+ }
+
+ const result_vals = pack.unpacked[0..len];
+ const result_offset = pack.byte_offset;
+
+ const extra_bytes = bytes - pack.byte_offset - need_bytes;
+ if (extra_bytes == 0) {
+ pack.unpacked = pack.unpacked[len..];
+ pack.byte_offset = 0;
+ } else {
+ pack.unpacked = pack.unpacked[len - 1 ..];
+ pack.byte_offset = Value.fromInterned(pack.unpacked[0]).typeOf(zcu).abiSize(zcu) - extra_bytes;
+ }
+
+ return .{ result_vals, result_offset };
+ }
+};
+
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const assert = std.debug.assert;
+
+const Sema = @import("../Sema.zig");
+const Zcu = @import("../Zcu.zig");
+const InternPool = @import("../InternPool.zig");
+const Type = @import("../Type.zig");
+const Value = @import("../Value.zig");
+const CompileError = Zcu.CompileError;
diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig
index 9f260a05795fd5993cb60f5f4bfffb8a1ffe644f..aabb8cfe2e3a48a7ee3830a3bcfbebe124faa950 100644
--- a/src/Sema/type_resolution.zig
+++ b/src/Sema/type_resolution.zig
@@ -87,6 +87,7 @@ fn ensureLayoutResolvedInner(sema: *Sema, ty: Type, orig_ty: Type, reason: *cons
.ptr_type,
.anyframe_type,
.simple_type,
+ .spirv_type,
.opaque_type,
.error_set_type,
.inferred_error_set_type,
@@ -288,10 +289,12 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
}
// Resolve the layout of all fields, and check their types are allowed.
+ const fields_len = struct_obj.field_types.len;
for (struct_obj.field_types.get(ip), 0..) |field_ty_ip, field_index| {
const field_ty: Type = .fromInterned(field_ty_ip);
assert(!field_ty.isGenericPoison());
const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) });
+ const field_name_src = block.src(.{ .container_field_name = @intCast(field_index) });
try sema.ensureLayoutResolved(field_ty, field_ty_src, .field);
if (field_ty.zigTypeTag(zcu) == .@"opaque") {
return sema.failWithOwnedErrorMsg(&block, msg: {
@@ -302,6 +305,35 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
break :msg msg;
});
}
+ if (field_ty.zigTypeTag(zcu) == .spirv) {
+ if (field_ty.isSpirvRuntimeArray(zcu)) {
+ if (struct_obj.layout != .@"extern") {
+ return sema.failWithOwnedErrorMsg(&block, msg: {
+ const msg = try sema.errMsg(struct_ty.srcLoc(zcu), "non-extern struct cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
+ errdefer msg.destroy(gpa);
+ try sema.errNote(field_name_src, msg, "while checking this field", .{});
+ break :msg msg;
+ });
+ }
+ if (field_index != fields_len - 1) {
+ return sema.failWithOwnedErrorMsg(&block, msg: {
+ const msg = try sema.errMsg(struct_ty.srcLoc(zcu), "struct field of type '{f}' must be the last field", .{field_ty.fmt(pt)});
+ errdefer msg.destroy(gpa);
+ try sema.errNote(field_name_src, msg, "while checking this field", .{});
+ break :msg msg;
+ });
+ }
+ } else {
+ return sema.failWithOwnedErrorMsg(&block, msg: {
+ const msg = try sema.errMsg(field_ty_src, "cannot directly embed SPIR-V type '{f}' in struct", .{field_ty.fmt(pt)});
+ errdefer msg.destroy(gpa);
+ try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{});
+ try sema.addDeclaredHereNote(msg, field_ty);
+ break :msg msg;
+ });
+ }
+ }
+
if (struct_obj.layout == .@"extern" and !field_ty.validateExtern(.struct_field, zcu)) {
return sema.failWithOwnedErrorMsg(&block, msg: {
const msg = try sema.errMsg(field_ty_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
@@ -413,7 +445,10 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
const field_ty: Type = .fromInterned(struct_obj.field_types.get(ip)[field_idx]);
const offset = resolved_field_aligns[field_idx].forward(cur_offset);
struct_obj.field_offsets.get(ip)[field_idx] = @truncate(offset); // truncate because the overflow is handled below
- cur_offset = offset + field_ty.abiSize(zcu);
+ // A SPIR-V `runtime_array` always trails the struct and
+ // contributes nothing to the struct's static size.
+ const field_size = if (field_ty.isSpirvRuntimeArray(zcu)) 0 else field_ty.abiSize(zcu);
+ cur_offset = offset + field_size;
}
const struct_size: u32 = switch (class) {
.no_possible_value => 0,
@@ -858,6 +893,14 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {
break :msg msg;
});
}
+ if (field_ty.zigTypeTag(zcu) == .spirv) {
+ return sema.failWithOwnedErrorMsg(&block, msg: {
+ const msg = try sema.errMsg(field_ty_src, "SPIR-V type '{f}' have unknown size and therefore cannot be directly embedded in unions", .{field_ty.fmt(pt)});
+ errdefer msg.destroy(gpa);
+ try sema.addDeclaredHereNote(msg, field_ty);
+ break :msg msg;
+ });
+ }
if (union_obj.layout == .@"extern" and !field_ty.validateExtern(.union_field, zcu)) {
return sema.failWithOwnedErrorMsg(&block, msg: {
const msg = try sema.errMsg(field_ty_src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
diff --git a/src/Type.zig b/src/Type.zig
index d2373c36e44a13e92ef64b3524bf9a553bb36fd7..546953b307df5bcb37e99942655801f6b5910676 100644
--- a/src/Type.zig
+++ b/src/Type.zig
@@ -170,6 +170,7 @@ pub fn classify(start_ty: Type, zcu: *const Zcu) Class {
.func_type => .fully_comptime,
+ .spirv_type => if (cur_ty.isSpirvRuntimeArray(zcu)) .runtime else .no_possible_value,
.opaque_type => .no_possible_value,
.error_union_type => |eu| {
@@ -323,6 +324,7 @@ pub fn isSelfComparable(ty: Type, zcu: *const Zcu, is_equality_cmp: bool) bool {
.error_set,
.@"fn",
.@"opaque",
+ .spirv,
.@"anyframe",
.@"enum",
.enum_literal,
@@ -383,8 +385,7 @@ pub fn ptrInfo(ty: Type, zcu: *const Zcu) InternPool.Key.PtrType {
};
}
-pub fn eql(a: Type, b: Type, zcu: *const Zcu) bool {
- _ = zcu; // TODO: remove this parameter
+pub fn eql(a: Type, b: Type) bool {
// The InternPool data structure hashes based on Key to make interned objects
// unique. An Index can be treated simply as u32 value for the
// purpose of Type/Value hashing and equality.
@@ -617,6 +618,10 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari
const name = ip.loadEnumType(ty.toIntern()).name;
try writer.print("{f}", .{name.fmt(ip)});
},
+ .spirv_type => {
+ const name = ip.loadSpirvType(ty.toIntern()).name;
+ try writer.print("{f}", .{name.fmt(ip)});
+ },
.func_type => |fn_info| {
if (fn_info.is_noinline) {
try writer.writeAll("noinline ");
@@ -704,6 +709,14 @@ pub fn toIntern(ty: Type) InternPool.Index {
return ty.ip_index;
}
+pub fn isSpirvRuntimeArray(ty: Type, zcu: *const Zcu) bool {
+ const ip = &zcu.intern_pool;
+ return switch (ip.indexToKey(ty.toIntern())) {
+ .spirv_type => ip.loadSpirvType(ty.toIntern()).flags.tag == .runtime_array,
+ else => false,
+ };
+}
+
pub fn toValue(self: Type) Value {
return .fromInterned(self.toIntern());
}
@@ -744,13 +757,14 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool {
const ip = &zcu.intern_pool;
return switch (ip.indexToKey(ty.toIntern())) {
.int_type,
- .vector_type,
=> true,
+ .vector_type,
.error_union_type,
.error_set_type,
.inferred_error_set_type,
.tuple_type,
+ .spirv_type,
.opaque_type,
.anyframe_type,
// These are function bodies, not function pointers.
@@ -1038,6 +1052,7 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment {
}
},
.enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).abiAlignment(zcu),
+ .spirv_type => if (ty.isSpirvRuntimeArray(zcu)) ty.childType(zcu).abiAlignment(zcu) else .@"1",
.opaque_type => .@"1",
// values, not types
@@ -1183,6 +1198,7 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 {
}
},
.enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).abiSize(zcu),
+ .spirv_type => unreachable,
.opaque_type => unreachable,
// values, not types
@@ -1225,112 +1241,17 @@ pub fn errorAbiSize(zcu: *const Zcu) u64 {
}
/// Asserts that `ty` is not an opaque or comptime-only type.
-/// Once #19755 is implemented, this query will only work on types with a defined bit-level representation.
pub fn bitSize(ty: Type, zcu: *const Zcu) u64 {
- const target = zcu.getTarget();
- const ip = &zcu.intern_pool;
- assertHasLayout(ty, zcu);
- return switch (ip.indexToKey(ty.toIntern())) {
- .int_type => |int_type| int_type.bits,
- .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
- .slice => target.ptrBitWidth() * 2,
- else => target.ptrBitWidth(),
- },
- .anyframe_type => target.ptrBitWidth(),
- .array_type => |array_type| {
- const elem_ty: Type = .fromInterned(array_type.child);
- const len = array_type.lenIncludingSentinel();
- return switch (zcu.comp.getZigBackend()) {
- .stage2_x86_64 => len * elem_ty.bitSize(zcu),
- // this case will be removed under #19755
- else => switch (len) {
- 0 => 0,
- else => (len - 1) * 8 * elem_ty.abiSize(zcu) + elem_ty.bitSize(zcu),
- },
- };
- },
- .vector_type => |vec| vec.len * Type.fromInterned(vec.child).bitSize(zcu),
- .error_set_type, .inferred_error_set_type => zcu.errorSetBits(),
- .func_type => unreachable,
-
- .simple_type => |t| switch (t) {
- .void => 0,
- .bool => 1,
- .anyerror, .adhoc_inferred_error_set => zcu.errorSetBits(),
- .usize, .isize => target.ptrBitWidth(),
-
- .c_char => target.cTypeBitSize(.char),
- .c_short => target.cTypeBitSize(.short),
- .c_ushort => target.cTypeBitSize(.ushort),
- .c_int => target.cTypeBitSize(.int),
- .c_uint => target.cTypeBitSize(.uint),
- .c_long => target.cTypeBitSize(.long),
- .c_ulong => target.cTypeBitSize(.ulong),
- .c_longlong => target.cTypeBitSize(.longlong),
- .c_ulonglong => target.cTypeBitSize(.ulonglong),
- .c_longdouble => target.cTypeBitSize(.longdouble),
-
- .f16 => 16,
- .f32 => 32,
- .f64 => 64,
- .f80 => 80,
- .f128 => 128,
-
- .anyopaque => unreachable,
- .type => unreachable,
- .comptime_int => unreachable,
- .comptime_float => unreachable,
- .noreturn => unreachable,
- .null => unreachable,
- .undefined => unreachable,
- .enum_literal => unreachable,
- .generic_poison => unreachable,
- },
-
- .struct_type => {
- const struct_obj = ip.loadStructType(ty.toIntern());
- switch (struct_obj.layout) {
- .@"packed" => return Type.fromInterned(struct_obj.packed_backing_int_type).bitSize(zcu),
- .auto, .@"extern" => return struct_obj.size * 8, // will be `unreachable` under #19755
- }
- },
- .union_type => {
- const union_obj = ip.loadUnionType(ty.toIntern());
- switch (union_obj.layout) {
- .@"packed" => return Type.fromInterned(union_obj.packed_backing_int_type).bitSize(zcu),
- .auto, .@"extern" => return union_obj.size * 8, // will be `unreachable` under #19755
- }
- },
- .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).bitSize(zcu),
-
- // will be `unreachable` under #19755
- .opt_type,
- .error_union_type,
- .tuple_type,
- => ty.abiSize(zcu) * 8,
-
- .opaque_type => unreachable,
-
- // values, not types
- .undef,
- .simple_value,
- .@"extern",
- .func,
- .int,
- .err,
- .error_union,
- .enum_literal,
- .enum_tag,
- .float,
- .ptr,
- .slice,
- .opt,
- .aggregate,
- .un,
- .bitpack,
- // memoization, not types
- .memoized_call,
- => unreachable,
+ return switch (ty.zigTypeTag(zcu)) {
+ .void => 0,
+ .bool => 1,
+ .float => ty.floatBits(zcu.getTarget()),
+ .pointer, .optional => {
+ assert(ty.isPtrAtRuntime(zcu));
+ return zcu.getTarget().ptrBitWidth();
+ },
+ .array, .vector => ty.arrayLenIncludingSentinel(zcu) * ty.childType(zcu).bitSize(zcu),
+ else => ty.intInfo(zcu).bits,
};
}
@@ -1511,14 +1432,18 @@ pub fn nullablePtrElem(ty: Type, zcu: *const Zcu) Type {
/// * `[]T`
/// * `[*]T`
/// * `[*c]T`
+/// * `@SpirvType(.{ .runtime_array = T })`
+/// * `*@SpirvType(.{ .runtime_array = T })`
pub fn indexableElem(ty: Type, zcu: *const Zcu) Type {
const ip = &zcu.intern_pool;
return switch (ip.indexToKey(ty.toIntern())) {
inline .array_type, .vector_type => |arr| .fromInterned(arr.child),
+ .spirv_type => ty.childType(zcu),
.ptr_type => |ptr_type| switch (ptr_type.flags.size) {
.many, .slice, .c => .fromInterned(ptr_type.child),
.one => switch (ip.indexToKey(ptr_type.child)) {
inline .array_type, .vector_type => |arr| .fromInterned(arr.child),
+ .spirv_type => Type.fromInterned(ptr_type.child).childType(zcu),
else => unreachable,
},
},
@@ -1864,6 +1789,7 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType {
.func_type => unreachable,
.simple_type => unreachable, // handled via Index enum tag above
+ .spirv_type => unreachable,
.opaque_type => unreachable,
// values, not types
@@ -2032,6 +1958,7 @@ pub fn onePossibleValue(ty: Type, pt: Zcu.PerThread) !?Value {
.error_set_type,
.inferred_error_set_type,
.opaque_type,
+ .spirv_type,
=> null,
.simple_type => |t| switch (t) {
@@ -2219,10 +2146,12 @@ pub fn isIndexable(ty: Type, zcu: *const Zcu) bool {
.one => switch (ty.childType(zcu).zigTypeTag(zcu)) {
.array, .vector => true,
.@"struct" => ty.childType(zcu).isTuple(zcu),
+ .spirv => ty.childType(zcu).isSpirvRuntimeArray(zcu),
else => false,
},
},
.@"struct" => ty.isTuple(zcu),
+ .spirv => ty.isSpirvRuntimeArray(zcu),
else => false,
};
}
@@ -2498,7 +2427,7 @@ pub fn defaultStructFieldAlignment(
((field_ty.isAbiInt(zcu) and field_ty.intInfo(zcu).bits > 64) or
(field_ty.toIntern() == .f80_type and zcu.getTarget().cTypeBitSize(.longdouble) != 80)))
{
- return abi_align.maxStrict(.@"16");
+ return abi_align.maxStrict(if (zcu.getTarget().cpu.arch == .s390x) .@"8" else .@"16");
}
return abi_align;
}
@@ -2844,6 +2773,7 @@ pub fn elemPtrType(ptr_ty: Type, index: ?u64, pt: Zcu.PerThread) Allocator.Error
.slice, .many, .c => .fromInterned(ptr_info.child),
.one => switch (ip.indexToKey(ptr_info.child)) {
.array_type => |array_type| .fromInterned(array_type.child),
+ .spirv_type => Type.fromInterned(ptr_info.child).childType(zcu),
else => unreachable,
},
};
@@ -3095,6 +3025,7 @@ pub fn unpackable(ty: Type, zcu: *const Zcu) ?UnpackableReason {
.noreturn,
.@"opaque",
+ .spirv,
.error_union,
.error_set,
.frame,
@@ -3156,6 +3087,8 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool
.frame,
=> false,
+ .vector => position == .param_ty or position == .ret_ty,
+
.void => switch (position) {
.ret_ty,
.union_field,
@@ -3170,6 +3103,7 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool
.noreturn => position == .ret_ty,
.@"opaque",
+ .spirv,
.bool,
.float,
.@"anyframe",
@@ -3233,7 +3167,6 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool
.other,
=> ty.childType(zcu).validateExtern(.element, zcu),
},
- .vector => ty.childType(zcu).validateExtern(.element, zcu),
.optional => ty.isPtrLikeOptional(zcu),
};
}
@@ -3246,6 +3179,40 @@ fn validateExternCallconv(cc: std.lang.CallingConvention) bool {
};
}
+/// Returns whether `ty` is considered by Zig to have a bit-level representation, meaning it is
+/// allowed as the operand to `@bitSizeOf`. This is a superset of packable types.
+pub fn hasBitRepresentation(ty: Type, zcu: *const Zcu) bool {
+ return switch (ty.zigTypeTag(zcu)) {
+ .@"fn",
+ .noreturn,
+ .undefined,
+ .null,
+ .@"opaque",
+ .spirv,
+ .type,
+ .enum_literal,
+ .comptime_float,
+ .comptime_int,
+ .error_set,
+ .error_union,
+ .frame,
+ .@"anyframe",
+ => false,
+
+ .void,
+ .bool,
+ .int,
+ .float,
+ => true,
+
+ .@"enum" => zcu.intern_pool.loadEnumType(ty.toIntern()).int_tag_mode == .explicit,
+ .pointer, .optional => ty.isPtrAtRuntime(zcu),
+ .@"struct", .@"union" => ty.containerLayout(zcu) == .@"packed",
+
+ .array, .vector => ty.childType(zcu).hasBitRepresentation(zcu),
+ };
+}
+
/// Asserts that `ty` has resolved layout.
pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void {
if (!std.debug.runtime_safety) {
@@ -3261,6 +3228,7 @@ pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void {
.simple_type,
.opaque_type,
.error_set_type,
+ .spirv_type,
.inferred_error_set_type,
=> {},
.func_type => |func_type| {
@@ -3313,7 +3281,7 @@ pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void {
}
/// Recursively walks the type and marks for each subtype how many times it has been seen
-fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.AutoArrayHashMapUnmanaged(Type, u16)) error{OutOfMemory}!void {
+fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.array_hash_map.Auto(Type, u16)) error{OutOfMemory}!void {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
@@ -3362,6 +3330,7 @@ fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.AutoArrayHashMapUn
.union_type,
.opaque_type,
.enum_type,
+ .spirv_type,
.simple_type,
.int_type,
=> {},
@@ -3427,8 +3396,8 @@ fn shouldDedupeType(ty: Type, ctx: *Comparison, pt: Zcu.PerThread) error{OutOfMe
/// the subtype length and number of occurences. Placeholders are then found by
/// iterating `type_dedupe_cache` which caches the inline/placeholder decisions.
pub const Comparison = struct {
- type_occurrences: std.AutoArrayHashMapUnmanaged(Type, u16),
- type_dedupe_cache: std.AutoArrayHashMapUnmanaged(Type, DedupeEntry),
+ type_occurrences: std.array_hash_map.Auto(Type, u16),
+ type_dedupe_cache: std.array_hash_map.Auto(Type, DedupeEntry),
placeholder_index: u8,
pub const Placeholder = struct {
diff --git a/src/Value.zig b/src/Value.zig
index 40ccd52792d18e9c0a7b989d433b597740e599d6..7db732c60e38d5a10353a230a1552530f58e7592 100644
--- a/src/Value.zig
+++ b/src/Value.zig
@@ -248,7 +248,6 @@ pub fn toBool(val: Value) bool {
pub fn writeToMemory(val: Value, zcu: *const Zcu, buffer: []u8) error{
ReinterpretDeclRef,
IllDefinedMemoryLayout,
- Unimplemented,
OutOfMemory,
}!void {
const target = zcu.getTarget();
@@ -257,35 +256,50 @@ pub fn writeToMemory(val: Value, zcu: *const Zcu, buffer: []u8) error{
const ty = val.typeOf(zcu);
if (val.isUndef(zcu)) {
const size: usize = @intCast(ty.abiSize(zcu));
- @memset(buffer[0..size], 0xaa);
+ @memset(buffer[0..size], 0xAA);
return;
}
- switch (ty.zigTypeTag(zcu)) {
+ tag: switch (ty.zigTypeTag(zcu)) {
+ .type => return error.IllDefinedMemoryLayout,
+ .comptime_float => return error.IllDefinedMemoryLayout,
+ .comptime_int => return error.IllDefinedMemoryLayout,
+ .undefined => return error.IllDefinedMemoryLayout,
+ .null => return error.IllDefinedMemoryLayout,
+ .error_union => return error.IllDefinedMemoryLayout,
+ .enum_literal => return error.IllDefinedMemoryLayout,
+ .@"fn" => return error.IllDefinedMemoryLayout,
+ .spirv => return error.IllDefinedMemoryLayout,
+ .@"opaque" => unreachable,
+ .frame => unreachable,
+ .@"anyframe" => unreachable,
+ .noreturn => unreachable,
.void => {},
.bool => {
buffer[0] = @intFromBool(val.toBool());
},
- .int, .@"enum", .error_set, .pointer => |tag| {
- const int_ty = if (tag == .pointer) int_ty: {
- if (ty.isSlice(zcu)) return error.IllDefinedMemoryLayout;
- if (ip.getBackingAddrTag(val.toIntern()).? != .int) return error.ReinterpretDeclRef;
- break :int_ty Type.usize;
- } else ty;
- const int_info = int_ty.intInfo(zcu);
- const bits = int_info.bits;
- const byte_count: u16 = @intCast((@as(u17, bits) + 7) / 8);
-
+ .pointer => {
+ if (ty.isSlice(zcu)) return error.IllDefinedMemoryLayout;
+ if (ip.getBackingAddrTag(val.toIntern()).? != .int) return error.ReinterpretDeclRef;
+ continue :tag .int;
+ },
+ .int, .@"enum", .error_set => {
var bigint_buffer: BigIntSpace = undefined;
const bigint = val.toBigInt(&bigint_buffer, zcu);
- bigint.writeTwosComplement(buffer[0..byte_count], endian);
+ bigint.writeTwosComplement(buffer[0..@intCast(ty.abiSize(zcu))], endian);
},
- .float => switch (ty.floatBits(target)) {
- 16 => std.mem.writeInt(u16, buffer[0..2], @bitCast(val.toFloat(f16, zcu)), endian),
- 32 => std.mem.writeInt(u32, buffer[0..4], @bitCast(val.toFloat(f32, zcu)), endian),
- 64 => std.mem.writeInt(u64, buffer[0..8], @bitCast(val.toFloat(f64, zcu)), endian),
- 80 => std.mem.writeInt(u80, buffer[0..10], @bitCast(val.toFloat(f80, zcu)), endian),
- 128 => std.mem.writeInt(u128, buffer[0..16], @bitCast(val.toFloat(f128, zcu)), endian),
- else => unreachable,
+ .float => {
+ const float_bits = ty.floatBits(target);
+ switch (float_bits) {
+ 16 => std.mem.writeInt(u16, buffer[0..2], @bitCast(val.toFloat(f16, zcu)), endian),
+ 32 => std.mem.writeInt(u32, buffer[0..4], @bitCast(val.toFloat(f32, zcu)), endian),
+ 64 => std.mem.writeInt(u64, buffer[0..8], @bitCast(val.toFloat(f64, zcu)), endian),
+ 80 => std.mem.writeInt(u80, buffer[0..10], @bitCast(val.toFloat(f80, zcu)), endian),
+ 128 => std.mem.writeInt(u128, buffer[0..16], @bitCast(val.toFloat(f128, zcu)), endian),
+ else => unreachable,
+ }
+ const float_bytes = @divExact(float_bits, 8);
+ const total_bytes: usize = @intCast(ty.abiSize(zcu));
+ @memset(buffer[float_bytes..total_bytes], 0); // padding
},
.array => {
const aggregate = ip.indexToKey(val.toIntern()).aggregate;
@@ -302,28 +316,33 @@ pub fn writeToMemory(val: Value, zcu: *const Zcu, buffer: []u8) error{
}
buf_off += elem_size;
}
+ if (ty.sentinel(zcu)) |sentinel_val| {
+ try sentinel_val.writeToMemory(zcu, buffer[buf_off..]);
+ }
},
- .vector => {
- // We use byte_count instead of abi_size here, so that any padding bytes
- // follow the data bytes, on both big- and little-endian systems.
- const byte_count = (@as(usize, @intCast(ty.bitSize(zcu))) + 7) / 8;
- return writeToPackedMemory(val, zcu, buffer[0..byte_count], 0);
- },
+ .vector => return error.IllDefinedMemoryLayout,
.@"struct" => {
const struct_type = zcu.typeToStruct(ty) orelse return error.IllDefinedMemoryLayout;
switch (struct_type.layout) {
.auto => return error.IllDefinedMemoryLayout,
- .@"extern" => for (0..struct_type.field_types.len) |field_index| {
- const off: usize = @intCast(ty.structFieldOffset(field_index, zcu));
- const field_val = Value.fromInterned(switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
- .bytes => |bytes| {
- buffer[off] = bytes.at(field_index, ip);
- continue;
- },
- .elems => |elems| elems[field_index],
- .repeated_elem => |elem| elem,
- });
- try writeToMemory(field_val, zcu, buffer[off..]);
+ .@"extern" => {
+ var last_off: usize = 0;
+ for (struct_type.field_types.get(ip), 0..) |field_ty_ip, field_index| {
+ const off: usize = @intCast(ty.structFieldOffset(field_index, zcu));
+ @memset(buffer[last_off..off], 0xAA);
+ const field_val = Value.fromInterned(switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
+ .bytes => |bytes| {
+ buffer[off] = bytes.at(field_index, ip);
+ continue;
+ },
+ .elems => |elems| elems[field_index],
+ .repeated_elem => |elem| elem,
+ });
+ try writeToMemory(field_val, zcu, buffer[off..]);
+ last_off = @intCast(off + Type.fromInterned(field_ty_ip).abiSize(zcu));
+ }
+ const struct_size: usize = @intCast(ty.abiSize(zcu));
+ @memset(buffer[last_off..struct_size], 0xAA);
},
.@"packed" => {
const int_index = ip.indexToKey(val.toIntern()).bitpack.backing_int_val;
@@ -335,6 +354,9 @@ pub fn writeToMemory(val: Value, zcu: *const Zcu, buffer: []u8) error{
.auto => return error.IllDefinedMemoryLayout, // Sema is supposed to have emitted a compile error already
.@"extern" => {
const payload_val = val.unionPayload(zcu);
+ const payload_size: usize = @intCast(payload_val.typeOf(zcu).abiSize(zcu));
+ const union_size: usize = @intCast(ty.abiSize(zcu));
+ @memset(buffer[payload_size..union_size], 0xAA);
return writeToMemory(payload_val, zcu, buffer);
},
.@"packed" => {
@@ -352,7 +374,6 @@ pub fn writeToMemory(val: Value, zcu: *const Zcu, buffer: []u8) error{
@memset(buffer[0..@intCast(byte_count)], 0); // null pointer
}
},
- else => return error.Unimplemented,
}
}
@@ -360,12 +381,15 @@ pub fn writeToMemory(val: Value, zcu: *const Zcu, buffer: []u8) error{
///
/// Both the start and the end of the provided buffer must be tight, since
/// big-endian packed memory layouts start at the end of the buffer.
+///
+/// Supports arrays and vectors, for which the value is written in logical bit
+/// order, i.e. with the first element at bit offset 0.
pub fn writeToPackedMemory(
val: Value,
zcu: *const Zcu,
buffer: []u8,
bit_offset: usize,
-) error{ ReinterpretDeclRef, OutOfMemory }!void {
+) void {
const ip = &zcu.intern_pool;
const target = zcu.getTarget();
const endian = target.cpu.arch.endian();
@@ -392,13 +416,7 @@ pub fn writeToPackedMemory(
},
.@"enum" => {
const int_val = val.intFromEnum(zcu);
- return int_val.writeToPackedMemory(zcu, buffer, bit_offset);
- },
- .pointer => {
- assert(!ty.isSlice(zcu)); // No well defined layout.
- if (ip.getBackingAddrTag(val.toIntern()).? != .int) return error.ReinterpretDeclRef;
- const addr = val.toUnsignedInt(zcu);
- std.mem.writeVarPackedInt(buffer, bit_offset, zcu.getTarget().ptrBitWidth(), addr, endian);
+ int_val.writeToPackedMemory(zcu, buffer, bit_offset);
},
.int => {
const bits = ty.intInfo(zcu).bits;
@@ -416,47 +434,46 @@ pub fn writeToPackedMemory(
128 => std.mem.writePackedInt(u128, buffer, bit_offset, @bitCast(val.toFloat(f128, zcu)), endian),
else => unreachable,
},
- .vector => {
- const elem_ty = ty.childType(zcu);
- const elem_bit_size: u16 = @intCast(elem_ty.bitSize(zcu));
- const len: usize = @intCast(ty.arrayLen(zcu));
-
- var bits: u16 = 0;
- var elem_i: usize = 0;
- const aggregate = ip.indexToKey(val.toIntern()).aggregate;
- while (elem_i < len) : (elem_i += 1) {
- // On big-endian systems, LLVM reverses the element order of vectors by default
- const tgt_elem_i = if (endian == .big) len - elem_i - 1 else elem_i;
- switch (aggregate.storage) {
- .bytes => |bytes| std.mem.writePackedInt(u8, buffer, bit_offset + bits, bytes.at(tgt_elem_i, ip), endian),
- .elems => |elems| try Value.fromInterned(elems[tgt_elem_i]).writeToPackedMemory(zcu, buffer, bit_offset + bits),
- .repeated_elem => |elem| try Value.fromInterned(elem).writeToPackedMemory(zcu, buffer, bit_offset + bits),
- }
- bits += elem_bit_size;
- }
- },
.@"struct", .@"union" => {
assert(ty.containerLayout(zcu) == .@"packed");
const int_val: Value = .fromInterned(ip.indexToKey(val.toIntern()).bitpack.backing_int_val);
- return int_val.writeToPackedMemory(zcu, buffer, bit_offset);
+ int_val.writeToPackedMemory(zcu, buffer, bit_offset);
},
- .optional => {
- assert(ty.isPtrLikeOptional(zcu));
- if (val.optionalValue(zcu)) |ptr_val| {
- return ptr_val.writeToPackedMemory(zcu, buffer, bit_offset);
- } else {
- return Value.zero_usize.writeToPackedMemory(zcu, buffer, bit_offset);
+ .array, .vector => {
+ const elem_bits: usize = @intCast(ty.childType(zcu).bitSize(zcu));
+ const len: usize = @intCast(ty.arrayLen(zcu));
+ var elem_bit_off: usize = bit_offset;
+ switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
+ .repeated_elem => |elem_val_ip| {
+ const elem_val: Value = .fromInterned(elem_val_ip);
+ for (0..len) |_| {
+ elem_val.writeToPackedMemory(zcu, buffer, elem_bit_off);
+ elem_bit_off += elem_bits;
+ }
+ },
+ .elems => |elems| for (elems[0..len]) |elem_val_ip| {
+ const elem_val: Value = .fromInterned(elem_val_ip);
+ elem_val.writeToPackedMemory(zcu, buffer, elem_bit_off);
+ elem_bit_off += elem_bits;
+ },
+ .bytes => |bytes| for (bytes.toSlice(len, ip)) |raw_byte| {
+ std.mem.writeVarPackedInt(buffer, elem_bit_off, elem_bits, raw_byte, endian);
+ elem_bit_off += elem_bits;
+ },
+ }
+ if (ty.sentinel(zcu)) |sentinel_val| {
+ sentinel_val.writeToPackedMemory(zcu, buffer, elem_bit_off);
}
},
- else => @panic("TODO implement writeToPackedMemory for more types"),
+ else => unreachable,
}
}
-/// Load a Value from the contents of `buffer`, where `ty` is an unsigned integer type.
+/// Load a Value from the contents of `buffer`, where `ty` is any integer type.
///
/// Asserts that buffer.len >= ty.abiSize(). The buffer is allowed to extend past
/// the end of the value in memory.
-pub fn readUintFromMemory(
+pub fn readIntFromMemory(
ty: Type,
pt: Zcu.PerThread,
buffer: []const u8,
@@ -465,23 +482,28 @@ pub fn readUintFromMemory(
const zcu = pt.zcu;
const endian = zcu.getTarget().cpu.arch.endian();
- assert(ty.isUnsignedInt(zcu));
- const bits = ty.intInfo(zcu).bits;
- const byte_count: u16 = @intCast((@as(u17, bits) + 7) / 8);
+ const int = ty.intInfo(zcu);
+ const abi_size: usize = @intCast(ty.abiSize(zcu));
+ const exact_buf = buffer[0..abi_size];
- assert(buffer.len >= byte_count);
-
- if (bits <= 64) {
- const val = std.mem.readVarInt(u64, buffer[0..byte_count], endian);
- const result = (val << @as(u6, @intCast(64 - bits))) >> @as(u6, @intCast(64 - bits));
- return pt.intValue(ty, result);
+ if (abi_size <= 8) {
+ const shift: u6 = @intCast(64 - int.bits);
+ switch (int.signedness) {
+ .unsigned => {
+ const x = std.mem.readVarInt(u64, exact_buf, endian);
+ return pt.intValue(ty, (x << shift) >> shift);
+ },
+ .signed => {
+ const x = std.mem.readVarInt(i64, exact_buf, endian);
+ return pt.intValue(ty, (x << shift) >> shift);
+ },
+ }
} else {
- const Limb = std.math.big.Limb;
- const limb_count = (byte_count + @sizeOf(Limb) - 1) / @sizeOf(Limb);
- const limbs_buffer = try arena.alloc(Limb, limb_count);
+ const limb_count = std.math.big.int.calcTwosCompLimbCount(int.bits);
+ const limbs_buffer = try arena.alloc(std.math.big.Limb, limb_count);
var bigint: BigIntMutable = .init(limbs_buffer, 0);
- bigint.readTwosComplement(buffer[0..byte_count], bits, endian, .unsigned);
+ bigint.readTwosComplement(exact_buf, int.bits, endian, int.signedness);
return pt.intValue_big(ty, bigint.toConst());
}
}
@@ -490,17 +512,17 @@ pub fn readUintFromMemory(
///
/// Both the start and the end of the provided buffer must be tight, since
/// big-endian packed memory layouts start at the end of the buffer.
+///
+/// Supports arrays and vectors, for which the value is read in logical bit
+/// order, i.e. with the first element at bit offset 0.
pub fn readFromPackedMemory(
ty: Type,
pt: Zcu.PerThread,
buffer: []const u8,
bit_offset: usize,
- gpa: Allocator,
-) error{
- IllDefinedMemoryLayout,
- OutOfMemory,
-}!Value {
+) Allocator.Error!Value {
const zcu = pt.zcu;
+ const gpa = zcu.comp.gpa;
const target = zcu.getTarget();
const endian = target.cpu.arch.endian();
switch (ty.zigTypeTag(zcu)) {
@@ -543,7 +565,7 @@ pub fn readFromPackedMemory(
},
.@"enum" => {
const int_ty = ty.intTagType(zcu);
- const int_val = try Value.readFromPackedMemory(int_ty, pt, buffer, bit_offset, gpa);
+ const int_val: Value = try .readFromPackedMemory(int_ty, pt, buffer, bit_offset);
return pt.getCoerced(int_val, ty);
},
.float => return Value.fromInterned(try pt.intern(.{ .float = .{
@@ -557,40 +579,25 @@ pub fn readFromPackedMemory(
else => unreachable,
},
} })),
- .vector => {
- const elem_ty = ty.childType(zcu);
- const elems = try gpa.alloc(InternPool.Index, @intCast(ty.arrayLen(zcu)));
- defer gpa.free(elems);
-
- var bits: u16 = 0;
- const elem_bit_size: u16 = @intCast(elem_ty.bitSize(zcu));
- for (elems, 0..) |_, i| {
- // On big-endian systems, LLVM reverses the element order of vectors by default
- const tgt_elem_i = if (endian == .big) elems.len - i - 1 else i;
- elems[tgt_elem_i] = (try readFromPackedMemory(elem_ty, pt, buffer, bit_offset + bits, gpa)).toIntern();
- bits += elem_bit_size;
- }
- return pt.aggregateValue(ty, elems);
- },
.@"struct", .@"union" => {
assert(ty.containerLayout(zcu) == .@"packed");
- const int_val: Value = try .readFromPackedMemory(ty.bitpackBackingInt(zcu), pt, buffer, bit_offset, gpa);
+ const int_val: Value = try .readFromPackedMemory(ty.bitpackBackingInt(zcu), pt, buffer, bit_offset);
return pt.bitpackValue(ty, int_val);
},
- .pointer => {
- assert(!ty.isSlice(zcu)); // No well defined layout.
- const addr = (try readFromPackedMemory(Type.usize, pt, buffer, bit_offset, gpa)).toUnsignedInt(zcu);
- return pt.ptrIntValue(ty, addr);
+ .array, .vector => {
+ const elem_ty = ty.childType(zcu);
+ const elem_bits: usize = @intCast(elem_ty.bitSize(zcu));
+ const elems_buf = try gpa.alloc(InternPool.Index, @intCast(ty.arrayLen(zcu)));
+ defer gpa.free(elems_buf);
+ var elem_bit_off: usize = bit_offset;
+ for (elems_buf) |*elem| {
+ const elem_val = try readFromPackedMemory(elem_ty, pt, buffer, elem_bit_off);
+ elem.* = elem_val.toIntern();
+ elem_bit_off += elem_bits;
+ }
+ return pt.aggregateValue(ty, elems_buf);
},
- .optional => {
- assert(ty.isPtrLikeOptional(zcu));
- const addr = (try readFromPackedMemory(Type.usize, pt, buffer, bit_offset, gpa)).toUnsignedInt(zcu);
- return .fromInterned(try pt.intern(.{ .opt = .{
- .ty = ty.toIntern(),
- .val = if (addr == 0) .none else (try pt.ptrIntValue(ty.childType(zcu), addr)).toIntern(),
- } }));
- },
- else => @panic("TODO implement readFromPackedMemory for more types"),
+ else => unreachable,
}
}
@@ -887,14 +894,9 @@ pub fn fieldValue(val: Value, pt: Zcu.PerThread, index: usize) !Value {
const bfa = bfa_state.allocator();
const buf = try bfa.alloc(u8, @intCast((ty.bitSize(zcu) + 7) / 8));
defer bfa.free(buf);
- int_val.writeToPackedMemory(zcu, buf, 0) catch |err| switch (err) {
- error.ReinterpretDeclRef => unreachable, // it's an integer
- error.OutOfMemory => |e| return e,
- };
- return Value.readFromPackedMemory(field_ty, pt, buf, field_bit_offset, bfa) catch |err| switch (err) {
- error.IllDefinedMemoryLayout => unreachable, // it's a bitpack
- error.OutOfMemory => |e| return e,
- };
+ @memset(buf, 0);
+ int_val.writeToPackedMemory(zcu, buf, 0);
+ return .readFromPackedMemory(field_ty, pt, buf, field_bit_offset);
},
else => unreachable,
};
@@ -1619,7 +1621,6 @@ pub fn hasRepeatedByteRepr(val: Value, zcu: *const Zcu) !?u8 {
// code late in compilation. So, this error handling is too aggressive and
// causes some false negatives, causing less-than-ideal code generation.
error.IllDefinedMemoryLayout => return null,
- error.Unimplemented => return null,
};
const first_byte = byte_buffer[0];
for (byte_buffer[1..]) |byte| {
@@ -2046,7 +2047,10 @@ pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, op
const ptr_ty_info = Type.fromInterned(ptr.ty).ptrInfo(zcu);
const need_child: Type = .fromInterned(ptr_ty_info.child);
- if (need_child.comptimeOnly(zcu) or need_child.zigTypeTag(zcu) == .@"opaque") {
+ if (need_child.comptimeOnly(zcu) or
+ need_child.zigTypeTag(zcu) == .@"opaque" or
+ need_child.isSpirvRuntimeArray(zcu))
+ {
// No refinement can happen - this pointer is presumably invalid.
// Just offset it.
const parent = try arena.create(PointerDeriveStep);
@@ -2078,6 +2082,7 @@ pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, op
.undefined,
.enum_literal,
.@"opaque",
+ .spirv,
.@"fn",
.error_union,
.int,
@@ -2229,6 +2234,7 @@ pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMe
.null,
.@"fn",
.@"opaque",
+ .spirv,
.enum_literal,
=> comptime unreachable, // comptime-only or otherwise impossible
@@ -2332,6 +2338,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory
.null,
.@"fn",
.@"opaque",
+ .spirv,
.enum_literal,
=> comptime unreachable, // comptime-only or otherwise impossible
diff --git a/src/Zcu.zig b/src/Zcu.zig
index 98ad151de349ac88d9f137e599fa8f8f6f744cf9..e3a36fe31b987dce03f89d1f4694cf718d72d3dc 100644
--- a/src/Zcu.zig
+++ b/src/Zcu.zig
@@ -97,20 +97,20 @@ free_exports: std.ArrayList(Export.Index) = .empty,
/// Maps from an `AnalUnit` which performs a single export, to the index into `all_exports` of
/// the export it performs. Note that the key is not the `Decl` being exported, but the `AnalUnit`
/// whose analysis triggered the export.
-single_exports: std.AutoArrayHashMapUnmanaged(AnalUnit, Export.Index) = .empty,
+single_exports: std.array_hash_map.Auto(AnalUnit, Export.Index) = .empty,
/// Like `single_exports`, but for `AnalUnit`s which perform multiple exports.
/// The exports are `all_exports.items[index..][0..len]`.
-multi_exports: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {
+multi_exports: std.array_hash_map.Auto(AnalUnit, extern struct {
index: u32,
len: u32,
}) = .{},
/// Key is the digest returned by `Builtin.hash`; value is the corresponding module.
-builtin_modules: std.AutoArrayHashMapUnmanaged(Cache.BinDigest, *Package.Module) = .empty,
+builtin_modules: std.array_hash_map.Auto(Cache.BinDigest, *Package.Module) = .empty,
/// Populated as soon as the `Compilation` is created. Guaranteed to contain all modules, even builtin ones.
/// Modules whose root file is not a Zig or ZON file have the value `.none`.
-module_roots: std.AutoArrayHashMapUnmanaged(*Package.Module, File.Index.Optional) = .empty,
+module_roots: std.array_hash_map.Auto(*Package.Module, File.Index.Optional) = .empty,
/// The set of all the Zig source files in the Zig Compilation Unit. Tracked in
/// order to iterate over it and check which source files have been modified on
@@ -125,7 +125,7 @@ module_roots: std.AutoArrayHashMapUnmanaged(*Package.Module, File.Index.Optional
///
/// Not serialized. This state is reconstructed during the first call to
/// `Compilation.update` of the process for a given `Compilation`.
-import_table: std.ArrayHashMapUnmanaged(
+import_table: std.array_hash_map.Custom(
File.Index,
void,
struct {
@@ -141,7 +141,7 @@ import_table: std.ArrayHashMapUnmanaged(
/// update removes an import, or if a module specified on the CLI is never imported.
/// Reconstructed on every update, after AstGen and before Sema.
/// Value is why the file is alive.
-alive_files: std.AutoArrayHashMapUnmanaged(File.Index, File.Reference) = .empty,
+alive_files: std.array_hash_map.Auto(File.Index, File.Reference) = .empty,
/// If this is populated, a "file exists in multiple modules" error should be emitted.
/// This causes file errors to not be shown, because we don't really know which files
@@ -162,7 +162,7 @@ multi_module_err: ?struct {
/// on the `Compilation.Path` of the `EmbedFile`.
///
/// This table owns all of the `*EmbedFile` memory, which is allocated into gpa.
-embed_table: std.ArrayHashMapUnmanaged(
+embed_table: std.array_hash_map.Custom(
*EmbedFile,
void,
struct {
@@ -179,27 +179,27 @@ intern_pool: InternPool = .empty,
/// Value explains why this `AnalUnit` is being analyzed. It is `null` for the topmost analysis
/// (index 0), and non-`null` for all others.
-analysis_in_progress: std.AutoArrayHashMapUnmanaged(AnalUnit, ?*const DependencyReason) = .empty,
+analysis_in_progress: std.array_hash_map.Auto(AnalUnit, ?*const DependencyReason) = .empty,
/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.
-failed_analysis: std.AutoArrayHashMapUnmanaged(AnalUnit, *ErrorMsg) = .empty,
+failed_analysis: std.array_hash_map.Auto(AnalUnit, *ErrorMsg) = .empty,
/// This `AnalUnit` failed semantic analysis because it required analysis of another `AnalUnit` which itself failed.
-transitive_failed_analysis: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .empty,
+transitive_failed_analysis: std.array_hash_map.Auto(AnalUnit, void) = .empty,
/// This `Nav` succeeded analysis, but failed codegen.
/// This may be a simple "value" `Nav`, or it may be a function.
/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.
/// While multiple threads are active (most of the time!), this is guarded by `zcu.comp.mutex`, as
/// codegen and linking run on a separate thread.
-failed_codegen: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, *ErrorMsg) = .empty,
-failed_types: std.AutoArrayHashMapUnmanaged(InternPool.Index, *ErrorMsg) = .empty,
+failed_codegen: std.array_hash_map.Auto(InternPool.Nav.Index, *ErrorMsg) = .empty,
+failed_types: std.array_hash_map.Auto(InternPool.Index, *ErrorMsg) = .empty,
/// Key is an `AnalUnit` which is in `dependency_loop_nodes`. For each dependency loop, exactly one
/// unit in the loop is in this map, though the choice is arbitrary and not necessarily reproducible
/// between compilations. So, instead of (for instance) defining where the dependency loop "starts",
/// this map simply exists to allow easily iterating all dependency loops exactly once.
-dependency_loops: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .empty,
+dependency_loops: std.array_hash_map.Auto(AnalUnit, void) = .empty,
/// Key is an `AnalUnit`, value is the `AnalUnit` which the key references and why it does so.
/// All units in here form loops. To iterate loops, see `dependency_loops`.
-dependency_loop_nodes: std.AutoArrayHashMapUnmanaged(AnalUnit, struct {
+dependency_loop_nodes: std.array_hash_map.Auto(AnalUnit, struct {
unit: AnalUnit,
reason: DependencyReason,
}) = .empty,
@@ -207,7 +207,7 @@ dependency_loop_nodes: std.AutoArrayHashMapUnmanaged(AnalUnit, struct {
/// Keep track of `@compileLog`s per `AnalUnit`.
/// We track the source location of the first `@compileLog` call, and all logged lines as a linked list.
/// The list is singly linked, but we do track its tail for fast appends (optimizing many logs in one unit).
-compile_logs: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {
+compile_logs: std.array_hash_map.Auto(AnalUnit, extern struct {
base_node_inst: InternPool.TrackedInst.Index,
node_offset: Ast.Node.Offset,
first_line: CompileLogLine.Index,
@@ -228,7 +228,7 @@ free_compile_log_lines: std.ArrayList(CompileLogLine.Index) = .empty,
/// We just store a `[]u8` instead of a full `*ErrorMsg`, because the source
/// location is always the entire file. The `[]u8` memory is owned by the map
/// and allocated into `gpa`.
-failed_files: std.AutoArrayHashMapUnmanaged(File.Index, ?[]u8) = .empty,
+failed_files: std.array_hash_map.Auto(File.Index, ?[]u8) = .empty,
/// AstGen is not aware of modules, and so cannot determine whether an import
/// string makes sense. That is the job of a traversal after AstGen.
///
@@ -256,10 +256,10 @@ failed_imports: std.ArrayList(struct {
import_token: Ast.TokenIndex,
kind: enum { file_outside_module_root, illegal_zig_import },
}) = .empty,
-failed_exports: std.AutoArrayHashMapUnmanaged(Export.Index, *ErrorMsg) = .empty,
+failed_exports: std.array_hash_map.Auto(Export.Index, *ErrorMsg) = .empty,
/// If analysis failed due to a cimport error, the corresponding Clang errors
/// are stored here.
-cimport_errors: std.AutoArrayHashMapUnmanaged(AnalUnit, std.zig.ErrorBundle) = .empty,
+cimport_errors: std.array_hash_map.Auto(AnalUnit, std.zig.ErrorBundle) = .empty,
/// Maximum amount of distinct error values, set by --error-limit
error_limit: ErrorInt,
@@ -271,19 +271,19 @@ outdated_lock: if (std.debug.runtime_safety) std.Io.RwLock else void = if (std.d
/// Value is the number of PO dependencies of this AnalUnit.
/// This value will decrease as we perform semantic analysis to learn what is outdated.
/// If any of these PO deps is outdated, this value will be moved to `outdated`.
-potentially_outdated: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .empty,
+potentially_outdated: std.array_hash_map.Auto(AnalUnit, u32) = .empty,
/// Value is the number of PO dependencies of this AnalUnit.
/// Once this value drops to 0, the AnalUnit is a candidate for re-analysis.
-outdated: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .empty,
+outdated: std.array_hash_map.Auto(AnalUnit, u32) = .empty,
/// This is the set of all `AnalUnit`s in `outdated` whose PO dependency count is 0.
/// Such `AnalUnit`s are ready for immediate re-analysis.
/// See `findOutdatedToAnalyze` for details.
outdated_ready: struct {
/// These are separate from other units because it allows `findOutdatedToAnalyze` to prioritize
/// functions, which is useful because it means they will be sent to codegen more quickly.
- funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
+ funcs: std.array_hash_map.Auto(InternPool.Index, void),
/// Does not contain `.func` units.
- other: std.AutoArrayHashMapUnmanaged(AnalUnit, void),
+ other: std.array_hash_map.Auto(AnalUnit, void),
} = .{ .funcs = .empty, .other = .empty },
/// This contains a list of AnalUnit whose analysis or codegen failed, but the
/// failure was something like running out of disk space, and trying again may
@@ -298,23 +298,23 @@ analysis_roots_len: usize = 0,
/// This is the cached result of `Zcu.resolveReferences`. It is computed on-demand, and
/// reset to `null` when any semantic analysis occurs (since this invalidates the data).
/// Allocated into `gpa`.
-resolved_references: ?std.AutoArrayHashMapUnmanaged(AnalUnit, ?ResolvedReference) = null,
+resolved_references: ?std.array_hash_map.Auto(AnalUnit, ?ResolvedReference) = null,
/// If `true`, then semantic analysis must not occur on this update due to AstGen errors.
/// Essentially the entire pipeline after AstGen, including Sema, codegen, and link, is skipped.
/// Reset to `false` at the start of each update in `Compilation.update`.
skip_analysis_this_update: bool = false,
-test_functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty,
+test_functions: std.array_hash_map.Auto(InternPool.Nav.Index, void) = .empty,
-global_assembly: std.AutoArrayHashMapUnmanaged(AnalUnit, []u8) = .empty,
+global_assembly: std.array_hash_map.Auto(AnalUnit, []u8) = .empty,
/// Key is the `AnalUnit` *performing* the reference. This representation allows
/// incremental updates to quickly delete references caused by a specific `AnalUnit`.
/// Value is index into `all_references` of the first reference triggered by the unit.
/// The `next` field on the `Reference` forms a linked list of all references
/// triggered by the key `AnalUnit`.
-reference_table: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .empty,
+reference_table: std.array_hash_map.Auto(AnalUnit, u32) = .empty,
all_references: std.ArrayList(Reference) = .empty,
/// Freelist of indices in `all_references`.
free_references: std.ArrayList(u32) = .empty,
@@ -327,7 +327,7 @@ free_inline_reference_frames: std.ArrayList(InlineReferenceFrame.Index) = .empty
/// Value is index into `all_type_reference` of the first reference triggered by the unit.
/// The `next` field on the `TypeReference` forms a linked list of all type references
/// triggered by the key `AnalUnit`.
-type_reference_table: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .empty,
+type_reference_table: std.array_hash_map.Auto(AnalUnit, u32) = .empty,
all_type_references: std.ArrayList(TypeReference) = .empty,
/// Freelist of indices in `all_type_references`.
free_type_references: std.ArrayList(u32) = .empty,
@@ -355,12 +355,12 @@ pub const DependencyReason = struct {
pub const IncrementalDebugState = struct {
/// All container types in the ZCU, even dead ones.
/// Value is the generation the type was created on.
- types: std.AutoArrayHashMapUnmanaged(InternPool.Index, u32),
+ types: std.array_hash_map.Auto(InternPool.Index, u32),
/// All `Nav`s in the ZCU, even dead ones.
/// Value is the generation the `Nav` was created on.
- navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, u32),
+ navs: std.array_hash_map.Auto(InternPool.Nav.Index, u32),
/// All `AnalUnit`s in the ZCU, even dead ones.
- units: std.AutoArrayHashMapUnmanaged(AnalUnit, UnitInfo),
+ units: std.array_hash_map.Auto(AnalUnit, UnitInfo),
pub const init: IncrementalDebugState = .{
.types = .empty,
@@ -468,6 +468,13 @@ pub const StdLangDecl = enum {
@"Type.Struct.FieldAttributes",
@"Type.ContainerLayout",
@"Type.Opaque",
+ @"Type.Spirv",
+ @"Type.Spirv.Image",
+ @"Type.Spirv.Image.Usage",
+ @"Type.Spirv.Image.Format",
+ @"Type.Spirv.Image.Dimensionality",
+ @"Type.Spirv.Image.Depth",
+ @"Type.Spirv.Image.Access",
panic,
@"panic.call",
@@ -548,6 +555,13 @@ pub const StdLangDecl = enum {
.@"Type.Struct.FieldAttributes",
.@"Type.ContainerLayout",
.@"Type.Opaque",
+ .@"Type.Spirv",
+ .@"Type.Spirv.Image",
+ .@"Type.Spirv.Image.Usage",
+ .@"Type.Spirv.Image.Format",
+ .@"Type.Spirv.Image.Dimensionality",
+ .@"Type.Spirv.Image.Depth",
+ .@"Type.Spirv.Image.Access",
=> .type,
.panic => .type,
@@ -601,7 +615,7 @@ pub const StdLangDecl = enum {
.VaList => .va_list,
.assembly, .@"assembly.Clobbers" => .assembly,
else => {
- if (@intFromEnum(decl) <= @intFromEnum(StdLangDecl.@"Type.Opaque")) {
+ if (@intFromEnum(decl) <= @intFromEnum(StdLangDecl.@"Type.Spirv.Image.Access")) {
return .main;
} else {
return .panic;
@@ -679,7 +693,7 @@ pub const SimplePanicId = enum {
}
};
-pub const GlobalErrorSet = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void);
+pub const GlobalErrorSet = std.array_hash_map.Auto(InternPool.NullTerminatedString, void);
pub const CImportError = struct {
offset: u32,
@@ -838,9 +852,9 @@ pub const Namespace = struct {
/// Will be a struct, enum, union, or opaque.
owner_type: InternPool.Index,
/// Members of the namespace which are marked `pub`.
- pub_decls: std.ArrayHashMapUnmanaged(InternPool.Nav.Index, void, NavNameContext, true) = .empty,
+ pub_decls: std.array_hash_map.Custom(InternPool.Nav.Index, void, NavNameContext, true) = .empty,
/// Members of the namespace which are *not* marked `pub`.
- priv_decls: std.ArrayHashMapUnmanaged(InternPool.Nav.Index, void, NavNameContext, true) = .empty,
+ priv_decls: std.array_hash_map.Custom(InternPool.Nav.Index, void, NavNameContext, true) = .empty,
/// All `comptime` declarations in this namespace. We store these purely so that incremental
/// compilation can re-use the existing `ComptimeUnit`s when a namespace changes.
comptime_decls: std.ArrayList(InternPool.ComptimeUnit.Id) = .empty,
@@ -1529,7 +1543,7 @@ pub const SrcLoc = struct {
.node_offset_deref_ptr => |node_off| {
const tree = try src_loc.file_scope.getTree(zcu);
const node = node_off.toAbsolute(src_loc.base_node);
- return tree.nodeToSpan(node);
+ return tree.nodeToSpan(tree.nodeData(node).node);
},
.node_offset_asm_source => |node_off| {
const tree = try src_loc.file_scope.getTree(zcu);
@@ -2740,6 +2754,7 @@ pub const LazySrcLoc = struct {
.reify_enum => zir.extraData(Zir.Inst.ReifyEnum, inst.data.extended.operand).data.node,
.reify_struct => zir.extraData(Zir.Inst.ReifyStruct, inst.data.extended.operand).data.node,
.reify_union => zir.extraData(Zir.Inst.ReifyUnion, inst.data.extended.operand).data.node,
+ .reify_spirv_type => zir.extraData(Zir.Inst.ReifySpirvType, inst.data.extended.operand).data.node,
else => unreachable,
},
else => unreachable,
@@ -2819,15 +2834,12 @@ pub fn deinit(zcu: *Zcu) void {
const io = comp.io;
const gpa = zcu.gpa;
{
- const pt: Zcu.PerThread = .activate(zcu, .main);
- defer pt.deactivate();
-
if (zcu.llvm_object) |llvm_object| llvm_object.deinit();
zcu.builtin_modules.deinit(gpa);
zcu.module_roots.deinit(gpa);
for (zcu.import_table.keys()) |file_index| {
- pt.destroyFile(file_index);
+ zcu.destroyFile(file_index);
}
zcu.import_table.deinit(gpa);
zcu.alive_files.deinit(gpa);
@@ -2910,6 +2922,26 @@ pub fn deinit(zcu: *Zcu) void {
zcu.intern_pool.deinit(gpa, io);
}
+fn deinitFile(zcu: *Zcu, file_index: Zcu.File.Index) void {
+ const gpa = zcu.gpa;
+ const file = zcu.fileByIndex(file_index);
+ log.debug("deinit File {f}", .{file.path.fmt(zcu.comp)});
+ file.path.deinit(gpa);
+ file.unload(gpa);
+ if (file.prev_zir) |prev_zir| {
+ prev_zir.deinit(gpa);
+ gpa.destroy(prev_zir);
+ }
+ file.* = undefined;
+}
+
+fn destroyFile(zcu: *Zcu, file_index: Zcu.File.Index) void {
+ const gpa = zcu.gpa;
+ const file = zcu.fileByIndex(file_index);
+ deinitFile(zcu, file_index);
+ gpa.destroy(file);
+}
+
pub fn namespacePtr(zcu: *Zcu, index: Namespace.Index) *Namespace {
return zcu.intern_pool.namespacePtr(index);
}
@@ -4168,13 +4200,13 @@ pub const ResolvedReference = struct {
/// If an `AnalUnit` is not in the returned map, it is unreferenced.
/// The returned hashmap is owned by the `Zcu`, so should not be freed by the caller.
/// This hashmap is cached, so repeated calls to this function are cheap.
-pub fn resolveReferences(zcu: *Zcu) Allocator.Error!*const std.AutoArrayHashMapUnmanaged(AnalUnit, ?ResolvedReference) {
+pub fn resolveReferences(zcu: *Zcu) Allocator.Error!*const std.array_hash_map.Auto(AnalUnit, ?ResolvedReference) {
if (zcu.resolved_references == null) {
zcu.resolved_references = try zcu.resolveReferencesInner();
}
return &zcu.resolved_references.?;
}
-fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.AutoArrayHashMapUnmanaged(AnalUnit, ?ResolvedReference) {
+fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(AnalUnit, ?ResolvedReference) {
const trace = tracy.trace(@src());
defer trace.end();
@@ -4182,8 +4214,8 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.AutoArrayHashMapUnmanag
const comp = zcu.comp;
const ip = &zcu.intern_pool;
- var units: std.AutoArrayHashMapUnmanaged(AnalUnit, ?ResolvedReference) = .empty;
- var types: std.AutoArrayHashMapUnmanaged(InternPool.Index, ?ResolvedReference) = .empty;
+ var units: std.array_hash_map.Auto(AnalUnit, ?ResolvedReference) = .empty;
+ var types: std.array_hash_map.Auto(InternPool.Index, ?ResolvedReference) = .empty;
defer {
units.deinit(gpa);
types.deinit(gpa);
@@ -4679,6 +4711,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
.stage2_spirv => switch (cc) {
.spirv_device, .spirv_kernel => true,
.spirv_fragment, .spirv_vertex => target.os.tag == .vulkan or target.os.tag == .opengl,
+ .spirv_task, .spirv_mesh => target.os.tag == .vulkan,
else => false,
},
};
@@ -5373,9 +5406,9 @@ pub const CodegenTaskPool = struct {
const io = zcu.comp.io;
const tid: Zcu.PerThread.Id = .acquire(io);
defer tid.release(io);
- const pt: Zcu.PerThread = .activate(zcu, tid);
- defer pt.deactivate();
- return pt.runCodegen(func_index, &air);
+ const active = zcu.activate(tid);
+ defer active.deactivate();
+ return active.pt.runCodegen(func_index, &air);
}
fn workerCodegenExternalAir(
zcu: *Zcu,
@@ -5385,9 +5418,9 @@ pub const CodegenTaskPool = struct {
const io = zcu.comp.io;
const tid: Zcu.PerThread.Id = .acquire(io);
defer tid.release(io);
- const pt: Zcu.PerThread = .activate(zcu, tid);
- defer pt.deactivate();
- return pt.runCodegen(func_index, air);
+ const active = zcu.activate(tid);
+ defer active.deactivate();
+ return active.pt.runCodegen(func_index, air);
}
};
@@ -5416,3 +5449,24 @@ fn updateTracyOutdatedPlots(zcu: *const Zcu) void {
zcu.updateTracyPlot("potentially_outdated", zcu.potentially_outdated.count());
zcu.updateTracyPlot("outdated_ready", zcu.outdated_ready.funcs.count() + zcu.outdated_ready.other.count());
}
+
+pub const Active = struct {
+ pt: Zcu.PerThread,
+ ip: InternPool.Active,
+ pub fn deactivate(active: Active) void {
+ active.ip.deactivate();
+ }
+ pub fn release(active: Active) void {
+ active.deactivate();
+ active.pt.tid.release(active.pt.zcu.comp.io);
+ }
+};
+pub fn activate(zcu: *Zcu, tid: PerThread.Id) Active {
+ return .{
+ .pt = .{ .zcu = zcu, .tid = tid },
+ .ip = zcu.intern_pool.activate(),
+ };
+}
+pub fn acquire(zcu: *Zcu) Active {
+ return zcu.activate(.acquire(zcu.comp.io));
+}
diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig
index 260d0eeba84d3cab63e22caf682ab82426d2d922..e1cda016c163cdfde8cb693c5f143f2f86057980 100644
--- a/src/Zcu/PerThread.zig
+++ b/src/Zcu/PerThread.zig
@@ -125,14 +125,6 @@ pub const Id = if (InternPool.single_threaded) enum {
}
};
-pub fn activate(zcu: *Zcu, tid: Id) Zcu.PerThread {
- zcu.intern_pool.activate();
- return .{ .zcu = zcu, .tid = tid };
-}
-pub fn deactivate(pt: Zcu.PerThread) void {
- pt.zcu.intern_pool.deactivate();
-}
-
/// Called from `Compilation.performAllTheWork`. Performs one incremental update of the ZCU: detects
/// changes to files, runs AstGen, and then enters the main semantic analysis loop, where we build
/// up a graph of declarations, functions, etc, while also sending declarations and functions to
@@ -378,10 +370,10 @@ fn workerUpdateFile(
const child_prog_node = prog_node.start(std.fs.path.basename(file.path.sub_path), 0);
defer child_prog_node.end();
- const pt: Zcu.PerThread = .activate(comp.zcu.?, tid);
- defer pt.deactivate();
- pt.updateFile(file_index, file) catch |err| {
- pt.reportRetryableFileError(file_index, "unable to load '{s}': {s}", .{ std.fs.path.basename(file.path.sub_path), @errorName(err) }) catch |oom| switch (oom) {
+ const active = comp.zcu.?.activate(tid);
+ defer active.deactivate();
+ active.pt.updateFile(file_index, file) catch |err| {
+ active.pt.reportRetryableFileError(file_index, "unable to load '{s}': {s}", .{ std.fs.path.basename(file.path.sub_path), @errorName(err) }) catch |oom| switch (oom) {
error.OutOfMemory => {
comp.mutex.lockUncancelable(io);
defer comp.mutex.unlock(io);
@@ -411,7 +403,7 @@ fn workerUpdateFile(
const import_path = file.zir.?.nullTerminatedString(item.data.name);
- if (pt.discoverImport(file.path, import_path)) |res| switch (res) {
+ if (active.pt.discoverImport(file.path, import_path)) |res| switch (res) {
.module, .existing_file => {},
.new_file => |new| {
group.async(io, workerUpdateFile, .{
@@ -443,13 +435,15 @@ fn workerUpdateEmbedFile(comp: *Compilation, ef_index: Zcu.EmbedFile.Index, ef:
fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) !void {
const io = comp.io;
const zcu = comp.zcu.?;
- const pt: Zcu.PerThread = .activate(zcu, tid);
- defer pt.deactivate();
const old_val = ef.val;
const old_err = ef.err;
- try pt.updateEmbedFile(ef, null);
+ {
+ const active = zcu.activate(tid);
+ defer active.deactivate();
+ try active.pt.updateEmbedFile(ef, null);
+ }
if (ef.val != .none and ef.val == old_val) return; // success, value unchanged
if (ef.val == .none and old_val == .none and ef.err == old_err) return; // failure, error unchanged
@@ -460,27 +454,6 @@ fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zc
try zcu.markDependeeOutdated(.not_marked_po, .{ .embed_file = ef_index });
}
-fn deinitFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void {
- const zcu = pt.zcu;
- const gpa = zcu.gpa;
- const file = zcu.fileByIndex(file_index);
- log.debug("deinit File {f}", .{file.path.fmt(zcu.comp)});
- file.path.deinit(gpa);
- file.unload(gpa);
- if (file.prev_zir) |prev_zir| {
- prev_zir.deinit(gpa);
- gpa.destroy(prev_zir);
- }
- file.* = undefined;
-}
-
-pub fn destroyFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void {
- const gpa = pt.zcu.gpa;
- const file = pt.zcu.fileByIndex(file_index);
- pt.deinitFile(file_index);
- gpa.destroy(file);
-}
-
/// Ensures that `file` has up-to-date ZIR. If not, loads the ZIR cache or runs
/// AstGen as needed. Also updates `file.status`. Does not assume that `file.mod`
/// is populated. Does not return `error.AnalysisFail` on AstGen failures.
@@ -814,7 +787,7 @@ const UpdatedFile = struct {
inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index),
};
-fn cleanupUpdatedFiles(gpa: Allocator, updated_files: *std.AutoArrayHashMapUnmanaged(Zcu.File.Index, UpdatedFile)) void {
+fn cleanupUpdatedFiles(gpa: Allocator, updated_files: *std.array_hash_map.Auto(Zcu.File.Index, UpdatedFile)) void {
for (updated_files.values()) |*elem| elem.inst_map.deinit(gpa);
updated_files.deinit(gpa);
}
@@ -832,7 +805,7 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void {
// We need to visit every updated File for every TrackedInst in InternPool.
// This only includes Zig files; ZON files are omitted.
- var updated_files: std.AutoArrayHashMapUnmanaged(Zcu.File.Index, UpdatedFile) = .empty;
+ var updated_files: std.array_hash_map.Auto(Zcu.File.Index, UpdatedFile) = .empty;
defer cleanupUpdatedFiles(gpa, &updated_files);
for (zcu.import_table.keys()) |file_index| {
@@ -934,7 +907,7 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void {
if (!has_namespace) continue;
// Value is whether the declaration is `pub`.
- var old_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, bool) = .empty;
+ var old_names: std.array_hash_map.Auto(InternPool.NullTerminatedString, bool) = .empty;
defer old_names.deinit(zcu.gpa);
for (old_zir.typeDecls(old_inst)) |decl_inst| {
const old_decl = old_zir.getDeclaration(decl_inst);
@@ -3595,8 +3568,8 @@ pub fn processExports(pt: Zcu.PerThread) !void {
}
// First, construct a mapping of every exported value and Nav to the indices of all its different exports.
- var nav_exports: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, std.ArrayList(Zcu.Export.Index)) = .empty;
- var uav_exports: std.AutoArrayHashMapUnmanaged(InternPool.Index, std.ArrayList(Zcu.Export.Index)) = .empty;
+ var nav_exports: std.array_hash_map.Auto(InternPool.Nav.Index, std.ArrayList(Zcu.Export.Index)) = .empty;
+ var uav_exports: std.array_hash_map.Auto(InternPool.Index, std.ArrayList(Zcu.Export.Index)) = .empty;
defer {
for (nav_exports.values()) |*exports| {
exports.deinit(gpa);
@@ -3692,7 +3665,7 @@ pub fn processExports(pt: Zcu.PerThread) !void {
}
}
-const SymbolExports = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, Zcu.Export.Index);
+const SymbolExports = std.array_hash_map.Auto(InternPool.NullTerminatedString, Zcu.Export.Index);
fn processExportsInner(
pt: Zcu.PerThread,
@@ -4540,7 +4513,6 @@ pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) Ru
comp.config.use_llvm,
)) {
else => unreachable, // assertion failure
- .stage2_spirv,
.stage2_llvm,
=> {},
},
@@ -4572,8 +4544,12 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
tracy_trace.addText(fqn.toSlice(ip));
tracy_trace.addTextFmt("func_ip_index={d}", .{func_index});
+ Air.Verify.run(pt, func_index, air);
+
if (codegen.legalizeFeatures(pt, nav)) |features| {
try air.legalize(pt, features);
+ // Verify the AIR again post-legalization.
+ Air.Verify.run(pt, func_index, air);
}
var liveness: ?Air.Liveness = if (codegen.wantsLiveness(pt, nav))
@@ -4621,18 +4597,6 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
const lf = comp.bin_file orelse return error.NoLinkFile;
- // Just like LLVM, the SPIR-V backend can't multi-threaded due to SPIR-V design limitations.
- if (lf.cast(.spirv)) |spirv_file| {
- assert(zcu.pending_codegen_jobs.load(.monotonic) == 2); // only one codegen at a time (but the value is 2 because 1 is the base)
- spirv_file.updateFunc(pt, func_index, air, &liveness) catch |err| {
- switch (err) {
- error.OutOfMemory => comp.link_diags.setAllocFailure(),
- }
- return error.AlreadyReported;
- };
- return error.BackendDoesNotProduceMir;
- }
-
return codegen.generateFunction(lf, pt, func_index, air, &liveness);
}
diff --git a/src/codegen.zig b/src/codegen.zig
index 4a2be3ea39e3fcdb117cd49c638058134d457d86..55d73b476a7a9a9a89a18fc4c8be9b8e139ac6c3 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -101,6 +101,7 @@ pub const AnyMir = union {
x86_64: if (dev.env.supports(.x86_64_backend)) @import("codegen/x86_64/Mir.zig") else noreturn,
wasm: if (dev.env.supports(.wasm_backend)) @import("codegen/wasm/Mir.zig") else noreturn,
c: if (dev.env.supports(.c_backend)) @import("codegen/c.zig").Mir else noreturn,
+ spirv: if (dev.env.supports(.spirv_backend)) @import("codegen/spirv/Mir.zig") else noreturn,
pub inline fn tag(comptime backend: std.lang.CompilerBackend) []const u8 {
return switch (backend) {
@@ -110,6 +111,7 @@ pub const AnyMir = union {
.stage2_x86_64 => "x86_64",
.stage2_wasm => "wasm",
.stage2_c => "c",
+ .stage2_spirv => "spirv",
else => unreachable,
};
}
@@ -125,6 +127,7 @@ pub const AnyMir = union {
.stage2_x86_64,
.stage2_wasm,
.stage2_c,
+ .stage2_spirv,
=> |backend_ct| @field(mir, tag(backend_ct)).deinit(gpa),
}
}
@@ -153,6 +156,7 @@ pub fn generateFunction(
.stage2_x86_64,
.stage2_wasm,
.stage2_c,
+ .stage2_spirv,
=> |backend| {
dev.check(devFeatureForBackend(backend));
const CodeGen = importBackend(backend);
@@ -329,6 +333,7 @@ pub fn generateSymbol(
.tuple_type,
.union_type,
.opaque_type,
+ .spirv_type,
.enum_type,
.func_type,
.error_set_type,
diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig
index e09ca268b9091dfcf149a9728b0641e303f00cf1..a4b072f448fde6ebb3d0ff7163064892fe88c4b3 100644
--- a/src/codegen/aarch64/Select.zig
+++ b/src/codegen/aarch64/Select.zig
@@ -4,12 +4,12 @@ air: Air,
nav_index: InternPool.Nav.Index,
// Blocks
-def_order: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, void),
-blocks: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, Block),
-loops: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, Loop),
+def_order: std.array_hash_map.Auto(Air.Inst.Index, void),
+blocks: std.array_hash_map.Auto(Air.Inst.Index, Block),
+loops: std.array_hash_map.Auto(Air.Inst.Index, Loop),
active_loops: std.ArrayList(Loop.Index),
loop_live: struct {
- set: std.AutoArrayHashMapUnmanaged(struct { Loop.Index, Air.Inst.Index }, void),
+ set: std.array_hash_map.Auto(struct { Loop.Index, Air.Inst.Index }, void),
list: std.ArrayList(Air.Inst.Index),
},
dom_start: u32,
@@ -255,6 +255,7 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
.work_item_id,
.work_group_size,
.work_group_id,
+ .spirv_runtime_array_len,
=> unreachable,
.ret_ptr => {
const ty = air_data[@intFromEnum(air_inst_index)].ty;
@@ -291,8 +292,8 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
.load,
.fptrunc,
.fpext,
- .intcast,
- .intcast_safe,
+ .int_cast,
+ .int_cast_safe,
.trunc,
.optional_payload,
.optional_payload_ptr,
@@ -333,7 +334,15 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
air_inst_index = air_body[air_body_index];
continue :air_tag air_tags[@intFromEnum(air_inst_index)];
},
- .bitcast => {
+ .bit_cast,
+ .ptr_cast,
+ .ptr_from_int,
+ .int_from_ptr,
+ .error_cast,
+ .error_from_int,
+ .int_from_error,
+ .union_from_enum,
+ => {
const ty_op = air_data[@intFromEnum(air_inst_index)].ty_op;
maybe_noop: {
if (ty_op.ty.toInterned().? != isel.air.typeOf(ty_op.operand, ip).toIntern()) break :maybe_noop;
@@ -3189,7 +3198,15 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
}
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
- .bitcast => |air_tag| {
+ .bit_cast,
+ .ptr_cast,
+ .ptr_from_int,
+ .int_from_ptr,
+ .error_cast,
+ .error_from_int,
+ .int_from_error,
+ .union_from_enum,
+ => |air_tag| {
if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
defer dst_vi.value.deref(isel);
const ty_op = air.data(air.inst_index).ty_op;
@@ -5220,7 +5237,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
}
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
- .intcast => |air_tag| {
+ .int_cast => |air_tag| {
if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
defer dst_vi.value.deref(isel);
@@ -5311,7 +5328,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
}
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
- .intcast_safe => |air_tag| {
+ .int_cast_safe => |air_tag| {
if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
defer dst_vi.value.deref(isel);
@@ -7491,7 +7508,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
}
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
- .work_item_id, .work_group_size, .work_group_id => unreachable,
+ .work_item_id, .work_group_size, .work_group_id, .spirv_runtime_array_len => unreachable,
}
assert(air.body_index == 0);
}
@@ -11224,7 +11241,7 @@ fn dumpValuesInner(isel: *Select, which: WhichValues) !void {
defer std.debug.unlockStderr();
const stderr = &locked_stderr.file_writer.interface;
- var reverse_live_values: std.AutoArrayHashMapUnmanaged(Value.Index, std.ArrayList(Air.Inst.Index)) = .empty;
+ var reverse_live_values: std.array_hash_map.Auto(Value.Index, std.ArrayList(Air.Inst.Index)) = .empty;
defer {
for (reverse_live_values.values()) |*list| list.deinit(gpa);
reverse_live_values.deinit(gpa);
@@ -11253,7 +11270,7 @@ fn dumpValuesInner(isel: *Select, which: WhichValues) !void {
};
}
- var roots: std.AutoArrayHashMapUnmanaged(Value.Index, u32) = .empty;
+ var roots: std.array_hash_map.Auto(Value.Index, u32) = .empty;
defer roots.deinit(gpa);
{
try roots.ensureTotalCapacity(gpa, isel.values.items.len);
@@ -11354,7 +11371,7 @@ fn writeToMemory(isel: *Select, constant: Constant, buffer: []u8) error{OutOfMem
if (try isel.writeKeyToMemory(ip.indexToKey(constant.toIntern()), buffer)) return true;
constant.writeToMemory(zcu, buffer) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
- error.ReinterpretDeclRef, error.Unimplemented, error.IllDefinedMemoryLayout => return false,
+ error.ReinterpretDeclRef, error.IllDefinedMemoryLayout => return false,
};
return true;
}
diff --git a/src/codegen/aarch64/abi.zig b/src/codegen/aarch64/abi.zig
index 369c0813f76a22d488c24e9165a3ba6362299b3a..dcd192da8395fc6fca07c101aebff596bc4e99cc 100644
--- a/src/codegen/aarch64/abi.zig
+++ b/src/codegen/aarch64/abi.zig
@@ -21,7 +21,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {
if (ty.containerLayout(zcu) == .@"packed") return .byval;
if (countFloats(ty, zcu)) |float| return .{ .float_array = float.count };
- const bit_size = ty.bitSize(zcu);
+ const bit_size = ty.abiSize(zcu) * 8;
if (bit_size > 128) return .memory;
if (bit_size > 64) return .double_integer;
return .integer;
@@ -30,7 +30,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {
if (ty.containerLayout(zcu) == .@"packed") return .byval;
if (countFloats(ty, zcu)) |float| return .{ .float_array = float.count };
- const bit_size = ty.bitSize(zcu);
+ const bit_size = ty.abiSize(zcu) * 8;
if (bit_size > 128) return .memory;
if (bit_size > 64) return .double_integer;
return .integer;
@@ -62,6 +62,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {
.null,
.@"fn",
.@"opaque",
+ .spirv,
.enum_literal,
.array,
=> unreachable,
diff --git a/src/codegen/arm/abi.zig b/src/codegen/arm/abi.zig
index 22bd34274f49e24d5538302a1a9c285414085c01..14acccbb7963991a3c9c201bcebaeb9218af7ff8 100644
--- a/src/codegen/arm/abi.zig
+++ b/src/codegen/arm/abi.zig
@@ -30,11 +30,11 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
const ip = &zcu.intern_pool;
switch (ty.zigTypeTag(zcu)) {
.@"struct" => {
- const bit_size = ty.bitSize(zcu);
if (ty.containerLayout(zcu) == .@"packed") {
- if (bit_size > 64) return .memory;
+ if (ty.bitSize(zcu) > 64) return .memory;
return .byval;
}
+ const bit_size = ty.abiSize(zcu) * 8;
if (bit_size > max_byval_size) return .memory;
const float_count = countFloats(ty, zcu, &maybe_float_bits);
if (float_count <= byval_float_count) return .byval;
@@ -47,17 +47,17 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
var i: u32 = 0;
while (i < fields) : (i += 1) {
const field_ty = ty.fieldType(i, zcu);
- if (field_ty.bitSize(zcu) > 32) return Class.arrSize(bit_size, 64);
+ if (field_ty.abiSize(zcu) > 4) return Class.arrSize(bit_size, 64);
}
return Class.arrSize(bit_size, 32);
},
.@"union" => {
- const bit_size = ty.bitSize(zcu);
const union_obj = zcu.typeToUnion(ty).?;
if (union_obj.layout == .@"packed") {
- if (bit_size > 64) return .memory;
+ if (ty.bitSize(zcu) > 64) return .memory;
return .byval;
}
+ const bit_size = ty.abiSize(zcu) * 8;
if (bit_size > max_byval_size) return .memory;
const float_count = countFloats(ty, zcu, &maybe_float_bits);
if (float_count <= byval_float_count) return .byval;
@@ -67,7 +67,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
}
for (union_obj.field_types.get(ip)) |field_ty| {
- if (Type.fromInterned(field_ty).bitSize(zcu) > 32) {
+ if (Type.fromInterned(field_ty).abiSize(zcu) > 4) {
return Class.arrSize(bit_size, 64);
}
}
@@ -113,6 +113,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
.null,
.@"fn",
.@"opaque",
+ .spirv,
.enum_literal,
.array,
=> unreachable,
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 08e49fa1e13355293532e4bebe108d27a8223193..70be045b9ae3d23ffa3d8a8a45f467bfbbe6f74b 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -27,7 +27,7 @@ pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features {
return comptime switch (dev.env.supports(.legalize)) {
inline false, true => |supports_legalize| &.init(.{
// we don't currently ask zig1 to use safe optimization modes
- .expand_intcast_safe = supports_legalize,
+ .expand_int_cast_safe = supports_legalize,
.expand_int_from_float_safe = supports_legalize,
.expand_int_from_float_optimized_safe = supports_legalize,
.expand_add_safe = supports_legalize,
@@ -38,6 +38,9 @@ pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features {
.expand_packed_store = true,
.expand_packed_struct_field_val = true,
.expand_packed_aggregate_init = true,
+
+ .scalarize_bit_cast_array = true,
+ .scalarize_bit_cast_vector_non_elementwise = true,
}),
};
}
@@ -59,14 +62,14 @@ pub const Mir = struct {
/// Key is the value of the UAV; value is the UAV's alignment, or
/// `.none` for natural alignment. The specified alignment is never
/// less than the natural alignment.
- need_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
+ need_uavs: std.array_hash_map.Auto(InternPool.Index, Alignment),
ctype_deps: CType.Dependencies,
/// Key is an enum type for which we need a generated `@tagName` function.
- need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
+ need_tag_name_funcs: std.array_hash_map.Auto(InternPool.Index, void),
/// Key is a function Nav for which we need a generated `zig_never_tail` wrapper.
- need_never_tail_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void),
+ need_never_tail_funcs: std.array_hash_map.Auto(InternPool.Nav.Index, void),
/// Key is a function Nav for which we need a generated `zig_never_inline` wrapper.
- need_never_inline_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void),
+ need_never_inline_funcs: std.array_hash_map.Auto(InternPool.Nav.Index, void),
pub fn deinit(mir: *Mir, gpa: Allocator) void {
gpa.free(mir.fwd_decl);
@@ -164,8 +167,8 @@ const LocalType = struct {
};
const LocalIndex = u16;
-const LocalsList = std.AutoArrayHashMapUnmanaged(LocalIndex, void);
-const LocalsMap = std.AutoArrayHashMapUnmanaged(LocalType, LocalsList);
+const LocalsList = std.array_hash_map.Auto(LocalIndex, void);
+const LocalsMap = std.array_hash_map.Auto(LocalType, LocalsList);
const ValueRenderLocation = enum {
initializer,
@@ -328,6 +331,9 @@ fn isReservedIdent(ident: []const u8) bool {
return true;
}
+ // zig.h
+ if (mem.startsWith(u8, ident, "zig_")) return true;
+
return reserved_idents.has(ident);
}
@@ -391,11 +397,11 @@ pub const Function = struct {
code: Writer.Allocating,
indent_counter: usize,
/// Key is an enum type for which we need a generated `@tagName` function.
- need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
+ need_tag_name_funcs: std.array_hash_map.Auto(InternPool.Index, void),
/// Key is a function Nav for which we need a generated `zig_never_tail` wrapper.
- need_never_tail_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void),
+ need_never_tail_funcs: std.array_hash_map.Auto(InternPool.Nav.Index, void),
/// Key is a function Nav for which we need a generated `zig_never_inline` wrapper.
- need_never_inline_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void),
+ need_never_inline_funcs: std.array_hash_map.Auto(InternPool.Nav.Index, void),
func_index: InternPool.Index,
/// All the locals, to be emitted at the top of the function.
locals: std.ArrayList(LocalType) = .empty,
@@ -407,7 +413,7 @@ pub const Function = struct {
/// of variable declarations at the top of a function, sorted descending
/// by type alignment.
/// The value is whether the alloc needs to be emitted in the header.
- allocs: std.AutoArrayHashMapUnmanaged(LocalIndex, bool) = .empty,
+ allocs: std.array_hash_map.Auto(LocalIndex, bool) = .empty,
/// Maps from `loop_switch_br` instructions to the allocated local used
/// for the switch cond. Dispatches should set this local to the new cond.
loop_switch_conds: std.AutoHashMapUnmanaged(Air.Inst.Index, LocalIndex) = .empty,
@@ -643,7 +649,7 @@ pub const DeclGen = struct {
/// Key is the value of the UAV; value is the UAV's alignment, or
/// `.none` for natural alignment. The specified alignment is never
/// less than the natural alignment.
- uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
+ uavs: std.array_hash_map.Auto(InternPool.Index, Alignment),
fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) Error {
@branchHint(.cold);
@@ -902,6 +908,7 @@ pub const DeclGen = struct {
.tuple_type,
.union_type,
.opaque_type,
+ .spirv_type,
.enum_type,
.func_type,
.error_set_type,
@@ -1119,7 +1126,7 @@ pub const DeclGen = struct {
}
try w.writeByte('{');
const ai = ty.arrayInfo(zcu);
- if (ai.elem_type.eql(.u8, zcu)) {
+ if (ai.elem_type.eql(.u8)) {
var literal: StringLiteral = .init(w, @intCast(ty.arrayLenIncludingSentinel(zcu)));
try literal.start();
var index: usize = 0;
@@ -1538,7 +1545,7 @@ pub const DeclGen = struct {
}
try w.writeByte('{');
const ai = ty.arrayInfo(zcu);
- if (ai.elem_type.eql(.u8, zcu)) {
+ if (ai.elem_type.eql(.u8)) {
var literal: StringLiteral = .init(w, @intCast(ty.arrayLenIncludingSentinel(zcu)));
try literal.start();
var index: u64 = 0;
@@ -1565,6 +1572,7 @@ pub const DeclGen = struct {
},
.anyframe_type,
.opaque_type,
+ .spirv_type,
.func_type,
=> unreachable,
@@ -1975,9 +1983,9 @@ pub const DeclGen = struct {
}
switch (CType.classifyInt(ty, zcu)) {
.void => unreachable, // opv
- .small => try w.print("{c}{d}", .{
+ .small => |s| try w.print("{c}{d}", .{
signAbbrev(ty.intInfo(zcu).signedness),
- ty.abiSize(zcu) * 8,
+ s.bits(zcu.getTarget()),
}),
.big => try w.writeAll("big"),
}
@@ -2631,9 +2639,9 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
// zig fmt: off
.inferred_alloc, .inferred_alloc_comptime => unreachable,
- // No "scalarize" legalizations are enabled, so these instructions never appear.
- .legalize_vec_elem_val => unreachable,
- .legalize_vec_store_elem => unreachable,
+ // Possible because `Air.Legalize.scalarize_bit_cast_vector_non_elementwise` is enabled.
+ .legalize_vec_elem_val => try airArrayElemVal(f, inst),
+ .legalize_vec_store_elem => try airLegalizeVecStoreElem(f, inst),
// No soft float legalizations are enabled.
.legalize_compiler_rt_call => unreachable,
@@ -2746,8 +2754,15 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
.alloc => try airAlloc(f, inst),
.ret_ptr => try airRetPtr(f, inst),
.assembly => try airAsm(f, inst),
- .bitcast => try airBitcast(f, inst),
- .intcast => try airIntCast(f, inst),
+ .ptr_cast => try airPtrCast(f, inst),
+ .ptr_from_int => try airSimpleCast(f, inst),
+ .int_from_ptr => try airSimpleCast(f, inst),
+ .error_cast => try airNopCast(f, inst),
+ .error_from_int => try airNopCast(f, inst),
+ .int_from_error => try airNopCast(f, inst),
+ .union_from_enum => try airUnionFromEnum(f, inst),
+ .bit_cast => try airBitCast(f, inst),
+ .int_cast => try airIntCast(f, inst),
.trunc => try airTrunc(f, inst),
.load => try airLoad(f, inst),
.store => try airStore(f, inst, false),
@@ -2859,7 +2874,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
.add_safe,
.sub_safe,
.mul_safe,
- .intcast_safe,
+ .int_cast_safe,
.int_from_float_safe,
.int_from_float_optimized_safe,
=> return f.fail("TODO implement safety_checked_instructions", .{}),
@@ -2877,6 +2892,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
.work_item_id,
.work_group_size,
.work_group_id,
+ .spirv_runtime_array_len,
=> unreachable,
// Instructions that are known to always be `noreturn` based on their tag.
@@ -3077,6 +3093,28 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
return local;
}
+fn airLegalizeVecStoreElem(f: *Function, inst: Air.Inst.Index) !CValue {
+ const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
+ const extra = f.air.extraData(Air.Bin, pl_op.payload).data;
+
+ const vec_ptr = try f.resolveInst(pl_op.operand);
+ const index = try f.resolveInst(extra.lhs);
+ const elem = try f.resolveInst(extra.rhs);
+ try reap(f, inst, &.{ pl_op.operand, extra.lhs, extra.rhs });
+
+ const w = &f.code.writer;
+
+ try f.writeCValueDerefMember(w, vec_ptr, .{ .identifier = "array" });
+ try w.writeByte('[');
+ try f.writeCValue(w, index, .other);
+ try w.writeAll("] = ");
+ try f.writeCValue(w, elem, .other);
+ try w.writeByte(';');
+ try f.newline();
+
+ return .none;
+}
+
fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
const pt = f.dg.pt;
const zcu = pt.zcu;
@@ -3184,35 +3222,42 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
try reap(f, inst, &.{ty_op.operand});
- const is_aligned = if (ptr_info.flags.alignment != .none)
- ptr_info.flags.alignment.order(src_ty.abiAlignment(zcu)).compare(.gte)
- else
- true;
+ const is_aligned = switch (ptr_info.flags.alignment) {
+ .none => true,
+ else => |ptr_align| ptr_align.compare(.gte, src_ty.abiAlignment(zcu)),
+ };
const w = &f.code.writer;
const local = try f.allocLocal(inst, src_ty);
- const v = try Vectorize.start(f, inst, w, ptr_ty);
if (!is_aligned) {
try w.writeAll("memcpy(&");
try f.writeCValue(w, local, .other);
- try v.elem(f, w);
try w.writeAll(", (const char *)");
- try f.writeCValue(w, operand, .other);
- try v.elem(f, w);
+ switch (ptr_info.flags.vector_index) {
+ .none => try f.writeCValue(w, operand, .other),
+ else => |index| {
+ try w.writeByte('&');
+ try f.writeCValue(w, operand, .other);
+ try w.print("[{d}]", .{@intFromEnum(index)});
+ },
+ }
try w.writeAll(", sizeof(");
try f.renderType(w, src_ty);
try w.writeAll("))");
} else {
try f.writeCValue(w, local, .other);
- try v.elem(f, w);
try w.writeAll(" = ");
- try f.writeCValueDeref(w, operand);
- try v.elem(f, w);
+ switch (ptr_info.flags.vector_index) {
+ .none => try f.writeCValueDeref(w, operand),
+ else => |index| {
+ try f.writeCValue(w, operand, .other);
+ try w.print("[{d}]", .{@intFromEnum(index)});
+ },
+ }
}
try w.writeByte(';');
try f.newline();
- try v.end(f, inst, w);
return local;
}
@@ -3425,23 +3470,26 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
if (!is_aligned) {
// For this memcpy to safely work we need the rhs to have the same
// underlying type as the lhs (i.e. they must both be arrays of the same underlying type).
- assert(src_ty.eql(.fromInterned(ptr_info.child), zcu));
+ assert(src_ty.eql(.fromInterned(ptr_info.child)));
- const v = try Vectorize.start(f, inst, w, ptr_ty);
try w.writeAll("memcpy((char *)");
- try f.writeCValue(w, ptr_val, .other);
- try v.elem(f, w);
+ switch (ptr_info.flags.vector_index) {
+ .none => try f.writeCValue(w, ptr_val, .other),
+ else => |index| {
+ try w.writeByte('&');
+ try f.writeCValue(w, ptr_val, .other);
+ try w.print("[{d}]", .{@intFromEnum(index)});
+ },
+ }
try w.writeAll(", &");
switch (src_val) {
.constant => |val| try f.dg.renderValueAsLvalue(w, val),
else => try f.writeCValue(w, src_val, .other),
}
- try v.elem(f, w);
try w.writeAll(", sizeof(");
try f.renderType(w, src_ty);
try w.writeAll("));");
try f.newline();
- try v.end(f, inst, w);
} else {
switch (ptr_val) {
.local_ref => |ptr_local_index| switch (src_val) {
@@ -3451,15 +3499,18 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
},
else => {},
}
- const v = try Vectorize.start(f, inst, w, ptr_ty);
- try f.writeCValueDeref(w, ptr_val);
- try v.elem(f, w);
+
+ switch (ptr_info.flags.vector_index) {
+ .none => try f.writeCValueDeref(w, ptr_val),
+ else => |index| {
+ try f.writeCValue(w, ptr_val, .other);
+ try w.print("[{d}]", .{@intFromEnum(index)});
+ },
+ }
try w.writeAll(" = ");
try f.writeCValue(w, src_val, .other);
- try v.elem(f, w);
try w.writeByte(';');
try f.newline();
- try v.end(f, inst, w);
}
return .none;
}
@@ -3607,9 +3658,9 @@ fn airCmpOp(
const lhs_ty = f.typeOf(data.lhs);
const scalar_ty = lhs_ty.scalarType(zcu);
- const scalar_bits = scalar_ty.bitSize(zcu);
- if (scalar_ty.isInt(zcu) and scalar_bits > 64)
- return airCmpBuiltinCall(
+ if (scalar_ty.isInt(zcu)) {
+ const scalar_bits = scalar_ty.bitSize(zcu);
+ if (scalar_bits > 64) return airCmpBuiltinCall(
f,
inst,
data,
@@ -3617,6 +3668,7 @@ fn airCmpOp(
.cmp,
if (scalar_bits > 128) .bits else .none,
);
+ }
if (scalar_ty.isRuntimeFloat())
return airCmpBuiltinCall(f, inst, data, operator, .operator, .none);
@@ -3662,9 +3714,9 @@ fn airEquality(
const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
const operand_ty = f.typeOf(bin_op.lhs);
- const operand_bits = operand_ty.bitSize(zcu);
- if (operand_ty.isAbiInt(zcu) and operand_bits > 64)
- return airCmpBuiltinCall(
+ if (operand_ty.isAbiInt(zcu)) {
+ const operand_bits = operand_ty.bitSize(zcu);
+ if (operand_bits > 64) return airCmpBuiltinCall(
f,
inst,
bin_op,
@@ -3672,6 +3724,7 @@ fn airEquality(
.cmp,
if (operand_bits > 128) .bits else .none,
);
+ }
if (operand_ty.isRuntimeFloat())
return airCmpBuiltinCall(f, inst, bin_op, operator, .operator, .none);
@@ -3752,7 +3805,7 @@ fn airCmpLteErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
try f.writeCValue(w, local, .other);
try w.writeAll(" = ");
try f.writeCValue(w, operand, .other);
- try w.print(" < sizeof({f}) / sizeof(*{0f});", .{fmtIdentSolo("zig_errorName")});
+ try w.writeAll(" < sizeof(zig_errorName) / sizeof(*zig_errorName);");
try f.newline();
return local;
}
@@ -4252,125 +4305,240 @@ fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void {
try w.print("goto zig_switch_{d}_loop;\n", .{@intFromEnum(br.block_inst)});
}
-fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
+fn airPtrCast(f: *Function, inst: Air.Inst.Index) Error!CValue {
+ const zcu = f.dg.pt.zcu;
+
+ const dest_ty = f.typeOfIndex(inst);
+ const ptr_ty = switch (dest_ty.zigTypeTag(zcu)) {
+ .optional => dest_ty.childType(zcu),
+ .pointer => dest_ty,
+ else => unreachable,
+ };
+
+ if (!ptr_ty.isSlice(zcu)) {
+ return airSimpleCast(f, inst);
+ }
+
+ // For slice casts we need to assign both fields.
+
const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
- const inst_ty = f.typeOfIndex(inst);
+ const operand = try f.resolveInst(ty_op.operand);
+ const w = &f.code.writer;
+ const dest_local = try f.allocLocal(inst, dest_ty);
+
+ try f.writeCValueMember(w, dest_local, .{ .identifier = "ptr" });
+ try w.writeAll(" = (");
+ try f.renderType(w, ptr_ty.slicePtrFieldType(zcu));
+ try w.writeByte(')');
+ try f.writeCValueMember(w, operand, .{ .identifier = "ptr" });
+ try w.writeByte(';');
+ try f.newline();
+
+ try f.writeCValueMember(w, dest_local, .{ .identifier = "len" });
+ try w.writeAll(" = ");
+ try f.writeCValueMember(w, operand, .{ .identifier = "len" });
+ try w.writeByte(';');
+ try f.newline();
+
+ try reap(f, inst, &.{ty_op.operand});
+ return dest_local;
+}
+
+fn airSimpleCast(f: *Function, inst: Air.Inst.Index) Error!CValue {
+ const zcu = f.dg.pt.zcu;
+
+ const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
+ const dest_ty = f.typeOfIndex(inst);
+ const operand_ty = f.typeOf(ty_op.operand);
const operand = try f.resolveInst(ty_op.operand);
+
+ const w = &f.code.writer;
+ const dest_local = try f.allocLocal(inst, dest_ty);
+ const v: Vectorize = try .start(f, inst, w, operand_ty);
+ try f.writeCValue(w, dest_local, .other);
+ try v.elem(f, w);
+ try w.writeAll(" = (");
+ try f.renderType(w, dest_ty.scalarType(zcu));
+ try w.writeByte(')');
+ try f.writeCValue(w, operand, .other);
+ try v.elem(f, w);
+ try w.writeByte(';');
+ try f.newline();
+ try v.end(f, inst, w);
+
+ try reap(f, inst, &.{ty_op.operand});
+ return dest_local;
+}
+
+fn airNopCast(f: *Function, inst: Air.Inst.Index) Error!CValue {
+ const zcu = f.dg.pt.zcu;
+
+ const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
+ const dest_ty = f.typeOfIndex(inst);
+ const operand_ty = f.typeOf(ty_op.operand);
+ const operand = try f.resolveInst(ty_op.operand);
+
+ assert(operand_ty.abiSize(zcu) == dest_ty.abiSize(zcu));
+ assert(operand_ty.isAbiInt(zcu) == dest_ty.isAbiInt(zcu));
+
+ try reap(f, inst, &.{ty_op.operand});
+ return f.moveCValue(inst, dest_ty, operand);
+}
+
+fn airUnionFromEnum(f: *Function, inst: Air.Inst.Index) Error!CValue {
+ const zcu = f.dg.pt.zcu;
+
+ const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
+ const dest_ty = f.typeOfIndex(inst);
const operand_ty = f.typeOf(ty_op.operand);
+ const operand = try f.resolveInst(ty_op.operand);
+
+ assert(dest_ty.zigTypeTag(zcu) == .@"union");
+ assert(operand_ty.zigTypeTag(zcu) == .@"enum");
+
+ const w = &f.code.writer;
+ const dest_local = try f.allocLocal(inst, dest_ty);
+ try f.writeCValueMember(w, dest_local, .{ .identifier = "tag" });
+ try w.writeAll(" = ");
+ try f.writeCValue(w, operand, .other);
+ try w.writeByte(';');
+ try f.newline();
- const bitcasted = try bitcast(f, inst_ty, operand, operand_ty);
try reap(f, inst, &.{ty_op.operand});
- return f.moveCValue(inst, inst_ty, bitcasted);
+ return dest_local;
}
-fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CValue {
+fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue {
const pt = f.dg.pt;
const zcu = pt.zcu;
- const target = &f.dg.mod.resolved_target.result;
const w = &f.code.writer;
- if (operand_ty.isAbiInt(zcu) and dest_ty.isAbiInt(zcu)) {
- const src_info = dest_ty.intInfo(zcu);
- const dest_info = operand_ty.intInfo(zcu);
- if (src_info.signedness == dest_info.signedness and
- src_info.bits == dest_info.bits) return operand;
- }
-
- if (dest_ty.isPtrAtRuntime(zcu) or operand_ty.isPtrAtRuntime(zcu)) {
- const local = try f.allocLocal(null, dest_ty);
- try f.writeCValue(w, local, .other);
+ const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
+ const dest_ty = f.typeOfIndex(inst);
+
+ const operand = try f.resolveInst(ty_op.operand);
+ const operand_ty = f.typeOf(ty_op.operand);
+
+ const dest_local = try f.allocLocal(inst, dest_ty);
+
+ // Because we have `scalarize_bit_cast_array` and `scalarize_bit_cast_vector_non_elementwise`
+ // enabled, we usually only see scalars here. The only case in which we may see vectors is when
+ // the operation happens elementwise, which we can handle with `Vectorize`.
+ var v: Vectorize = try .start(f, inst, w, operand_ty);
+ const operand_scalar_ty = operand_ty.scalarType(zcu);
+ const dest_scalar_ty = dest_ty.scalarType(zcu);
+
+ // Some cases are handled with a simple cast:
+ // * float -> float
+ // * bool -> int
+ if ((operand_scalar_ty.isRuntimeFloat() and dest_scalar_ty.isRuntimeFloat()) or
+ (operand_scalar_ty.toIntern() == .bool_type and dest_scalar_ty.isAbiInt(zcu)))
+ {
+ try f.writeCValue(w, dest_local, .other);
+ try v.elem(f, w);
try w.writeAll(" = (");
- try f.renderType(w, dest_ty);
+ try f.renderType(w, dest_scalar_ty);
try w.writeByte(')');
try f.writeCValue(w, operand, .other);
+ try v.elem(f, w);
try w.writeByte(';');
try f.newline();
- return local;
- }
-
- const local = try f.allocLocal(null, dest_ty);
- // On big-endian targets, copying ABI integers with padding bits is awkward, because the padding bits are at the low bytes of the value.
- // We need to offset the source or destination pointer appropriately and copy the right number of bytes.
- if (target.cpu.arch.endian() == .big and dest_ty.isAbiInt(zcu) and !operand_ty.isAbiInt(zcu)) {
- // e.g. [10]u8 -> u80. We need to offset the destination so that we copy to the least significant bits of the integer.
- const offset = dest_ty.abiSize(zcu) - operand_ty.abiSize(zcu);
- try w.writeAll("memcpy((char *)&");
- try f.writeCValue(w, local, .other);
- try w.print(" + {d}, &", .{offset});
- switch (operand) {
- .constant => |val| try f.dg.renderValueAsLvalue(w, val),
- else => try f.writeCValue(w, operand, .other),
- }
- try w.print(", {d});", .{operand_ty.abiSize(zcu)});
- } else if (target.cpu.arch.endian() == .big and operand_ty.isAbiInt(zcu) and !dest_ty.isAbiInt(zcu)) {
- // e.g. u80 -> [10]u8. We need to offset the source so that we copy from the least significant bits of the integer.
- const offset = operand_ty.abiSize(zcu) - dest_ty.abiSize(zcu);
+ } else if (dest_scalar_ty.toIntern() == .bool_type) {
+ // If the result is a boolean type, just check if the operand is non-zero.
+ assert(operand_scalar_ty.isAbiInt(zcu));
+ try f.writeCValue(w, dest_local, .other);
+ try v.elem(f, w);
+ try w.writeAll(" = ");
+ try f.writeCValue(w, operand, .other);
+ try v.elem(f, w);
+ try w.writeAll(" != 0;");
+ try f.newline();
+ } else if (dest_scalar_ty.isRuntimeFloat()) {
+ // For int->float, just do a memcpy.
+ assert(operand_scalar_ty.isAbiInt(zcu));
try w.writeAll("memcpy(&");
- try f.writeCValue(w, local, .other);
- try w.writeAll(", (const char *)&");
+ try f.writeCValue(w, dest_local, .other);
+ try v.elem(f, w);
+ try w.writeAll(", &");
switch (operand) {
.constant => |val| try f.dg.renderValueAsLvalue(w, val),
else => try f.writeCValue(w, operand, .other),
}
- try w.print(" + {d}, {d});", .{ offset, dest_ty.abiSize(zcu) });
+ try v.elem(f, w);
+ try w.print(", {d});", .{@min(operand_scalar_ty.abiSize(zcu), dest_scalar_ty.abiSize(zcu))});
+ try f.newline();
} else {
+ // The only remaining possibility is that the result is an integer. We will need to use
+ // `zig_wrap_*` to correct the "padding" bits after we populate the value bits.
+ assert(dest_scalar_ty.isAbiInt(zcu));
+ assert(operand_scalar_ty.isRuntimeFloat() or operand_scalar_ty.isAbiInt(zcu));
+
+ // memcpy the value...
try w.writeAll("memcpy(&");
- try f.writeCValue(w, local, .other);
+ try f.writeCValue(w, dest_local, .other);
+ try v.elem(f, w);
try w.writeAll(", &");
switch (operand) {
.constant => |val| try f.dg.renderValueAsLvalue(w, val),
else => try f.writeCValue(w, operand, .other),
}
- try w.print(", {d});", .{@min(dest_ty.abiSize(zcu), operand_ty.abiSize(zcu))});
- }
+ try v.elem(f, w);
+ try w.print(", {d});", .{@min(operand_scalar_ty.abiSize(zcu), dest_scalar_ty.abiSize(zcu))});
+ try f.newline();
- try f.newline();
-
- // Ensure padding bits have the expected value.
- if (dest_ty.isAbiInt(zcu)) {
- switch (CType.classifyInt(dest_ty, zcu)) {
+ // ...and ensure padding bits have the correct value.
+ switch (CType.classifyInt(dest_scalar_ty, zcu)) {
.void => unreachable, // opv
.small => {
- try f.writeCValue(w, local, .other);
+ try f.writeCValue(w, dest_local, .other);
+ try v.elem(f, w);
try w.writeAll(" = zig_wrap_");
- try f.dg.renderTypeForBuiltinFnName(w, dest_ty);
+ try f.dg.renderTypeForBuiltinFnName(w, dest_scalar_ty);
try w.writeByte('(');
- try f.writeCValue(w, local, .other);
- try f.dg.renderBuiltinInfo(w, dest_ty, .bits);
+ try f.writeCValue(w, dest_local, .other);
+ try v.elem(f, w);
+ try f.dg.renderBuiltinInfo(w, dest_scalar_ty, .bits);
try w.writeAll(");");
try f.newline();
},
.big => |big| {
- const dest_info = dest_ty.intInfo(zcu);
- const padding_index: u16 = switch (target.cpu.arch.endian()) {
+ const dest_info = dest_scalar_ty.intInfo(zcu);
+ const padding_index: u16 = switch (f.dg.mod.resolved_target.result.cpu.arch.endian()) {
.little => big.limbs_len - 1,
.big => 0,
};
const wrap_bits = ((dest_info.bits - 1) % big.limb_size.bits()) + 1;
if (big.limb_size != .@"128" or dest_info.signedness == .unsigned) {
- try f.writeCValueMember(w, local, .{ .identifier = "limbs" });
- try w.print("[{d}] = zig_wrap_{c}{d}(", .{
+ try f.writeCValue(w, dest_local, .other);
+ try v.elem(f, w);
+ try w.print(".limbs[{d}] = zig_wrap_{c}{d}(", .{
padding_index,
signAbbrev(dest_info.signedness),
big.limb_size.bits(),
});
- try f.writeCValueMember(w, local, .{ .identifier = "limbs" });
- try w.print("[{d}], {d});", .{ padding_index, wrap_bits });
+ try f.writeCValue(w, dest_local, .other);
+ try v.elem(f, w);
+ try w.print(".limbs[{d}], {d});", .{ padding_index, wrap_bits });
} else {
- try f.writeCValueMember(w, local, .{ .identifier = "limbs" });
- try w.print("[{d}] = zig_bitCast_u128(zig_wrap_i128(zig_bitCast_i128(", .{
+ try f.writeCValue(w, dest_local, .other);
+ try v.elem(f, w);
+ try w.print(".limbs[{d}] = zig_bitCast_u128(zig_wrap_i128(zig_bitCast_i128(", .{
padding_index,
});
- try f.writeCValueMember(w, local, .{ .identifier = "limbs" });
- try w.print("[{d}]), {d}));", .{ padding_index, wrap_bits });
+ try f.writeCValue(w, dest_local, .other);
+ try v.elem(f, w);
+ try w.print(".limbs[{d}]), {d}));", .{ padding_index, wrap_bits });
try f.newline();
}
},
}
}
- return local;
+ try v.end(f, inst, w);
+
+ try reap(f, inst, &.{ty_op.operand});
+ return dest_local;
}
fn airTrap(f: *Function) !void {
@@ -4784,7 +4952,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
while (it.next()) |output| {
const constraint = output.constraint;
- if (constraint.len < 2 or constraint[0] != '=' or
+ if (constraint.len < 2 or
+ (constraint[0] != '=' and constraint[0] != '+') or
(constraint[1] == '{' and constraint[constraint.len - 1] != '}'))
{
return f.fail("CBE: constraint not supported: '{s}'", .{constraint});
@@ -6145,28 +6314,32 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
return .none;
}
- if (elem_abi_size == 1 and !dest_ty.isVolatilePtr(zcu)) {
- const bitcasted = try bitcast(f, .u8, value, elem_ty);
+ if (elem_abi_size == 1 and elem_ty.isAbiInt(zcu) and !dest_ty.isVolatilePtr(zcu)) {
try w.writeAll("memset(");
switch (dest_ty.ptrSize(zcu)) {
.slice => {
try f.writeCValueMember(w, dest_slice, .{ .identifier = "ptr" });
- try w.writeAll(", ");
- try f.writeCValue(w, bitcasted, .other);
+ try w.writeAll(", *(const char *)&");
+ switch (value) {
+ .constant => |v| try f.dg.renderValueAsLvalue(w, v),
+ else => try f.writeCValue(w, value, .other),
+ }
try w.writeAll(", ");
try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" });
},
.one => {
try f.writeCValue(w, dest_slice, .other);
- try w.writeAll(", ");
- try f.writeCValue(w, bitcasted, .other);
+ try w.writeAll(", *(const char *)&");
+ switch (value) {
+ .constant => |v| try f.dg.renderValueAsLvalue(w, v),
+ else => try f.writeCValue(w, value, .other),
+ }
try w.print(", {d}", .{dest_ty.childType(zcu).arrayLen(zcu)});
},
.many, .c => unreachable,
}
try w.writeAll(");");
try f.newline();
- try f.freeCValue(inst, bitcasted);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
return .none;
}
diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig
index c800605168e7481d109a7cd194911e7cbf937ba5..2944d1092e2c119cfd91eeb2e7221b67437cd398 100644
--- a/src/codegen/c/type.zig
+++ b/src/codegen/c/type.zig
@@ -249,6 +249,7 @@ pub const CType = union(enum) {
.null,
.enum_literal,
.@"opaque",
+ .spirv,
.noreturn,
.void,
=> return .void,
@@ -513,40 +514,39 @@ pub const CType = union(enum) {
}
}
fn classifyBitInt(signedness: std.lang.Signedness, bits: u16, zcu: *const Zcu) IntClass {
- const is_ez80 = zcu.getTarget().cpu.arch == .ez80;
- return switch (bits) {
+ const target = zcu.getTarget();
+ return switch (std.zig.target.intByteSize(target, bits)) {
0 => .void,
- 1...8 => switch (signedness) {
+ 1 => switch (signedness) {
.unsigned => .{ .small = .uint8_t },
.signed => .{ .small = .int8_t },
},
- 9...16 => switch (signedness) {
+ 2 => switch (signedness) {
.unsigned => .{ .small = .uint16_t },
.signed => .{ .small = .int16_t },
},
- 17...24 => switch (signedness) {
- .unsigned => .{ .small = if (is_ez80) .uint24_t else .uint32_t },
- .signed => .{ .small = if (is_ez80) .int24_t else .int32_t },
+ 3 => switch (signedness) {
+ .unsigned => .{ .small = .uint24_t },
+ .signed => .{ .small = .int24_t },
},
- 25...32 => switch (signedness) {
+ 4 => switch (signedness) {
.unsigned => .{ .small = .uint32_t },
.signed => .{ .small = .int32_t },
},
- 33...48 => switch (signedness) {
- .unsigned => .{ .small = if (is_ez80) .uint48_t else .uint64_t },
- .signed => .{ .small = if (is_ez80) .int48_t else .int64_t },
+ 6 => switch (signedness) {
+ .unsigned => .{ .small = .uint48_t },
+ .signed => .{ .small = .int48_t },
},
- 49...64 => switch (signedness) {
+ 8 => switch (signedness) {
.unsigned => .{ .small = .uint64_t },
.signed => .{ .small = .int64_t },
},
- 65...128 => switch (signedness) {
+ 16 => switch (signedness) {
.unsigned => .{ .small = .zig_u128 },
.signed => .{ .small = .zig_i128 },
},
- else => {
+ else => |n| {
@branchHint(.unlikely);
- const target = zcu.getTarget();
const limb_bytes = std.zig.target.intAlignment(target, bits);
return .{ .big = .{
.limb_size = switch (limb_bytes) {
@@ -557,10 +557,7 @@ pub const CType = union(enum) {
16 => .@"128",
else => unreachable,
},
- .limbs_len = @divExact(
- std.zig.target.intByteSize(target, bits),
- limb_bytes,
- ),
+ .limbs_len = @divExact(n, limb_bytes),
} };
},
};
@@ -571,30 +568,30 @@ pub const CType = union(enum) {
pub const Dependencies = struct {
/// Key is any Zig type which corresponds to a C `struct`, `union`, or `typedef`. That C
/// type must be declared and complete.
- type: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
+ type: std.array_hash_map.Auto(InternPool.Index, void),
/// Key is a Zig type which is the *payload* of an error union. The C `struct` type
/// corresponding to such an error union must be declared and complete.
///
/// These are separate from `type` to avoid redundant types for every different error set
/// used with the same payload type---for instance a different C type for every `E!void`.
- errunion_type: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
+ errunion_type: std.array_hash_map.Auto(InternPool.Index, void),
/// Like `type`, but the type does not necessarily need to be completed yet: a forward
/// declaration is sufficient.
- type_fwd: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
+ type_fwd: std.array_hash_map.Auto(InternPool.Index, void),
/// Like `errunion_type`, but the type does not necessarily need to be completed yet: a
/// forward declaration is sufficient.
- errunion_type_fwd: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
+ errunion_type_fwd: std.array_hash_map.Auto(InternPool.Index, void),
/// Key is a Zig type; value is a bitmask of alignments. For every bit which is set, an
/// aligned typedef is required. For instance, if bit 3 is set, the C type 'aligned__8_foo'
/// must be declared through `typedef` (but not necessarily completed yet).
- aligned_type_fwd: std.AutoArrayHashMapUnmanaged(InternPool.Index, u64),
+ aligned_type_fwd: std.array_hash_map.Auto(InternPool.Index, u64),
/// Key specifies a big-int type whose C `struct` must be declared and complete.
- bigint: std.AutoArrayHashMapUnmanaged(BigInt, void),
+ bigint: std.array_hash_map.Auto(BigInt, void),
pub const empty: Dependencies = .{
.type = .empty,
@@ -865,6 +862,7 @@ pub const CType = union(enum) {
switch (ty.zigTypeTag(zcu)) {
.frame => unreachable,
.@"anyframe" => unreachable,
+ .spirv => unreachable,
.type => try w.writeAll("type"),
.void => try w.writeAll("void"),
@@ -988,6 +986,7 @@ pub const CType = union(enum) {
.anyframe_type,
.simple_type,
.opaque_type,
+ .spirv_type,
.error_set_type,
.inferred_error_set_type,
=> true,
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 3de01b1e6516d05af12c0ec131290d567b279bd9..6361963ab4d898bcf84a08fed641c7390e476e4a 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -20,10 +20,8 @@ const Value = @import("../Value.zig");
const Zcu = @import("../Zcu.zig");
const aarch64_c_abi = @import("aarch64/abi.zig");
const FuncGen = @import("llvm/FuncGen.zig");
-const buildAllocaInner = FuncGen.buildAllocaInner;
const isByRef = FuncGen.isByRef;
-const firstParamSRet = FuncGen.firstParamSRet;
-const lowerFnRetTy = FuncGen.lowerFnRetTy;
+const fnReturnStrat = FuncGen.fnReturnStrat;
const iterateParamTypes = FuncGen.iterateParamTypes;
const ccAbiPromoteInt = FuncGen.ccAbiPromoteInt;
@@ -37,6 +35,11 @@ pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features {
return comptime &.initMany(&.{
.expand_int_from_float_safe,
.expand_int_from_float_optimized_safe,
+
+ .scalarize_bit_cast_array,
+ // Needed because LLVM's `bitcast` on vectors is endian-specific unless the source and dest
+ // types are vectors with equal length (hence also with equal bits-per-element).
+ .scalarize_bit_cast_vector_non_elementwise,
});
}
@@ -243,9 +246,11 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8
.opengl,
.other,
.plan9,
+ .psx,
.psp,
- .tios,
.vita,
+ .tios,
+ .wiiu,
=> "unknown",
};
try llvm_triple.appendSlice(llvm_os);
@@ -284,6 +289,8 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8
.ilp32 => "unknown",
.eabi => "eabi",
.eabihf => "eabihf",
+ .abin32 => "unknown",
+ .x32 => "muslx32", // https://github.com/ziglang/zig/issues/25649
.android => "android",
.androideabi => "androideabi",
.musl => switch (target.os.tag) {
@@ -369,18 +376,18 @@ pub fn dataLayout(target: *const std.Target) []const u8 {
"e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
else
"e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
- .avr => "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8",
+ .avr => "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8:16-a:8",
.bpfeb => "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
.bpfel => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
.msp430 => "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16",
.mips => "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64",
.mipsel => "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64",
.mips64 => switch (target.abi) {
- .gnuabin32, .muslabin32 => "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
+ .gnuabin32, .muslabin32, .abin32 => "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
else => "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
},
.mips64el => switch (target.abi) {
- .gnuabin32, .muslabin32 => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
+ .gnuabin32, .muslabin32, .abin32 => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
else => "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
},
.m68k => "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16",
@@ -395,8 +402,8 @@ pub fn dataLayout(target: *const std.Target) []const u8 {
"e-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512"
else
"e-m:e-Fn32-i64:64-i128:128-n32:64",
- .nvptx => "e-p:32:32-p6:32:32-p7:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64",
- .nvptx64 => "e-p6:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64",
+ .nvptx => "e-p:32:32-p6:32:32-p7:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64",
+ .nvptx64 => "e-p6:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64",
.amdgcn => "e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9",
.riscv32 => if (target.cpu.has(.riscv, .e))
"e-m:e-p:32:32-i64:64-n32-S32"
@@ -445,7 +452,7 @@ pub fn dataLayout(target: *const std.Target) []const u8 {
.x86_64 => if (target.os.tag.isDarwin() or target.ofmt == .macho)
"e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
else switch (target.abi) {
- .gnux32, .muslx32 => "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
+ .gnux32, .muslx32, .x32 => "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
else => if ((target.os.tag == .windows or target.os.tag == .uefi) and target.ofmt == .coff)
"e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
else
@@ -724,8 +731,8 @@ pub const Object = struct {
// TODO: Address space
const slice_ty = Type.slice_const_u8_sentinel_0;
- const llvm_usize_ty = try o.lowerType(.usize);
- const llvm_slice_ty = try o.lowerType(slice_ty);
+ const llvm_usize_ty = try o.lowerType(.usize, .in_memory);
+ const llvm_slice_ty = try o.lowerType(slice_ty, .in_memory);
const llvm_table_ty = try o.builder.arrayType(1 + error_name_list.len, llvm_slice_ty);
llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty);
@@ -791,7 +798,7 @@ pub const Object = struct {
{
if (o.errors_len_variable != .none) {
const errors_len = zcu.intern_pool.global_error_set.getNamesFromMainThread().len;
- const init_val = try o.builder.intConst(try o.errorIntType(), errors_len);
+ const init_val = try o.builder.intConst(try o.errorIntType(.in_memory), errors_len);
try o.errors_len_variable.setInitializer(init_val, &o.builder);
}
try o.genErrorNameTable();
@@ -1183,7 +1190,7 @@ pub const Object = struct {
};
{
const global = llvm_function.ptrConst(&o.builder).global.ptr(&o.builder);
- global.type = try o.lowerType(fn_ty);
+ global.type = try o.lowerType(fn_ty, .in_memory);
global.addr_space = toLlvmAddressSpace(nav.resolved.?.@"addrspace", target);
global.linkage = if (o.builder.strip) .private else .internal;
global.visibility = .default;
@@ -1270,165 +1277,7 @@ pub const Object = struct {
} }, &o.builder);
}
- var deinit_wip = true;
- var wip = try Builder.WipFunction.init(&o.builder, .{
- .function = llvm_function,
- .strip = owner_mod.strip,
- });
- defer if (deinit_wip) wip.deinit();
- wip.cursor = .{ .block = try wip.block(0, "Entry") };
-
- // This is the list of args we will use that correspond directly to the AIR arg
- // instructions. Depending on the calling convention, this list is not necessarily
- // a bijection with the actual LLVM parameters of the function.
- var args: std.ArrayList(Builder.Value) = .empty;
- defer args.deinit(gpa);
-
- const ret_ptr: Builder.Value, const err_ret_trace: Builder.Value = implicit_args: {
- var it = iterateParamTypes(o, fn_info);
-
- const ret_ptr: Builder.Value = if (firstParamSRet(fn_info, zcu, target)) param: {
- const param = wip.arg(it.llvm_index);
- it.llvm_index += 1;
- break :param param;
- } else .none;
-
- const err_return_tracing = fn_info.cc == .auto and comp.config.any_error_tracing;
- const err_ret_trace: Builder.Value = if (err_return_tracing) param: {
- const param = wip.arg(it.llvm_index);
- it.llvm_index += 1;
- break :param param;
- } else .none;
-
- while (try it.next()) |lowering| {
- try args.ensureUnusedCapacity(gpa, 1);
-
- switch (lowering) {
- .no_bits => continue,
- .byval => {
- assert(!it.byval_attr);
- const param_index = it.zig_index - 1;
- const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]);
- const param = wip.arg(it.llvm_index - 1);
-
- if (isByRef(param_ty, zcu)) {
- const alignment = param_ty.abiAlignment(zcu).toLlvm();
- const param_llvm_ty = param.typeOfWip(&wip);
- const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, alignment, target);
- _ = try wip.store(.normal, param, arg_ptr, alignment);
- args.appendAssumeCapacity(arg_ptr);
- } else {
- args.appendAssumeCapacity(param);
- }
- },
- .byref => {
- const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
- const param = wip.arg(it.llvm_index - 1);
-
- if (isByRef(param_ty, zcu)) {
- args.appendAssumeCapacity(param);
- } else {
- const param_llvm_ty = try o.lowerType(param_ty);
- const alignment = param_ty.abiAlignment(zcu).toLlvm();
- args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, param, alignment, ""));
- }
- },
- .byref_mut => {
- const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
- const param = wip.arg(it.llvm_index - 1);
-
- if (isByRef(param_ty, zcu)) {
- args.appendAssumeCapacity(param);
- } else {
- const param_llvm_ty = try o.lowerType(param_ty);
- const alignment = param_ty.abiAlignment(zcu).toLlvm();
- args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, param, alignment, ""));
- }
- },
- .abi_sized_int => {
- assert(!it.byval_attr);
- const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
- const param = wip.arg(it.llvm_index - 1);
-
- const param_llvm_ty = try o.lowerType(param_ty);
- const alignment = param_ty.abiAlignment(zcu).toLlvm();
- const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, alignment, target);
- _ = try wip.store(.normal, param, arg_ptr, alignment);
-
- if (isByRef(param_ty, zcu)) {
- args.appendAssumeCapacity(arg_ptr);
- } else {
- args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, ""));
- }
- },
- .slice => {
- assert(!it.byval_attr);
- const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
- assert(!isByRef(param_ty, zcu));
- const slice_val = try wip.buildAggregate(
- try o.lowerType(param_ty),
- &.{ wip.arg(it.llvm_index - 2), wip.arg(it.llvm_index - 1) },
- "",
- );
- args.appendAssumeCapacity(slice_val);
- },
- .multiple_llvm_types => {
- assert(!it.byval_attr);
- const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
- const param_llvm_ty = try o.lowerType(param_ty);
- const param_alignment = param_ty.abiAlignment(zcu);
- const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8);
- const arg_ptr = try buildAllocaInner(&wip, llvm_ty, param_alignment.toLlvm(), target);
- const llvm_args_start = it.llvm_index - it.types_len;
- for (llvm_args_start.., it.offsets_buffer[0..it.types_len]) |llvm_arg_index, offset| {
- const param = wip.arg(@intCast(llvm_arg_index));
- const part_ptr = try o.ptraddConst(&wip, arg_ptr, offset);
- _ = try wip.store(.normal, param, part_ptr, param_alignment.offset(offset).toLlvm());
- }
-
- if (isByRef(param_ty, zcu)) {
- args.appendAssumeCapacity(arg_ptr);
- } else {
- args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, arg_ptr, param_alignment.toLlvm(), ""));
- }
- },
- .float_array => {
- const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
- const param_llvm_ty = try o.lowerType(param_ty);
- const param = wip.arg(it.llvm_index - 1);
-
- const alignment = param_ty.abiAlignment(zcu).toLlvm();
- const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, alignment, target);
- _ = try wip.store(.normal, param, arg_ptr, alignment);
-
- if (isByRef(param_ty, zcu)) {
- args.appendAssumeCapacity(arg_ptr);
- } else {
- args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, ""));
- }
- },
- .i32_array, .i64_array => {
- const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
- const param_llvm_ty = try o.lowerType(param_ty);
- const param = wip.arg(it.llvm_index - 1);
-
- const alignment = param_ty.abiAlignment(zcu).toLlvm();
- const arg_ptr = try buildAllocaInner(&wip, param.typeOfWip(&wip), alignment, target);
- _ = try wip.store(.normal, param, arg_ptr, alignment);
-
- if (isByRef(param_ty, zcu)) {
- args.appendAssumeCapacity(arg_ptr);
- } else {
- args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, ""));
- }
- },
- }
- }
-
- break :implicit_args .{ ret_ptr, err_ret_trace };
- };
-
- const file, const subprogram = if (!wip.strip) debug_info: {
+ const file, const subprogram = if (!owner_mod.strip) debug_info: {
const file = try o.getDebugFile(file_scope);
const line_number = zcu.navSrcLine(func.owner_nav) + 1;
@@ -1494,11 +1343,12 @@ pub const Object = struct {
.gpa = gpa,
.air = air.*,
.liveness = liveness.*.?,
- .wip = wip,
+ .wip = try .init(&o.builder, .{
+ .function = llvm_function,
+ .strip = owner_mod.strip,
+ }),
.is_naked = fn_info.cc == .naked,
.fuzz = fuzz,
- .ret_ptr = ret_ptr,
- .args = args.items,
.arg_index = 0,
.arg_inline_index = 0,
.func_inst_table = .empty,
@@ -1512,14 +1362,18 @@ pub const Object = struct {
.base_line = zcu.navSrcLine(func.owner_nav),
.prev_dbg_line = 0,
.prev_dbg_column = 0,
- .err_ret_trace = err_ret_trace,
.disable_intrinsics = disable_intrinsics,
.allowzero_access = false,
+
+ .ret_ptr = undefined, // populated by `genMainBody`
+ .err_ret_trace = undefined, // populated by `genMainBody`
+ .args = undefined, // populated by `genMainBody`
};
defer fg.deinit();
- deinit_wip = false;
- try fg.genBody(air.getMainBody(), .poi);
+ fg.wip.cursor = .{ .block = try fg.wip.block(0, "Entry") };
+
+ try fg.genMainBody();
// If we saw any loads or stores involving `allowzero` pointers, we need to mark the whole
// function as considering null pointers valid so that LLVM's optimizers don't remove these
@@ -1585,10 +1439,10 @@ pub const Object = struct {
// represent (because it doesn't have runtime bits), we instead lower as the zero-size
// type `[0 x i8]`. I don't think the type on an extern declaration actually does much
// anyway.
- if (nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) break :ty try o.lowerType(nav_ty);
+ if (nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) break :ty try o.lowerType(nav_ty, .in_memory);
break :ty try o.builder.arrayType(0, .i8);
} else if (nav_ty.hasRuntimeBits(zcu)) ty: {
- break :ty try o.lowerType(nav_ty);
+ break :ty try o.lowerType(nav_ty, .in_memory);
} else {
// This is a non-extern zero-bit `Nav`---we're not interested in it.
// TODO: we might need to rethink this a little under incremental compilation. If a
@@ -1681,7 +1535,7 @@ pub const Object = struct {
llvm_variable.setAlignment(llvm_align, &o.builder);
llvm_variable.setSection(llvm_section, &o.builder);
llvm_variable.setMutability(if (resolved.@"const") .constant else .global, &o.builder);
- try llvm_variable.setInitializer(if (opt_extern != null) .no_init else try o.lowerValue(resolved.value), &o.builder);
+ try llvm_variable.setInitializer(if (opt_extern != null) .no_init else try o.lowerValue(resolved.value, .in_memory), &o.builder);
llvm_variable.setThreadLocal(tl: {
if (resolved.@"threadlocal" and !mod.single_threaded) break :tl .generaldynamic;
break :tl .default;
@@ -1863,6 +1717,7 @@ pub const Object = struct {
}
pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void {
+ _ = o.type_map.remove(ty);
try o.type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success);
if (o.named_enum_map.get(ty)) |function_index| {
try o.updateIsNamedEnumValueFunction(.fromInterned(ty), function_index);
@@ -2279,7 +2134,7 @@ pub const Object = struct {
defer debug_param_types.deinit(gpa);
// Return type goes first.
- if (firstParamSRet(fn_info, zcu, target)) {
+ if (try fnReturnStrat(o, fn_info) == .sret) {
// Actual return type is void, then first arg is the sret pointer.
const ptr_ty = try pt.singleMutPtrType(.fromInterned(fn_info.return_type));
debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, .void));
@@ -2662,6 +2517,7 @@ pub const Object = struct {
},
.frame => @panic("TODO implement lowerDebugType for Frame types"),
.@"anyframe" => @panic("TODO implement lowerDebugType for AnyFrame types"),
+ .spirv => unreachable,
}
}
@@ -2826,12 +2682,12 @@ pub const Object = struct {
if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);
var it = iterateParamTypes(o, fn_info);
- if (firstParamSRet(fn_info, zcu, target)) {
+ if (try fnReturnStrat(o, fn_info) == .sret) {
// Sret pointers must not be address 0
try attributes.addParamAttr(it.llvm_index, .nonnull, &o.builder);
try attributes.addParamAttr(it.llvm_index, .@"noalias", &o.builder);
- const raw_llvm_ret_ty = try o.lowerType(.fromInterned(fn_info.return_type));
+ const raw_llvm_ret_ty = try o.lowerType(.fromInterned(fn_info.return_type), .in_memory);
try attributes.addParamAttr(it.llvm_index, .{ .sret = raw_llvm_ret_ty }, &o.builder);
it.llvm_index += 1;
} else if (ccAbiPromoteInt(fn_info.cc, zcu, Type.fromInterned(fn_info.return_type))) |s| switch (s) {
@@ -2873,9 +2729,7 @@ pub const Object = struct {
},
.byref => {
const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
- const param_llvm_ty = try o.lowerType(param_ty);
- const alignment = param_ty.abiAlignment(zcu);
- try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment.toLlvm(), it.byval_attr, param_llvm_ty);
+ try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, it.byval_attr, param_ty);
},
.byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),
.slice => {
@@ -2985,14 +2839,31 @@ pub const Object = struct {
}
}
- pub fn errorIntType(o: *Object) Allocator.Error!Builder.Type {
- return o.builder.intType(o.zcu.errorSetBits());
+ pub const TypeRepr = enum {
+ /// The representation of the type when it is being manipulated as a value in a function.
+ /// e.g. Zig `u5` -> LLVM `i5`
+ by_value,
+ /// The representation of the type when it is stored in memory.
+ /// e.g. Zig `u5` -> LLVM `i8`
+ in_memory,
+ };
+
+ pub fn errorIntType(o: *Object, repr: TypeRepr) Allocator.Error!Builder.Type {
+ return o.builder.intType(switch (repr) {
+ .by_value => o.zcu.errorSetBits(),
+ .in_memory => @intCast(Type.anyerror.abiSize(o.zcu) * 8),
+ });
}
- pub fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type {
+ pub fn lowerType(o: *Object, t: Type, repr: TypeRepr) Allocator.Error!Builder.Type {
const zcu = o.zcu;
const target = zcu.getTarget();
const ip = &zcu.intern_pool;
+
+ if (repr == .by_value) {
+ assert(!isByRef(t, zcu)); // by-ref types must only be manipulated in memory
+ }
+
return switch (t.toIntern()) {
.u0_type => unreachable, // no runtime bits
inline .u1_type,
@@ -3008,7 +2879,10 @@ pub const Object = struct {
.u80_type,
.u128_type,
.i128_type,
- => |tag| @field(Builder.Type, "i" ++ @tagName(tag)[1 .. @tagName(tag).len - "_type".len]),
+ => |tag| switch (repr) {
+ .by_value => @field(Builder.Type, "i" ++ @tagName(tag)[1 .. @tagName(tag).len - "_type".len]),
+ .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)),
+ },
.usize_type, .isize_type => try o.builder.intType(target.ptrBitWidth()),
inline .c_char_type,
.c_short_type,
@@ -3043,7 +2917,7 @@ pub const Object = struct {
return .i8;
},
.bool_type => .i1,
- .anyerror_type => try o.errorIntType(),
+ .anyerror_type => try o.errorIntType(repr),
.void_type => unreachable, // no runtime bits
.type_type => unreachable, // no runtime bits
.comptime_int_type => unreachable, // no runtime bits
@@ -3063,10 +2937,10 @@ pub const Object = struct {
=> .ptr,
.slice_const_u8_type,
.slice_const_u8_sentinel_0_type,
- => try o.builder.structType(.normal, &.{ .ptr, try o.lowerType(.usize) }),
+ => try o.builder.structType(.normal, &.{ .ptr, try o.lowerType(.usize, repr) }),
.anyerror_void_error_union_type,
.adhoc_inferred_error_set_type,
- => try o.errorIntType(),
+ => try o.errorIntType(repr),
.generic_poison_type => unreachable,
// values, not types
.undef,
@@ -3092,7 +2966,10 @@ pub const Object = struct {
.none,
=> unreachable,
else => switch (ip.indexToKey(t.toIntern())) {
- .int_type => |int_type| try o.builder.intType(int_type.bits),
+ .int_type => |int_type| switch (repr) {
+ .by_value => try o.builder.intType(int_type.bits),
+ .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)),
+ },
.ptr_type => |ptr_type| type: {
const ptr_ty = try o.builder.ptrType(
toLlvmAddressSpace(ptr_type.flags.address_space, target),
@@ -3101,18 +2978,18 @@ pub const Object = struct {
.one, .many, .c => ptr_ty,
.slice => try o.builder.structType(.normal, &.{
ptr_ty,
- try o.lowerType(.usize),
+ try o.lowerType(.usize, repr),
}),
};
},
.array_type => |array_type| o.builder.arrayType(
array_type.lenIncludingSentinel(),
- try o.lowerType(.fromInterned(array_type.child)),
+ try o.lowerType(.fromInterned(array_type.child), repr),
),
.vector_type => |vector_type| o.builder.vectorType(
.normal,
vector_type.len,
- try o.lowerType(.fromInterned(vector_type.child)),
+ try o.lowerType(.fromInterned(vector_type.child), .by_value),
),
.opt_type => |child_ty| {
// Must stay in sync with `opt_payload` logic in `lowerPtr`.
@@ -3122,8 +2999,11 @@ pub const Object = struct {
.runtime, .partially_comptime => {},
}
- const payload_ty = try o.lowerType(.fromInterned(child_ty));
- if (t.optionalReprIsPayload(zcu)) return payload_ty;
+ if (t.optionalReprIsPayload(zcu)) {
+ return o.lowerType(.fromInterned(child_ty), repr);
+ }
+
+ const payload_ty = try o.lowerType(.fromInterned(child_ty), repr);
comptime assert(optional_layout_version == 3);
var fields: [3]Builder.Type = .{ payload_ty, .i8, undefined };
@@ -3141,7 +3021,7 @@ pub const Object = struct {
.error_union_type => |error_union_type| {
// Must stay in sync with `codegen.errUnionPayloadOffset`.
// See logic in `lowerPtr`.
- const error_type = try o.errorIntType();
+ const error_type = try o.errorIntType(repr);
switch (Type.fromInterned(error_union_type.payload_type).classify(zcu)) {
.fully_comptime => unreachable,
@@ -3149,7 +3029,7 @@ pub const Object = struct {
.runtime, .partially_comptime => {},
}
- const payload_type = try o.lowerType(.fromInterned(error_union_type.payload_type));
+ const payload_type = try o.lowerType(.fromInterned(error_union_type.payload_type), repr);
const payload_align = Type.fromInterned(error_union_type.payload_type).abiAlignment(zcu);
const error_align: InternPool.Alignment = .fromByteUnits(std.zig.target.intAlignment(target, zcu.errorSetBits()));
@@ -3184,16 +3064,14 @@ pub const Object = struct {
},
.simple_type => unreachable,
.struct_type => {
- if (o.type_map.get(t.toIntern())) |value| return value;
-
const struct_type = ip.loadStructType(t.toIntern());
if (struct_type.layout == .@"packed") {
- const int_ty = try o.lowerType(.fromInterned(struct_type.packed_backing_int_type));
- try o.type_map.put(o.gpa, t.toIntern(), int_ty);
- return int_ty;
+ return o.lowerType(.fromInterned(struct_type.packed_backing_int_type), repr);
}
+ if (o.type_map.get(t.toIntern())) |value| return value;
+
assert(struct_type.size > 0);
var llvm_field_types: std.ArrayList(Builder.Type) = .empty;
@@ -3227,7 +3105,7 @@ pub const Object = struct {
if (!field_ty.hasRuntimeBits(zcu)) continue;
- try llvm_field_types.append(o.gpa, try o.lowerType(field_ty));
+ try llvm_field_types.append(o.gpa, try o.lowerType(field_ty, repr));
offset += field_ty.abiSize(zcu);
}
@@ -3283,7 +3161,7 @@ pub const Object = struct {
if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) {
continue;
}
- try llvm_field_types.append(o.gpa, try o.lowerType(.fromInterned(field_ty)));
+ try llvm_field_types.append(o.gpa, try o.lowerType(.fromInterned(field_ty), repr));
offset += Type.fromInterned(field_ty).abiSize(zcu);
}
@@ -3300,28 +3178,24 @@ pub const Object = struct {
return o.builder.structType(.normal, llvm_field_types.items);
},
.union_type => {
- if (o.type_map.get(t.toIntern())) |value| return value;
-
const union_obj = ip.loadUnionType(t.toIntern());
if (union_obj.layout == .@"packed") {
- const int_ty = try o.lowerType(.fromInterned(union_obj.packed_backing_int_type));
- try o.type_map.put(o.gpa, t.toIntern(), int_ty);
- return int_ty;
+ return o.lowerType(.fromInterned(union_obj.packed_backing_int_type), repr);
}
- assert(union_obj.size > 0);
-
const layout = Type.getUnionLayout(union_obj, zcu);
if (layout.payload_size == 0) {
- const enum_tag_ty = try o.lowerType(.fromInterned(union_obj.enum_tag_type));
- try o.type_map.put(o.gpa, t.toIntern(), enum_tag_ty);
- return enum_tag_ty;
+ return o.lowerType(.fromInterned(union_obj.enum_tag_type), repr);
}
+ if (o.type_map.get(t.toIntern())) |value| return value;
+
+ assert(union_obj.size > 0);
+
const aligned_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[layout.most_aligned_field]);
- const aligned_field_llvm_ty = try o.lowerType(aligned_field_ty);
+ const aligned_field_llvm_ty = try o.lowerType(aligned_field_ty, repr);
const payload_ty = ty: {
if (layout.most_aligned_field_size == layout.payload_size) {
@@ -3347,7 +3221,7 @@ pub const Object = struct {
);
return ty;
}
- const enum_tag_ty = try o.lowerType(.fromInterned(union_obj.enum_tag_type));
+ const enum_tag_ty = try o.lowerType(.fromInterned(union_obj.enum_tag_type), repr);
// Put the tag before or after the payload depending on which one's
// alignment is greater.
@@ -3375,10 +3249,10 @@ pub const Object = struct {
);
return ty;
},
- .opaque_type => unreachable, // no runtime bits
- .enum_type => try o.lowerType(t.intTagType(zcu)),
+ .opaque_type, .spirv_type => unreachable, // no runtime bits
+ .enum_type => try o.lowerType(t.intTagType(zcu), repr),
.func_type => |func_type| try o.lowerFnType(t, func_type),
- .error_set_type, .inferred_error_set_type => try o.errorIntType(),
+ .error_set_type, .inferred_error_set_type => try o.errorIntType(repr),
// values, not types
.undef,
.simple_value,
@@ -3410,12 +3284,12 @@ pub const Object = struct {
assert(fn_ty.fnHasRuntimeBits(zcu));
- const ret_ty = try lowerFnRetTy(o, fn_info);
+ const ret_strat = try fnReturnStrat(o, fn_info);
var llvm_params: std.ArrayList(Builder.Type) = .empty;
defer llvm_params.deinit(o.gpa);
- if (firstParamSRet(fn_info, zcu, target)) {
+ if (ret_strat == .sret) {
try llvm_params.append(o.gpa, .ptr);
}
@@ -3430,7 +3304,7 @@ pub const Object = struct {
.no_bits => continue,
.byval => {
const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
- try llvm_params.append(o.gpa, try o.lowerType(param_ty));
+ try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .in_memory else .by_value));
},
.byref, .byref_mut => {
try llvm_params.append(o.gpa, .ptr);
@@ -3445,7 +3319,7 @@ pub const Object = struct {
const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
try llvm_params.appendSlice(o.gpa, &.{
try o.builder.ptrType(toLlvmAddressSpace(param_ty.ptrAddressSpace(zcu), target)),
- try o.lowerType(.usize),
+ try o.lowerType(.usize, .by_value),
});
},
.multiple_llvm_types => {
@@ -3453,7 +3327,7 @@ pub const Object = struct {
},
.float_array => |count| {
const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
- const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?);
+ const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?, .in_memory);
try llvm_params.append(o.gpa, try o.builder.arrayType(count, float_ty));
},
.i32_array, .i64_array => |arr_len| {
@@ -3465,14 +3339,19 @@ pub const Object = struct {
},
};
- return o.builder.fnType(
- ret_ty,
- llvm_params.items,
- if (fn_info.is_var_args) .vararg else .normal,
- );
+ const llvm_ret_ty: Builder.Type = switch (ret_strat) {
+ .void, .sret => .void,
+ .by_val => try o.lowerType(.fromInterned(fn_info.return_type), .by_value),
+ .mem_cast => |llvm_ret_ty| llvm_ret_ty,
+ };
+ const llvm_fn_kind: Builder.Type.Function.Kind = switch (fn_info.is_var_args) {
+ true => .vararg,
+ false => .normal,
+ };
+ return o.builder.fnType(llvm_ret_ty, llvm_params.items, llvm_fn_kind);
}
- pub fn lowerValue(o: *Object, arg_val: InternPool.Index) Allocator.Error!Builder.Constant {
+ pub fn lowerValue(o: *Object, arg_val: InternPool.Index, repr: TypeRepr) Allocator.Error!Builder.Constant {
const zcu = o.zcu;
const ip = &zcu.intern_pool;
const target = zcu.getTarget();
@@ -3497,13 +3376,14 @@ pub const Object = struct {
.tuple_type,
.union_type,
.opaque_type,
+ .spirv_type,
.enum_type,
.func_type,
.error_set_type,
.inferred_error_set_type,
=> unreachable, // types, not values
- .undef => return o.builder.undefConst(try o.lowerType(ty)),
+ .undef => return o.builder.undefConst(try o.lowerType(ty, repr)),
.simple_value => |simple_value| switch (simple_value) {
.void => unreachable, // non-runtime value
.null => unreachable, // non-runtime value
@@ -3518,15 +3398,15 @@ pub const Object = struct {
.int => {
var bigint_space: Value.BigIntSpace = undefined;
const bigint = val.toBigInt(&bigint_space, zcu);
- const llvm_int_ty = try o.builder.intType(ty.intInfo(zcu).bits);
+ const llvm_int_ty = try o.lowerType(ty, repr);
return o.builder.bigIntConst(llvm_int_ty, bigint);
},
.err => |err| {
const int = zcu.intern_pool.getErrorValueIfExists(err.name).?;
- return o.builder.intConst(try o.errorIntType(), int);
+ return o.builder.intConst(try o.errorIntType(repr), int);
},
.error_union => |error_union| {
- const llvm_error_ty = try o.errorIntType();
+ const llvm_error_ty = try o.errorIntType(repr);
const llvm_error_value = switch (error_union.val) {
.err_name => |name| try o.builder.intConst(
llvm_error_ty,
@@ -3544,8 +3424,8 @@ pub const Object = struct {
const payload_align = payload_type.abiAlignment(zcu);
const error_align = Type.errorAbiAlignment(zcu);
const llvm_payload_value = switch (error_union.val) {
- .err_name => try o.builder.undefConst(try o.lowerType(payload_type)),
- .payload => |payload| try o.lowerValue(payload),
+ .err_name => try o.builder.undefConst(try o.lowerType(payload_type, repr)),
+ .payload => |payload| try o.lowerValue(payload, repr),
};
var fields: [3]Builder.Type = undefined;
@@ -3560,7 +3440,7 @@ pub const Object = struct {
fields[0] = vals[0].typeOf(&o.builder);
fields[1] = vals[1].typeOf(&o.builder);
- const llvm_ty = try o.lowerType(ty);
+ const llvm_ty = try o.lowerType(ty, repr);
const llvm_ty_fields = llvm_ty.structFields(&o.builder);
if (llvm_ty_fields.len > 2) {
assert(llvm_ty_fields.len == 3);
@@ -3572,7 +3452,7 @@ pub const Object = struct {
fields[0..llvm_ty_fields.len],
), vals[0..llvm_ty_fields.len]);
},
- .enum_tag => |enum_tag| o.lowerValue(enum_tag.int),
+ .enum_tag => |enum_tag| o.lowerValue(enum_tag.int, repr),
.float => switch (ty.floatBits(target)) {
16 => if (backendSupportsF16(target))
try o.builder.halfConst(val.toFloat(f16, zcu))
@@ -3588,9 +3468,9 @@ pub const Object = struct {
else => unreachable,
},
.ptr => try o.lowerPtr(arg_val, 0),
- .slice => |slice| return o.builder.structConst(try o.lowerType(ty), &.{
- try o.lowerValue(slice.ptr),
- try o.lowerValue(slice.len),
+ .slice => |slice| return o.builder.structConst(try o.lowerType(ty, repr), &.{
+ try o.lowerValue(slice.ptr, repr),
+ try o.lowerValue(slice.len, repr),
}),
.opt => |opt| {
comptime assert(optional_layout_version == 3);
@@ -3600,7 +3480,7 @@ pub const Object = struct {
if (!payload_ty.hasRuntimeBits(zcu)) {
return non_null_bit;
}
- const llvm_ty = try o.lowerType(ty);
+ const llvm_ty = try o.lowerType(ty, repr);
if (ty.optionalReprIsPayload(zcu)) return switch (opt.val) {
.none => switch (llvm_ty.tag(&o.builder)) {
.integer => try o.builder.intConst(llvm_ty, 0),
@@ -3608,15 +3488,15 @@ pub const Object = struct {
.structure => try o.builder.zeroInitConst(llvm_ty),
else => unreachable,
},
- else => |payload| try o.lowerValue(payload),
+ else => |payload| try o.lowerValue(payload, repr),
};
assert(payload_ty.zigTypeTag(zcu) != .@"fn");
var fields: [3]Builder.Type = undefined;
var vals: [3]Builder.Constant = undefined;
vals[0] = switch (opt.val) {
- .none => try o.builder.undefConst(try o.lowerType(payload_ty)),
- else => |payload| try o.lowerValue(payload),
+ .none => try o.builder.undefConst(try o.lowerType(payload_ty, repr)),
+ else => |payload| try o.lowerValue(payload, repr),
};
vals[1] = non_null_bit;
fields[0] = vals[0].typeOf(&o.builder);
@@ -3633,14 +3513,14 @@ pub const Object = struct {
fields[0..llvm_ty_fields.len],
), vals[0..llvm_ty_fields.len]);
},
- .bitpack => |bitpack| return o.lowerValue(bitpack.backing_int_val),
+ .bitpack => |bitpack| return o.lowerValue(bitpack.backing_int_val, repr),
.aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) {
.array_type => |array_type| switch (aggregate.storage) {
.bytes => |bytes| try o.builder.stringConst(try o.builder.string(
bytes.toSlice(array_type.lenIncludingSentinel(), ip),
)),
.elems => |elems| {
- const array_ty = try o.lowerType(ty);
+ const array_ty = try o.lowerType(ty, repr);
const elem_ty = array_ty.childType(&o.builder);
assert(elems.len == array_ty.aggregateLen(&o.builder));
@@ -3658,7 +3538,7 @@ pub const Object = struct {
var need_unnamed = false;
for (vals, fields, elems) |*result_val, *result_field, elem| {
- result_val.* = try o.lowerValue(elem);
+ result_val.* = try o.lowerValue(elem, repr);
result_field.* = result_val.typeOf(&o.builder);
if (result_field.* != elem_ty) need_unnamed = true;
}
@@ -3670,7 +3550,7 @@ pub const Object = struct {
.repeated_elem => |elem| {
const len: usize = @intCast(array_type.len);
const len_including_sentinel: usize = @intCast(array_type.lenIncludingSentinel());
- const array_ty = try o.lowerType(ty);
+ const array_ty = try o.lowerType(ty, repr);
const elem_ty = array_ty.childType(&o.builder);
const ExpectedContents = extern struct {
@@ -3686,12 +3566,12 @@ pub const Object = struct {
defer allocator.free(fields);
var need_unnamed = false;
- @memset(vals[0..len], try o.lowerValue(elem));
+ @memset(vals[0..len], try o.lowerValue(elem, repr));
@memset(fields[0..len], vals[0].typeOf(&o.builder));
if (fields[0] != elem_ty) need_unnamed = true;
if (array_type.sentinel != .none) {
- vals[len] = try o.lowerValue(array_type.sentinel);
+ vals[len] = try o.lowerValue(array_type.sentinel, repr);
fields[len] = vals[len].typeOf(&o.builder);
if (fields[len] != elem_ty) need_unnamed = true;
}
@@ -3703,7 +3583,7 @@ pub const Object = struct {
},
},
.vector_type => |vector_type| {
- const vector_ty = try o.lowerType(ty);
+ const vector_ty = try o.lowerType(ty, repr);
switch (aggregate.storage) {
.bytes, .elems => {
const ExpectedContents = [Builder.expected_fields_len]Builder.Constant;
@@ -3718,7 +3598,7 @@ pub const Object = struct {
result_val.* = try o.builder.intConst(.i8, byte);
},
.elems => |elems| for (vals, elems) |*result_val, elem| {
- result_val.* = try o.lowerValue(elem);
+ result_val.* = try o.lowerValue(elem, .by_value);
},
.repeated_elem => unreachable,
}
@@ -3726,12 +3606,12 @@ pub const Object = struct {
},
.repeated_elem => |elem| return o.builder.splatConst(
vector_ty,
- try o.lowerValue(elem),
+ try o.lowerValue(elem, .by_value),
),
}
},
.tuple_type => |tuple| {
- const struct_ty = try o.lowerType(ty);
+ const struct_ty = try o.lowerType(ty, repr);
const llvm_len = struct_ty.aggregateLen(&o.builder);
const ExpectedContents = extern struct {
@@ -3776,8 +3656,8 @@ pub const Object = struct {
vals[llvm_index] = switch (aggregate.storage) {
.bytes => |bytes| try o.builder.intConst(.i8, bytes.at(field_index, ip)),
- .elems => |elems| try o.lowerValue(elems[field_index]),
- .repeated_elem => |elem| try o.lowerValue(elem),
+ .elems => |elems| try o.lowerValue(elems[field_index], repr),
+ .repeated_elem => |elem| try o.lowerValue(elem, repr),
};
fields[llvm_index] = vals[llvm_index].typeOf(&o.builder);
if (fields[llvm_index] != struct_ty.structFields(&o.builder)[llvm_index])
@@ -3806,7 +3686,7 @@ pub const Object = struct {
},
.struct_type => {
const struct_type = ip.loadStructType(ty.toIntern());
- const struct_ty = try o.lowerType(ty);
+ const struct_ty = try o.lowerType(ty, repr);
assert(struct_type.layout != .@"packed");
const llvm_len = struct_ty.aggregateLen(&o.builder);
@@ -3850,8 +3730,8 @@ pub const Object = struct {
vals[llvm_index] = switch (aggregate.storage) {
.bytes => |bytes| try o.builder.intConst(.i8, bytes.at(field_index, ip)),
- .elems => |elems| try o.lowerValue(elems[field_index]),
- .repeated_elem => |elem| try o.lowerValue(elem),
+ .elems => |elems| try o.lowerValue(elems[field_index], repr),
+ .repeated_elem => |elem| try o.lowerValue(elem, repr),
};
fields[llvm_index] = vals[llvm_index].typeOf(&o.builder);
if (fields[llvm_index] != struct_ty.structFields(&o.builder)[llvm_index])
@@ -3881,9 +3761,9 @@ pub const Object = struct {
else => unreachable,
},
.un => |un| {
- const union_ty = try o.lowerType(ty);
+ const union_ty = try o.lowerType(ty, repr);
const layout = ty.unionGetLayout(zcu);
- if (layout.payload_size == 0) return o.lowerValue(un.tag);
+ if (layout.payload_size == 0) return o.lowerValue(un.tag, repr);
const union_obj = zcu.typeToUnion(ty).?;
const container_layout = union_obj.layout;
@@ -3904,7 +3784,7 @@ pub const Object = struct {
const padding_len = layout.payload_size;
break :p try o.builder.undefConst(try o.builder.arrayType(padding_len, .i8));
}
- const payload = try o.lowerValue(un.val);
+ const payload = try o.lowerValue(un.val, repr);
const payload_ty = payload.typeOf(&o.builder);
if (payload_ty != union_ty.structFields(&o.builder)[
@intFromBool(layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align))
@@ -3919,7 +3799,7 @@ pub const Object = struct {
);
} else p: {
assert(layout.tag_size == 0);
- const union_val = try o.lowerValue(un.val);
+ const union_val = try o.lowerValue(un.val, repr);
need_unnamed = true;
break :p union_val;
};
@@ -3929,7 +3809,7 @@ pub const Object = struct {
try o.builder.structType(union_ty.structKind(&o.builder), &.{payload_ty})
else
union_ty, &.{payload});
- const tag = try o.lowerValue(un.tag);
+ const tag = try o.lowerValue(un.tag, repr);
const tag_ty = tag.typeOf(&o.builder);
var fields: [3]Builder.Type = undefined;
var vals: [3]Builder.Constant = undefined;
@@ -3983,8 +3863,8 @@ pub const Object = struct {
},
.int => try o.builder.castConst(
.inttoptr,
- try o.builder.intConst(try o.lowerType(.usize), offset),
- try o.lowerType(.fromInterned(ptr.ty)),
+ try o.builder.intConst(try o.lowerType(.usize, .by_value), offset),
+ try o.lowerType(.fromInterned(ptr.ty), .by_value),
),
.eu_payload => |eu_ptr| try o.lowerPtr(
eu_ptr,
@@ -4031,7 +3911,7 @@ pub const Object = struct {
@"addrspace": std.lang.AddressSpace,
) Allocator.Error!Builder.Constant {
const addr: u64 = @"align".toByteUnits().?;
- const llvm_usize = try o.lowerType(.usize);
+ const llvm_usize = try o.lowerType(.usize, .by_value);
const llvm_addr = try o.builder.intConst(llvm_usize, addr);
const llvm_ptr_ty = try o.builder.ptrType(toLlvmAddressSpace(@"addrspace", o.zcu.getTarget()));
return o.builder.castConst(.inttoptr, llvm_addr, llvm_ptr_ty);
@@ -4068,17 +3948,18 @@ pub const Object = struct {
if (gop.found_existing) {
// Keep the greater of the two alignments.
const llvm_variable = gop.value_ptr.*;
- const old_align: InternPool.Alignment = .fromLlvm(llvm_variable.getAlignment(&o.builder));
- llvm_variable.setAlignment(old_align.maxStrict(@"align").toLlvm(), &o.builder);
+ const llvm_old_align = llvm_variable.getAlignment(&o.builder);
+ const llvm_new_align = llvm_old_align.max(@"align".toLlvm());
+ llvm_variable.setAlignment(llvm_new_align, &o.builder);
return llvm_variable.ptrConst(&o.builder).global.toConst();
}
errdefer assert(o.uav_map.remove(.{ .val = uav_val, .@"addrspace" = @"addrspace" }));
- const llvm_ty = try o.lowerType(uav_ty);
+ const llvm_ty = try o.lowerType(uav_ty, .in_memory);
const llvm_name = try o.builder.strtabStringFmt("__anon_{d}", .{@intFromEnum(uav_val)});
const llvm_variable = try o.builder.addVariable(llvm_name, llvm_ty, llvm_addrspace);
gop.value_ptr.* = llvm_variable;
- try llvm_variable.setInitializer(try o.lowerValue(uav_val), &o.builder);
+ try llvm_variable.setInitializer(try o.lowerValue(uav_val, .in_memory), &o.builder);
llvm_variable.setMutability(.constant, &o.builder);
llvm_variable.setAlignment(@"align".toLlvm(), &o.builder);
const llvm_global = llvm_variable.ptrConst(&o.builder).global;
@@ -4150,7 +4031,7 @@ pub const Object = struct {
.x86_64_interrupt,
.x86_interrupt,
=> {
- const child_type = try lowerType(o, Type.fromInterned(ptr_info.child));
+ const child_type = try o.lowerType(.fromInterned(ptr_info.child), .in_memory);
try attributes.addParamAttr(llvm_arg_i, .{ .byval = child_type }, &o.builder);
},
}
@@ -4172,14 +4053,15 @@ pub const Object = struct {
o: *Object,
attributes: *Builder.FunctionAttributes.Wip,
llvm_arg_i: u32,
- alignment: Builder.Alignment,
byval: bool,
- param_llvm_ty: Builder.Type,
+ param_ty: Type,
) Allocator.Error!void {
+ const llvm_param_ty = try o.lowerType(param_ty, .in_memory);
+ const alignment = param_ty.abiAlignment(o.zcu).toLlvm();
try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = .wrap(alignment) }, &o.builder);
- if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder);
+ if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = llvm_param_ty }, &o.builder);
}
pub fn getErrorNameTable(o: *Object) Allocator.Error!Builder.Variable.Index {
@@ -4204,7 +4086,7 @@ pub const Object = struct {
pub fn getErrorsLen(o: *Object) Allocator.Error!Builder.Variable.Index {
const builder = &o.builder;
if (o.errors_len_variable == .none) {
- const llvm_err_int_ty = try o.errorIntType();
+ const llvm_err_int_ty = try o.errorIntType(.in_memory);
const name = try builder.strtabString("__zig_errors_len");
const variable_index = try builder.addVariable(name, llvm_err_int_ty, .default);
variable_index.setMutability(.constant, builder);
@@ -4244,9 +4126,9 @@ pub const Object = struct {
const ip = &zcu.intern_pool;
const loaded_enum = ip.loadEnumType(enum_ty.toIntern());
- const llvm_usize_ty = try o.lowerType(.usize);
- const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0);
- const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type));
+ const llvm_usize_ty = try o.lowerType(.usize, .by_value);
+ const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0, .by_value);
+ const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .by_value);
function_index.ptrConst(&o.builder).global.ptr(&o.builder).type =
try o.builder.fnType(llvm_ret_ty, &.{llvm_int_ty}, .normal);
@@ -4295,7 +4177,7 @@ pub const Object = struct {
const return_block = try wip.block(1, "Name");
const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, field_index)) {
.none => try o.builder.intConst(llvm_int_ty, field_index), // auto-numbered
- else => |tag_val_ip| try o.lowerValue(tag_val_ip),
+ else => |tag_val_ip| try o.lowerValue(tag_val_ip, .by_value),
};
try wip_switch.addCase(llvm_tag_val, return_block, &wip);
@@ -4341,7 +4223,7 @@ pub const Object = struct {
const ip = &zcu.intern_pool;
const loaded_enum = ip.loadEnumType(enum_ty.toIntern());
- const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type));
+ const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .by_value);
function_index.ptrConst(&o.builder).global.ptr(&o.builder).type =
try o.builder.fnType(.i1, &.{llvm_int_ty}, .normal);
@@ -4368,7 +4250,7 @@ pub const Object = struct {
if (loaded_enum.field_values.len > 0) {
for (loaded_enum.field_values.get(ip)) |tag_val_ip| {
- const llvm_tag_val = try o.lowerValue(tag_val_ip);
+ const llvm_tag_val = try o.lowerValue(tag_val_ip, .by_value);
try wip_switch.addCase(llvm_tag_val, named_block, &wip);
}
} else {
@@ -4405,13 +4287,6 @@ pub const Object = struct {
toLlvmAddressSpace(.generic, o.zcu.getTarget()),
);
}
-
- pub fn ptraddConst(o: *Object, wip: *Builder.WipFunction, ptr: Builder.Value, offset: u64) Allocator.Error!Builder.Value {
- if (offset == 0) return ptr;
- const llvm_usize_ty = try o.lowerType(.usize);
- const offset_val = try o.builder.intValue(llvm_usize_ty, offset);
- return wip.gep(.inbounds, .i8, ptr, &.{offset_val}, "");
- }
};
const CallingConventionInfo = struct {
@@ -4443,6 +4318,10 @@ pub fn toLlvmCallConv(cc: std.lang.CallingConvention, target: *const std.Target)
std.lang.CallingConvention.CommonOptions,
=> .{ pl.incoming_stack_alignment, 0, 0 },
std.lang.CallingConvention.X86RegparmOptions => .{ pl.incoming_stack_alignment, pl.register_params, 0 },
+ std.lang.CallingConvention.SpirvKernelOptions,
+ std.lang.CallingConvention.SpirvFragmentOptions,
+ std.lang.CallingConvention.SpirvMeshOptions,
+ => .{ null, 0, 0 },
else => @compileError("TODO: toLlvmCallConv" ++ @tagName(pl)),
},
};
@@ -4586,6 +4465,8 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const
.spirv_kernel,
.spirv_fragment,
.spirv_vertex,
+ .spirv_task,
+ .spirv_mesh,
=> null,
};
}
@@ -4666,8 +4547,8 @@ fn llvmAddrSpaceInfo(target: *const std.Target) []const AddrSpaceInfo {
.wasm32, .wasm64 => &.{
.{ .zig = .generic, .llvm = Builder.AddrSpace.wasm.default, .force_in_data_layout = true },
.{ .zig = null, .llvm = Builder.AddrSpace.wasm.variable, .non_integral = true },
- .{ .zig = null, .llvm = Builder.AddrSpace.wasm.externref, .non_integral = true, .size = 8, .abi = 8 },
- .{ .zig = null, .llvm = Builder.AddrSpace.wasm.funcref, .non_integral = true, .size = 8, .abi = 8 },
+ .{ .zig = .externref, .llvm = Builder.AddrSpace.wasm.externref, .non_integral = true, .size = 8, .abi = 8 },
+ .{ .zig = .funcref, .llvm = Builder.AddrSpace.wasm.funcref, .non_integral = true, .size = 8, .abi = 8 },
},
.m68k => &.{
.{ .zig = .generic, .llvm = .default, .abi = 16, .pref = 32 },
diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig
index dd9f28d93e2a085f85f18f105576a8ebd6adfa7e..2c214c0c3259051d26588c207272f2da5b56f1aa 100644
--- a/src/codegen/llvm/FuncGen.zig
+++ b/src/codegen/llvm/FuncGen.zig
@@ -164,7 +164,7 @@ fn resolveValue(self: *FuncGen, val: Value) Allocator.Error!Builder.Constant {
const zcu = o.zcu;
const ty = val.typeOf(zcu);
if (!isByRef(ty, zcu)) {
- return o.lowerValue(val.toIntern());
+ return o.lowerValue(val.toIntern(), .by_value);
} else {
// We need a pointer to a global constant, i.e. a UAV.
return o.lowerUavRef(
@@ -175,7 +175,157 @@ fn resolveValue(self: *FuncGen, val: Value) Allocator.Error!Builder.Constant {
}
}
-pub fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air.CoveragePoint) TodoError!void {
+/// Populates `fg.ret_ptr`, `fg.err_ret_trace`, and `fg.args` based on the parameters of the
+/// function type, then generates the entire function body.
+///
+/// The caller may initialize `fg.ret_ptr`, `fg.err_ret_trace`, and `fg.args` to undefined.
+pub fn genMainBody(fg: *FuncGen) TodoError!void {
+ const o = fg.object;
+ const zcu = o.zcu;
+ const ip = &zcu.intern_pool;
+ const comp = zcu.comp;
+ const gpa = comp.gpa;
+
+ const fn_ty: Type = .fromInterned(ip.getNav(fg.nav_index).resolved.?.type);
+ const fn_info = zcu.typeToFunc(fn_ty).?;
+ const param_types = fn_info.param_types.get(ip);
+
+ var it = iterateParamTypes(o, fn_info);
+
+ // Populate `fg.ret_ptr`...
+ fg.ret_ptr = switch (try fnReturnStrat(o, fn_info)) {
+ .sret => rp: {
+ defer it.llvm_index += 1;
+ break :rp fg.wip.arg(it.llvm_index);
+ },
+ else => .none,
+ };
+ // ...and `fg.err_ret_trace`...
+ if (fn_info.cc == .auto and comp.config.any_error_tracing) {
+ fg.err_ret_trace = fg.wip.arg(it.llvm_index);
+ it.llvm_index += 1;
+ } else {
+ fg.err_ret_trace = .none;
+ }
+ // ...and as for `fg.args`, we'll put all of the arguments into this ArrayList, and once that's
+ // done we'll use its buffer as `fg.args`.
+ var args: std.ArrayList(Builder.Value) = .empty;
+ defer args.deinit(gpa);
+
+ while (try it.next()) |lowering| {
+ try args.ensureUnusedCapacity(gpa, 1);
+
+ switch (lowering) {
+ .no_bits => continue,
+ .byval => {
+ assert(!it.byval_attr);
+ const param_index = it.zig_index - 1;
+ const param_ty: Type = .fromInterned(param_types[param_index]);
+ const param = fg.wip.arg(it.llvm_index - 1);
+
+ if (isByRef(param_ty, zcu)) {
+ const alignment = param_ty.abiAlignment(zcu).toLlvm();
+ const arg_ptr = try fg.buildZigAlloca(param_ty, .none);
+ // We don't need to handle non-ABI-sized integer types in memory here since they
+ // are never by-ref.
+ _ = try fg.wip.store(.normal, param, arg_ptr, alignment);
+ args.appendAssumeCapacity(arg_ptr);
+ } else {
+ args.appendAssumeCapacity(param);
+ }
+ },
+ .byref, .byref_mut => {
+ const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
+ const param = fg.wip.arg(it.llvm_index - 1);
+
+ if (isByRef(param_ty, zcu)) {
+ args.appendAssumeCapacity(param);
+ } else {
+ args.appendAssumeCapacity(try fg.load(param, .none, param_ty, .normal));
+ }
+ },
+ .abi_sized_int => {
+ assert(!it.byval_attr);
+ const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
+ const param = fg.wip.arg(it.llvm_index - 1);
+
+ const alignment = param_ty.abiAlignment(zcu).toLlvm();
+ const arg_ptr = try fg.buildZigAlloca(param_ty, .none);
+ _ = try fg.wip.store(.normal, param, arg_ptr, alignment);
+
+ if (isByRef(param_ty, zcu)) {
+ args.appendAssumeCapacity(arg_ptr);
+ } else {
+ args.appendAssumeCapacity(try fg.load(arg_ptr, .none, param_ty, .normal));
+ }
+ },
+ .slice => {
+ assert(!it.byval_attr);
+ const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
+ assert(!isByRef(param_ty, zcu));
+ const slice_val = try fg.wip.buildAggregate(
+ try o.lowerType(param_ty, .by_value),
+ &.{ fg.wip.arg(it.llvm_index - 2), fg.wip.arg(it.llvm_index - 1) },
+ "",
+ );
+ args.appendAssumeCapacity(slice_val);
+ },
+ .multiple_llvm_types => {
+ assert(!it.byval_attr);
+ const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
+ const param_alignment = param_ty.abiAlignment(zcu);
+ const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8);
+ const arg_ptr = try fg.buildAlloca(llvm_ty, param_alignment.toLlvm());
+ const llvm_args_start = it.llvm_index - it.types_len;
+ for (llvm_args_start.., it.offsets_buffer[0..it.types_len]) |llvm_arg_index, offset| {
+ const param = fg.wip.arg(@intCast(llvm_arg_index));
+ const part_ptr = try fg.ptraddConst(arg_ptr, offset);
+ _ = try fg.wip.store(.normal, param, part_ptr, param_alignment.offset(offset).toLlvm());
+ }
+
+ if (isByRef(param_ty, zcu)) {
+ args.appendAssumeCapacity(arg_ptr);
+ } else {
+ args.appendAssumeCapacity(try fg.load(arg_ptr, .none, param_ty, .normal));
+ }
+ },
+ .float_array => {
+ const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
+ const param = fg.wip.arg(it.llvm_index - 1);
+
+ const alignment = param_ty.abiAlignment(zcu).toLlvm();
+ const arg_ptr = try fg.buildZigAlloca(param_ty, .none);
+ _ = try fg.wip.store(.normal, param, arg_ptr, alignment);
+
+ if (isByRef(param_ty, zcu)) {
+ args.appendAssumeCapacity(arg_ptr);
+ } else {
+ args.appendAssumeCapacity(try fg.load(arg_ptr, .none, param_ty, .normal));
+ }
+ },
+ .i32_array, .i64_array => {
+ const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
+ const param = fg.wip.arg(it.llvm_index - 1);
+
+ const alignment = param_ty.abiAlignment(zcu).toLlvm();
+ const arg_ptr = try fg.buildAlloca(param.typeOfWip(&fg.wip), alignment);
+ _ = try fg.wip.store(.normal, param, arg_ptr, alignment);
+
+ if (isByRef(param_ty, zcu)) {
+ args.appendAssumeCapacity(arg_ptr);
+ } else {
+ args.appendAssumeCapacity(try fg.load(arg_ptr, .none, param_ty, .normal));
+ }
+ },
+ }
+ }
+
+ fg.args = args.items;
+
+ try fg.genBody(fg.air.getMainBody(), .poi);
+}
+
+fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air.CoveragePoint) TodoError!void {
const o = self.object;
const zcu = self.object.zcu;
const ip = &zcu.intern_pool;
@@ -198,15 +348,16 @@ pub fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air
try fuzz.pcs.append(gpa, pc);
},
}
- for (body, 0..) |inst, i| {
+ for (body) |inst| {
if (self.liveness.isUnused(inst) and !self.air.mustLower(inst, ip)) continue;
const val: Builder.Value = switch (air_tags[@intFromEnum(inst)]) {
// zig fmt: off
- // No "scalarize" legalizations are enabled, so these instructions never appear.
- .legalize_vec_elem_val => unreachable,
- .legalize_vec_store_elem => unreachable,
+ // Required due to `.scalarize_bit_cast_vector_non_elementwise` being enabled.
+ .legalize_vec_elem_val => try self.airLegalizeVecElemVal(inst),
+ .legalize_vec_store_elem => try self.airLegalizeVecStoreElem(inst),
+
// No soft float legalizations are enabled.
.legalize_compiler_rt_call => unreachable,
@@ -309,29 +460,36 @@ pub fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air
.is_err => try self.airIsErr(inst, .ne, false),
.is_err_ptr => try self.airIsErr(inst, .ne, true),
- .alloc => try self.airAlloc(inst),
- .ret_ptr => try self.airRetPtr(inst),
- .arg => try self.airArg(inst),
- .bitcast => try self.airBitCast(inst),
- .breakpoint => try self.airBreakpoint(inst),
- .ret_addr => try self.airRetAddr(inst),
- .frame_addr => try self.airFrameAddress(inst),
- .@"try" => try self.airTry(inst, false),
- .try_cold => try self.airTry(inst, true),
- .try_ptr => try self.airTryPtr(inst, false),
- .try_ptr_cold => try self.airTryPtr(inst, true),
- .intcast => try self.airIntCast(inst, false),
- .intcast_safe => try self.airIntCast(inst, true),
- .trunc => try self.airTrunc(inst),
- .fptrunc => try self.airFptrunc(inst),
- .fpext => try self.airFpext(inst),
- .load => try self.airLoad(inst),
- .not => try self.airNot(inst),
- .store => try self.airStore(inst, false),
- .store_safe => try self.airStore(inst, true),
- .assembly => try self.airAssembly(inst),
- .slice_ptr => try self.airSliceField(inst, 0),
- .slice_len => try self.airSliceField(inst, 1),
+ .alloc => try self.airAlloc(inst),
+ .ret_ptr => try self.airRetPtr(inst),
+ .arg => try self.airArg(inst),
+ .bit_cast => try self.airBitCast(inst),
+ .ptr_cast => try self.airNopCast(inst),
+ .ptr_from_int => try self.airPtrFromInt(inst),
+ .int_from_ptr => try self.airIntFromPtr(inst),
+ .error_cast => try self.airNopCast(inst),
+ .error_from_int => try self.airNopCast(inst),
+ .int_from_error => try self.airNopCast(inst),
+ .union_from_enum => try self.airUnionFromEnum(inst),
+ .breakpoint => try self.airBreakpoint(inst),
+ .ret_addr => try self.airRetAddr(inst),
+ .frame_addr => try self.airFrameAddress(inst),
+ .@"try" => try self.airTry(inst, false),
+ .try_cold => try self.airTry(inst, true),
+ .try_ptr => try self.airTryPtr(inst, false),
+ .try_ptr_cold => try self.airTryPtr(inst, true),
+ .int_cast => try self.airIntCast(inst, false),
+ .int_cast_safe => try self.airIntCast(inst, true),
+ .trunc => try self.airTrunc(inst),
+ .fptrunc => try self.airFptrunc(inst),
+ .fpext => try self.airFpext(inst),
+ .load => try self.airLoad(inst),
+ .not => try self.airNot(inst),
+ .store => try self.airStore(inst, false),
+ .store_safe => try self.airStore(inst, true),
+ .assembly => try self.airAssembly(inst),
+ .slice_ptr => try self.airSliceField(inst, 0),
+ .slice_len => try self.airSliceField(inst, 1),
.ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0),
.ptr_slice_len_ptr => try self.airPtrSliceFieldPtr(inst, 1),
@@ -400,8 +558,8 @@ pub fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air
.optional_payload_ptr => try self.airOptionalPayloadPtr(inst),
.optional_payload_ptr_set => try self.airOptionalPayloadPtrSet(inst),
- .unwrap_errunion_payload => try self.airErrUnionPayload(inst, false),
- .unwrap_errunion_payload_ptr => try self.airErrUnionPayload(inst, true),
+ .unwrap_errunion_payload => try self.airErrUnionPayload(inst),
+ .unwrap_errunion_payload_ptr => try self.airErrUnionPayloadPtr(inst),
.unwrap_errunion_err => try self.airErrUnionErr(inst, false),
.unwrap_errunion_err_ptr => try self.airErrUnionErr(inst, true),
.errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
@@ -409,9 +567,9 @@ pub fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air
.set_err_return_trace => try self.airSetErrReturnTrace(inst),
.save_err_return_trace_index => try self.airSaveErrReturnTraceIndex(inst),
- .wrap_optional => try self.airWrapOptional(body[i..]),
- .wrap_errunion_payload => try self.airWrapErrUnionPayload(body[i..]),
- .wrap_errunion_err => try self.airWrapErrUnionErr(body[i..]),
+ .wrap_optional => try self.airWrapOptional(inst),
+ .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
+ .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
.wasm_memory_size => try self.airWasmMemorySize(inst),
.wasm_memory_grow => try self.airWasmMemoryGrow(inst),
@@ -434,6 +592,7 @@ pub fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air
.work_item_id => try self.airWorkItemId(inst),
.work_group_size => try self.airWorkGroupSize(inst),
.work_group_id => try self.airWorkGroupId(inst),
+ .spirv_runtime_array_len => unreachable,
// Instructions that are known to always be `noreturn` based on their tag.
.br => return self.airBr(inst),
@@ -593,7 +752,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
break :llvm_fn try self.resolveInst(air_call.callee);
};
const target = zcu.getTarget();
- const sret = firstParamSRet(fn_info, zcu, target);
+ const ret_strat = try fnReturnStrat(o, fn_info);
var llvm_args = std.array_list.Managed(Builder.Value).init(self.gpa);
defer llvm_args.deinit();
@@ -611,20 +770,21 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
.no_suspend, .always_inline, .compile_time => unreachable,
}
- const ret_ptr = if (sret) ret_ptr: {
- const llvm_ret_ty = try o.lowerType(return_type);
- try attributes.addParamAttr(0, .{ .sret = llvm_ret_ty }, &o.builder);
+ const sret_alloc: ?Builder.Value = switch (ret_strat) {
+ .sret => sret_alloc: {
+ try attributes.addParamAttr(0, .{ .sret = try o.lowerType(return_type, .in_memory) }, &o.builder);
- const alignment = return_type.abiAlignment(zcu).toLlvm();
- const ret_ptr = try self.buildAlloca(llvm_ret_ty, alignment);
- try llvm_args.append(ret_ptr);
- break :ret_ptr ret_ptr;
- } else ret_ptr: {
- if (ccAbiPromoteInt(fn_info.cc, zcu, Type.fromInterned(fn_info.return_type))) |s| switch (s) {
- .signed => try attributes.addRetAttr(.signext, &o.builder),
- .unsigned => try attributes.addRetAttr(.zeroext, &o.builder),
- };
- break :ret_ptr null;
+ const ptr = try self.buildZigAlloca(return_type, .none);
+ try llvm_args.append(ptr);
+ break :sret_alloc ptr;
+ },
+ else => sret_alloc: {
+ if (ccAbiPromoteInt(fn_info.cc, zcu, .fromInterned(fn_info.return_type))) |s| switch (s) {
+ .signed => try attributes.addRetAttr(.signext, &o.builder),
+ .unsigned => try attributes.addRetAttr(.zeroext, &o.builder),
+ };
+ break :sret_alloc null;
+ },
};
const err_return_tracing = fn_info.cc == .auto and zcu.comp.config.any_error_tracing;
@@ -640,9 +800,11 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
const arg = args[it.zig_index - 1];
const param_ty = self.typeOf(arg);
const llvm_arg = try self.resolveInst(arg);
- const llvm_param_ty = try o.lowerType(param_ty);
if (isByRef(param_ty, zcu)) {
const alignment = param_ty.abiAlignment(zcu).toLlvm();
+ // We don't need to handle non-ABI-sized integer types in memory here since they are
+ // never by-ref.
+ const llvm_param_ty = try o.lowerType(param_ty, .in_memory);
const loaded = try self.wip.load(.normal, llvm_param_ty, llvm_arg, alignment, "");
try llvm_args.append(loaded);
} else {
@@ -656,10 +818,8 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
if (isByRef(param_ty, zcu)) {
try llvm_args.append(llvm_arg);
} else {
- const alignment = param_ty.abiAlignment(zcu).toLlvm();
- const param_llvm_ty = llvm_arg.typeOfWip(&self.wip);
- const arg_ptr = try self.buildAlloca(param_llvm_ty, alignment);
- _ = try self.wip.store(.normal, llvm_arg, arg_ptr, alignment);
+ const arg_ptr = try self.buildZigAlloca(param_ty, .none);
+ try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal);
try llvm_args.append(arg_ptr);
}
},
@@ -668,15 +828,8 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
const param_ty = self.typeOf(arg);
const llvm_arg = try self.resolveInst(arg);
- const alignment = param_ty.abiAlignment(zcu).toLlvm();
- const param_llvm_ty = try o.lowerType(param_ty);
- const arg_ptr = try self.buildAlloca(param_llvm_ty, alignment);
- if (isByRef(param_ty, zcu)) {
- const loaded = try self.wip.load(.normal, param_llvm_ty, llvm_arg, alignment, "");
- _ = try self.wip.store(.normal, loaded, arg_ptr, alignment);
- } else {
- _ = try self.wip.store(.normal, llvm_arg, arg_ptr, alignment);
- }
+ const arg_ptr = try self.buildZigAlloca(param_ty, .none);
+ try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal);
try llvm_args.append(arg_ptr);
},
.abi_sized_int => {
@@ -693,9 +846,9 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
// LLVM does not allow bitcasting structs so we must allocate
// a local, store as one type, and then load as another type.
const alignment = param_ty.abiAlignment(zcu).toLlvm();
- const int_ptr = try self.buildAlloca(int_llvm_ty, alignment);
- _ = try self.wip.store(.normal, llvm_arg, int_ptr, alignment);
- const loaded = try self.wip.load(.normal, int_llvm_ty, int_ptr, alignment, "");
+ const ptr = try self.buildAlloca(int_llvm_ty, alignment);
+ try self.store(ptr, .none, llvm_arg, param_ty, .normal);
+ const loaded = try self.wip.load(.normal, int_llvm_ty, ptr, alignment, "");
try llvm_args.append(loaded);
}
},
@@ -710,19 +863,10 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
const arg = args[it.zig_index - 1];
const param_ty = self.typeOf(arg);
const llvm_arg = try self.resolveInst(arg);
- const is_by_ref = isByRef(param_ty, zcu);
const param_alignment = param_ty.abiAlignment(zcu);
const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8);
const arg_ptr = try self.buildAlloca(llvm_ty, param_alignment.toLlvm());
- if (is_by_ref) _ = try self.wip.callMemCpy(
- arg_ptr,
- param_alignment.toLlvm(),
- llvm_arg,
- param_alignment.toLlvm(),
- try o.builder.intValue(try o.lowerType(.usize), param_ty.abiSize(zcu)),
- .normal,
- self.disable_intrinsics,
- ) else _ = try self.wip.store(.normal, llvm_arg, arg_ptr, param_alignment.toLlvm());
+ try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal);
try llvm_args.ensureUnusedCapacity(it.types_len);
for (it.types_buffer[0..it.types_len], it.offsets_buffer[0..it.types_len]) |field_ty, offset| {
@@ -734,35 +878,34 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
.float_array => |count| {
const arg = args[it.zig_index - 1];
const arg_ty = self.typeOf(arg);
- var llvm_arg = try self.resolveInst(arg);
- const alignment = arg_ty.abiAlignment(zcu).toLlvm();
- if (!isByRef(arg_ty, zcu)) {
- const ptr = try self.buildAlloca(llvm_arg.typeOfWip(&self.wip), alignment);
- _ = try self.wip.store(.normal, llvm_arg, ptr, alignment);
- llvm_arg = ptr;
- }
+ const arg_val = try self.resolveInst(arg);
- const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?);
+ const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: {
+ const ptr = try self.buildZigAlloca(arg_ty, .none);
+ try self.store(ptr, .none, arg_val, arg_ty, .normal);
+ break :ptr ptr;
+ } else arg_val;
+
+ const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?, .in_memory);
const array_ty = try o.builder.arrayType(count, float_ty);
- const loaded = try self.wip.load(.normal, array_ty, llvm_arg, alignment, "");
+ const loaded = try self.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), "");
try llvm_args.append(loaded);
},
.i32_array, .i64_array => |arr_len| {
const elem_size: u8 = if (lowering == .i32_array) 32 else 64;
const arg = args[it.zig_index - 1];
const arg_ty = self.typeOf(arg);
- var llvm_arg = try self.resolveInst(arg);
- const alignment = arg_ty.abiAlignment(zcu).toLlvm();
- if (!isByRef(arg_ty, zcu)) {
- const ptr = try self.buildAlloca(llvm_arg.typeOfWip(&self.wip), alignment);
- _ = try self.wip.store(.normal, llvm_arg, ptr, alignment);
- llvm_arg = ptr;
- }
+ const arg_val = try self.resolveInst(arg);
- const array_ty =
- try o.builder.arrayType(arr_len, try o.builder.intType(@intCast(elem_size)));
- const loaded = try self.wip.load(.normal, array_ty, llvm_arg, alignment, "");
+ const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: {
+ const ptr = try self.buildZigAlloca(arg_ty, .none);
+ try self.store(ptr, .none, arg_val, arg_ty, .normal);
+ break :ptr ptr;
+ } else arg_val;
+
+ const array_ty = try o.builder.arrayType(arr_len, try o.builder.intType(@intCast(elem_size)));
+ const loaded = try self.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), "");
try llvm_args.append(loaded);
},
};
@@ -772,7 +915,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
{
// Add argument attributes.
it = iterateParamTypes(o, fn_info);
- it.llvm_index += @intFromBool(sret);
+ it.llvm_index += @intFromBool(ret_strat == .sret);
it.llvm_index += @intFromBool(err_return_tracing);
var remaining_inreg_int = cc_info.inreg_int_params;
var remaining_inreg_float = cc_info.inreg_float_params;
@@ -801,10 +944,8 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
},
.byref => {
const param_index = it.zig_index - 1;
- const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]);
- const param_llvm_ty = try o.lowerType(param_ty);
- const alignment = param_ty.abiAlignment(zcu).toLlvm();
- try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
+ const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[param_index]);
+ try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, it.byval_attr, param_ty);
},
.byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),
// No attributes needed for these.
@@ -854,7 +995,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
},
cc_info.llvm_cc,
try attributes.finish(&o.builder),
- try o.lowerType(zig_fn_ty),
+ try o.lowerType(zig_fn_ty, .by_value),
llvm_fn,
llvm_args.items,
"",
@@ -864,45 +1005,27 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
return .none;
}
- if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBits(zcu)) {
+ if (self.liveness.isUnused(inst)) {
return .none;
}
- const llvm_ret_ty = try o.lowerType(return_type);
- if (ret_ptr) |rp| {
- if (isByRef(return_type, zcu)) {
- return rp;
- } else {
- // our by-ref status disagrees with sret so we must load.
- const return_alignment = return_type.abiAlignment(zcu).toLlvm();
- return self.wip.load(.normal, llvm_ret_ty, rp, return_alignment, "");
- }
- }
-
- const abi_ret_ty = try lowerFnRetTy(o, fn_info);
-
- if (abi_ret_ty != llvm_ret_ty) {
- // In this case the function return type is honoring the calling convention by having
- // a different LLVM type than the usual one. We solve this here at the callsite
- // by using our canonical type, then loading it if necessary.
- const alignment = return_type.abiAlignment(zcu).toLlvm();
- const rp = try self.buildAlloca(abi_ret_ty, alignment);
- _ = try self.wip.store(.normal, call, rp, alignment);
- return if (isByRef(return_type, zcu))
- rp
- else
- try self.wip.load(.normal, llvm_ret_ty, rp, alignment, "");
- }
+ // We exit this `switch` if we have a pointer to the return value.
+ const ret_val_ptr: Builder.Value = switch (ret_strat) {
+ .void => return .none,
+ .by_val => return call,
+ .sret => sret_alloc.?,
+ .mem_cast => |llvm_ret_ty| ret_val_ptr: {
+ const alignment = return_type.abiAlignment(zcu).toLlvm();
+ const ptr = try self.buildAlloca(llvm_ret_ty, alignment);
+ _ = try self.wip.store(.normal, call, ptr, alignment);
+ break :ret_val_ptr ptr;
+ },
+ };
if (isByRef(return_type, zcu)) {
- // our by-ref status disagrees with sret so we must allocate, store,
- // and return the allocation pointer.
- const alignment = return_type.abiAlignment(zcu).toLlvm();
- const rp = try self.buildAlloca(llvm_ret_ty, alignment);
- _ = try self.wip.store(.normal, call, rp, alignment);
- return rp;
+ return ret_val_ptr;
} else {
- return call;
+ return self.load(ret_val_ptr, .none, return_type, .normal);
}
}
@@ -912,7 +1035,7 @@ fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) Allocator.Error!v
const target = zcu.getTarget();
const panic_func = zcu.funcInfo(zcu.std_lang_decl_values.get(panic_id.toStdLangDecl()));
const fn_info = zcu.typeToFunc(.fromInterned(panic_func.ty)).?;
- const llvm_panic_fn_ty = try o.lowerType(.fromInterned(panic_func.ty));
+ const llvm_panic_fn_ty = try o.lowerType(.fromInterned(panic_func.ty), .by_value);
const llvm_panic_fn_ref = try o.lowerNavRef(panic_func.owner_nav);
@@ -936,72 +1059,24 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo
const zcu = o.zcu;
const ip = &zcu.intern_pool;
const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
+
const ret_ty = self.typeOf(un_op);
- if (self.ret_ptr != .none) {
- const operand = try self.resolveInst(un_op);
- const val_is_undef = if (un_op.toInterned()) |i| Value.fromInterned(i).isUndef(zcu) else false;
- if (val_is_undef and safety and !self.needMemsetWorkaround(ret_ty.abiSize(zcu))) {
- const len = try o.builder.intValue(try o.lowerType(.usize), ret_ty.abiSize(zcu));
- _ = try self.wip.callMemSet(
- self.ret_ptr,
- ret_ty.abiAlignment(zcu).toLlvm(),
- try o.builder.intValue(.i8, 0xaa),
- len,
- .normal,
- self.disable_intrinsics,
- );
- const owner_mod = self.ownerModule();
- if (owner_mod.valgrind) {
- try self.valgrindMarkUndef(self.ret_ptr, len);
- }
- _ = try self.wip.retVoid();
- return;
- }
-
- const unwrapped_operand = operand.unwrap();
- const unwrapped_ret = self.ret_ptr.unwrap();
-
- // Return value was stored previously
- if (unwrapped_operand == .instruction and unwrapped_ret == .instruction and unwrapped_operand.instruction == unwrapped_ret.instruction) {
- _ = try self.wip.retVoid();
- return;
- }
-
- try self.store(
- self.ret_ptr,
- .none,
- operand,
- ret_ty,
- );
- _ = try self.wip.retVoid();
- return;
- }
const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.nav_index).resolved.?.type)).?;
- if (!ret_ty.hasRuntimeBits(zcu)) {
- if (Type.fromInterned(fn_info.return_type).isError(zcu)) {
- // Functions with an empty error set are emitted with an error code
- // return type and return zero so they can be function pointers coerced
- // to functions that return anyerror.
- _ = try self.wip.ret(try o.builder.intValue(try o.errorIntType(), 0));
- } else {
- _ = try self.wip.retVoid();
- }
- return;
- }
- const abi_ret_ty = try lowerFnRetTy(o, fn_info);
- const operand = try self.resolveInst(un_op);
+ const ret_strat = try fnReturnStrat(o, fn_info);
const val_is_undef = if (un_op.toInterned()) |i| Value.fromInterned(i).isUndef(zcu) else false;
- const alignment = ret_ty.abiAlignment(zcu).toLlvm();
+ const ret_ty_align = ret_ty.abiAlignment(zcu);
if (val_is_undef and safety and !self.needMemsetWorkaround(ret_ty.abiSize(zcu))) {
- const llvm_ret_ty = operand.typeOfWip(&self.wip);
- const rp = try self.buildAlloca(llvm_ret_ty, alignment);
- const len = try o.builder.intValue(try o.lowerType(.usize), ret_ty.abiSize(zcu));
+ const rp = switch (self.ret_ptr) {
+ .none => try self.buildZigAlloca(ret_ty, .none),
+ else => |rp| rp,
+ };
+ const len = try o.builder.intValue(try o.lowerType(.usize, .by_value), ret_ty.abiSize(zcu));
_ = try self.wip.callMemSet(
rp,
- alignment,
+ ret_ty_align.toLlvm(),
try o.builder.intValue(.i8, 0xaa),
len,
.normal,
@@ -1011,27 +1086,47 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo
if (owner_mod.valgrind) {
try self.valgrindMarkUndef(rp, len);
}
- _ = try self.wip.ret(try self.wip.load(.normal, abi_ret_ty, rp, alignment, ""));
+ switch (ret_strat) {
+ .void => unreachable, // value is undef so return type cannot be OPV
+ .sret => {
+ // We just stored directly to `self.ret_ptr`.
+ _ = try self.wip.retVoid();
+ },
+ .by_val => {
+ const loaded = try self.load(rp, .none, ret_ty, .normal);
+ _ = try self.wip.ret(loaded);
+ },
+ .mem_cast => |llvm_abi_ret_ty| {
+ const loaded = try self.wip.load(.normal, llvm_abi_ret_ty, rp, ret_ty_align.toLlvm(), "");
+ _ = try self.wip.ret(loaded);
+ },
+ }
return;
}
- if (isByRef(ret_ty, zcu)) {
- // operand is a pointer however self.ret_ptr is null so that means
- // we need to return a value.
- _ = try self.wip.ret(try self.wip.load(.normal, abi_ret_ty, operand, alignment, ""));
- return;
+ switch (ret_strat) {
+ .void => _ = try self.wip.retVoid(),
+ .sret => {
+ const operand = try self.resolveInst(un_op);
+ try self.store(self.ret_ptr, .none, operand, ret_ty, .normal);
+ _ = try self.wip.retVoid();
+ },
+ .by_val => {
+ assert(!isByRef(ret_ty, zcu));
+ const operand = try self.resolveInst(un_op);
+ _ = try self.wip.ret(operand);
+ },
+ .mem_cast => |llvm_ret_ty| {
+ const operand = try self.resolveInst(un_op);
+ const ptr: Builder.Value = if (!isByRef(ret_ty, zcu)) ptr: {
+ const ptr = try self.buildZigAlloca(ret_ty, .none);
+ try self.store(ptr, .none, operand, ret_ty, .normal);
+ break :ptr ptr;
+ } else operand;
+ const ret_val = try self.wip.load(.normal, llvm_ret_ty, ptr, ret_ty_align.toLlvm(), "");
+ _ = try self.wip.ret(ret_val);
+ },
}
-
- const llvm_ret_ty = operand.typeOfWip(&self.wip);
- if (abi_ret_ty == llvm_ret_ty) {
- _ = try self.wip.ret(operand);
- return;
- }
-
- const rp = try self.buildAlloca(llvm_ret_ty, alignment);
- _ = try self.wip.store(.normal, operand, rp, alignment);
- _ = try self.wip.ret(try self.wip.load(.normal, abi_ret_ty, rp, alignment, ""));
- return;
}
fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void {
@@ -1042,33 +1137,32 @@ fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void {
const ptr_ty = self.typeOf(un_op);
const ret_ty = ptr_ty.childType(zcu);
const fn_info = zcu.typeToFunc(.fromInterned(ip.getNav(self.nav_index).resolved.?.type)).?;
- if (!ret_ty.hasRuntimeBits(zcu)) {
- if (Type.fromInterned(fn_info.return_type).isError(zcu)) {
- // Functions with an empty error set are emitted with an error code
- // return type and return zero so they can be function pointers coerced
- // to functions that return anyerror.
- _ = try self.wip.ret(try o.builder.intValue(try o.errorIntType(), 0));
- } else {
- _ = try self.wip.retVoid();
- }
- return;
- }
- if (self.ret_ptr != .none) {
- _ = try self.wip.retVoid();
- return;
- }
const ptr = try self.resolveInst(un_op);
- const abi_ret_ty = try lowerFnRetTy(o, fn_info);
- const alignment = ret_ty.abiAlignment(zcu).toLlvm();
- _ = try self.wip.ret(try self.wip.load(.normal, abi_ret_ty, ptr, alignment, ""));
- return;
+ switch (try fnReturnStrat(o, fn_info)) {
+ .void => _ = try self.wip.retVoid(),
+ .sret => {
+ assert(self.ret_ptr != .none);
+ _ = try self.wip.retVoid();
+ },
+ .by_val => {
+ assert(self.ret_ptr == .none);
+ const loaded = try self.load(ptr, .none, ret_ty, .normal);
+ _ = try self.wip.ret(loaded);
+ },
+ .mem_cast => |llvm_abi_ret_ty| {
+ assert(self.ret_ptr == .none);
+ const ret_ty_align = ret_ty.abiAlignment(zcu);
+ const loaded = try self.wip.load(.normal, llvm_abi_ret_ty, ptr, ret_ty_align.toLlvm(), "");
+ _ = try self.wip.ret(loaded);
+ },
+ }
}
fn airCVaArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const list = try self.resolveInst(ty_op.operand);
const arg_ty = ty_op.ty.toType();
- const llvm_arg_ty = try self.object.lowerType(arg_ty);
+ const llvm_arg_ty = try self.object.lowerType(arg_ty, .by_value);
return self.wip.vaArg(list, llvm_arg_ty, "");
}
@@ -1079,16 +1173,14 @@ fn airCVaCopy(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const src_list = try self.resolveInst(ty_op.operand);
const va_list_ty = ty_op.ty.toType();
- const llvm_va_list_ty = try o.lowerType(va_list_ty);
- const result_alignment = va_list_ty.abiAlignment(zcu).toLlvm();
- const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment);
+ const dest_list = try self.buildZigAlloca(va_list_ty, .none);
_ = try self.wip.callIntrinsic(.normal, .none, .va_copy, &.{dest_list.typeOfWip(&self.wip)}, &.{ dest_list, src_list }, "");
return if (isByRef(va_list_ty, zcu))
dest_list
else
- try self.wip.load(.normal, llvm_va_list_ty, dest_list, result_alignment, "");
+ try self.load(dest_list, .none, va_list_ty, .normal);
}
fn airCVaEnd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
@@ -1103,16 +1195,14 @@ fn airCVaStart(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
const o = self.object;
const zcu = o.zcu;
const va_list_ty = self.typeOfIndex(inst);
- const llvm_va_list_ty = try o.lowerType(va_list_ty);
- const result_alignment = va_list_ty.abiAlignment(zcu).toLlvm();
- const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment);
+ const dest_list = try self.buildZigAlloca(va_list_ty, .none);
_ = try self.wip.callIntrinsic(.normal, .none, .va_start, &.{dest_list.typeOfWip(&self.wip)}, &.{dest_list}, "");
return if (isByRef(va_list_ty, zcu))
dest_list
else
- try self.wip.load(.normal, llvm_va_list_ty, dest_list, result_alignment, "");
+ try self.load(dest_list, .none, va_list_ty, .normal);
}
fn airCmp(
@@ -1146,13 +1236,7 @@ fn airCmpLteErrorsLen(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Buil
const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
const operand = try self.resolveInst(un_op);
const errors_len_ptr = try o.getErrorsLen();
- const errors_len_val = try self.wip.load(
- .normal,
- try o.errorIntType(),
- errors_len_ptr.toValue(&o.builder),
- Type.errorAbiAlignment(o.zcu).toLlvm(),
- "",
- );
+ const errors_len_val = try self.load(errors_len_ptr.toValue(&o.builder), .none, .anyerror, .normal);
return self.wip.icmp(.ule, operand, errors_len_val, "");
}
@@ -1290,18 +1374,10 @@ fn lowerBlock(
// Create a phi node only if the block returns a value.
if (have_block_result) {
- const raw_llvm_ty = try o.lowerType(inst_ty);
- const llvm_ty: Builder.Type = ty: {
- // If the zig tag type is a function, this represents an actual function body; not
- // a pointer to it. LLVM IR allows the call instruction to use function bodies instead
- // of function pointers, however the phi makes it a runtime value and therefore
- // the LLVM type has to be wrapped in a pointer.
- if (inst_ty.zigTypeTag(zcu) == .@"fn" or isByRef(inst_ty, zcu)) {
- break :ty .ptr;
- }
- break :ty raw_llvm_ty;
+ const llvm_ty: Builder.Type = switch (isByRef(inst_ty, zcu)) {
+ true => .ptr,
+ false => try o.lowerType(inst_ty, .by_value),
};
-
parent_bb.ptr(&self.wip).incoming = @intCast(breaks.list.len);
const phi = try self.wip.phi(llvm_ty, "");
phi.finish(breaks.list.items(.val), breaks.list.items(.bb), &self.wip);
@@ -1407,7 +1483,7 @@ fn lowerSwitchDispatch(
const table_index = try self.wip.conv(
.unsigned,
try self.wip.bin(.@"sub nuw", cond, jmp_table.min.toValue(), ""),
- try o.lowerType(.usize),
+ try o.lowerType(.usize, .by_value),
"",
);
const target_ptr_ptr = try self.ptraddScaled(
@@ -1432,7 +1508,7 @@ fn lowerSwitchDispatch(
// The switch prongs will correspond to our scalar cases. Ranges will
// be handled by conditional branches in the `else` prong.
- const llvm_usize = try o.lowerType(.usize);
+ const llvm_usize = try o.lowerType(.usize, .by_value);
const cond_int = if (cond_ty.zigTypeTag(zcu) == .pointer)
try self.wip.cast(.ptrtoint, cond, llvm_usize, "")
else
@@ -1627,37 +1703,27 @@ fn lowerTry(
const zcu = o.zcu;
const payload_ty = err_union_ty.errorUnionPayload(zcu);
const payload_has_bits = payload_ty.hasRuntimeBits(zcu);
- const error_type = try o.errorIntType();
- const err_set_align: InternPool.Alignment, const payload_align: InternPool.Alignment = if (operand_is_ptr) .{
- operand_ptr_align.minStrict(Type.anyerror.abiAlignment(zcu)),
- operand_ptr_align.minStrict(payload_ty.abiAlignment(zcu)),
- } else .{ .none, .none };
+ const operand_align: InternPool.Alignment = if (operand_is_ptr) operand_ptr_align else err_union_ty.abiAlignment(zcu);
if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) {
const loaded = loaded: {
- const access_kind: Builder.MemoryAccessKind =
- if (err_union_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
-
- if (!payload_has_bits) {
- break :loaded if (operand_is_ptr)
- try fg.wip.load(access_kind, error_type, err_union, err_set_align.toLlvm(), "")
- else
- err_union;
+ if (payload_has_bits) {
+ assert(isByRef(err_union_ty, zcu)); // error unions are by-ref unless the payload has no bits
+ } else if (!operand_is_ptr) {
+ break :loaded err_union;
}
- assert(isByRef(err_union_ty, zcu)); // error unions are by-ref unless the payload has no bits
const offset = codegen.errUnionErrorOffset(payload_ty, zcu);
const err_field_ptr = try fg.ptraddConst(err_union, offset);
- break :loaded try fg.wip.load(
- if (operand_is_ptr) access_kind else .normal,
- error_type,
+ break :loaded try fg.load(
err_field_ptr,
- err_set_align.toLlvm(),
- "",
+ operand_align.offset(offset),
+ .anyerror,
+ if (err_union_ty.isVolatilePtr(zcu)) .@"volatile" else .normal,
);
};
- const zero = try o.builder.intValue(error_type, 0);
+ const zero = try o.builder.intValue(try o.errorIntType(.by_value), 0);
const is_err = try fg.wip.icmp(.ne, loaded, zero, "");
const return_block = try fg.wip.block(1, "TryRet");
@@ -1671,15 +1737,18 @@ fn lowerTry(
fg.wip.cursor = .{ .block = continue_block };
}
if (is_unused) return .none;
- if (!payload_has_bits) return if (operand_is_ptr) err_union else .none;
- assert(isByRef(err_union_ty, zcu)); // error unions are by-ref unless the payload has no bits
- const payload_ptr = try fg.ptraddConst(err_union, codegen.errUnionPayloadOffset(payload_ty, zcu));
+
+ if (!operand_is_ptr) {
+ assert(payload_has_bits); // otherwise the result should be comptime-known
+ assert(isByRef(err_union_ty, zcu)); // error unions are by-ref unless the payload has no bits
+ }
+
+ const offset = codegen.errUnionPayloadOffset(payload_ty, zcu);
+ const payload_ptr = try fg.ptraddConst(err_union, offset);
if (operand_is_ptr) {
return payload_ptr;
- } else if (isByRef(payload_ty, zcu)) {
- return fg.loadByRef(payload_ptr, payload_ty, payload_align.toLlvm(), .normal);
} else {
- return fg.wip.load(.normal, try o.lowerType(payload_ty), payload_ptr, payload_align.toLlvm(), "");
+ return fg.load(payload_ptr, operand_align.offset(offset), payload_ty, .normal);
}
}
@@ -1791,8 +1860,8 @@ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Tod
const table_includes_else = item_count != table_len;
break :jmp_table .{
- .min = try o.lowerValue(min.toIntern()),
- .max = try o.lowerValue(max.toIntern()),
+ .min = try o.lowerValue(min.toIntern(), .by_value),
+ .max = try o.lowerValue(max.toIntern(), .by_value),
.in_bounds_hint = if (table_includes_else) .none else switch (switch_br.getElseHint()) {
.none, .cold => .none,
.unpredictable => .unpredictable,
@@ -1950,9 +2019,9 @@ fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const operand_ty = self.typeOf(ty_op.operand);
const array_ty = operand_ty.childType(zcu);
- const llvm_usize = try o.lowerType(.usize);
+ const llvm_usize = try o.lowerType(.usize, .by_value);
const len = try o.builder.intValue(llvm_usize, array_ty.arrayLen(zcu));
- const slice_llvm_ty = try o.lowerType(self.typeOfIndex(inst));
+ const slice_llvm_ty = try o.lowerType(self.typeOfIndex(inst), .by_value);
const operand = try self.resolveInst(ty_op.operand);
return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, "");
}
@@ -1969,7 +2038,7 @@ fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value
const dest_ty = self.typeOfIndex(inst);
const dest_scalar_ty = dest_ty.scalarType(zcu);
- const dest_llvm_ty = try o.lowerType(dest_ty);
+ const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);
const target = zcu.getTarget();
if (intrinsicsAllowed(dest_scalar_ty, target)) return self.wip.conv(
@@ -2037,7 +2106,7 @@ fn airIntFromFloat(
const dest_ty = self.typeOfIndex(inst);
const dest_scalar_ty = dest_ty.scalarType(zcu);
- const dest_llvm_ty = try o.lowerType(dest_ty);
+ const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);
if (intrinsicsAllowed(operand_scalar_ty, target)) {
// TODO set fast math flag
@@ -2071,7 +2140,7 @@ fn airIntFromFloat(
compiler_rt_dest_abbrev,
});
- const operand_llvm_ty = try o.lowerType(operand_ty);
+ const operand_llvm_ty = try o.lowerType(operand_ty, .by_value);
const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, libc_ret_ty);
var result = try self.wip.call(
.normal,
@@ -2096,7 +2165,7 @@ fn sliceOrArrayPtr(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!B
fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value {
const o = fg.object;
const zcu = o.zcu;
- const llvm_usize = try o.lowerType(.usize);
+ const llvm_usize = try o.lowerType(.usize, .by_value);
switch (ty.ptrSize(zcu)) {
.slice => {
const len = try fg.wip.extractValue(ptr, &.{1}, "");
@@ -2143,11 +2212,7 @@ fn airSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder
const elem_align = slice_ty.ptrAlignment(zcu).min(elem_ty.abiAlignment(zcu));
const access_kind: Builder.MemoryAccessKind = if (slice_info.flags.is_volatile) .@"volatile" else .normal;
self.maybeMarkAllowZeroAccess(slice_info);
- if (isByRef(elem_ty, zcu)) {
- return self.loadByRef(ptr, elem_ty, elem_align.toLlvm(), access_kind);
- } else {
- return self.loadTruncate(access_kind, elem_ty, ptr, elem_align.toLlvm());
- }
+ return self.load(ptr, elem_align, elem_ty, access_kind);
}
fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
@@ -2172,18 +2237,41 @@ fn airArrayElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder
const elem_ty = array_ty.childType(zcu);
if (isByRef(array_ty, zcu)) {
const elem_ptr = try self.ptraddScaled(array_llvm_val, rhs, elem_ty.abiSize(zcu));
- if (isByRef(elem_ty, zcu)) {
- const elem_align = elem_ty.abiAlignment(zcu).toLlvm();
- return self.loadByRef(elem_ptr, elem_ty, elem_align, .normal);
- } else {
- return self.loadTruncate(.normal, elem_ty, elem_ptr, .default);
- }
+ return self.load(elem_ptr, .none, elem_ty, .normal);
}
// This branch can be reached for vectors, which are always by-value.
return self.wip.extractElement(array_llvm_val, rhs, "");
}
+fn airLegalizeVecElemVal(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
+ const bin_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
+ const vec = try fg.resolveInst(bin_op.lhs);
+ const index = try fg.resolveInst(bin_op.rhs);
+ return fg.wip.extractElement(vec, index, "");
+}
+fn airLegalizeVecStoreElem(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
+ const zcu = fg.object.zcu;
+
+ const pl_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
+ const extra = fg.air.extraData(Air.Bin, pl_op.payload).data;
+
+ const ptr_ty = fg.typeOf(pl_op.operand);
+ const vec_ty = ptr_ty.childType(zcu);
+
+ const ptr_align = ptr_ty.ptrAlignment(zcu);
+
+ const vec_ptr = try fg.resolveInst(pl_op.operand);
+ const index = try fg.resolveInst(extra.lhs);
+ const elem = try fg.resolveInst(extra.rhs);
+
+ const old_vec = try fg.load(vec_ptr, ptr_align, vec_ty, .normal);
+ const new_vec = try fg.wip.insertElement(old_vec, elem, index, "");
+ try fg.store(vec_ptr, ptr_align, new_vec, vec_ty, .normal);
+
+ return .none;
+}
+
fn airPtrElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
const zcu = self.object.zcu;
const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
@@ -2196,8 +2284,8 @@ fn airPtrElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V
return self.load(
try self.ptraddScaled(base_ptr, rhs, elem_ty.abiSize(zcu)),
+ ptr_ty.ptrAlignment(zcu).min(elem_ty.abiAlignment(zcu)),
elem_ty,
- ptr_ty.ptrAlignment(zcu).min(elem_ty.abiAlignment(zcu)).toLlvm(),
if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal,
);
}
@@ -2213,9 +2301,6 @@ fn airPtrElemPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V
const base_ptr = try self.resolveInst(bin_op.lhs);
const rhs = try self.resolveInst(bin_op.rhs);
- const elem_ptr = ty_pl.ty.toType();
- if (elem_ptr.ptrInfo(zcu).flags.vector_index != .none) return base_ptr;
-
return self.ptraddScaled(base_ptr, rhs, elem_ty.abiSize(zcu));
}
@@ -2278,7 +2363,7 @@ fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build
},
.float => {
// bitcast int->float
- return self.wip.cast(.bitcast, field_int_val, try o.lowerType(field_ty), "");
+ return self.wip.cast(.bitcast, field_int_val, try o.lowerType(field_ty, .by_value), "");
},
}
}
@@ -2293,11 +2378,7 @@ fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build
const field_ptr = try self.ptraddConst(struct_llvm_val, offset);
const field_ptr_align = struct_ptr_align.offset(offset);
- if (isByRef(field_ty, zcu)) {
- return self.loadByRef(field_ptr, field_ty, field_ptr_align.toLlvm(), .normal);
- } else {
- return self.loadTruncate(.normal, field_ty, field_ptr, field_ptr_align.toLlvm());
- }
+ return self.load(field_ptr, field_ptr_align, field_ty, .normal);
}
fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
@@ -2312,8 +2393,8 @@ fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build
const field_offset = parent_ty.structFieldOffset(extra.field_index, zcu);
if (field_offset == 0) return field_ptr;
- const res_ty = try o.lowerType(ty_pl.ty.toType());
- const llvm_usize = try o.lowerType(.usize);
+ const res_ty = try o.lowerType(ty_pl.ty.toType(), .by_value);
+ const llvm_usize = try o.lowerType(.usize, .by_value);
const field_ptr_int = try self.wip.cast(.ptrtoint, field_ptr, llvm_usize, "");
const base_ptr_int = try self.wip.bin(
@@ -2437,9 +2518,8 @@ fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index, is_arg: bool) Allocator.Er
// We avoid taking this path for naked functions because there's no guarantee that such
// functions even have a valid stack pointer, making the `alloca` + `store` unsafe.
- const alignment = operand_ty.abiAlignment(zcu).toLlvm();
- const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment);
- _ = try self.wip.store(.normal, operand, alloca, alignment);
+ const alloca = try self.buildZigAlloca(operand_ty, .none);
+ try self.store(alloca, .none, operand, operand_ty, .normal);
_ = try self.wip.callIntrinsic(
.normal,
.none,
@@ -2512,7 +2592,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
var llvm_param_i: usize = 0;
var total_i: usize = 0;
- var name_map: std.StringArrayHashMapUnmanaged(u16) = .empty;
+ var name_map: std.array_hash_map.String(u16) = .empty;
try name_map.ensureUnusedCapacity(arena, max_param_count);
var it = unwrapped_asm.iterateOutputs();
@@ -2530,7 +2610,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
const output_inst = try self.resolveInst(output.operand);
const output_ty = self.typeOf(output.operand);
assert(output_ty.zigTypeTag(zcu) == .pointer);
- const elem_llvm_ty = try o.lowerType(output_ty.childType(zcu));
+ const elem_llvm_ty = try o.lowerType(output_ty.childType(zcu), .by_value);
switch (constraint[0]) {
'=' => {},
@@ -2568,7 +2648,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
llvm_ret_indirect[output.index] = false;
const ret_ty = self.typeOfIndex(inst);
- llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty);
+ llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty, .by_value);
llvm_ret_i += 1;
}
@@ -2607,9 +2687,8 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
llvm_param_types[llvm_param_i] = arg_llvm_value.typeOfWip(&self.wip);
} else {
const alignment = arg_ty.abiAlignment(zcu).toLlvm();
- const arg_llvm_ty = try o.lowerType(arg_ty);
- const load_inst =
- try self.wip.load(.normal, arg_llvm_ty, arg_llvm_value, alignment, "");
+ const arg_llvm_ty = try o.lowerType(arg_ty, .by_value);
+ const load_inst = try self.wip.load(.normal, arg_llvm_ty, arg_llvm_value, alignment, "");
llvm_param_values[llvm_param_i] = load_inst;
llvm_param_types[llvm_param_i] = arg_llvm_ty;
}
@@ -2620,7 +2699,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
} else {
const alignment = arg_ty.abiAlignment(zcu).toLlvm();
const arg_ptr = try self.buildAlloca(arg_llvm_value.typeOfWip(&self.wip), alignment);
- _ = try self.wip.store(.normal, arg_llvm_value, arg_ptr, alignment);
+ try self.store(arg_ptr, .none, arg_llvm_value, arg_ty, .normal);
llvm_param_values[llvm_param_i] = arg_ptr;
llvm_param_types[llvm_param_i] = arg_ptr.typeOfWip(&self.wip);
}
@@ -2648,7 +2727,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
llvm_param_attrs[llvm_param_i] = if (constraint[0] == '*') blk: {
if (!is_by_ref) self.maybeMarkAllowZeroAccess(arg_ty.ptrInfo(zcu));
- break :blk try o.lowerType(if (is_by_ref) arg_ty else arg_ty.childType(zcu));
+ break :blk try o.lowerType(if (is_by_ref) arg_ty else arg_ty.childType(zcu), .by_value);
} else .none;
llvm_param_i += 1;
@@ -2662,19 +2741,13 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
if (constraint[0] != '+') continue;
const rw_ty = self.typeOf(output.operand);
- const llvm_elem_ty = try o.lowerType(rw_ty.childType(zcu));
+ const llvm_elem_ty = try o.lowerType(rw_ty.childType(zcu), .by_value);
if (llvm_ret_indirect[output.index]) {
llvm_param_values[llvm_param_i] = llvm_rw_vals[output.index];
llvm_param_types[llvm_param_i] = llvm_rw_vals[output.index].typeOfWip(&self.wip);
} else {
- const alignment = rw_ty.abiAlignment(zcu).toLlvm();
- const loaded = try self.wip.load(
- if (rw_ty.isVolatilePtr(zcu)) .@"volatile" else .normal,
- llvm_elem_ty,
- llvm_rw_vals[output.index],
- alignment,
- "",
- );
+ const access_kind: Builder.MemoryAccessKind = if (rw_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
+ const loaded = try self.load(llvm_rw_vals[output.index], .none, rw_ty.childType(zcu), access_kind);
llvm_param_values[llvm_param_i] = loaded;
llvm_param_types[llvm_param_i] = llvm_elem_ty;
}
@@ -2834,12 +2907,12 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value {
if (output != .none) {
const output_ptr = try self.resolveInst(output);
const output_ptr_ty = self.typeOf(output);
- const alignment = output_ptr_ty.ptrAlignment(zcu).toLlvm();
- _ = try self.wip.store(
- if (output_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal,
- output_value,
+ try self.store(
output_ptr,
- alignment,
+ output_ptr_ty.ptrAlignment(zcu),
+ output_value,
+ output_ptr_ty.childType(zcu),
+ if (output_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal,
);
} else {
ret_val = output_value;
@@ -2862,7 +2935,6 @@ fn airIsNonNull(
const operand = try self.resolveInst(un_op);
const operand_ty = self.typeOf(un_op);
const optional_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty;
- const optional_llvm_ty = try o.lowerType(optional_ty);
const payload_ty = optional_ty.optionalChild(zcu);
const access_kind: Builder.MemoryAccessKind =
@@ -2872,7 +2944,7 @@ fn airIsNonNull(
if (optional_ty.optionalReprIsPayload(zcu)) {
const loaded = if (operand_is_ptr)
- try self.wip.load(access_kind, optional_llvm_ty, operand, operand_ty.ptrAlignment(zcu).toLlvm(), "")
+ try self.load(operand, operand_ty.ptrAlignment(zcu), optional_ty, access_kind)
else
operand;
if (payload_ty.isSlice(zcu)) {
@@ -2883,14 +2955,14 @@ fn airIsNonNull(
));
return self.wip.icmp(cond, slice_ptr, try o.builder.nullValue(ptr_ty), "");
}
- return self.wip.icmp(cond, loaded, try o.builder.zeroInitValue(optional_llvm_ty), "");
+ return self.wip.icmp(cond, loaded, try o.builder.zeroInitValue(try o.lowerType(optional_ty, .by_value)), "");
}
comptime assert(optional_layout_version == 3);
if (!payload_ty.hasRuntimeBits(zcu)) {
const loaded = if (operand_is_ptr)
- try self.wip.load(access_kind, optional_llvm_ty, operand, operand_ty.ptrAlignment(zcu).toLlvm(), "")
+ try self.load(operand, operand_ty.ptrAlignment(zcu), optional_ty, access_kind)
else
operand;
return self.wip.icmp(cond, loaded, try o.builder.intValue(.i8, 0), "");
@@ -2912,8 +2984,7 @@ fn airIsErr(
const operand_ty = self.typeOf(un_op);
const err_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty;
const payload_ty = err_union_ty.errorUnionPayload(zcu);
- const error_type = try o.errorIntType();
- const zero = try o.builder.intValue(error_type, 0);
+ const zero_err = try o.builder.intValue(try o.errorIntType(.by_value), 0);
const access_kind: Builder.MemoryAccessKind =
if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
@@ -2931,10 +3002,10 @@ fn airIsErr(
if (!payload_ty.hasRuntimeBits(zcu)) {
const loaded = if (operand_is_ptr)
- try self.wip.load(access_kind, try o.lowerType(err_union_ty), operand, operand_ty.ptrAlignment(zcu).toLlvm(), "")
+ try self.load(operand, operand_ty.ptrAlignment(zcu), err_union_ty, access_kind)
else
operand;
- return self.wip.icmp(cond, loaded, zero, "");
+ return self.wip.icmp(cond, loaded, zero_err, "");
}
assert(isByRef(err_union_ty, zcu)); // error unions with runtime bits are always by-ref
@@ -2943,8 +3014,8 @@ fn airIsErr(
else
.none;
const err_field_ptr = try self.ptraddConst(operand, codegen.errUnionErrorOffset(payload_ty, zcu));
- const loaded = try self.wip.load(access_kind, error_type, err_field_ptr, err_align.toLlvm(), "");
- return self.wip.icmp(cond, loaded, zero, "");
+ const loaded = try self.load(err_field_ptr, err_align, .anyerror, access_kind);
+ return self.wip.icmp(cond, loaded, zero_err, "");
}
fn airOptionalPayloadPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
@@ -2965,7 +3036,6 @@ fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Erro
const optional_ptr_ty = self.typeOf(ty_op.operand);
const optional_ty = optional_ptr_ty.childType(zcu);
const payload_ty = optional_ty.optionalChild(zcu);
- const non_null_bit = try o.builder.intValue(.i8, 1);
const access_kind: Builder.MemoryAccessKind =
if (optional_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
@@ -2975,7 +3045,7 @@ fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Erro
// We have a pointer to a i8. We need to set it to 1 and then return the same pointer.
// Default alignment store because align of the non null bit is 1 anyway.
- _ = try self.wip.store(access_kind, non_null_bit, operand, .default);
+ try self.store(operand, .@"1", .true, .bool, access_kind);
return operand;
}
if (optional_ty.optionalReprIsPayload(zcu)) {
@@ -2991,7 +3061,7 @@ fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Erro
self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu));
// Default alignment store because align of the non null bit is 1 anyway.
- _ = try self.wip.store(access_kind, non_null_bit, non_null_ptr, .default);
+ try self.store(non_null_ptr, .@"1", .true, .bool, access_kind);
// Then return the payload pointer (only if it's used).
if (self.liveness.isUnused(inst)) return .none;
@@ -3015,31 +3085,29 @@ fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Buil
return self.optPayloadHandle(operand, optional_ty, false);
}
-fn airErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index, operand_is_ptr: bool) Allocator.Error!Builder.Value {
- const o = self.object;
+fn airErrUnionPayload(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
+ const o = fg.object;
const zcu = o.zcu;
- const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
- const operand = try self.resolveInst(ty_op.operand);
- const operand_ty = self.typeOf(ty_op.operand);
- const err_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty;
- const result_ty = self.typeOfIndex(inst);
- const payload_ty = if (operand_is_ptr) result_ty.childType(zcu) else result_ty;
+ const ty_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
+ const operand = try fg.resolveInst(ty_op.operand);
+ const err_union_ty = fg.typeOf(ty_op.operand);
+ const payload_ty = fg.typeOfIndex(inst);
- if (!payload_ty.hasRuntimeBits(zcu)) {
- return if (operand_is_ptr) operand else .none;
- }
- const payload_ptr = try self.ptraddConst(operand, codegen.errUnionPayloadOffset(payload_ty, zcu));
- if (operand_is_ptr) {
- return payload_ptr;
- }
+ assert(payload_ty.hasRuntimeBits(zcu));
assert(isByRef(err_union_ty, zcu)); // error unions are by-ref unless the payload lacks runtime bits
- const payload_alignment = payload_ty.abiAlignment(zcu).toLlvm();
- if (isByRef(payload_ty, zcu)) {
- return self.loadByRef(payload_ptr, payload_ty, payload_alignment, .normal);
- } else {
- const payload_llvm_ty = try o.lowerType(payload_ty);
- return self.wip.load(.normal, payload_llvm_ty, payload_ptr, payload_alignment, "");
- }
+
+ const payload_offset = codegen.errUnionPayloadOffset(payload_ty, zcu);
+ const payload_ptr = try fg.ptraddConst(operand, payload_offset);
+ return fg.load(payload_ptr, err_union_ty.abiAlignment(zcu).offset(payload_offset), payload_ty, .normal);
+}
+
+fn airErrUnionPayloadPtr(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
+ const o = fg.object;
+ const zcu = o.zcu;
+ const ty_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
+ const operand = try fg.resolveInst(ty_op.operand);
+ const payload_ty = fg.typeOfIndex(inst).childType(zcu);
+ return fg.ptraddConst(operand, codegen.errUnionPayloadOffset(payload_ty, zcu));
}
fn airErrUnionErr(
@@ -3052,40 +3120,28 @@ fn airErrUnionErr(
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const operand = try self.resolveInst(ty_op.operand);
const operand_ty = self.typeOf(ty_op.operand);
- const error_type = try o.errorIntType();
const err_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty;
- if (err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) {
- if (operand_is_ptr) {
- return operand;
- } else {
- return o.builder.intValue(error_type, 0);
- }
- }
const access_kind: Builder.MemoryAccessKind =
if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
const payload_ty = err_union_ty.errorUnionPayload(zcu);
- if (!payload_ty.hasRuntimeBits(zcu)) {
- if (!operand_is_ptr) return operand;
- self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu));
-
- return self.wip.load(access_kind, error_type, operand, operand_ty.ptrAlignment(zcu).toLlvm(), "");
+ if (payload_ty.hasRuntimeBits(zcu)) {
+ assert(isByRef(err_union_ty, zcu)); // error unions are by-ref unless the payload lacks runtime bits
+ } else if (!operand_is_ptr) {
+ return operand;
}
- assert(isByRef(err_union_ty, zcu)); // error unions are by-ref unless the payload lacks runtime bits
-
if (operand_is_ptr) self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu));
- const err_align: InternPool.Alignment = a: {
- const err_abi_align = Type.anyerror.abiAlignment(zcu);
- if (!operand_is_ptr) break :a err_abi_align;
- break :a err_abi_align.minStrict(operand_ty.ptrAlignment(zcu));
- };
+ const ptr_align = if (operand_is_ptr) operand_ty.ptrAlignment(zcu) else err_union_ty.abiAlignment(zcu);
- const err_field_ptr = try self.ptraddConst(operand, codegen.errUnionErrorOffset(payload_ty, zcu));
- return self.wip.load(access_kind, error_type, err_field_ptr, err_align.toLlvm(), "");
+ const err_offset = codegen.errUnionErrorOffset(payload_ty, zcu);
+ const err_align = ptr_align.offset(err_offset);
+ const err_ptr = try self.ptraddConst(operand, err_offset);
+
+ return self.load(err_ptr, err_align, .anyerror, access_kind);
}
fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
@@ -3098,7 +3154,7 @@ fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Erro
const err_union_ptr_align = err_union_ptr_ty.ptrAlignment(zcu);
const payload_ty = err_union_ty.errorUnionPayload(zcu);
- const non_error_val = try o.builder.intValue(try o.errorIntType(), 0);
+ const non_error_val = try o.builder.intValue(try o.errorIntType(.by_value), 0);
const access_kind: Builder.MemoryAccessKind =
if (err_union_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
@@ -3106,10 +3162,10 @@ fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Erro
self.maybeMarkAllowZeroAccess(err_union_ptr_ty.ptrInfo(zcu));
{
- const error_align = Type.anyerror.abiAlignment(zcu).minStrict(err_union_ptr_align).toLlvm();
// First set the non-error value.
- const error_ptr = try self.ptraddConst(operand, codegen.errUnionErrorOffset(payload_ty, zcu));
- _ = try self.wip.store(access_kind, non_error_val, error_ptr, error_align);
+ const error_off = codegen.errUnionErrorOffset(payload_ty, zcu);
+ const error_ptr = try self.ptraddConst(operand, error_off);
+ try self.store(error_ptr, err_union_ptr_align.offset(error_off), non_error_val, .anyerror, access_kind);
}
// Then return the payload pointer (only if it is used).
@@ -3141,127 +3197,73 @@ fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) Allocator.Er
const field_offset = struct_ty.structFieldOffset(field_index, zcu);
const field_align = struct_ty.abiAlignment(zcu).offset(field_offset);
const field_ptr = try self.ptraddConst(self.err_ret_trace, field_offset);
- return self.load(field_ptr, field_ty, field_align.toLlvm(), .normal);
+ return self.load(field_ptr, field_align, field_ty, .normal);
}
-/// As an optimization, we want to avoid unnecessary copies of
-/// error union/optional types when returning from a function.
-/// Here, we scan forward in the current block, looking to see
-/// if the next instruction is a return (ignoring debug instructions).
-///
-/// The first instruction of `body_tail` is a wrap instruction.
-fn isNextRet(
- self: *FuncGen,
- body_tail: []const Air.Inst.Index,
-) bool {
- const air_tags = self.air.instructions.items(.tag);
- for (body_tail[1..]) |body_inst| {
- switch (air_tags[@intFromEnum(body_inst)]) {
- .ret => return true,
- .dbg_stmt => continue,
- else => return false,
- }
- }
- // The only way to get here is to hit the end of a loop instruction
- // (implicit repeat).
- return false;
-}
-
-fn airWrapOptional(self: *FuncGen, body_tail: []const Air.Inst.Index) Allocator.Error!Builder.Value {
+fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
const o = self.object;
const zcu = o.zcu;
- const inst = body_tail[0];
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const payload_ty = self.typeOf(ty_op.operand);
- const non_null_bit = try o.builder.intValue(.i8, 1);
comptime assert(optional_layout_version == 3);
assert(payload_ty.hasRuntimeBits(zcu));
const operand = try self.resolveInst(ty_op.operand);
const optional_ty = self.typeOfIndex(inst);
if (optional_ty.optionalReprIsPayload(zcu)) return operand;
assert(isByRef(optional_ty, zcu)); // optionals with runtime bits are by-ref unless `optionalReprIsPayload`
- const llvm_optional_ty = try o.lowerType(optional_ty);
- const optional_ptr = if (self.isNextRet(body_tail))
- self.ret_ptr
- else brk: {
- const alignment = optional_ty.abiAlignment(zcu).toLlvm();
- const optional_ptr = try self.buildAlloca(llvm_optional_ty, alignment);
- break :brk optional_ptr;
- };
+ const optional_ptr = try self.buildZigAlloca(optional_ty, .none);
const payload_ptr = optional_ptr; // payload always at offset 0
- try self.store(
- payload_ptr,
- .none,
- operand,
- payload_ty,
- );
+ try self.store(payload_ptr, .none, operand, payload_ty, .normal);
+
// Non-null bit immediately after payload (no padding because the bit has alignment 1).
const non_null_ptr = try self.ptraddConst(optional_ptr, payload_ty.abiSize(zcu));
- _ = try self.wip.store(.normal, non_null_bit, non_null_ptr, .default);
+ try self.store(non_null_ptr, .none, .true, .bool, .normal);
+
return optional_ptr;
}
-fn airWrapErrUnionPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) Allocator.Error!Builder.Value {
+fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
const o = self.object;
const zcu = o.zcu;
- const inst = body_tail[0];
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const err_un_ty = self.typeOfIndex(inst);
const operand = try self.resolveInst(ty_op.operand);
const payload_ty = self.typeOf(ty_op.operand);
assert(payload_ty.hasRuntimeBits(zcu));
assert(isByRef(err_un_ty, zcu)); // error unions with runtime bits are always by-ref
- const ok_err_code = try o.builder.intValue(try o.errorIntType(), 0);
- const err_un_llvm_ty = try o.lowerType(err_un_ty);
+ const ok_err_code = try o.builder.intValue(try o.errorIntType(.by_value), 0);
- const result_ptr = if (self.isNextRet(body_tail))
- self.ret_ptr
- else brk: {
- const alignment = err_un_ty.abiAlignment(o.zcu).toLlvm();
- const result_ptr = try self.buildAlloca(err_un_llvm_ty, alignment);
- break :brk result_ptr;
- };
+ const result_ptr = try self.buildZigAlloca(err_un_ty, .none);
const err_ptr = try self.ptraddConst(result_ptr, codegen.errUnionErrorOffset(payload_ty, zcu));
- const error_alignment = Type.anyerror.abiAlignment(o.zcu).toLlvm();
- _ = try self.wip.store(.normal, ok_err_code, err_ptr, error_alignment);
+ try self.store(err_ptr, .none, ok_err_code, .anyerror, .normal);
+
const payload_ptr = try self.ptraddConst(result_ptr, codegen.errUnionPayloadOffset(payload_ty, zcu));
- try self.store(
- payload_ptr,
- .none,
- operand,
- payload_ty,
- );
+ try self.store(payload_ptr, .none, operand, payload_ty, .normal);
+
return result_ptr;
}
-fn airWrapErrUnionErr(self: *FuncGen, body_tail: []const Air.Inst.Index) Allocator.Error!Builder.Value {
+fn airWrapErrUnionErr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
const o = self.object;
const zcu = o.zcu;
- const inst = body_tail[0];
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const err_un_ty = self.typeOfIndex(inst);
const payload_ty = err_un_ty.errorUnionPayload(zcu);
const operand = try self.resolveInst(ty_op.operand);
if (!payload_ty.hasRuntimeBits(zcu)) return operand;
assert(isByRef(err_un_ty, zcu)); // error unions with runtime bits are always by-ref
- const err_un_llvm_ty = try o.lowerType(err_un_ty);
- const result_ptr = if (self.isNextRet(body_tail))
- self.ret_ptr
- else brk: {
- const alignment = err_un_ty.abiAlignment(zcu).toLlvm();
- const result_ptr = try self.buildAlloca(err_un_llvm_ty, alignment);
- break :brk result_ptr;
- };
+ const result_ptr = try self.buildZigAlloca(err_un_ty, .none);
const err_ptr = try self.ptraddConst(result_ptr, codegen.errUnionErrorOffset(payload_ty, zcu));
- const error_alignment = Type.anyerror.abiAlignment(zcu).toLlvm();
- _ = try self.wip.store(.normal, operand, err_ptr, error_alignment);
+ try self.store(err_ptr, .none, operand, .anyerror, .normal);
+
const payload_ptr = try self.ptraddConst(result_ptr, codegen.errUnionPayloadOffset(payload_ty, zcu));
// TODO store undef to payload_ptr
_ = payload_ptr;
+
return result_ptr;
}
@@ -3269,7 +3271,7 @@ fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build
const o = self.object;
const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
const index = pl_op.payload;
- const llvm_usize = try o.lowerType(.usize);
+ const llvm_usize = try o.lowerType(.usize, .by_value);
return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.size", &.{llvm_usize}, &.{
try o.builder.intValue(.i32, index),
}, "");
@@ -3279,7 +3281,7 @@ fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build
const o = self.object;
const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
const index = pl_op.payload;
- const llvm_isize = try o.lowerType(.isize);
+ const llvm_isize = try o.lowerType(.isize, .by_value);
return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.grow", &.{llvm_isize}, &.{
try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand),
}, "");
@@ -3306,7 +3308,7 @@ fn airMin(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
.normal,
.none,
if (scalar_ty.isSignedInt(zcu)) .smin else .umin,
- &.{try o.lowerType(inst_ty)},
+ &.{try o.lowerType(inst_ty, .by_value)},
&.{ lhs, rhs },
"",
);
@@ -3326,7 +3328,7 @@ fn airMax(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
.normal,
.none,
if (scalar_ty.isSignedInt(zcu)) .smax else .umax,
- &.{try o.lowerType(inst_ty)},
+ &.{try o.lowerType(inst_ty, .by_value)},
&.{ lhs, rhs },
"",
);
@@ -3338,7 +3340,7 @@ fn airSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
const ptr = try self.resolveInst(bin_op.lhs);
const len = try self.resolveInst(bin_op.rhs);
const inst_ty = self.typeOfIndex(inst);
- return self.wip.buildAggregate(try self.object.lowerType(inst_ty), &.{ ptr, len }, "");
+ return self.wip.buildAggregate(try self.object.lowerType(inst_ty, .by_value), &.{ ptr, len }, "");
}
fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value {
@@ -3369,7 +3371,7 @@ fn airSafeArithmetic(
const scalar_ty = inst_ty.scalarType(zcu);
const intrinsic = if (scalar_ty.isSignedInt(zcu)) signed_intrinsic else unsigned_intrinsic;
- const llvm_inst_ty = try o.lowerType(inst_ty);
+ const llvm_inst_ty = try o.lowerType(inst_ty, .by_value);
const results =
try fg.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_inst_ty}, &.{ lhs, rhs }, "");
@@ -3419,7 +3421,7 @@ fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
.normal,
.none,
if (scalar_ty.isSignedInt(zcu)) .@"sadd.sat" else .@"uadd.sat",
- &.{try o.lowerType(inst_ty)},
+ &.{try o.lowerType(inst_ty, .by_value)},
&.{ lhs, rhs },
"",
);
@@ -3458,7 +3460,7 @@ fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
.normal,
.none,
if (scalar_ty.isSignedInt(zcu)) .@"ssub.sat" else .@"usub.sat",
- &.{try o.lowerType(inst_ty)},
+ &.{try o.lowerType(inst_ty, .by_value)},
&.{ lhs, rhs },
"",
);
@@ -3497,7 +3499,7 @@ fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
.normal,
.none,
if (scalar_ty.isSignedInt(zcu)) .@"smul.fix.sat" else .@"umul.fix.sat",
- &.{try o.lowerType(inst_ty)},
+ &.{try o.lowerType(inst_ty, .by_value)},
&.{ lhs, rhs, .@"0" },
"",
);
@@ -3541,8 +3543,8 @@ fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind)
return self.buildFloatOp(.floor, fast, inst_ty, 1, .{result});
}
if (scalar_ty.isSignedInt(zcu)) {
- const scalar_llvm_ty = try o.lowerType(scalar_ty);
- const inst_llvm_ty = try o.lowerType(inst_ty);
+ const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value);
+ const inst_llvm_ty = try o.lowerType(inst_ty, .by_value);
const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb;
var bfa_buf: ExpectedContents = undefined;
@@ -3616,7 +3618,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo
const lhs = try self.resolveInst(bin_op.lhs);
const rhs = try self.resolveInst(bin_op.rhs);
const inst_ty = self.typeOfIndex(inst);
- const inst_llvm_ty = try o.lowerType(inst_ty);
+ const inst_llvm_ty = try o.lowerType(inst_ty, .by_value);
const scalar_ty = inst_ty.scalarType(zcu);
if (scalar_ty.isRuntimeFloat()) {
@@ -3645,7 +3647,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo
defer allocator.free(smin_big_int.limbs);
smin_big_int.setTwosCompIntLimit(.min, .signed, scalar_bits);
const smin = try o.builder.splatValue(inst_llvm_ty, try o.builder.bigIntConst(
- try o.lowerType(scalar_ty),
+ try o.lowerType(scalar_ty, .by_value),
smin_big_int.toConst(),
));
@@ -3681,7 +3683,7 @@ fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
const ptr_or_slice = try self.resolveInst(bin_op.lhs);
- const llvm_usize_ty = try o.lowerType(.usize);
+ const llvm_usize_ty = try o.lowerType(.usize, .by_value);
const ptr_ty = self.typeOf(bin_op.lhs);
const elem_ty = ptr_ty.indexableElem(zcu);
const ptr = switch (ptr_ty.ptrSize(zcu)) {
@@ -3714,27 +3716,28 @@ fn airOverflow(
assert(isByRef(inst_ty, zcu)); // auto structs are by-ref
const intrinsic = if (scalar_ty.isSignedInt(zcu)) signed_intrinsic else unsigned_intrinsic;
- const llvm_inst_ty = try o.lowerType(inst_ty);
- const llvm_lhs_ty = try o.lowerType(lhs_ty);
+ const llvm_lhs_ty = try o.lowerType(lhs_ty, .by_value);
const results =
try self.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_lhs_ty}, &.{ lhs, rhs }, "");
const result_val = try self.wip.extractValue(results, &.{0}, "");
const overflow_bit = try self.wip.extractValue(results, &.{1}, "");
- const result_alignment = inst_ty.abiAlignment(zcu).toLlvm();
- const alloca_inst = try self.buildAlloca(llvm_inst_ty, result_alignment);
+ const result_alignment = inst_ty.abiAlignment(zcu);
+ const alloca_inst = try self.buildZigAlloca(inst_ty, .none);
{
// Store to 'result: IntType' field
- const field_ptr = try self.ptraddConst(alloca_inst, inst_ty.structFieldOffset(0, zcu));
- _ = try self.wip.store(.normal, result_val, field_ptr, lhs_ty.abiAlignment(zcu).toLlvm());
+ const field_off = inst_ty.structFieldOffset(0, zcu);
+ const field_ptr = try self.ptraddConst(alloca_inst, field_off);
+ try self.store(field_ptr, result_alignment.offset(field_off), result_val, lhs_ty, .normal);
}
{
// Store to 'overflow: u1' field
- const field_ptr = try self.ptraddConst(alloca_inst, inst_ty.structFieldOffset(1, zcu));
- _ = try self.wip.store(.normal, overflow_bit, field_ptr, comptime .fromByteUnits(1));
+ const field_off = inst_ty.structFieldOffset(1, zcu);
+ const field_ptr = try self.ptraddConst(alloca_inst, field_off);
+ try self.store(field_ptr, result_alignment.offset(field_off), overflow_bit, inst_ty.fieldType(1, zcu), .normal);
}
return alloca_inst;
@@ -3786,7 +3789,7 @@ fn buildFloatCmp(
const zcu = o.zcu;
const target = zcu.getTarget();
const scalar_ty = ty.scalarType(zcu);
- const scalar_llvm_ty = try o.lowerType(scalar_ty);
+ const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value);
if (intrinsicsAllowed(scalar_ty, target)) {
const cond: Builder.FloatCondition = switch (pred) {
@@ -3892,7 +3895,7 @@ fn buildFloatOp(
const zcu = o.zcu;
const target = zcu.getTarget();
const scalar_ty = ty.scalarType(zcu);
- const llvm_ty = try o.lowerType(ty);
+ const llvm_ty = try o.lowerType(ty, .by_value);
if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) {
// Some operations are dedicated LLVM instructions, not available as intrinsics
@@ -3997,7 +4000,7 @@ fn buildFloatOp(
}),
};
- const scalar_llvm_ty = try o.lowerType(scalar_ty);
+ const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value);
const libc_fn = try o.getLibcFunction(
fn_name,
@as([3]Builder.Type, @splat(scalar_llvm_ty))[0..params.len],
@@ -4051,9 +4054,8 @@ fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Buil
const dest_ty = self.typeOfIndex(inst);
assert(isByRef(dest_ty, zcu)); // auto structs are by-ref
- const llvm_dest_ty = try o.lowerType(dest_ty);
- const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), "");
+ const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), "");
const result = try self.wip.bin(.shl, lhs, casted_rhs, "");
const reconstructed = try self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu))
@@ -4063,19 +4065,21 @@ fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Buil
const overflow_bit = try self.wip.icmp(.ne, lhs, reconstructed, "");
- const result_alignment = dest_ty.abiAlignment(zcu).toLlvm();
- const alloca_inst = try self.buildAlloca(llvm_dest_ty, result_alignment);
+ const result_alignment = dest_ty.abiAlignment(zcu);
+ const alloca_inst = try self.buildZigAlloca(dest_ty, .none);
{
// Store to 'result: IntType' field
- const field_ptr = try self.ptraddConst(alloca_inst, dest_ty.structFieldOffset(0, zcu));
- _ = try self.wip.store(.normal, result, field_ptr, lhs_ty.abiAlignment(zcu).toLlvm());
+ const field_off = dest_ty.structFieldOffset(0, zcu);
+ const field_ptr = try self.ptraddConst(alloca_inst, field_off);
+ try self.store(field_ptr, result_alignment.offset(field_off), result, lhs_ty, .normal);
}
{
// Store to 'overflow: u1' field
- const field_ptr = try self.ptraddConst(alloca_inst, dest_ty.structFieldOffset(1, zcu));
- _ = try self.wip.store(.normal, overflow_bit, field_ptr, comptime .fromByteUnits(1));
+ const field_off = dest_ty.structFieldOffset(1, zcu);
+ const field_ptr = try self.ptraddConst(alloca_inst, field_off);
+ try self.store(field_ptr, result_alignment.offset(field_off), overflow_bit, dest_ty.fieldType(1, zcu), .normal);
}
return alloca_inst;
@@ -4118,7 +4122,7 @@ fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
}
const lhs_scalar_ty = lhs_ty.scalarType(zcu);
- const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), "");
+ const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), "");
return self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu))
.@"shl nsw"
else
@@ -4139,7 +4143,7 @@ fn airShl(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
// features which we do not use. Therefore this branch is currently impossible.
unreachable;
}
- const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), "");
+ const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), "");
return self.wip.bin(.shl, lhs, casted_rhs, "");
}
@@ -4153,8 +4157,8 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
const lhs_ty = self.typeOf(bin_op.lhs);
const lhs_info = lhs_ty.intInfo(zcu);
- const llvm_lhs_ty = try o.lowerType(lhs_ty);
- const llvm_lhs_scalar_ty = try o.lowerType(lhs_ty.scalarType(zcu));
+ const llvm_lhs_ty = try o.lowerType(lhs_ty, .by_value);
+ const llvm_lhs_scalar_ty = try o.lowerType(lhs_ty.scalarType(zcu), .by_value);
const rhs_ty = self.typeOf(bin_op.rhs);
if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) {
@@ -4164,8 +4168,8 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
}
const rhs_info = rhs_ty.intInfo(zcu);
assert(rhs_info.signedness == .unsigned);
- const llvm_rhs_ty = try o.lowerType(rhs_ty);
- const llvm_rhs_scalar_ty = try o.lowerType(rhs_ty.scalarType(zcu));
+ const llvm_rhs_ty = try o.lowerType(rhs_ty, .by_value);
+ const llvm_rhs_scalar_ty = try o.lowerType(rhs_ty.scalarType(zcu), .by_value);
const result = try self.wip.callIntrinsic(
.normal,
@@ -4241,7 +4245,7 @@ fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) Allocator.Error!
}
const lhs_scalar_ty = lhs_ty.scalarType(zcu);
- const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), "");
+ const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), "");
const is_signed_int = lhs_scalar_ty.isSignedInt(zcu);
return self.wip.bin(if (is_exact)
@@ -4262,8 +4266,8 @@ fn airAbs(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
.normal,
.none,
.abs,
- &.{try o.lowerType(operand_ty)},
- &.{ operand, try o.builder.intValue(.i1, 0) },
+ &.{try o.lowerType(operand_ty, .by_value)},
+ &.{ operand, .false },
"",
),
.float => return self.buildFloatOp(.fabs, .normal, operand_ty, 1, .{operand}),
@@ -4276,7 +4280,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
const zcu = o.zcu;
const ty_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const dest_ty = fg.typeOfIndex(inst);
- const dest_llvm_ty = try o.lowerType(dest_ty);
+ const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);
const operand = try fg.resolveInst(ty_op.operand);
const operand_ty = fg.typeOf(ty_op.operand);
const operand_info = operand_ty.intInfo(zcu);
@@ -4304,8 +4308,8 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
if (!have_min_check and !have_max_check) break :bounds_check;
- const operand_llvm_ty = try o.lowerType(operand_ty);
- const operand_scalar_llvm_ty = try o.lowerType(operand_scalar);
+ const operand_llvm_ty = try o.lowerType(operand_ty, .by_value);
+ const operand_scalar_llvm_ty = try o.lowerType(operand_scalar, .by_value);
const is_vector = operand_ty.zigTypeTag(zcu) == .vector;
assert(is_vector == (dest_ty.zigTypeTag(zcu) == .vector));
@@ -4383,7 +4387,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const operand = try self.resolveInst(ty_op.operand);
- const dest_llvm_ty = try self.object.lowerType(self.typeOfIndex(inst));
+ const dest_llvm_ty = try self.object.lowerType(self.typeOfIndex(inst), .by_value);
return self.wip.cast(.trunc, operand, dest_llvm_ty, "");
}
@@ -4397,10 +4401,10 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu
const target = zcu.getTarget();
if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) {
- return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty), "");
+ return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .by_value), "");
} else {
- const operand_llvm_ty = try o.lowerType(operand_ty);
- const dest_llvm_ty = try o.lowerType(dest_ty);
+ const operand_llvm_ty = try o.lowerType(operand_ty, .by_value);
+ const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);
const dest_bits = dest_ty.floatBits(target);
const src_bits = operand_ty.floatBits(target);
@@ -4431,10 +4435,10 @@ fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
const target = zcu.getTarget();
if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) {
- return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty), "");
+ return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .by_value), "");
} else {
- const operand_llvm_ty = try o.lowerType(operand_ty);
- const dest_llvm_ty = try o.lowerType(dest_ty);
+ const operand_llvm_ty = try o.lowerType(operand_ty, .by_value);
+ const dest_llvm_ty = try o.lowerType(dest_ty, .by_value);
const dest_bits = dest_ty.scalarType(zcu).floatBits(target);
const src_bits = operand_ty.scalarType(zcu).floatBits(target);
@@ -4461,114 +4465,80 @@ fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
}
}
-fn airBitCast(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
- const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
- const operand_ty = self.typeOf(ty_op.operand);
- const inst_ty = self.typeOfIndex(inst);
- const operand = try self.resolveInst(ty_op.operand);
- return self.bitCast(operand, operand_ty, inst_ty);
-}
-
-fn bitCast(self: *FuncGen, operand: Builder.Value, operand_ty: Type, inst_ty: Type) Allocator.Error!Builder.Value {
- const o = self.object;
+fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
+ const o = fg.object;
const zcu = o.zcu;
- const operand_is_ref = isByRef(operand_ty, zcu);
- const result_is_ref = isByRef(inst_ty, zcu);
- const llvm_dest_ty = try o.lowerType(inst_ty);
- if (operand_is_ref and result_is_ref) {
- // They are both pointers, so just return the same opaque pointer :)
- return operand;
- }
+ const ty_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
+ const operand_ty = fg.typeOf(ty_op.operand);
+ const dest_ty = fg.typeOfIndex(inst);
+ const operand = try fg.resolveInst(ty_op.operand);
- if (inst_ty.isAbiInt(zcu) and operand_ty.isAbiInt(zcu)) {
- return self.wip.conv(.unsigned, operand, llvm_dest_ty, "");
- }
+ // We have the following `Air.Legalize` features enabled:
+ //
+ // * `.scalarize_bit_cast_array`
+ // * `.scalarize_bit_cast_vector_non_elementwise`
+ //
+ // That means the `bit_cast` instructions we might see are limited to the following:
+ //
+ // * bool/int/float <-> bool/int/float
+ // * `@Vector(n, A)` <-> `@Vector(n, B)`
+ //
+ // All of these cases can be handled by LLVM's `bitcast` instruction.
- const operand_scalar_ty = operand_ty.scalarType(zcu);
- const inst_scalar_ty = inst_ty.scalarType(zcu);
- if (operand_scalar_ty.zigTypeTag(zcu) == .int and inst_scalar_ty.isPtrAtRuntime(zcu)) {
- return self.wip.cast(.inttoptr, operand, llvm_dest_ty, "");
- }
- if (operand_scalar_ty.isPtrAtRuntime(zcu) and inst_scalar_ty.zigTypeTag(zcu) == .int) {
- return self.wip.cast(.ptrtoint, operand, llvm_dest_ty, "");
- }
+ assert(!isByRef(operand_ty, zcu));
+ assert(!isByRef(dest_ty, zcu));
- if (operand_ty.zigTypeTag(zcu) == .vector and inst_ty.zigTypeTag(zcu) == .array) {
- const elem_ty = operand_scalar_ty;
- assert(result_is_ref); // arrays are always by-ref provided they have runtime bits
- const alignment = inst_ty.abiAlignment(zcu).toLlvm();
- const array_ptr = try self.buildAlloca(llvm_dest_ty, alignment);
- const bitcast_ok = elem_ty.bitSize(zcu) == elem_ty.abiSize(zcu) * 8;
- if (bitcast_ok) {
- _ = try self.wip.store(.normal, operand, array_ptr, alignment);
- } else {
- // If the ABI size of the element type is not evenly divisible by size in bits;
- // a simple bitcast will not work, and we fall back to extractelement.
- const elem_size = elem_ty.abiSize(zcu);
- const vector_len = operand_ty.arrayLen(zcu);
- var i: u64 = 0;
- while (i < vector_len) : (i += 1) {
- const arr_elem_ptr = try self.ptraddConst(array_ptr, i * elem_size);
- const vec_elem = try self.wip.extractElement(operand, try o.builder.intValue(.i32, i), "");
- _ = try self.wip.store(.normal, vec_elem, arr_elem_ptr, .default);
- }
- }
- return array_ptr;
- } else if (operand_ty.zigTypeTag(zcu) == .array and inst_ty.zigTypeTag(zcu) == .vector) {
- const elem_ty = operand_ty.childType(zcu);
- assert(operand_is_ref); // arrays are always by-ref provided they have runtime bits
- const llvm_vector_ty = try o.lowerType(inst_ty);
+ const llvm_dest_ty = try o.lowerType(dest_ty, .by_value);
+ return fg.wip.cast(.bitcast, operand, llvm_dest_ty, "");
+}
- const bitcast_ok = elem_ty.bitSize(zcu) == elem_ty.abiSize(zcu) * 8;
- if (bitcast_ok) {
- // The array is aligned to the element's alignment, while the vector might have a completely
- // different alignment. This means we need to enforce the alignment of this load.
- const alignment = elem_ty.abiAlignment(zcu).toLlvm();
- return self.wip.load(.normal, llvm_vector_ty, operand, alignment, "");
- } else {
- // If the ABI size of the element type is not evenly divisible by size in bits;
- // a simple bitcast will not work, and we fall back to extractelement.
- const elem_llvm_ty = try o.lowerType(elem_ty);
- const elem_size = elem_ty.abiSize(zcu);
- const vector_len = operand_ty.arrayLen(zcu);
- var vector = try o.builder.poisonValue(llvm_vector_ty);
- var i: u64 = 0;
- while (i < vector_len) : (i += 1) {
- const arr_elem_ptr = try self.ptraddConst(operand, i * elem_size);
- const arr_elem = try self.wip.load(.normal, elem_llvm_ty, arr_elem_ptr, .default, "");
- vector = try self.wip.insertElement(vector, arr_elem, try o.builder.intValue(.i32, i), "");
- }
- return vector;
- }
- }
+fn airNopCast(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
+ const zcu = fg.object.zcu;
+ const ty_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
+ const operand_ty = fg.typeOf(ty_op.operand);
+ const dest_ty = fg.typeOfIndex(inst);
+ assert(isByRef(operand_ty, zcu) == isByRef(dest_ty, zcu));
+ assert(operand_ty.abiSize(zcu) == dest_ty.abiSize(zcu));
+ return fg.resolveInst(ty_op.operand);
+}
- if (operand_is_ref) {
- const alignment = operand_ty.abiAlignment(zcu).toLlvm();
- return self.wip.load(.normal, llvm_dest_ty, operand, alignment, "");
- }
+fn airPtrFromInt(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
+ const o = fg.object;
+ const zcu = o.zcu;
+ const ty_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
+ const operand_ty = fg.typeOf(ty_op.operand);
+ const dest_ty = fg.typeOfIndex(inst);
+ assert(operand_ty.scalarType(zcu).toIntern() == .usize_type);
+ assert(dest_ty.scalarType(zcu).isPtrAtRuntime(zcu));
- if (result_is_ref) {
- const alignment = operand_ty.abiAlignment(zcu).max(inst_ty.abiAlignment(zcu)).toLlvm();
- const result_ptr = try self.buildAlloca(llvm_dest_ty, alignment);
- _ = try self.wip.store(.normal, operand, result_ptr, alignment);
- return result_ptr;
- }
+ const operand = try fg.resolveInst(ty_op.operand);
+ const llvm_dest_ty = try o.lowerType(dest_ty, .by_value);
+ return fg.wip.cast(.inttoptr, operand, llvm_dest_ty, "");
+}
+
+fn airIntFromPtr(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
+ const o = fg.object;
+ const zcu = o.zcu;
+ const ty_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
+ const operand_ty = fg.typeOf(ty_op.operand);
+ const dest_ty = fg.typeOfIndex(inst);
+ assert(operand_ty.scalarType(zcu).isPtrAtRuntime(zcu));
+ assert(dest_ty.scalarType(zcu).toIntern() == .usize_type);
- if (inst_ty.isSliceAtRuntime(zcu) or
- ((operand_ty.zigTypeTag(zcu) == .vector or inst_ty.zigTypeTag(zcu) == .vector) and
- operand_ty.bitSize(zcu) != inst_ty.bitSize(zcu)))
- {
- // Both our operand and our result are values, not pointers,
- // but LLVM won't let us bitcast struct values or vectors with padding bits.
- // Therefore, we store operand to alloca, then load for result.
- const alignment = operand_ty.abiAlignment(zcu).max(inst_ty.abiAlignment(zcu)).toLlvm();
- const result_ptr = try self.buildAlloca(llvm_dest_ty, alignment);
- _ = try self.wip.store(.normal, operand, result_ptr, alignment);
- return self.wip.load(.normal, llvm_dest_ty, result_ptr, alignment, "");
- }
+ const operand = try fg.resolveInst(ty_op.operand);
+ const llvm_dest_ty = try o.lowerType(dest_ty, .by_value);
+ return fg.wip.cast(.ptrtoint, operand, llvm_dest_ty, "");
+}
- return self.wip.cast(.bitcast, operand, llvm_dest_ty, "");
+fn airUnionFromEnum(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
+ const ty_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
+ const enum_ty = fg.typeOf(ty_op.operand);
+ const union_ty = fg.typeOfIndex(inst);
+ const enum_val = try fg.resolveInst(ty_op.operand);
+ const union_ptr = try fg.buildZigAlloca(union_ty, .none);
+ try fg.store(union_ptr, .none, enum_val, enum_ty, .normal);
+ return union_ptr;
}
fn airArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
@@ -4627,9 +4597,8 @@ fn airArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
"",
);
} else if (mod.optimize_mode == .Debug) {
- const alignment = inst_ty.abiAlignment(zcu).toLlvm();
- const alloca = try self.buildAlloca(arg_val.typeOfWip(&self.wip), alignment);
- _ = try self.wip.store(.normal, arg_val, alloca, alignment);
+ const alloca = try self.buildZigAlloca(inst_ty, .none);
+ try self.store(alloca, .none, arg_val, inst_ty, .normal);
_ = try self.wip.callIntrinsic(
.normal,
.none,
@@ -4670,8 +4639,7 @@ fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
if (!elem_ty.hasRuntimeBits(zcu)) {
return (try o.lowerPtrToVoid(ptr_align, ptr_ty.ptrAddressSpace(zcu))).toValue();
}
- const llvm_elem_ty = try o.lowerType(elem_ty);
- return self.buildAlloca(llvm_elem_ty, ptr_align.toLlvm());
+ return self.buildZigAlloca(elem_ty, ptr_align);
}
fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
@@ -4684,32 +4652,71 @@ fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value
if (!elem_ty.hasRuntimeBits(zcu)) {
return (try o.lowerPtrToVoid(ptr_align, ptr_ty.ptrAddressSpace(zcu))).toValue();
}
- const llvm_elem_ty = try o.lowerType(elem_ty);
- return self.buildAlloca(llvm_elem_ty, ptr_align.toLlvm());
+ return self.buildZigAlloca(elem_ty, ptr_align);
}
-/// Use this instead of builder.buildAlloca, because this function makes sure to
-/// put the alloca instruction at the top of the function!
+fn buildZigAlloca(fg: *FuncGen, ty: Type, @"align": InternPool.Alignment) Allocator.Error!Builder.Value {
+ const o = fg.object;
+ const resolved_align: InternPool.Alignment = switch (@"align") {
+ .none => ty.abiAlignment(o.zcu),
+ else => |a| a,
+ };
+ return fg.buildAlloca(
+ try o.lowerType(ty, .in_memory),
+ resolved_align.toLlvm(),
+ );
+}
+
+/// Unlike `WipFunction.alloca`, this puts the alloca instruction at the top of the function.
fn buildAlloca(
- self: *FuncGen,
+ fg: *FuncGen,
llvm_ty: Builder.Type,
alignment: Builder.Alignment,
) Allocator.Error!Builder.Value {
- const target = self.object.zcu.getTarget();
- return buildAllocaInner(&self.wip, llvm_ty, alignment, target);
+ const wip = &fg.wip;
+
+ const alloca = blk: {
+ const prev_cursor = wip.cursor;
+ const prev_debug_location = wip.debug_location;
+ defer {
+ wip.cursor = prev_cursor;
+ if (wip.cursor.block == .entry) wip.cursor.instruction += 1;
+ wip.debug_location = prev_debug_location;
+ }
+
+ wip.cursor = .{ .block = .entry };
+ wip.debug_location = .no_location;
+ const address_space = llvmAllocaAddressSpace(fg.object.zcu.getTarget());
+ break :blk try wip.alloca(.normal, llvm_ty, .none, alignment, address_space, "");
+ };
+
+ // The pointer returned from this function should have the generic address space,
+ // if this isn't the case then cast it to the generic address space.
+ return fg.wip.conv(.unneeded, alloca, .ptr, "");
}
-fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Builder.Value {
- const o = self.object;
+fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Builder.Value {
+ const o = fg.object;
const zcu = o.zcu;
- const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
- const dest_ptr = try self.resolveInst(bin_op.lhs);
- const ptr_ty = self.typeOf(bin_op.lhs);
- const operand_ty = ptr_ty.childType(zcu);
+ const bin_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
+ const ptr = try fg.resolveInst(bin_op.lhs);
+ const ptr_ty = fg.typeOf(bin_op.lhs);
+ const ptr_info = ptr_ty.ptrInfo(zcu);
+ const ptr_alignment = ptr_ty.ptrAlignment(zcu);
+
+ const elem_ty = fg.typeOf(bin_op.rhs);
+ assert(elem_ty.hasRuntimeBits(zcu));
+
+ fg.maybeMarkAllowZeroAccess(ptr_info);
+
+ const access_kind: Builder.MemoryAccessKind = switch (ptr_info.flags.is_volatile) {
+ true => .@"volatile",
+ false => .normal,
+ };
const val_is_undef = if (bin_op.rhs.toInterned()) |i| Value.fromInterned(i).isUndef(zcu) else false;
- if (val_is_undef and !self.needMemsetWorkaround(operand_ty.abiSize(zcu))) {
- const owner_mod = self.ownerModule();
+ if (val_is_undef and !fg.needMemsetWorkaround(elem_ty.abiSize(zcu))) {
+ const owner_mod = fg.ownerModule();
// Even if safety is disabled, we still emit a memset to undefined since it conveys
// extra information to LLVM, and LLVM will optimize it out. Safety makes the difference
@@ -4724,7 +4731,6 @@ fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
return .none;
}
- const ptr_info = ptr_ty.ptrInfo(zcu);
const needs_bitmask = (ptr_info.packed_offset.host_size != 0);
if (needs_bitmask) {
// TODO: only some bits are to be undef, we cannot write with a simple memset.
@@ -4733,27 +4739,82 @@ fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!
return .none;
}
- self.maybeMarkAllowZeroAccess(ptr_info);
-
- const len = try o.builder.intValue(try o.lowerType(.usize), operand_ty.abiSize(zcu));
- _ = try self.wip.callMemSet(
- dest_ptr,
- ptr_ty.ptrAlignment(zcu).toLlvm(),
+ const len = try o.builder.intValue(try o.lowerType(.usize, .by_value), elem_ty.abiSize(zcu));
+ _ = try fg.wip.callMemSet(
+ ptr,
+ ptr_alignment.toLlvm(),
if (safety) try o.builder.intValue(.i8, 0xaa) else try o.builder.undefValue(.i8),
len,
- if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal,
- self.disable_intrinsics,
+ access_kind,
+ fg.disable_intrinsics,
);
if (safety and owner_mod.valgrind) {
- try self.valgrindMarkUndef(dest_ptr, len);
+ try fg.valgrindMarkUndef(ptr, len);
}
return .none;
}
- self.maybeMarkAllowZeroAccess(ptr_ty.ptrInfo(zcu));
+ const elem = try fg.resolveInst(bin_op.rhs);
- const src_operand = try self.resolveInst(bin_op.rhs);
- try self.storeFull(dest_ptr, ptr_ty, src_operand, .none);
+ if (ptr_info.flags.vector_index != .none) {
+ // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
+ const vec_ty = try fg.pt.vectorType(.{
+ .len = ptr_info.packed_offset.host_size,
+ .child = elem_ty.toIntern(),
+ });
+
+ const loaded_vector = try fg.load(ptr, ptr_alignment, vec_ty, access_kind);
+ const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index);
+ const modified_vector = try fg.wip.insertElement(loaded_vector, elem, index_val, "");
+
+ try fg.store(ptr, ptr_alignment, modified_vector, vec_ty, access_kind);
+ return .none;
+ }
+
+ if (ptr_info.packed_offset.host_size != 0) {
+ // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
+ const backing_int_ty = try fg.pt.intType(.unsigned, @intCast(ptr_info.packed_offset.host_size * 8));
+ const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .by_value);
+
+ const backing_int_val = try fg.load(ptr, ptr_alignment, backing_int_ty, access_kind);
+
+ const elem_bits = ptr_ty.childType(zcu).bitSize(zcu);
+ const shift_amt = try o.builder.intConst(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset);
+
+ // Convert to equally-sized integer type in order to perform the bit
+ // operations on the value to store
+ const new_val_bits_type = try o.builder.intType(@intCast(elem_bits));
+ const new_val_bits = if (elem_ty.isPtrAtRuntime(zcu))
+ try fg.wip.cast(.ptrtoint, elem, new_val_bits_type, "")
+ else
+ try fg.wip.cast(.bitcast, elem, new_val_bits_type, "");
+
+ const mask_val = blk: {
+ const zext = try fg.wip.cast(
+ .zext,
+ try o.builder.intValue(new_val_bits_type, -1),
+ llvm_backing_int_ty,
+ "",
+ );
+ const shl = try fg.wip.bin(.shl, zext, shift_amt.toValue(), "");
+ break :blk try fg.wip.bin(
+ .xor,
+ shl,
+ try o.builder.intValue(llvm_backing_int_ty, -1),
+ "",
+ );
+ };
+
+ const masked_backing_int_val = try fg.wip.bin(.@"and", backing_int_val, mask_val, "");
+ const extended_new_val = try fg.wip.cast(.zext, new_val_bits, llvm_backing_int_ty, "");
+ const shifted_new_val = try fg.wip.bin(.shl, extended_new_val, shift_amt.toValue(), "");
+ const new_backing_int_val = try fg.wip.bin(.@"or", shifted_new_val, masked_backing_int_val, "");
+
+ try fg.store(ptr, ptr_alignment, new_backing_int_val, backing_int_ty, access_kind);
+ return .none;
+ }
+
+ try fg.store(ptr, ptr_alignment, elem, elem_ty, access_kind);
return .none;
}
@@ -4765,7 +4826,7 @@ fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
const ptr_info = ptr_ty.ptrInfo(zcu);
const ptr = try fg.resolveInst(ty_op.operand);
const elem_ty = ptr_ty.childType(zcu);
- const llvm_ptr_align = ptr_ty.ptrAlignment(zcu).toLlvm();
+ const ptr_align = ptr_ty.ptrAlignment(zcu);
fg.maybeMarkAllowZeroAccess(ptr_info);
@@ -4773,36 +4834,32 @@ fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
if (ptr_info.flags.is_volatile) .@"volatile" else .normal;
if (ptr_info.flags.vector_index != .none) {
- const index_u32 = try o.builder.intValue(.i32, ptr_info.flags.vector_index);
- const vec_elem_ty = try o.lowerType(elem_ty);
- const vec_ty = try o.builder.vectorType(.normal, ptr_info.packed_offset.host_size, vec_elem_ty);
-
- const loaded_vector = try fg.wip.load(access_kind, vec_ty, ptr, llvm_ptr_align, "");
- return fg.wip.extractElement(loaded_vector, index_u32, "");
+ // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
+ const vec_ty = try fg.pt.vectorType(.{
+ .len = ptr_info.packed_offset.host_size,
+ .child = elem_ty.toIntern(),
+ });
+ const vector_val = try fg.load(ptr, ptr_align, vec_ty, access_kind);
+ const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index);
+ return fg.wip.extractElement(vector_val, index_val, "");
}
if (ptr_info.packed_offset.host_size == 0) {
- return fg.load(ptr, elem_ty, llvm_ptr_align, access_kind);
+ return fg.load(ptr, ptr_align, elem_ty, access_kind);
}
- const containing_int_ty = try o.builder.intType(@intCast(ptr_info.packed_offset.host_size * 8));
- const containing_int =
- try fg.wip.load(access_kind, containing_int_ty, ptr, llvm_ptr_align, "");
+ assert(!isByRef(elem_ty, zcu)); // all packable types are by-val
+
+ // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`.
+ const backing_int_ty = try fg.pt.intType(.unsigned, @intCast(ptr_info.packed_offset.host_size * 8));
+ const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .by_value);
+
+ const backing_int_val = try fg.load(ptr, ptr_align, backing_int_ty, .normal);
const elem_bits = ptr_ty.childType(zcu).bitSize(zcu);
- const shift_amt = try o.builder.intValue(containing_int_ty, ptr_info.packed_offset.bit_offset);
- const shifted_value = try fg.wip.bin(.lshr, containing_int, shift_amt, "");
- const elem_llvm_ty = try o.lowerType(elem_ty);
-
- if (isByRef(elem_ty, zcu)) {
- const result_align = elem_ty.abiAlignment(zcu).toLlvm();
- const result_ptr = try fg.buildAlloca(elem_llvm_ty, result_align);
-
- const same_size_int = try o.builder.intType(@intCast(elem_bits));
- const truncated_int = try fg.wip.cast(.trunc, shifted_value, same_size_int, "");
- _ = try fg.wip.store(.normal, truncated_int, result_ptr, result_align);
- return result_ptr;
- }
+ const shift_amt = try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset);
+ const shifted_value = try fg.wip.bin(.lshr, backing_int_val, shift_amt, "");
+ const elem_llvm_ty = try o.lowerType(elem_ty, .by_value);
if (elem_ty.zigTypeTag(zcu) == .float or elem_ty.zigTypeTag(zcu) == .vector) {
const same_size_int = try o.builder.intType(@intCast(elem_bits));
@@ -4852,7 +4909,7 @@ fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V
fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
_ = inst;
const o = self.object;
- const llvm_usize = try o.lowerType(.usize);
+ const llvm_usize = try o.lowerType(.usize, .by_value);
if (!target_util.supportsReturnAddress(self.object.zcu.getTarget(), self.ownerModule().optimize_mode)) {
// https://github.com/ziglang/zig/issues/11946
return o.builder.intValue(llvm_usize, 0);
@@ -4864,7 +4921,7 @@ fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu
fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
_ = inst;
const result = try self.wip.callIntrinsic(.normal, .none, .frameaddress, &.{.ptr}, &.{.@"0"}, "");
- return self.wip.cast(.ptrtoint, result, try self.object.lowerType(.usize), "");
+ return self.wip.cast(.ptrtoint, result, try self.object.lowerType(.usize, .by_value), "");
}
fn airCmpxchg(
@@ -4881,7 +4938,7 @@ fn airCmpxchg(
var expected_value = try self.resolveInst(extra.expected_value);
var new_value = try self.resolveInst(extra.new_value);
const operand_ty = ptr_ty.childType(zcu);
- const llvm_operand_ty = try o.lowerType(operand_ty);
+ const llvm_operand_ty = try o.lowerType(operand_ty, .by_value);
const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, false);
if (llvm_abi_ty != .none) {
// operand needs widening and truncating
@@ -4917,21 +4974,22 @@ fn airCmpxchg(
return self.wip.select(.normal, success_bit, zero, payload, "");
}
- assert(isByRef(optional_ty, zcu));
+ assert(!isByRef(operand_ty, zcu)); // can only cmpxchg non-by-ref types
+ assert(isByRef(optional_ty, zcu)); // all optionals are by-ref
comptime assert(optional_layout_version == 3);
const non_null_bit = try self.wip.not(success_bit, "");
- const payload_align = operand_ty.abiAlignment(zcu).toLlvm();
- const alloca_inst = try self.buildAlloca(try o.lowerType(optional_ty), payload_align);
+ const payload_align = operand_ty.abiAlignment(zcu);
+ const alloca_inst = try self.buildZigAlloca(optional_ty, .none);
// Payload is always the first field at offset 0, so address is `alloca_inst`
- _ = try self.wip.store(.normal, payload, alloca_inst, payload_align);
+ try self.store(alloca_inst, .none, payload, operand_ty, .normal);
// Non-null bit is after payload with no padding because it has alignment 1
const non_null_ptr = try self.ptraddConst(alloca_inst, operand_ty.abiSize(zcu));
- _ = try self.wip.store(.normal, non_null_bit, non_null_ptr, comptime .fromByteUnits(1));
+ try self.store(non_null_ptr, payload_align, non_null_bit, .bool, .normal);
return alloca_inst;
}
@@ -4950,7 +5008,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float);
const ordering = toLlvmAtomicOrdering(extra.ordering());
const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, op == .xchg);
- const llvm_operand_ty = try o.lowerType(operand_ty);
+ const llvm_operand_ty = try o.lowerType(operand_ty, .by_value);
const access_kind: Builder.MemoryAccessKind =
if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
@@ -4979,7 +5037,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
// If we are storing a pointer we need to convert to and from a plain old integer.
const non_ptr_operand = switch (operand_ty.zigTypeTag(zcu)) {
- .pointer => try self.wip.cast(.ptrtoint, operand, try o.lowerType(.usize), ""),
+ .pointer => try self.wip.cast(.ptrtoint, operand, try o.lowerType(.usize, .by_value), ""),
else => operand,
};
@@ -5018,7 +5076,7 @@ fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V
Type.fromInterned(info.child).abiAlignment(zcu)).toLlvm();
const access_kind: Builder.MemoryAccessKind =
if (info.flags.is_volatile) .@"volatile" else .normal;
- const elem_llvm_ty = try o.lowerType(elem_ty);
+ const elem_llvm_ty = try o.lowerType(elem_ty, .by_value);
self.maybeMarkAllowZeroAccess(info);
@@ -5072,7 +5130,17 @@ fn airAtomicStore(
self.maybeMarkAllowZeroAccess(ptr_ty.ptrInfo(zcu));
- try self.storeFull(ptr, ptr_ty, element, ordering);
+ assert(!isByRef(operand_ty, zcu));
+
+ _ = try self.wip.storeAtomic(
+ if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal,
+ element,
+ ptr,
+ self.sync_scope,
+ ordering,
+ ptr_ty.ptrAlignment(zcu).toLlvm(),
+ );
+
return .none;
}
@@ -5083,7 +5151,7 @@ fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error
const dest_slice = try self.resolveInst(bin_op.lhs);
const ptr_ty = self.typeOf(bin_op.lhs);
const elem_ty = self.typeOf(bin_op.rhs);
- const dest_ptr_align = ptr_ty.ptrAlignment(zcu).toLlvm();
+ const dest_ptr_align = ptr_ty.ptrAlignment(zcu);
const dest_ptr = try self.sliceOrArrayPtr(dest_slice, ptr_ty);
const access_kind: Builder.MemoryAccessKind =
if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
@@ -5109,7 +5177,7 @@ fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error
const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
_ = try self.wip.callMemSet(
dest_ptr,
- dest_ptr_align,
+ dest_ptr_align.toLlvm(),
fill_byte,
len,
access_kind,
@@ -5131,7 +5199,7 @@ fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error
const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
_ = try self.wip.callMemSet(
dest_ptr,
- dest_ptr_align,
+ dest_ptr_align.toLlvm(),
fill_byte,
len,
access_kind,
@@ -5144,14 +5212,31 @@ fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error
const value = try self.resolveInst(bin_op.rhs);
const elem_abi_size = elem_ty.abiSize(zcu);
- if (allow_byte_memset and elem_abi_size == 1 and elem_ty.bitSize(zcu) == 8) {
- // In this case we can take advantage of LLVM's intrinsic.
- const fill_byte = try self.bitCast(value, elem_ty, Type.u8);
+ intrinsic: {
+ if (!allow_byte_memset) break :intrinsic;
+ if (elem_abi_size != 1) break :intrinsic;
+ // To use LLVM's intrinsic, we need to convert the operand to a raw 8-bit integer value.
+ const fill_byte: Builder.Value = byte: {
+ if (isByRef(elem_ty, zcu)) {
+ break :byte try self.load(value, elem_ty.abiAlignment(zcu), .u8, .normal);
+ }
+ if (elem_ty.isAbiInt(zcu)) {
+ const info = elem_ty.intInfo(zcu);
+ break :byte try self.wip.conv(switch (info.signedness) {
+ .unsigned => .unsigned,
+ .signed => .signed,
+ }, value, .i8, "");
+ }
+ if (elem_ty.toIntern() == .bool_type) {
+ break :byte try self.wip.cast(.zext, value, .i8, "");
+ }
+ break :intrinsic;
+ };
+ // Great, we can use the intrinsic!
const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
-
_ = try self.wip.callMemSet(
dest_ptr,
- dest_ptr_align,
+ dest_ptr_align.toLlvm(),
fill_byte,
len,
access_kind,
@@ -5181,7 +5266,6 @@ fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error
const body_block = try self.wip.block(1, "InlineMemsetBody");
const end_block = try self.wip.block(1, "InlineMemsetEnd");
- const llvm_usize_ty = try o.lowerType(.usize);
const end_ptr = switch (ptr_ty.ptrSize(zcu)) {
.slice => try self.ptraddScaled(
dest_ptr,
@@ -5200,18 +5284,8 @@ fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error
self.wip.cursor = .{ .block = body_block };
const elem_abi_align = elem_ty.abiAlignment(zcu);
- const it_ptr_align = InternPool.Alignment.fromLlvm(dest_ptr_align).min(elem_abi_align).toLlvm();
- if (isByRef(elem_ty, zcu)) {
- _ = try self.wip.callMemCpy(
- it_ptr.toValue(),
- it_ptr_align,
- value,
- elem_abi_align.toLlvm(),
- try o.builder.intValue(llvm_usize_ty, elem_abi_size),
- access_kind,
- self.disable_intrinsics,
- );
- } else _ = try self.wip.store(access_kind, value, it_ptr.toValue(), it_ptr_align);
+ const it_ptr_align: InternPool.Alignment = dest_ptr_align.min(elem_abi_align);
+ try self.store(it_ptr.toValue(), it_ptr_align, value, elem_ty, access_kind);
const next_ptr = try self.ptraddConst(it_ptr.toValue(), elem_abi_size);
_ = try self.wip.br(loop_block);
@@ -5288,14 +5362,11 @@ fn airSetUnionTag(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.
const union_ptr = try self.resolveInst(bin_op.lhs);
const new_tag = try self.resolveInst(bin_op.rhs);
+ const tag_ty = self.typeOf(bin_op.rhs);
const union_ptr_align = un_ptr_ty.ptrAlignment(zcu);
- if (layout.payload_size == 0) {
- _ = try self.wip.store(access_kind, new_tag, union_ptr, union_ptr_align.toLlvm());
- return .none;
- }
const tag_field_ptr = try self.ptraddConst(union_ptr, layout.tagOffset());
const tag_ptr_align = union_ptr_align.offset(layout.tagOffset());
- _ = try self.wip.store(access_kind, new_tag, tag_field_ptr, tag_ptr_align.toLlvm());
+ try self.store(tag_field_ptr, tag_ptr_align, new_tag, tag_ty, access_kind);
return .none;
}
@@ -5307,16 +5378,9 @@ fn airGetUnionTag(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.
const layout = un_ty.unionGetLayout(zcu);
assert(layout.tag_size != 0);
const operand = try self.resolveInst(ty_op.operand);
- if (isByRef(un_ty, zcu)) {
- const llvm_tag_ty = try o.lowerType(un_ty.unionTagTypeRuntime(zcu).?);
- const tag_field_ptr = try self.ptraddConst(operand, layout.tagOffset());
- return self.wip.load(.normal, llvm_tag_ty, tag_field_ptr, .default, "");
- } else {
- // This is only possible if all fields are zero-bit, in which case `operand` is already an
- // integer value (the union is lowered as its enum tag).
- assert(layout.payload_size == 0);
- return operand;
- }
+ assert(isByRef(un_ty, zcu));
+ const tag_field_ptr = try self.ptraddConst(operand, layout.tagOffset());
+ return self.load(tag_field_ptr, .none, un_ty.unionTagTypeRuntime(zcu).?, .normal);
}
fn airUnaryOp(self: *FuncGen, inst: Air.Inst.Index, comptime op: FloatOp) Allocator.Error!Builder.Value {
@@ -5346,11 +5410,11 @@ fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic)
.normal,
.none,
intrinsic,
- &.{try o.lowerType(operand_ty)},
+ &.{try o.lowerType(operand_ty, .by_value)},
&.{ operand, .false },
"",
);
- return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), "");
+ return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .by_value), "");
}
fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) Allocator.Error!Builder.Value {
@@ -5364,11 +5428,11 @@ fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic)
.normal,
.none,
intrinsic,
- &.{try o.lowerType(operand_ty)},
+ &.{try o.lowerType(operand_ty, .by_value)},
&.{operand},
"",
);
- return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), "");
+ return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .by_value), "");
}
fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
@@ -5381,7 +5445,7 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
const inst_ty = self.typeOfIndex(inst);
var operand = try self.resolveInst(ty_op.operand);
- var llvm_operand_ty = try o.lowerType(operand_ty);
+ var llvm_operand_ty = try o.lowerType(operand_ty, .by_value);
if (bits % 16 == 8) {
// If not an even byte-multiple, we need zero-extend + shift-left 1 byte
@@ -5402,7 +5466,7 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
const result =
try self.wip.callIntrinsic(.normal, .none, .bswap, &.{llvm_operand_ty}, &.{operand}, "");
- return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), "");
+ return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .by_value), "");
}
fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
@@ -5422,7 +5486,7 @@ fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Bui
for (0..names.len) |name_index| {
const err_int = ip.getErrorValueIfExists(names.get(ip)[name_index]).?;
- const this_tag_int_value = try o.builder.intConst(try o.errorIntType(), err_int);
+ const this_tag_int_value = try o.builder.intConst(try o.errorIntType(.by_value), err_int);
try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip);
}
self.wip.cursor = .{ .block = valid_block };
@@ -5479,21 +5543,20 @@ fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
const operand = try self.resolveInst(un_op);
const slice_ty = self.typeOfIndex(inst);
- const slice_llvm_ty = try o.lowerType(slice_ty);
// If operand is small (e.g. `u8`), then signedness becomes a problem -- GEP always treats the index as signed.
- const operand_usize = try self.wip.conv(.unsigned, operand, try o.lowerType(.usize), "");
+ const operand_usize = try self.wip.conv(.unsigned, operand, try o.lowerType(.usize, .by_value), "");
const error_name_table_ptr = try o.getErrorNameTable();
const error_name_ptr = try self.ptraddScaled(error_name_table_ptr.toValue(&o.builder), operand_usize, slice_ty.abiSize(zcu));
- return self.wip.load(.normal, slice_llvm_ty, error_name_ptr, .default, "");
+ return self.load(error_name_ptr, .none, slice_ty, .normal);
}
fn airSplat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const scalar = try self.resolveInst(ty_op.operand);
const vector_ty = self.typeOfIndex(inst);
- return self.wip.splatVector(try self.object.lowerType(vector_ty), scalar, "");
+ return self.wip.splatVector(try self.object.lowerType(vector_ty, .by_value), scalar, "");
}
fn airSelect(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
@@ -5516,9 +5579,9 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
const operand = try fg.resolveInst(unwrapped.operand);
const mask = unwrapped.mask;
const operand_ty = fg.typeOf(unwrapped.operand);
- const llvm_operand_ty = try o.lowerType(operand_ty);
- const llvm_result_ty = try o.lowerType(unwrapped.result_ty);
- const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu));
+ const llvm_operand_ty = try o.lowerType(operand_ty, .by_value);
+ const llvm_result_ty = try o.lowerType(unwrapped.result_ty, .by_value);
+ const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .by_value);
const llvm_poison_elem = try o.builder.poisonConst(llvm_elem_ty);
const llvm_poison_mask_elem = try o.builder.poisonConst(.i32);
const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32);
@@ -5548,7 +5611,7 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
.elem => llvm_poison_elem,
.value => |val| if (!Value.fromInterned(val).isUndef(zcu)) elem: {
any_defined_comptime_value = true;
- break :elem try o.lowerValue(val);
+ break :elem try o.lowerValue(val, .by_value);
} else llvm_poison_elem,
};
}
@@ -5620,7 +5683,7 @@ fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
const unwrapped = fg.air.unwrapShuffleTwo(zcu, inst);
const mask = unwrapped.mask;
- const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu));
+ const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .by_value);
const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32);
const llvm_poison_mask_elem = try o.builder.poisonConst(.i32);
@@ -5695,15 +5758,13 @@ fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val
/// Reduce a vector by repeatedly applying `llvm_fn` to produce an accumulated result.
///
/// Equivalent to:
-/// reduce: {
-/// var i: usize = 0;
-/// var accum: T = init;
-/// while (i < vec.len) : (i += 1) {
-/// accum = llvm_fn(accum, vec[i]);
-/// }
-/// break :reduce accum;
-/// }
-///
+/// ```
+/// var accum: T = init;
+/// for (0..i) |i| {
+/// accum = llvm_fn(accum, vec[i]);
+/// }
+/// // result is 'accum'
+/// ```
fn buildReducedCall(
self: *FuncGen,
llvm_fn: Builder.Function.Index,
@@ -5712,56 +5773,54 @@ fn buildReducedCall(
accum_init: Builder.Value,
) Allocator.Error!Builder.Value {
const o = self.object;
- const usize_ty = try o.lowerType(.usize);
- const llvm_vector_len = try o.builder.intValue(usize_ty, vector_len);
+ const llvm_usize_ty = try o.lowerType(.usize, .by_value);
+ const llvm_vector_len = try o.builder.intValue(llvm_usize_ty, vector_len);
const llvm_result_ty = accum_init.typeOfWip(&self.wip);
- // Allocate and initialize our mutable variables
- const i_ptr = try self.buildAlloca(usize_ty, .default);
- _ = try self.wip.store(.normal, try o.builder.intValue(usize_ty, 0), i_ptr, .default);
- const accum_ptr = try self.buildAlloca(llvm_result_ty, .default);
- _ = try self.wip.store(.normal, accum_init, accum_ptr, .default);
+ const entry_block = self.wip.cursor.block;
- // Setup the loop
- const loop = try self.wip.block(2, "ReduceLoop");
- const loop_exit = try self.wip.block(1, "AfterReduce");
- _ = try self.wip.br(loop);
- {
- self.wip.cursor = .{ .block = loop };
+ const cond_block = try self.wip.block(2, "ReduceLoopCond");
+ const body_block = try self.wip.block(1, "ReduceLoopBody");
+ const exit_block = try self.wip.block(1, "ReduceLoopExit");
- // while (i < vec.len)
- const i = try self.wip.load(.normal, usize_ty, i_ptr, .default, "");
- const cond = try self.wip.icmp(.ult, i, llvm_vector_len, "");
- const loop_then = try self.wip.block(1, "ReduceLoopThen");
+ _ = try self.wip.br(cond_block);
- _ = try self.wip.brCond(cond, loop_then, loop_exit, .none);
+ // ReduceLoopCond:
+ // %index = phi iN [0, %Entry], [%new_index, %ReduceLoopBody]
+ // %accum = phi T [%accum_init, %Entry], [%new_accum, %ReduceLoopBody]
+ // %cond = icmp ult iN %index, %vector_len
+ // br i1 %cond, label %ReduceLoopBody, label %ReduceLoopExit
+ self.wip.cursor = .{ .block = cond_block };
+ const index = try self.wip.phi(llvm_usize_ty, "");
+ const accum = try self.wip.phi(llvm_result_ty, "");
+ const cond = try self.wip.icmp(.ult, index.toValue(), llvm_vector_len, "");
+ _ = try self.wip.brCond(cond, body_block, exit_block, .none);
- {
- self.wip.cursor = .{ .block = loop_then };
+ // ReduceLoopBody:
+ // %elem = extractelement %operand_vec, iN %index
+ // %new_accum = call T @llvm_fn(T %accum, T %elem)
+ // %new_index = add nuw iN %index, 1
+ // br label %ReduceLoopCond
+ self.wip.cursor = .{ .block = body_block };
+ const elem = try self.wip.extractElement(operand_vector, index.toValue(), "");
+ const new_accum = try self.wip.call(
+ .normal,
+ .ccc,
+ .none,
+ llvm_fn.typeOf(&o.builder),
+ llvm_fn.toValue(&o.builder),
+ &.{ accum.toValue(), elem },
+ "",
+ );
+ const new_index = try self.wip.bin(.@"add nuw", index.toValue(), try o.builder.intValue(llvm_usize_ty, 1), "");
+ _ = try self.wip.br(cond_block);
- // accum = f(accum, vec[i]);
- const accum = try self.wip.load(.normal, llvm_result_ty, accum_ptr, .default, "");
- const element = try self.wip.extractElement(operand_vector, i, "");
- const new_accum = try self.wip.call(
- .normal,
- .ccc,
- .none,
- llvm_fn.typeOf(&o.builder),
- llvm_fn.toValue(&o.builder),
- &.{ accum, element },
- "",
- );
- _ = try self.wip.store(.normal, new_accum, accum_ptr, .default);
+ const index_init = try o.builder.intValue(llvm_usize_ty, 0);
+ index.finish(&.{ index_init, new_index }, &.{ entry_block, body_block }, &self.wip);
+ accum.finish(&.{ accum_init, new_accum }, &.{ entry_block, body_block }, &self.wip);
- // i += 1
- const new_i = try self.wip.bin(.add, i, try o.builder.intValue(usize_ty, 1), "");
- _ = try self.wip.store(.normal, new_i, i_ptr, .default);
- _ = try self.wip.br(loop);
- }
- }
-
- self.wip.cursor = .{ .block = loop_exit };
- return self.wip.load(.normal, llvm_result_ty, accum_ptr, .default, "");
+ self.wip.cursor = .{ .block = exit_block };
+ return accum.toValue();
}
fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value {
@@ -5772,9 +5831,9 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A
const reduce = self.air.instructions.items(.data)[@intFromEnum(inst)].reduce;
const operand = try self.resolveInst(reduce.operand);
const operand_ty = self.typeOf(reduce.operand);
- const llvm_operand_ty = try o.lowerType(operand_ty);
+ const llvm_operand_ty = try o.lowerType(operand_ty, .by_value);
const scalar_ty = self.typeOfIndex(inst);
- const llvm_scalar_ty = try o.lowerType(scalar_ty);
+ const llvm_scalar_ty = try o.lowerType(scalar_ty, .by_value);
switch (reduce.operation) {
.And, .Or, .Xor => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) {
@@ -5881,10 +5940,10 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
const result_ty = self.typeOfIndex(inst);
const len: usize = @intCast(result_ty.arrayLen(zcu));
const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[ty_pl.payload..][0..len]);
- const llvm_result_ty = try o.lowerType(result_ty);
switch (result_ty.zigTypeTag(zcu)) {
.vector => {
+ const llvm_result_ty = try o.lowerType(result_ty, .by_value);
var vector = try o.builder.poisonValue(llvm_result_ty);
for (elements, 0..) |elem, i| {
const index_u32 = try o.builder.intValue(.i32, i);
@@ -5926,7 +5985,7 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
// TODO in debug builds init to undef so that the padding will be 0xaa
// even if we fully populate the fields.
const struct_align = result_ty.abiAlignment(zcu);
- const alloca_inst = try self.buildAlloca(llvm_result_ty, struct_align.toLlvm());
+ const alloca_inst = try self.buildZigAlloca(result_ty, .none);
for (elements, 0..) |elem, field_index| {
if (result_ty.structFieldIsComptime(field_index, zcu)) continue;
@@ -5938,24 +5997,7 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
const llvm_field_val = try self.resolveInst(elem);
- if (isByRef(field_ty, zcu)) {
- _ = try self.wip.callMemCpy(
- field_ptr,
- field_ptr_align.toLlvm(),
- llvm_field_val,
- field_ty.abiAlignment(zcu).toLlvm(),
- try o.builder.intValue(try o.lowerType(.usize), field_ty.abiSize(zcu)),
- .normal,
- self.disable_intrinsics,
- );
- } else {
- _ = try self.wip.store(
- .normal,
- llvm_field_val,
- field_ptr,
- field_ptr_align.toLlvm(),
- );
- }
+ try self.store(field_ptr, field_ptr_align, llvm_field_val, field_ty, .normal);
}
return alloca_inst;
@@ -5964,8 +6006,7 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
.array => {
assert(isByRef(result_ty, zcu));
- const alignment = result_ty.abiAlignment(zcu).toLlvm();
- const alloca_inst = try self.buildAlloca(llvm_result_ty, alignment);
+ const alloca_inst = try self.buildZigAlloca(result_ty, .none);
const array_info = result_ty.arrayInfo(zcu);
@@ -5974,12 +6015,12 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
for (elements, 0..) |elem, i| {
const elem_ptr = try self.ptraddConst(alloca_inst, elem_size * i);
const llvm_elem = try self.resolveInst(elem);
- try self.store(elem_ptr, .none, llvm_elem, array_info.elem_type);
+ try self.store(elem_ptr, .none, llvm_elem, array_info.elem_type, .normal);
}
if (array_info.sentinel) |sent_val| {
const elem_ptr = try self.ptraddConst(alloca_inst, elem_size * array_info.len);
const llvm_elem = try self.resolveValue(sent_val);
- try self.store(elem_ptr, .none, llvm_elem.toValue(), array_info.elem_type);
+ try self.store(elem_ptr, .none, llvm_elem.toValue(), array_info.elem_type, .normal);
}
return alloca_inst;
@@ -5995,7 +6036,6 @@ fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
const union_ty = self.typeOfIndex(inst);
- const union_llvm_ty = try o.lowerType(union_ty);
const union_obj = zcu.typeToUnion(union_ty).?;
assert(union_obj.layout != .@"packed");
@@ -6005,28 +6045,28 @@ fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va
assert(layout.payload_size != 0); // otherwise the value would be comptime-known
assert(isByRef(union_ty, zcu));
- const alignment = layout.abi_align.toLlvm();
- const result_ptr = try self.buildAlloca(union_llvm_ty, alignment);
+ const result_ptr = try self.buildZigAlloca(union_ty, layout.abi_align);
const llvm_payload = try self.resolveInst(extra.init);
const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]);
assert(field_ty.hasRuntimeBits(zcu));
{
const payload_ptr = try self.ptraddConst(result_ptr, layout.payloadOffset());
- try self.store(payload_ptr, layout.payload_align, llvm_payload, field_ty);
+ try self.store(payload_ptr, layout.payload_align, llvm_payload, field_ty, .normal);
}
if (layout.tag_size != 0) {
- const loaded_enum = ip.loadEnumType(union_obj.enum_tag_type);
+ const tag_ty: Type = .fromInterned(union_obj.enum_tag_type);
+ const loaded_enum = ip.loadEnumType(tag_ty.toIntern());
const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, extra.field_index)) {
.none => try o.builder.intConst(
- try o.lowerType(.fromInterned(union_obj.enum_tag_type)),
+ try o.lowerType(.fromInterned(union_obj.enum_tag_type), .by_value),
extra.field_index, // auto-numbered
),
- else => |tag_val_ip| try o.lowerValue(tag_val_ip),
+ else => |tag_val_ip| try o.lowerValue(tag_val_ip, .by_value),
};
const tag_ptr = try self.ptraddConst(result_ptr, layout.tagOffset());
- _ = try self.wip.store(.normal, llvm_tag_val.toValue(), tag_ptr, layout.tag_align.toLlvm());
+ try self.store(tag_ptr, layout.tag_align, llvm_tag_val.toValue(), tag_ty, .normal);
}
return result_ptr;
@@ -6085,7 +6125,7 @@ fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const inst_ty = self.typeOfIndex(inst);
const operand = try self.resolveInst(ty_op.operand);
- return self.wip.cast(.addrspacecast, operand, try self.object.lowerType(inst_ty), "");
+ return self.wip.cast(.addrspacecast, operand, try self.object.lowerType(inst_ty, .by_value), "");
}
fn workIntrinsic(
@@ -6133,7 +6173,7 @@ fn airWorkGroupSize(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde
// Load the work_group_* member from the struct as u16.
// Just treat the dispatch pointer as an array of u16 to keep things simple.
const workgroup_size_ptr = try self.ptraddConst(dispatch_ptr, (2 + dimension) * 2);
- return self.wip.load(.normal, .i16, workgroup_size_ptr, comptime .fromByteUnits(2), "");
+ return self.load(workgroup_size_ptr, .@"2", .u16, .normal);
},
.nvptx, .nvptx64 => {
return self.workIntrinsic(dimension, 1, "nvvm.read.ptx.sreg.ntid");
@@ -6168,8 +6208,8 @@ fn optCmpNull(
comptime assert(optional_layout_version == 3);
// Non-null bit is always after the payload, with no padding because it has alignment 1.
const non_null_ptr = try self.ptraddConst(opt_ptr, opt_ty.optionalChild(zcu).abiSize(zcu));
- const non_null = try self.wip.load(access_kind, .i8, non_null_ptr, .default, "");
- return self.wip.icmp(cond, non_null, try self.object.builder.intValue(.i8, 0), "");
+ const non_null = try self.load(non_null_ptr, .@"1", .bool, access_kind);
+ return self.wip.icmp(cond, non_null, .false, "");
}
/// Assumes that `Type.optionalReprIsPayload` is `false` for `opt_ty` and that the payload has bits.
@@ -6186,13 +6226,9 @@ fn optPayloadHandle(
// Payload is first field so always at the same address as the optional itself.
const payload_ptr = opt_ptr;
- const payload_align = payload_ty.abiAlignment(zcu).toLlvm();
- if (isByRef(payload_ty, zcu)) {
- if (can_elide_load) return payload_ptr;
- return fg.loadByRef(payload_ptr, payload_ty, payload_align, .normal);
- } else {
- return fg.loadTruncate(.normal, payload_ty, payload_ptr, payload_align);
- }
+ if (can_elide_load and isByRef(payload_ty, zcu)) return payload_ptr;
+
+ return fg.load(payload_ptr, .none, payload_ty, .normal);
}
fn fieldPtr(
@@ -6216,220 +6252,156 @@ fn fieldPtr(
return self.ptraddConst(aggregate_ptr, offset);
}
-/// Load a value and, if needed, mask out padding bits for non byte-sized integer values.
-fn loadTruncate(
- fg: *FuncGen,
- access_kind: Builder.MemoryAccessKind,
- payload_ty: Type,
- payload_ptr: Builder.Value,
- payload_alignment: Builder.Alignment,
-) Allocator.Error!Builder.Value {
- // from https://llvm.org/docs/LangRef.html#load-instruction :
- // "When loading a value of a type like i20 with a size that is not an integral number of bytes, the result is undefined if the value was not originally written using a store of the same type. "
- // => so load the byte aligned value and trunc the unwanted bits.
-
- const o = fg.object;
- const zcu = o.zcu;
- const payload_llvm_ty = try o.lowerType(payload_ty);
- const abi_size = payload_ty.abiSize(zcu);
-
- const load_llvm_ty = if (payload_ty.isAbiInt(zcu))
- try o.builder.intType(@intCast(abi_size * 8))
- else
- payload_llvm_ty;
- const loaded = try fg.wip.load(access_kind, load_llvm_ty, payload_ptr, payload_alignment, "");
- const shifted = if (payload_llvm_ty != load_llvm_ty and zcu.getTarget().cpu.arch.endian() == .big)
- try fg.wip.bin(.lshr, loaded, try o.builder.intValue(
- load_llvm_ty,
- (payload_ty.abiSize(zcu) - (std.math.divCeil(u64, payload_ty.bitSize(zcu), 8) catch unreachable)) * 8,
- ), "")
- else
- loaded;
-
- return fg.wip.conv(.unneeded, shifted, payload_llvm_ty, "");
-}
-
-/// Load a by-ref type by constructing a new alloca and performing a memcpy.
-fn loadByRef(
- fg: *FuncGen,
- ptr: Builder.Value,
- pointee_type: Type,
- ptr_alignment: Builder.Alignment,
- access_kind: Builder.MemoryAccessKind,
-) Allocator.Error!Builder.Value {
- const o = fg.object;
- const pointee_llvm_ty = try o.lowerType(pointee_type);
- const result_align = InternPool.Alignment.fromLlvm(ptr_alignment)
- .max(pointee_type.abiAlignment(o.zcu)).toLlvm();
- const result_ptr = try fg.buildAlloca(pointee_llvm_ty, result_align);
- const size_bytes = pointee_type.abiSize(o.zcu);
- _ = try fg.wip.callMemCpy(
- result_ptr,
- result_align,
- ptr,
- ptr_alignment,
- try o.builder.intValue(try o.lowerType(.usize), size_bytes),
- access_kind,
- fg.disable_intrinsics,
- );
- return result_ptr;
-}
-
-/// If `isByRef` returns `true` for `elem_ty`, this still performs a copy by memcpy'ing the value
-/// into a new alloca.
+/// Non-atomic, non-bitpacked load of type `load_ty` from pointer `ptr`.
+///
+/// `ptr` has alignment `ptr_align`, or `load_ty.abiAlignment(zcu)` if `ptr_align` is `.none`.
+///
+/// If `load_ty` is a by-ref type, then the value is copied to a new alloca with a memcpy, and a
+/// pointer to that alloca is returned.
fn load(
fg: *FuncGen,
ptr: Builder.Value,
- elem_ty: Type,
- ptr_alignment: Builder.Alignment,
+ ptr_align: InternPool.Alignment,
+ load_ty: Type,
access_kind: Builder.MemoryAccessKind,
) Allocator.Error!Builder.Value {
- const zcu = fg.object.zcu;
- if (isByRef(elem_ty, zcu)) {
- return fg.loadByRef(ptr, elem_ty, ptr_alignment, access_kind);
- } else {
- return fg.loadTruncate(access_kind, elem_ty, ptr, ptr_alignment);
- }
-}
-
-fn storeFull(
- self: *FuncGen,
- ptr: Builder.Value,
- ptr_ty: Type,
- elem: Builder.Value,
- ordering: Builder.AtomicOrdering,
-) Allocator.Error!void {
- const o = self.object;
+ const o = fg.object;
const zcu = o.zcu;
- const info = ptr_ty.ptrInfo(zcu);
- const elem_ty = Type.fromInterned(info.child);
- if (!elem_ty.hasRuntimeBits(zcu)) {
- return;
- }
- const ptr_alignment = ptr_ty.ptrAlignment(zcu).toLlvm();
- const access_kind: Builder.MemoryAccessKind =
- if (info.flags.is_volatile) .@"volatile" else .normal;
- if (info.flags.vector_index != .none) {
- const index_u32 = try o.builder.intValue(.i32, info.flags.vector_index);
- const vec_elem_ty = try o.lowerType(elem_ty);
- const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty);
+ const abi_align = load_ty.abiAlignment(zcu);
+ const abi_size = load_ty.abiSize(zcu);
- const loaded_vector = try self.wip.load(.normal, vec_ty, ptr, ptr_alignment, "");
+ const llvm_ptr_align: Builder.Alignment = switch (ptr_align) {
+ .none => abi_align.toLlvm(),
+ else => |a| a.toLlvm(),
+ };
- const modified_vector = try self.wip.insertElement(loaded_vector, elem, index_u32, "");
-
- assert(ordering == .none);
- _ = try self.wip.store(access_kind, modified_vector, ptr, ptr_alignment);
- return;
- }
-
- if (info.packed_offset.host_size != 0) {
- const containing_int_ty = try o.builder.intType(@intCast(info.packed_offset.host_size * 8));
- assert(ordering == .none);
- const containing_int =
- try self.wip.load(.normal, containing_int_ty, ptr, ptr_alignment, "");
- const elem_bits = ptr_ty.childType(zcu).bitSize(zcu);
- const shift_amt = try o.builder.intConst(containing_int_ty, info.packed_offset.bit_offset);
- // Convert to equally-sized integer type in order to perform the bit
- // operations on the value to store
- const value_bits_type = try o.builder.intType(@intCast(elem_bits));
- const value_bits = if (elem_ty.isPtrAtRuntime(zcu))
- try self.wip.cast(.ptrtoint, elem, value_bits_type, "")
- else
- try self.wip.cast(.bitcast, elem, value_bits_type, "");
-
- const mask_val = blk: {
- const zext = try self.wip.cast(
- .zext,
- try o.builder.intValue(value_bits_type, -1),
- containing_int_ty,
- "",
- );
- const shl = try self.wip.bin(.shl, zext, shift_amt.toValue(), "");
- break :blk try self.wip.bin(
- .xor,
- shl,
- try o.builder.intValue(containing_int_ty, -1),
- "",
- );
- };
-
- const anded_containing_int = try self.wip.bin(.@"and", containing_int, mask_val, "");
- const extended_value = try self.wip.cast(.zext, value_bits, containing_int_ty, "");
- const shifted_value = try self.wip.bin(.shl, extended_value, shift_amt.toValue(), "");
- const ored_value = try self.wip.bin(.@"or", shifted_value, anded_containing_int, "");
-
- assert(ordering == .none);
- _ = try self.wip.store(access_kind, ored_value, ptr, ptr_alignment);
- return;
- }
- if (!isByRef(elem_ty, zcu)) {
- _ = try self.wip.storeAtomic(
- access_kind,
- elem,
+ if (isByRef(load_ty, zcu)) {
+ const llvm_usize_ty = try o.lowerType(.usize, .by_value);
+ const result_ptr = try fg.buildZigAlloca(load_ty, .none);
+ _ = try fg.wip.callMemCpy(
+ result_ptr,
+ abi_align.toLlvm(),
ptr,
- self.sync_scope,
- ordering,
- ptr_alignment,
+ llvm_ptr_align,
+ try o.builder.intValue(llvm_usize_ty, abi_size),
+ access_kind,
+ fg.disable_intrinsics,
);
- return;
+ return result_ptr;
}
- assert(ordering == .none);
- _ = try self.wip.callMemCpy(
- ptr,
- ptr_alignment,
- elem,
- elem_ty.abiAlignment(zcu).toLlvm(),
- try o.builder.intValue(try o.lowerType(.usize), elem_ty.abiSize(zcu)),
- access_kind,
- self.disable_intrinsics,
- );
+
+ const llvm_memory_ty = try o.lowerType(load_ty, .in_memory);
+ const llvm_value_ty = try o.lowerType(load_ty, .by_value);
+
+ if (llvm_memory_ty != llvm_value_ty) {
+ assert(load_ty.isAbiInt(zcu));
+ // `load_ty` is an integer type with padding bits. In theory, we shouldn't need any special
+ // handling for these, as LLVM's documented semantics are a valid implementation of Zig's
+ // semantics. However:
+ //
+ // * LLVM's lowering for these integer types generally leads to poor codegen, as integers
+ // are only extended to the next byte, instead of to the next "natural" integer type.
+ //
+ // * Clang never emits loads or stores of these types, so LLVM's support for them is rather
+ // flaky---we have encountered several LLVM bugs caused by incorrect handling of them.
+ //
+ // Therefore, we handle these memory accesses specially: in this case we will actually load
+ // the next-largest "natural" integer type and then truncate to `load_ty`.
+ const loaded = try fg.wip.load(access_kind, llvm_memory_ty, ptr, llvm_ptr_align, "");
+ // For packed structs, current Zig semantics don't really allow us to make the padding bits
+ // well-defined. This should be solved once https://github.com/ziglang/zig/issues/24061 is
+ // implemented, but until then, do a normal trunc for packed types.
+ return fg.wip.cast(switch (load_ty.zigTypeTag(zcu)) {
+ .@"struct", .@"union" => .trunc,
+ else => switch (load_ty.intInfo(zcu).signedness) {
+ .unsigned => .@"trunc nuw",
+ .signed => .@"trunc nsw",
+ },
+ }, loaded, llvm_value_ty, "");
+ }
+
+ // `load_ty` is a simple by-val type which requires no special handling.
+ return fg.wip.load(access_kind, llvm_value_ty, ptr, llvm_ptr_align, "");
}
-/// Non-atomic, non-volatile, non-packed store.
+/// Non-atomic, non-bitpacked store of `elem` to pointer `ptr`.
+///
+/// `ptr` has alignment `ptr_align`, or `elem_ty.abiAlignment(zcu)` if `ptr_align` is `.none`.
+///
+/// If `elem_ty` is a by-ref type, then `elem` is itself a pointer, and a memcpy is emitted.
fn store(
fg: *FuncGen,
ptr: Builder.Value,
ptr_align: InternPool.Alignment,
elem: Builder.Value,
elem_ty: Type,
+ access_kind: Builder.MemoryAccessKind,
) Allocator.Error!void {
const o = fg.object;
const zcu = o.zcu;
+
+ const abi_align = elem_ty.abiAlignment(zcu);
+ const abi_size = elem_ty.abiSize(zcu);
+
const llvm_ptr_align = switch (ptr_align) {
- .none => elem_ty.abiAlignment(zcu).toLlvm(),
+ .none => abi_align.toLlvm(),
else => ptr_align.toLlvm(),
};
+
if (isByRef(elem_ty, zcu)) {
+ const llvm_usize_ty = try o.lowerType(.usize, .by_value);
_ = try fg.wip.callMemCpy(
ptr,
llvm_ptr_align,
elem,
- elem_ty.abiAlignment(zcu).toLlvm(),
- try o.builder.intValue(
- try o.lowerType(.usize),
- elem_ty.abiSize(zcu),
- ),
- .normal,
+ abi_align.toLlvm(),
+ try o.builder.intValue(llvm_usize_ty, abi_size),
+ access_kind,
fg.disable_intrinsics,
);
- } else {
+ return;
+ }
+
+ assert(elem.typeOfWip(&fg.wip) == try o.lowerType(elem_ty, .by_value));
+
+ const llvm_memory_ty = try o.lowerType(elem_ty, .in_memory);
+ const llvm_value_ty = try o.lowerType(elem_ty, .by_value);
+
+ if (llvm_memory_ty != llvm_value_ty) {
+ assert(elem_ty.isAbiInt(zcu));
+ // `elem_ty` is an integer type with padding bits, so we need to handle it specially---see
+ // the corresponding comment in `FuncGen.load` for more details.
+ const extended = try fg.wip.cast(switch (elem_ty.intInfo(zcu).signedness) {
+ .unsigned => .zext,
+ .signed => .sext,
+ }, elem, llvm_memory_ty, "");
_ = try fg.wip.storeAtomic(
- .normal,
- elem,
+ access_kind,
+ extended,
ptr,
fg.sync_scope,
.none,
llvm_ptr_align,
);
+ return;
}
+
+ // `elem_ty` is a simple by-val type which requires no special handling.
+ _ = try fg.wip.storeAtomic(
+ access_kind,
+ elem,
+ ptr,
+ fg.sync_scope,
+ .none,
+ llvm_ptr_align,
+ );
}
fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void {
const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545;
const o = fg.object;
- const usize_ty = try o.lowerType(.usize);
+ const usize_ty = try o.lowerType(.usize, .by_value);
const zero = try o.builder.intValue(usize_ty, 0);
const req = try o.builder.intValue(usize_ty, VG_USERREQ__MAKE_MEM_UNDEFINED);
const ptr_as_usize = try fg.wip.cast(.ptrtoint, ptr, usize_ty, "");
@@ -6451,19 +6423,19 @@ fn valgrindClientRequest(
const target = zcu.getTarget();
if (!target_util.hasValgrindSupport(target, .stage2_llvm)) return default_value;
- const llvm_usize = try o.lowerType(.usize);
- const usize_alignment = Type.usize.abiAlignment(zcu).toLlvm();
+ const llvm_usize = try o.lowerType(.usize, .by_value);
+ const usize_align = Type.usize.abiAlignment(zcu).toLlvm();
const array_llvm_ty = try o.builder.arrayType(6, llvm_usize);
const array_ptr = if (fg.valgrind_client_request_array == .none) a: {
- const array_ptr = try fg.buildAlloca(array_llvm_ty, usize_alignment);
+ const array_ptr = try fg.buildAlloca(array_llvm_ty, usize_align);
fg.valgrind_client_request_array = array_ptr;
break :a array_ptr;
} else fg.valgrind_client_request_array;
const array_elements = [_]Builder.Value{ request, a1, a2, a3, a4, a5 };
for (array_elements, 0..) |elem, i| {
const elem_ptr = try fg.ptraddConst(array_ptr, i * Type.usize.abiSize(zcu));
- _ = try fg.wip.store(.normal, elem, elem_ptr, usize_alignment);
+ try fg.store(elem_ptr, .none, elem, .usize, .normal);
}
const arch_specific: struct {
@@ -6662,7 +6634,7 @@ const ParamTypeIterator = struct {
.async => {
@panic("TODO implement async function lowering in the LLVM backend");
},
- .x86_64_sysv => return it.nextSystemV(ty),
+ .x86_64_sysv, .x86_64_x32 => return it.nextSystemV(ty),
.x86_64_win => return it.nextWin64(ty),
.x86_stdcall => {
it.zig_index += 1;
@@ -6733,7 +6705,7 @@ const ParamTypeIterator = struct {
while (field_it.next()) |field_index| {
const field_ty = ty.fieldType(field_index, zcu);
if (!field_ty.hasRuntimeBits(zcu)) continue;
- it.types_buffer[it.types_len] = try it.object.lowerType(field_ty);
+ it.types_buffer[it.types_len] = try it.object.lowerType(field_ty, .by_value);
it.offsets_buffer[it.types_len] = ty.structFieldOffset(field_index, zcu);
it.types_len += 1;
}
@@ -6750,7 +6722,7 @@ const ParamTypeIterator = struct {
it.llvm_index += 1;
return .byval;
} else {
- it.types_buffer[0..1].* = .{try it.object.lowerType(scalar_ty)};
+ it.types_buffer[0..1].* = .{try it.object.lowerType(scalar_ty, .by_value)};
it.offsets_buffer[0..2].* = .{ 0, scalar_ty.abiSize(zcu) };
it.types_len = 1;
it.llvm_index += 1;
@@ -6788,22 +6760,30 @@ const ParamTypeIterator = struct {
return .abi_sized_int;
}
},
- .win_i128 => {
+ .sse,
+ .bool_vector_mask,
+ .integer_per_element,
+ .sse_per_element,
+ .sse_sse_x87_per_qword,
+ .sse_per_xword,
+ .sse_per_yword,
+ .sse_per_zword,
+ => {
it.zig_index += 1;
it.llvm_index += 1;
- return .byref;
+ return .byval;
},
+ .sseup, .x87, .x87up, .none, .float, .float_combine => unreachable,
.memory => {
it.zig_index += 1;
it.llvm_index += 1;
return .byref_mut;
},
- .sse => {
+ .win_i128 => {
it.zig_index += 1;
it.llvm_index += 1;
- return .byval;
+ return .byref;
},
- else => unreachable,
}
}
@@ -6866,9 +6846,14 @@ const ParamTypeIterator = struct {
.none => break,
.memory => unreachable, // handled above
.win_i128 => unreachable, // windows only
- .integer_per_element => {
- @panic("TODO");
- },
+ .bool_vector_mask,
+ .integer_per_element,
+ .sse_per_element,
+ .sse_sse_x87_per_qword,
+ .sse_per_xword,
+ .sse_per_yword,
+ .sse_per_zword,
+ => unreachable, // vectors already handled by `isScalar` above
}
offset += 8;
}
@@ -6911,159 +6896,176 @@ pub fn iterateParamTypes(object: *Object, fn_info: InternPool.Key.FuncType) Para
.fn_info = fn_info,
.zig_index = 0,
.llvm_index = 0,
- .types_len = 0,
+ .types_len = undefined,
.types_buffer = undefined,
.offsets_buffer = undefined,
.byval_attr = false,
};
}
-fn returnTypeByRef(zcu: *Zcu, target: *const std.Target, ty: Type) bool {
- if (isByRef(ty, zcu)) {
- return true;
- } else if (target.cpu.arch.isX86() and
- !target.cpu.has(.x86, .avx512f) and
- ty.totalVectorBits(zcu) >= 512)
- {
- // As of LLVM 18, passing a vector byval with fastcc that is 512 bits or more returns
- // "512-bit vector arguments require 'avx512f' for AVX512"
- return true;
- } else {
- return false;
+pub const FnReturnStrat = union(enum) {
+ /// The function return type is OPV (zero-bit), so the LLVM function return type is `void`.
+ void,
+ /// An sret parameter is used. The LLVM function return type is `void`.
+ sret,
+ /// The function's return type directly corresponds to the LLVM function return type.
+ ///
+ /// The return type is by-val, i.e. `isByRef` returns `false`.
+ by_val,
+ /// The LLVM function returns the given `Builder.Type` by reinterpreting memory containing the
+ /// actual return value. The actual return type may be by-val or by-ref.
+ mem_cast: Builder.Type,
+
+ fn forceByVal(o: *Object, ret_ty: Type) Allocator.Error!FnReturnStrat {
+ if (!isByRef(ret_ty, o.zcu)) return .by_val;
+ return .{ .mem_cast = try o.lowerType(ret_ty, .in_memory) };
}
-}
-
-pub fn firstParamSRet(fn_info: InternPool.Key.FuncType, zcu: *Zcu, target: *const std.Target) bool {
- const return_type = Type.fromInterned(fn_info.return_type);
- if (!return_type.hasRuntimeBits(zcu)) return false;
-
- return switch (fn_info.cc) {
- .auto => returnTypeByRef(zcu, target, return_type),
- .x86_64_sysv => firstParamSRetSystemV(return_type, zcu, target),
- .x86_64_win => x86_64_abi.classifyWindows(return_type, zcu, target, .ret) == .memory,
- .x86_sysv, .x86_win => isByRef(return_type, zcu),
- .x86_stdcall => !isScalar(zcu, return_type),
- .wasm_mvp => wasm_c_abi.classifyType(return_type, zcu) == .indirect,
- .aarch64_aapcs,
- .aarch64_aapcs_darwin,
- .aarch64_aapcs_win,
- => aarch64_c_abi.classifyType(return_type, zcu) == .memory,
- .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) {
- .memory, .i64_array => true,
- .i32_array => |size| size != 1,
- .byval => false,
- },
- .riscv64_lp64, .riscv32_ilp32 => riscv_c_abi.classifyType(return_type, zcu) == .memory,
- .mips_o32 => switch (mips_c_abi.classifyType(return_type, zcu, .ret)) {
- .memory, .i32_array => true,
- .byval => false,
- },
- else => false, // TODO: investigate other targets/callconvs
- };
-}
-
-fn firstParamSRetSystemV(ty: Type, zcu: *Zcu, target: *const std.Target) bool {
- const class = x86_64_abi.classifySystemV(ty, zcu, target, .ret);
- if (class[0] == .memory) return true;
- if (class[0] == .x87 and class[2] != .none) return true;
- return false;
-}
-
+};
/// In order to support the C calling convention, some return types need to be lowered
/// completely differently in the function prototype to honor the C ABI, and then
/// be effectively bitcasted to the actual return type.
-pub fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {
+pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat {
const zcu = o.zcu;
- const return_type = Type.fromInterned(fn_info.return_type);
- if (!return_type.hasRuntimeBits(zcu)) {
- assert(!return_type.isError(zcu));
- return .void;
- }
- const target = zcu.getTarget();
+ const ret_ty: Type = .fromInterned(fn_info.return_type);
+ ret_ty.assertHasLayout(zcu);
+ if (!ret_ty.hasRuntimeBits(zcu)) return .void;
switch (fn_info.cc) {
.@"inline" => unreachable,
- .auto => return if (returnTypeByRef(zcu, target, return_type)) .void else o.lowerType(return_type),
+ .auto => {
+ if (isByRef(ret_ty, zcu)) return .sret;
- .x86_64_sysv => return lowerSystemVFnRetTy(o, fn_info),
+ const target = zcu.getTarget();
+ if (target.cpu.arch.isX86() and
+ !target.cpu.has(.x86, .avx512f) and
+ ret_ty.totalVectorBits(zcu) >= 512)
+ {
+ // As of LLVM 18, passing a vector byval with fastcc that is 512 bits or more returns
+ // "512-bit vector arguments require 'avx512f' for AVX512"
+ return .sret;
+ }
+
+ return .by_val;
+ },
+ .x86_64_sysv, .x86_64_x32 => return lowerSystemVFnRetTy(o, fn_info),
.x86_64_win => return lowerWin64FnRetTy(o, fn_info),
- .x86_stdcall => return if (isScalar(zcu, return_type)) o.lowerType(return_type) else .void,
- .x86_sysv, .x86_win => return if (isByRef(return_type, zcu)) .void else o.lowerType(return_type),
- .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => switch (aarch64_c_abi.classifyType(return_type, zcu)) {
- .memory => return .void,
- .float_array => return o.lowerType(return_type),
- .byval => return o.lowerType(return_type),
- .integer => return .i64,
- .double_integer => return o.builder.arrayType(2, .i64),
+ .x86_stdcall => if (isScalar(zcu, ret_ty)) {
+ assert(!isByRef(ret_ty, zcu));
+ return .by_val;
+ } else return .sret,
+ .x86_fastcall => return lowerX86FastcallFnRetTy(o, zcu, ret_ty),
+ .x86_sysv, .x86_win => return if (isByRef(ret_ty, zcu)) .sret else .by_val,
+ .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => switch (aarch64_c_abi.classifyType(ret_ty, zcu)) {
+ .memory => return .sret,
+ .float_array, .byval => return .forceByVal(o, ret_ty),
+ .integer => return .{ .mem_cast = .i64 },
+ .double_integer => return .{ .mem_cast = try o.builder.arrayType(2, .i64) },
},
- .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) {
- .memory, .i64_array => return .void,
- .i32_array => |len| return if (len == 1) .i32 else .void,
- .byval => return o.lowerType(return_type),
+ .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(ret_ty, zcu, .ret)) {
+ .memory, .i64_array => return .sret,
+ .i32_array => |len| return if (len == 1) .{ .mem_cast = .i32 } else .sret,
+ .byval => return .forceByVal(o, ret_ty),
},
- .mips_o32 => switch (mips_c_abi.classifyType(return_type, zcu, .ret)) {
- .memory, .i32_array => return .void,
- .byval => return o.lowerType(return_type),
+ .mips_o32 => switch (mips_c_abi.classifyType(ret_ty, zcu, .ret)) {
+ .memory, .i32_array => return .sret,
+ .byval => return .forceByVal(o, ret_ty),
},
- .riscv64_lp64, .riscv32_ilp32 => switch (riscv_c_abi.classifyType(return_type, zcu)) {
- .memory => return .void,
- .integer => return o.builder.intType(@intCast(return_type.bitSize(zcu))),
+ .riscv64_lp64, .riscv32_ilp32 => switch (riscv_c_abi.classifyType(ret_ty, zcu)) {
+ .memory => return .sret,
+ .integer => return .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) },
.double_integer => {
const integer: Builder.Type = switch (zcu.getTarget().cpu.arch) {
.riscv64, .riscv64be => .i64,
.riscv32, .riscv32be => .i32,
else => unreachable,
};
- return o.builder.structType(.normal, &.{ integer, integer });
+ return .{ .mem_cast = try o.builder.structType(.normal, &.{ integer, integer }) };
},
- .byval => return o.lowerType(return_type),
+ .byval => return .forceByVal(o, ret_ty),
.fields => {
var types_len: usize = 0;
var types: [8]Builder.Type = undefined;
- for (0..return_type.structFieldCount(zcu)) |field_index| {
- const field_ty = return_type.fieldType(field_index, zcu);
+ for (0..ret_ty.structFieldCount(zcu)) |field_index| {
+ const field_ty = ret_ty.fieldType(field_index, zcu);
if (!field_ty.hasRuntimeBits(zcu)) continue;
- types[types_len] = try o.lowerType(field_ty);
+ types[types_len] = try o.lowerType(field_ty, .by_value);
types_len += 1;
}
- return o.builder.structType(.normal, types[0..types_len]);
+ return .{ .mem_cast = try o.builder.structType(.normal, types[0..types_len]) };
},
},
- .wasm_mvp => switch (wasm_c_abi.classifyType(return_type, zcu)) {
- .direct => |scalar_ty| return o.lowerType(scalar_ty),
- .indirect => return .void,
+ .wasm_mvp => switch (wasm_c_abi.classifyType(ret_ty, zcu)) {
+ .direct => |scalar_ty| if (scalar_ty.toIntern() == ret_ty.toIntern()) {
+ assert(!isByRef(ret_ty, zcu));
+ return .by_val;
+ } else {
+ return .{ .mem_cast = try o.lowerType(scalar_ty, .by_value) };
+ },
+ .indirect => return .sret,
},
// TODO investigate other callconvs
- else => return o.lowerType(return_type),
+ else => return .forceByVal(o, ret_ty),
}
}
-fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {
+fn lowerX86FastcallFnRetTy(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnReturnStrat {
+ if (isScalar(zcu, ty)) {
+ assert(!isByRef(ty, zcu));
+ return .by_val;
+ }
+ const tag = ty.zigTypeTag(zcu);
+ if (tag == .@"struct" or tag == .@"union") {
+ const size = ty.abiSize(zcu);
+ if (size == 1 or size == 2 or size == 4 or size == 8) {
+ return .{ .mem_cast = try o.builder.intType(@intCast(size * 8)) };
+ }
+ }
+ return .sret;
+}
+
+fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat {
const zcu = o.zcu;
- const return_type = Type.fromInterned(fn_info.return_type);
- switch (x86_64_abi.classifyWindows(return_type, zcu, zcu.getTarget(), .ret)) {
- .integer => {
- if (isScalar(zcu, return_type)) {
- return o.lowerType(return_type);
- } else {
- return o.builder.intType(@intCast(return_type.abiSize(zcu) * 8));
- }
+ const ret_ty = Type.fromInterned(fn_info.return_type);
+ switch (x86_64_abi.classifyWindows(ret_ty, zcu, zcu.getTarget(), .ret)) {
+ .integer => if (isScalar(zcu, ret_ty)) {
+ assert(!isByRef(ret_ty, zcu));
+ return .by_val;
+ } else {
+ return .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) };
},
- .win_i128 => return o.builder.vectorType(.normal, 2, .i64),
- .memory => return .void,
- .sse => return o.lowerType(return_type),
- else => unreachable,
+ .win_i128 => return .{ .mem_cast = try o.builder.vectorType(.normal, 2, .i64) },
+ .memory => return .sret,
+
+ .sse,
+ .bool_vector_mask,
+ .integer_per_element,
+ .sse_per_element,
+ .sse_sse_x87_per_qword,
+ .sse_per_xword,
+ .sse_per_yword,
+ .sse_per_zword,
+ => {
+ assert(!isByRef(ret_ty, zcu));
+ return .by_val;
+ },
+ .sseup,
+ .x87,
+ .x87up,
+ .none,
+ .float,
+ .float_combine,
+ => unreachable,
}
}
-fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {
+fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat {
const zcu = o.zcu;
const ip = &zcu.intern_pool;
- const return_type = Type.fromInterned(fn_info.return_type);
- return_type.assertHasLayout(zcu);
- if (isScalar(zcu, return_type)) {
- return o.lowerType(return_type);
+ const ret_ty = Type.fromInterned(fn_info.return_type);
+ if (isScalar(zcu, ret_ty)) {
+ assert(!isByRef(ret_ty, zcu));
+ return .by_val;
}
- const classes = x86_64_abi.classifySystemV(return_type, zcu, zcu.getTarget(), .ret);
+ const classes = x86_64_abi.classifySystemV(ret_ty, zcu, zcu.getTarget(), .ret);
var types_index: u32 = 0;
var types_buffer: [8]Builder.Type = undefined;
for (classes) |class| {
@@ -7093,22 +7095,30 @@ fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.E
types_index += 1;
},
.x87 => {
- if (types_index != 0 or classes[2] != .none) return .void;
+ if (types_index != 0 or classes[2] != .none) return .sret;
types_buffer[types_index] = .x86_fp80;
types_index += 1;
},
.x87up => continue,
.none => break,
- .memory, .integer_per_element => return .void,
+ .memory => return .sret,
.win_i128 => unreachable, // windows only
+ .bool_vector_mask,
+ .integer_per_element,
+ .sse_per_element,
+ .sse_sse_x87_per_qword,
+ .sse_per_xword,
+ .sse_per_yword,
+ .sse_per_zword,
+ => unreachable, // vectors already handled by `isScalar` above
}
}
const first_non_integer = std.mem.indexOfNone(x86_64_abi.Class, &classes, &.{.integer});
if (first_non_integer == null or classes[first_non_integer.?] == .none) {
assert(first_non_integer orelse classes.len == types_index);
- switch (ip.indexToKey(return_type.toIntern())) {
+ switch (ip.indexToKey(ret_ty.toIntern())) {
.struct_type => {
- const size = return_type.abiSize(zcu);
+ const size = ret_ty.abiSize(zcu);
assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index);
if (size % 8 > 0) {
types_buffer[types_index - 1] = try o.builder.intType(@intCast(size % 8 * 8));
@@ -7116,9 +7126,9 @@ fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.E
},
else => {},
}
- if (types_index == 1) return types_buffer[0];
+ if (types_index == 1) return .{ .mem_cast = types_buffer[0] };
}
- return o.builder.structType(.normal, types_buffer[0..types_index]);
+ return .{ .mem_cast = try o.builder.structType(.normal, types_buffer[0..types_index]) };
}
/// This function deliberately does not handle `_BitInt` because it typically
@@ -7217,33 +7227,6 @@ fn isScalar(zcu: *Zcu, ty: Type) bool {
};
}
-pub fn buildAllocaInner(
- wip: *Builder.WipFunction,
- llvm_ty: Builder.Type,
- alignment: Builder.Alignment,
- target: *const std.Target,
-) Allocator.Error!Builder.Value {
- const address_space = llvmAllocaAddressSpace(target);
-
- const alloca = blk: {
- const prev_cursor = wip.cursor;
- const prev_debug_location = wip.debug_location;
- defer {
- wip.cursor = prev_cursor;
- if (wip.cursor.block == .entry) wip.cursor.instruction += 1;
- wip.debug_location = prev_debug_location;
- }
-
- wip.cursor = .{ .block = .entry };
- wip.debug_location = .no_location;
- break :blk try wip.alloca(.normal, llvm_ty, .none, alignment, address_space, "");
- };
-
- // The pointer returned from this function should have the generic address space,
- // if this isn't the case then cast it to the generic address space.
- return wip.conv(.unneeded, alloca, .ptr, "");
-}
-
/// This is the one source of truth for whether a type is passed around as an LLVM pointer,
/// or as an LLVM value.
pub fn isByRef(ty: Type, zcu: *const Zcu) bool {
@@ -7255,6 +7238,7 @@ pub fn isByRef(ty: Type, zcu: *const Zcu) bool {
.undefined,
.null,
.@"opaque",
+ .spirv,
=> unreachable,
.noreturn,
@@ -7284,7 +7268,7 @@ pub fn isByRef(ty: Type, zcu: *const Zcu) bool {
},
.@"union" => switch (ty.containerLayout(zcu)) {
.@"packed" => false,
- else => ty.hasRuntimeBits(zcu) and !ty.unionHasAllZeroBitFieldTypes(zcu),
+ else => ty.hasRuntimeBits(zcu),
},
};
}
@@ -7313,7 +7297,11 @@ fn getAtomicAbiType(fg: *const FuncGen, ty: Type, is_rmw_xchg: bool) Allocator.E
}
fn ptraddConst(fg: *FuncGen, ptr: Builder.Value, offset: u64) Allocator.Error!Builder.Value {
- return fg.object.ptraddConst(&fg.wip, ptr, offset);
+ if (offset == 0) return ptr;
+ const o = fg.object;
+ const llvm_usize_ty = try o.lowerType(.usize, .by_value);
+ const offset_val = try o.builder.intValue(llvm_usize_ty, offset);
+ return fg.wip.gep(.inbounds, .i8, ptr, &.{offset_val}, "");
}
fn ptraddScaled(fg: *FuncGen, ptr: Builder.Value, index: Builder.Value, scale: u64) Allocator.Error!Builder.Value {
if (scale == 0) return ptr;
diff --git a/src/codegen/mips/abi.zig b/src/codegen/mips/abi.zig
index a27adb7ace40ff937a820a2e8bdfacea12f85d31..f512f1e6db98031dd581bc9cb19ef7be42b7ae29 100644
--- a/src/codegen/mips/abi.zig
+++ b/src/codegen/mips/abi.zig
@@ -18,24 +18,23 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
const max_direct_size = target.ptrBitWidth() * 2;
switch (ty.zigTypeTag(zcu)) {
.@"struct" => {
- const bit_size = ty.bitSize(zcu);
if (ty.containerLayout(zcu) == .@"packed") {
- if (bit_size > max_direct_size) return .memory;
+ if (ty.bitSize(zcu) > max_direct_size) return .memory;
return .byval;
}
+ const bit_size = ty.abiSize(zcu) * 8;
if (bit_size > max_direct_size) return .memory;
// TODO: for bit_size <= 32 using byval is more correct, but that needs inreg argument attribute
const count = @as(u8, @intCast(std.mem.alignForward(u64, bit_size, 32) / 32));
return .{ .i32_array = count };
},
.@"union" => {
- const bit_size = ty.bitSize(zcu);
if (ty.containerLayout(zcu) == .@"packed") {
- if (bit_size > max_direct_size) return .memory;
+ if (ty.bitSize(zcu) > max_direct_size) return .memory;
return .byval;
}
+ const bit_size = ty.abiSize(zcu) * 8;
if (bit_size > max_direct_size) return .memory;
-
return .byval;
},
.bool => return .byval,
@@ -77,6 +76,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
.null,
.@"fn",
.@"opaque",
+ .spirv,
.enum_literal,
.array,
=> unreachable,
diff --git a/src/codegen/riscv64/CodeGen.zig b/src/codegen/riscv64/CodeGen.zig
index 1c882c0270b3378a72508de2ab343a0e9d49d1d2..bbbe85884910a935e8b2501807993643030213f5 100644
--- a/src/codegen/riscv64/CodeGen.zig
+++ b/src/codegen/riscv64/CodeGen.zig
@@ -51,7 +51,7 @@ const InnerError = codegen.Error || error{OutOfRegisters};
pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
return comptime &.initMany(&.{
- .expand_intcast_safe,
+ .expand_int_cast_safe,
.expand_int_from_float_safe,
.expand_int_from_float_optimized_safe,
.expand_add_safe,
@@ -112,7 +112,7 @@ const_tracking: ConstTrackingMap = .{},
inst_tracking: InstTrackingMap = .{},
frame_allocs: std.MultiArrayList(FrameAlloc) = .{},
-free_frame_indices: std.AutoArrayHashMapUnmanaged(FrameIndex, void) = .empty,
+free_frame_indices: std.array_hash_map.Auto(FrameIndex, void) = .empty,
frame_locs: std.MultiArrayList(Mir.FrameLoc) = .{},
loops: std.AutoHashMapUnmanaged(Air.Inst.Index, struct {
@@ -338,7 +338,7 @@ const MCValue = union(enum) {
};
const Branch = struct {
- inst_table: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, MCValue) = .empty,
+ inst_table: std.array_hash_map.Auto(Air.Inst.Index, MCValue) = .empty,
fn deinit(func: *Branch, gpa: Allocator) void {
func.inst_table.deinit(gpa);
@@ -346,8 +346,8 @@ const Branch = struct {
}
};
-const InstTrackingMap = std.AutoArrayHashMapUnmanaged(Air.Inst.Index, InstTracking);
-const ConstTrackingMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, InstTracking);
+const InstTrackingMap = std.array_hash_map.Auto(Air.Inst.Index, InstTracking);
+const ConstTrackingMap = std.array_hash_map.Auto(InternPool.Index, InstTracking);
const InstTracking = struct {
long: MCValue,
@@ -1453,7 +1453,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
.add_safe,
.sub_safe,
.mul_safe,
- .intcast_safe,
+ .int_cast_safe,
.int_from_float_safe,
.int_from_float_optimized_safe,
=> return func.fail("TODO implement safety_checked_instructions", .{}),
@@ -1479,7 +1479,14 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
.ret_ptr => try func.airRetPtr(inst),
.arg => try func.airArg(inst),
.assembly => try func.airAsm(inst),
- .bitcast => try func.airBitCast(inst),
+ .bit_cast => try func.airBitCast(inst),
+ .ptr_cast => try func.airBitCast(inst),
+ .ptr_from_int => try func.airBitCast(inst),
+ .int_from_ptr => try func.airBitCast(inst),
+ .error_cast => try func.airBitCast(inst),
+ .error_from_int => try func.airBitCast(inst),
+ .int_from_error => try func.airBitCast(inst),
+ .union_from_enum => try func.airBitCast(inst),
.block => try func.airBlock(inst),
.br => try func.airBr(inst),
.repeat => try func.airRepeat(inst),
@@ -1493,7 +1500,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
.dbg_empty_stmt => func.finishAirBookkeeping(),
.fptrunc => try func.airFptrunc(inst),
.fpext => try func.airFpext(inst),
- .intcast => try func.airIntCast(inst),
+ .int_cast => try func.airIntCast(inst),
.trunc => try func.airTrunc(inst),
.is_non_null => try func.airIsNonNull(inst),
.is_non_null_ptr => try func.airIsNonNullPtr(inst),
@@ -1642,6 +1649,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
.work_item_id => unreachable,
.work_group_size => unreachable,
.work_group_id => unreachable,
+ .spirv_runtime_array_len => unreachable,
// zig fmt: on
}
@@ -3162,7 +3170,7 @@ fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
switch (lhs_ty.zigTypeTag(zcu)) {
else => |x| return func.fail("TODO: airMulWithOverflow {s}", .{@tagName(x)}),
.int => {
- if (std.debug.runtime_safety) assert(lhs_ty.eql(rhs_ty, zcu));
+ if (std.debug.runtime_safety) assert(lhs_ty.eql(rhs_ty));
const trunc_reg = try func.copyToTmpRegister(lhs_ty, .{ .register = dest_reg });
const trunc_reg_lock = func.register_manager.lockRegAssumeUnused(trunc_reg);
@@ -3952,9 +3960,7 @@ fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void {
const elem_ptr_ty = func.typeOfIndex(inst);
const base_ptr_ty = func.typeOf(extra.lhs);
- if (elem_ptr_ty.ptrInfo(zcu).flags.vector_index != .none) {
- @panic("audit");
- }
+ assert(elem_ptr_ty.ptrInfo(zcu).flags.vector_index == .none);
const base_ptr_mcv = try func.resolveInst(extra.lhs);
const base_ptr_lock: ?RegisterLock = switch (base_ptr_mcv) {
diff --git a/src/codegen/riscv64/abi.zig b/src/codegen/riscv64/abi.zig
index 7c00ba13a55f8d284bdb20104d5a78d0b5a86521..5c89a35f7bd4e718e8e032093856f6068b751c9b 100644
--- a/src/codegen/riscv64/abi.zig
+++ b/src/codegen/riscv64/abi.zig
@@ -16,9 +16,8 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {
const max_byval_size = target.ptrBitWidth() * 2;
switch (ty.zigTypeTag(zcu)) {
.@"struct" => {
- const bit_size = ty.bitSize(zcu);
if (ty.containerLayout(zcu) == .@"packed") {
- if (bit_size > max_byval_size) return .memory;
+ if (ty.bitSize(zcu) > max_byval_size) return .memory;
return .byval;
}
@@ -40,17 +39,18 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {
}
// TODO this doesn't exactly match what clang produces but its better than nothing
+ const bit_size = ty.abiSize(zcu) * 8;
if (bit_size > max_byval_size) return .memory;
if (bit_size > max_byval_size / 2) return .double_integer;
return .integer;
},
.@"union" => {
- const bit_size = ty.bitSize(zcu);
if (ty.containerLayout(zcu) == .@"packed") {
- if (bit_size > max_byval_size) return .memory;
+ if (ty.bitSize(zcu) > max_byval_size) return .memory;
return .byval;
}
// TODO this doesn't exactly match what clang produces but its better than nothing
+ const bit_size = ty.abiSize(zcu) * 8;
if (bit_size > max_byval_size) return .memory;
if (bit_size > max_byval_size / 2) return .double_integer;
return .integer;
@@ -87,6 +87,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {
.null,
.@"fn",
.@"opaque",
+ .spirv,
.enum_literal,
.array,
=> unreachable,
@@ -152,13 +153,12 @@ pub fn classifySystem(ty: Type, zcu: *Zcu) [8]SystemClass {
},
.error_union => {
const payload_ty = ty.errorUnionPayload(zcu);
- const payload_bits = payload_ty.bitSize(zcu);
// the error union itself
result[0] = .integer;
// anyerror!void can fit into one register
- if (payload_bits == 0) return result;
+ if (!payload_ty.hasRuntimeBits(zcu)) return result;
return memory_class;
},
diff --git a/src/codegen/sparc64/CodeGen.zig b/src/codegen/sparc64/CodeGen.zig
index 7ad950d22e2e628187a384b814735ea292b06009..32bfd50773ac78455aa52ef2fd250a7c55f68abd 100644
--- a/src/codegen/sparc64/CodeGen.zig
+++ b/src/codegen/sparc64/CodeGen.zig
@@ -200,7 +200,7 @@ const MCValue = union(enum) {
};
const Branch = struct {
- inst_table: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, MCValue) = .empty,
+ inst_table: std.array_hash_map.Auto(Air.Inst.Index, MCValue) = .empty,
fn deinit(self: *Branch, gpa: Allocator) void {
self.inst_table.deinit(gpa);
@@ -538,7 +538,14 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.ret_ptr => try self.airRetPtr(inst),
.arg => try self.airArg(inst),
.assembly => try self.airAsm(inst),
- .bitcast => try self.airBitCast(inst),
+ .bit_cast => try self.airBitCast(inst),
+ .ptr_cast => try self.airBitCast(inst),
+ .ptr_from_int => try self.airBitCast(inst),
+ .int_from_ptr => try self.airBitCast(inst),
+ .error_cast => try self.airBitCast(inst),
+ .error_from_int => try self.airBitCast(inst),
+ .int_from_error => try self.airBitCast(inst),
+ .union_from_enum => try self.airBitCast(inst),
.block => try self.airBlock(inst),
.br => try self.airBr(inst),
.repeat => return self.fail("TODO implement `repeat`", .{}),
@@ -550,7 +557,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.cond_br => try self.airCondBr(inst),
.fptrunc => @panic("TODO try self.airFptrunc(inst)"),
.fpext => @panic("TODO try self.airFpext(inst)"),
- .intcast => try self.airIntCast(inst),
+ .int_cast => try self.airIntCast(inst),
.trunc => try self.airTrunc(inst),
.is_non_null => try self.airIsNonNull(inst),
.is_non_null_ptr => @panic("TODO try self.airIsNonNullPtr(inst)"),
@@ -689,7 +696,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.add_safe,
.sub_safe,
.mul_safe,
- .intcast_safe,
+ .int_cast_safe,
.int_from_float_safe,
.int_from_float_optimized_safe,
=> @panic("TODO implement safety_checked_instructions"),
@@ -709,6 +716,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.work_item_id => unreachable,
.work_group_size => unreachable,
.work_group_id => unreachable,
+ .spirv_runtime_array_len => unreachable,
// zig fmt: on
}
@@ -743,7 +751,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
switch (lhs_ty.zigTypeTag(zcu)) {
.vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}),
.int => {
- assert(lhs_ty.eql(rhs_ty, zcu));
+ assert(lhs_ty.eql(rhs_ty));
const int_info = lhs_ty.intInfo(zcu);
switch (int_info.bits) {
32, 64 => {
@@ -1658,7 +1666,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
const info_a = operand_ty.intInfo(zcu);
const info_b = self.typeOfIndex(inst).intInfo(zcu);
if (info_a.signedness != info_b.signedness)
- return self.fail("TODO gen intcast sign safety in semantic analysis", .{});
+ return self.fail("TODO gen int_cast sign safety in semantic analysis", .{});
if (info_a.bits == info_b.bits)
return self.finishAir(inst, operand, .{ ty_op.operand, .none, .none });
@@ -1796,7 +1804,7 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
const rhs = try self.resolveInst(bin_op.rhs);
const lhs_ty = self.typeOf(bin_op.lhs);
const rhs_ty = self.typeOf(bin_op.rhs);
- assert(lhs_ty.eql(rhs_ty, self.pt.zcu));
+ assert(lhs_ty.eql(rhs_ty));
if (self.liveness.isUnused(inst))
return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
@@ -1949,7 +1957,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
switch (lhs_ty.zigTypeTag(zcu)) {
.vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),
.int => {
- assert(lhs_ty.eql(rhs_ty, zcu));
+ assert(lhs_ty.eql(rhs_ty));
const int_info = lhs_ty.intInfo(zcu);
switch (int_info.bits) {
1...32 => {
@@ -2779,7 +2787,7 @@ fn binOp(
.float => return self.fail("TODO binary operations on floats", .{}),
.vector => return self.fail("TODO binary operations on vectors", .{}),
.int => {
- assert(lhs_ty.eql(rhs_ty, zcu));
+ assert(lhs_ty.eql(rhs_ty));
const int_info = lhs_ty.intInfo(zcu);
if (int_info.bits <= 64) {
// Only say yes if the operation is
@@ -2869,7 +2877,7 @@ fn binOp(
switch (lhs_ty.zigTypeTag(zcu)) {
.vector => return self.fail("TODO binary operations on vectors", .{}),
.int => {
- assert(lhs_ty.eql(rhs_ty, zcu));
+ assert(lhs_ty.eql(rhs_ty));
const int_info = lhs_ty.intInfo(zcu);
if (int_info.bits <= 64) {
const rhs_immediate_ok = switch (tag) {
@@ -4225,7 +4233,7 @@ fn minMax(
) InnerError!MCValue {
const pt = self.pt;
const zcu = pt.zcu;
- assert(lhs_ty.eql(rhs_ty, zcu));
+ assert(lhs_ty.eql(rhs_ty));
switch (lhs_ty.zigTypeTag(zcu)) {
.float => return self.fail("TODO min/max on floats", .{}),
.vector => return self.fail("TODO min/max on vectors", .{}),
diff --git a/src/codegen/spirv/Assembler.zig b/src/codegen/spirv/Assembler.zig
index c80c246b10a4218b126155efb262885e3d4d0746..f18f9028212b4916ed70a89d080e28a3bad75f3f 100644
--- a/src/codegen/spirv/Assembler.zig
+++ b/src/codegen/spirv/Assembler.zig
@@ -3,7 +3,7 @@ const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
const CodeGen = @import("CodeGen.zig");
-const Decl = @import("Module.zig").Decl;
+const Decl = @import("CodeGen.zig").Decl;
const spec = @import("spec.zig");
const Opcode = spec.Opcode;
@@ -35,8 +35,8 @@ inst: struct {
return null;
}
} = .{},
-value_map: std.StringArrayHashMapUnmanaged(AsmValue) = .{},
-inst_map: std.StringArrayHashMapUnmanaged(void) = .empty,
+value_map: std.array_hash_map.String(AsmValue) = .{},
+inst_map: std.array_hash_map.String(void) = .empty,
const Operand = union(enum) {
/// Any 'simple' 32-bit value. This could be a mask or
@@ -56,7 +56,7 @@ const Operand = union(enum) {
};
pub fn deinit(ass: *Assembler) void {
- const gpa = ass.cg.module.gpa;
+ const gpa = ass.cg.gpa;
for (ass.errors.items) |err| gpa.free(err.msg);
ass.tokens.deinit(gpa);
ass.errors.deinit(gpa);
@@ -69,7 +69,7 @@ pub fn deinit(ass: *Assembler) void {
const Error = error{ AssembleFail, OutOfMemory };
pub fn assemble(ass: *Assembler, src: []const u8) Error!void {
- const gpa = ass.cg.module.gpa;
+ const gpa = ass.cg.gpa;
ass.src = src;
ass.errors.clearRetainingCapacity();
@@ -100,7 +100,7 @@ const ErrorMsg = struct {
};
fn addError(ass: *Assembler, offset: u32, comptime fmt: []const u8, args: anytype) !void {
- const gpa = ass.cg.module.gpa;
+ const gpa = ass.cg.gpa;
const msg = try std.fmt.allocPrint(gpa, fmt, args);
errdefer gpa.free(msg);
try ass.errors.append(gpa, .{
@@ -159,7 +159,7 @@ const AsmValue = union(enum) {
/// If this function returns `error.AssembleFail`, an explanatory
/// error message has already been emitted into `ass.errors`.
fn processInstruction(ass: *Assembler) !void {
- const module = ass.cg.module;
+ const cg = ass.cg;
const result: AsmValue = switch (ass.inst.opcode) {
.OpEntryPoint => {
return ass.fail(ass.currentToken().start, "cannot export entry points in assembly", .{});
@@ -167,15 +167,8 @@ fn processInstruction(ass: *Assembler) !void {
.OpExecutionMode, .OpExecutionModeId => {
return ass.fail(ass.currentToken().start, "cannot set execution mode in assembly", .{});
},
- .OpCapability => {
- try module.addCapability(@enumFromInt(ass.inst.operands.items[0].value));
- return;
- },
- .OpExtension => {
- const ext_name_offset = ass.inst.operands.items[0].string;
- const ext_name = std.mem.sliceTo(ass.inst.string_bytes.items[ext_name_offset..], 0);
- try module.addExtension(ext_name);
- return;
+ .OpCapability, .OpExtension => {
+ return ass.fail(ass.currentToken().start, "cannot declare capabilities or extensions in assembly; use -mcpu instead", .{});
},
.OpExtInstImport => blk: {
const set_name_offset = ass.inst.operands.items[1].string;
@@ -183,7 +176,7 @@ fn processInstruction(ass: *Assembler) !void {
const set_tag = std.meta.stringToEnum(spec.InstructionSet, set_name) orelse {
return ass.fail(set_name_offset, "unknown instruction set: {s}", .{set_name});
};
- break :blk .{ .value = try module.importInstructionSet(set_tag) };
+ break :blk .{ .value = try cg.importInstructionSet(set_tag) };
},
else => switch (ass.inst.opcode.class()) {
.type_declaration => try ass.processTypeInstruction(),
@@ -204,13 +197,12 @@ fn processInstruction(ass: *Assembler) !void {
fn processTypeInstruction(ass: *Assembler) !AsmValue {
const cg = ass.cg;
- const gpa = cg.module.gpa;
- const module = cg.module;
+ const gpa = cg.gpa;
const operands = ass.inst.operands.items;
- const section = &module.sections.globals;
+ const section = &cg.sections.globals;
const id = switch (ass.inst.opcode) {
- .OpTypeVoid => try module.voidType(),
- .OpTypeBool => try module.boolType(),
+ .OpTypeVoid => try cg.voidType(),
+ .OpTypeBool => try cg.boolType(),
.OpTypeInt => blk: {
const signedness: std.lang.Signedness = switch (operands[2].literal32) {
0 => .unsigned,
@@ -223,7 +215,7 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue {
const width = std.math.cast(u16, operands[1].literal32) orelse {
return ass.fail(0, "int type of {} bits is too large", .{operands[1].literal32});
};
- break :blk try module.intType(signedness, width);
+ break :blk try cg.intType(signedness, width);
},
.OpTypeFloat => blk: {
const bits = operands[1].literal32;
@@ -233,11 +225,11 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue {
return ass.fail(0, "{} is not a valid bit count for floats (expected 16, 32 or 64)", .{bits});
},
}
- break :blk try module.floatType(@intCast(bits));
+ break :blk try cg.floatType(@intCast(bits));
},
.OpTypeVector => blk: {
const child_type = try ass.resolveRefId(operands[1].ref_id);
- break :blk try module.vectorType(operands[2].literal32, child_type);
+ break :blk try cg.vectorType(operands[2].literal32, child_type);
},
.OpTypeArray => {
// TODO: The length of an OpTypeArray is determined by a constant (which may be a spec constant),
@@ -246,8 +238,8 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue {
},
.OpTypeRuntimeArray => blk: {
const element_type = try ass.resolveRefId(operands[1].ref_id);
- const result_id = module.allocId();
- try section.emit(module.gpa, .OpTypeRuntimeArray, .{
+ const result_id = cg.allocId();
+ try section.emit(cg.gpa, .OpTypeRuntimeArray, .{
.id_result = result_id,
.element_type = element_type,
});
@@ -256,8 +248,8 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue {
.OpTypePointer => blk: {
const storage_class: StorageClass = @enumFromInt(operands[1].value);
const child_type = try ass.resolveRefId(operands[2].ref_id);
- const result_id = module.allocId();
- try section.emit(module.gpa, .OpTypePointer, .{
+ const result_id = cg.allocId();
+ try section.emit(cg.gpa, .OpTypePointer, .{
.id_result = result_id,
.storage_class = storage_class,
.type = child_type,
@@ -269,11 +261,11 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue {
defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
const ids = try cg.id_scratch.addManyAsSlice(gpa, operands[1..].len);
for (operands[1..], ids) |op, *id| id.* = try ass.resolveRefId(op.ref_id);
- break :blk try module.structType(ids, null, null, .none);
+ break :blk try cg.structType(ids, null, .none);
},
.OpTypeImage => blk: {
const sampled_type = try ass.resolveRefId(operands[1].ref_id);
- const result_id = module.allocId();
+ const result_id = cg.allocId();
try section.emit(gpa, .OpTypeImage, .{
.id_result = result_id,
.sampled_type = sampled_type,
@@ -287,13 +279,13 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue {
break :blk result_id;
},
.OpTypeSampler => blk: {
- const result_id = module.allocId();
+ const result_id = cg.allocId();
try section.emit(gpa, .OpTypeSampler, .{ .id_result = result_id });
break :blk result_id;
},
.OpTypeSampledImage => blk: {
const image_type = try ass.resolveRefId(operands[1].ref_id);
- const result_id = module.allocId();
+ const result_id = cg.allocId();
try section.emit(gpa, .OpTypeSampledImage, .{ .id_result = result_id, .image_type = image_type });
break :blk result_id;
},
@@ -308,8 +300,8 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue {
for (param_types, param_operands) |*param, operand| {
param.* = try ass.resolveRefId(operand.ref_id);
}
- const result_id = module.allocId();
- try section.emit(module.gpa, .OpTypeFunction, .{
+ const result_id = cg.allocId();
+ try section.emit(cg.gpa, .OpTypeFunction, .{
.id_result = result_id,
.return_type = return_type,
.id_ref_2 = param_types,
@@ -325,27 +317,27 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue {
/// - No forward references are allowed in operands.
/// - Target section is determined from instruction type.
fn processGenericInstruction(ass: *Assembler) !?AsmValue {
- const module = ass.cg.module;
- const target = module.zcu.getTarget();
+ const cg = ass.cg;
+ const target = cg.zcu.getTarget();
const operands = ass.inst.operands.items;
var maybe_spv_decl_index: ?Decl.Index = null;
const section = switch (ass.inst.opcode.class()) {
- .constant_creation => &module.sections.globals,
- .annotation => &module.sections.annotations,
+ .constant_creation => &cg.sections.globals,
+ .annotation => &cg.sections.annotations,
.type_declaration => unreachable, // Handled elsewhere.
else => switch (ass.inst.opcode) {
.OpEntryPoint => unreachable,
- .OpExecutionMode, .OpExecutionModeId => &module.sections.execution_modes,
+ .OpExecutionMode, .OpExecutionModeId => &cg.sections.execution_modes,
.OpVariable => section: {
const storage_class: spec.StorageClass = @enumFromInt(operands[2].value);
if (storage_class == .function) break :section &ass.cg.prologue;
- maybe_spv_decl_index = try module.allocDecl(.global);
+ maybe_spv_decl_index = try cg.allocDecl(.global);
if (!target.cpu.has(.spirv, .v1_4) and storage_class != .input and storage_class != .output) {
// Before version 1.4, the interface’s storage classes are limited to the Input and Output
- break :section &module.sections.globals;
+ break :section &cg.sections.globals;
}
- try ass.cg.module.decl_deps.append(module.gpa, maybe_spv_decl_index.?);
- break :section &module.sections.globals;
+ try ass.cg.decl_deps.append(cg.gpa, maybe_spv_decl_index.?);
+ break :section &cg.sections.globals;
},
else => &ass.cg.body,
},
@@ -355,36 +347,36 @@ fn processGenericInstruction(ass: *Assembler) !?AsmValue {
const first_word = section.instructions.items.len;
// At this point we're not quite sure how many operands this instruction is
// going to have, so insert 0 and patch up the actual opcode word later.
- try section.ensureUnusedCapacity(module.gpa, 1);
+ try section.ensureUnusedCapacity(cg.gpa, 1);
section.writeWord(0);
for (operands) |operand| {
switch (operand) {
.value, .literal32 => |word| {
- try section.ensureUnusedCapacity(module.gpa, 1);
+ try section.ensureUnusedCapacity(cg.gpa, 1);
section.writeWord(word);
},
.literal64 => |dword| {
- try section.ensureUnusedCapacity(module.gpa, 2);
+ try section.ensureUnusedCapacity(cg.gpa, 2);
section.writeDoubleWord(dword);
},
.result_id => {
maybe_result_id = if (maybe_spv_decl_index) |spv_decl_index|
- module.declPtr(spv_decl_index).result_id
+ cg.declPtr(spv_decl_index).result_id
else
- module.allocId();
- try section.ensureUnusedCapacity(module.gpa, 1);
+ cg.allocId();
+ try section.ensureUnusedCapacity(cg.gpa, 1);
section.writeOperand(Id, maybe_result_id.?);
},
.ref_id => |index| {
const result = try ass.resolveRef(index);
- try section.ensureUnusedCapacity(module.gpa, 1);
+ try section.ensureUnusedCapacity(cg.gpa, 1);
section.writeOperand(spec.Id, result.resultId());
},
.string => |offset| {
const text = std.mem.sliceTo(ass.inst.string_bytes.items[offset..], 0);
const size = std.math.divCeil(usize, text.len + 1, @sizeOf(Word)) catch unreachable;
- try section.ensureUnusedCapacity(module.gpa, size);
+ try section.ensureUnusedCapacity(cg.gpa, size);
section.writeOperand(spec.LiteralString, text);
},
}
@@ -393,6 +385,15 @@ fn processGenericInstruction(ass: *Assembler) !?AsmValue {
const actual_word_count = section.instructions.items.len - first_word;
section.instructions.items[first_word] |= @as(u32, @as(u16, @intCast(actual_word_count))) << 16 | @intFromEnum(ass.inst.opcode);
+ switch (ass.inst.opcode) {
+ .OpKill,
+ .OpReturn,
+ .OpReturnValue,
+ .OpUnreachable,
+ => ass.cg.block_terminated = true,
+ else => {},
+ }
+
if (maybe_result_id) |result| return .{ .value = result };
return null;
}
@@ -428,7 +429,7 @@ fn resolveRefId(ass: *Assembler, ref: AsmValue.Ref) !Id {
}
fn parseInstruction(ass: *Assembler) !void {
- const gpa = ass.cg.module.gpa;
+ const gpa = ass.cg.gpa;
ass.inst.opcode = undefined;
ass.inst.operands.clearRetainingCapacity();
@@ -520,7 +521,7 @@ fn parseOperand(ass: *Assembler, kind: spec.OperandKind) Error!void {
/// Also handles parsing any required extra operands.
fn parseBitEnum(ass: *Assembler, kind: spec.OperandKind) !void {
- const gpa = ass.cg.module.gpa;
+ const gpa = ass.cg.gpa;
var tok = ass.currentToken();
try ass.expectToken(.value);
@@ -569,7 +570,7 @@ fn parseBitEnum(ass: *Assembler, kind: spec.OperandKind) !void {
/// Also handles parsing any required extra operands.
fn parseValueEnum(ass: *Assembler, kind: spec.OperandKind) !void {
- const gpa = ass.cg.module.gpa;
+ const gpa = ass.cg.gpa;
const tok = ass.currentToken();
if (ass.eatToken(.placeholder)) {
@@ -620,7 +621,7 @@ fn parseValueEnum(ass: *Assembler, kind: spec.OperandKind) !void {
}
fn parseRefId(ass: *Assembler) !void {
- const gpa = ass.cg.module.gpa;
+ const gpa = ass.cg.gpa;
const tok = ass.currentToken();
try ass.expectToken(.result_id);
@@ -636,7 +637,7 @@ fn parseRefId(ass: *Assembler) !void {
}
fn parseLiteralInteger(ass: *Assembler) !void {
- const gpa = ass.cg.module.gpa;
+ const gpa = ass.cg.gpa;
const tok = ass.currentToken();
if (ass.eatToken(.placeholder)) {
@@ -669,7 +670,7 @@ fn parseLiteralInteger(ass: *Assembler) !void {
}
fn parseLiteralExtInstInteger(ass: *Assembler) !void {
- const gpa = ass.cg.module.gpa;
+ const gpa = ass.cg.gpa;
const tok = ass.currentToken();
if (ass.eatToken(.placeholder)) {
@@ -697,7 +698,7 @@ fn parseLiteralExtInstInteger(ass: *Assembler) !void {
}
fn parseString(ass: *Assembler) !void {
- const gpa = ass.cg.module.gpa;
+ const gpa = ass.cg.gpa;
const tok = ass.currentToken();
try ass.expectToken(.string);
@@ -720,46 +721,36 @@ fn parseString(ass: *Assembler) !void {
}
fn parseContextDependentNumber(ass: *Assembler) !void {
- const module = ass.cg.module;
-
- // For context dependent numbers, the actual type to parse is determined by the instruction.
- // Currently, this operand appears in OpConstant and OpSpecConstant, where the too-be-parsed type
- // is determined by the result type. That means that in this instructions we have to resolve the
- // operand type early and look at the result to see how we need to proceed.
+ const cg = ass.cg;
assert(ass.inst.opcode == .OpConstant or ass.inst.opcode == .OpSpecConstant);
const tok = ass.currentToken();
const result = try ass.resolveRef(ass.inst.operands.items[0].ref_id);
const result_id = result.resultId();
- // We are going to cheat a little bit: The types we are interested in, int and float,
- // are added to the module and cached via module.intType and module.floatType. Therefore,
- // we can determine the width of these types by directly checking the cache.
- // This only works if the Assembler and codegen both use spv.intType and spv.floatType though.
- // We don't expect there to be many of these types, so just look it up every time.
- // TODO: Count be improved to be a little bit more efficent.
- {
- var it = module.cache.int_types.iterator();
- while (it.next()) |entry| {
- const id = entry.value_ptr.*;
- if (id != result_id) continue;
- const info = entry.key_ptr.*;
- return try ass.parseContextDependentInt(info.signedness, info.bits);
- }
- }
-
- {
- var it = module.cache.float_types.iterator();
- while (it.next()) |entry| {
- const id = entry.value_ptr.*;
- if (id != result_id) continue;
- const info = entry.key_ptr.*;
- switch (info.bits) {
- 16 => try ass.parseContextDependentFloat(16),
- 32 => try ass.parseContextDependentFloat(32),
- 64 => try ass.parseContextDependentFloat(64),
- else => return ass.fail(tok.start, "cannot parse {}-bit info literal", .{info.bits}),
- }
+ const words = cg.sections.globals.instructions.items;
+ var offset: usize = 0;
+ while (offset < words.len) {
+ const word_count = words[offset] >> 16;
+ const opcode: Opcode = @enumFromInt(words[offset] & 0xFFFF);
+ defer offset += word_count;
+ if (word_count == 0) break;
+ switch (opcode) {
+ .OpTypeInt => if (word_count >= 4 and @as(Id, @enumFromInt(words[offset + 1])) == result_id) {
+ const width: u16 = @intCast(words[offset + 2]);
+ const signedness: std.lang.Signedness = if (words[offset + 3] == 0) .unsigned else .signed;
+ return ass.parseContextDependentInt(signedness, width);
+ },
+ .OpTypeFloat => if (word_count >= 3 and @as(Id, @enumFromInt(words[offset + 1])) == result_id) {
+ const bits = words[offset + 2];
+ return switch (bits) {
+ 16 => ass.parseContextDependentFloat(16),
+ 32 => ass.parseContextDependentFloat(32),
+ 64 => ass.parseContextDependentFloat(64),
+ else => ass.fail(tok.start, "cannot parse {}-bit info literal", .{bits}),
+ };
+ },
+ else => {},
}
}
@@ -767,7 +758,7 @@ fn parseContextDependentNumber(ass: *Assembler) !void {
}
fn parseContextDependentInt(ass: *Assembler, signedness: std.lang.Signedness, width: u32) !void {
- const gpa = ass.cg.module.gpa;
+ const gpa = ass.cg.gpa;
const tok = ass.currentToken();
if (ass.eatToken(.placeholder)) {
@@ -818,7 +809,7 @@ fn parseContextDependentInt(ass: *Assembler, signedness: std.lang.Signedness, wi
}
fn parseContextDependentFloat(ass: *Assembler, comptime width: u16) !void {
- const gpa = ass.cg.module.gpa;
+ const gpa = ass.cg.gpa;
const Float = std.meta.Float(width);
const Int = @Int(.unsigned, width);
@@ -891,7 +882,7 @@ fn tokenText(ass: Assembler, tok: Token) []const u8 {
/// Tokenize `ass.src` and put the tokens in `ass.tokens`.
/// Any errors encountered are appended to `ass.errors`.
fn tokenize(ass: *Assembler) !void {
- const gpa = ass.cg.module.gpa;
+ const gpa = ass.cg.gpa;
ass.tokens.clearRetainingCapacity();
diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig
index e2969777c165c416ab68578b10d2eebaf3492ba1..80b8ceafb3f0dc84b12c878665784441597b5add 100644
--- a/src/codegen/spirv/CodeGen.zig
+++ b/src/codegen/spirv/CodeGen.zig
@@ -1,177 +1,723 @@
-const std = @import("std");
-const Allocator = std.mem.Allocator;
-const Target = std.Target;
-const Signedness = std.lang.Signedness;
-const assert = std.debug.assert;
-const log = std.log.scoped(.codegen);
-
-const Zcu = @import("../../Zcu.zig");
-const Type = @import("../../Type.zig");
-const Value = @import("../../Value.zig");
-const Air = @import("../../Air.zig");
-const InternPool = @import("../../InternPool.zig");
-const Section = @import("Section.zig");
-const Assembler = @import("Assembler.zig");
-
-const spec = @import("spec.zig");
-const Opcode = spec.Opcode;
-const Word = spec.Word;
-const Id = spec.Id;
-const IdRange = spec.IdRange;
-const StorageClass = spec.StorageClass;
-
-const Module = @import("Module.zig");
-const Decl = Module.Decl;
-const Repr = Module.Repr;
-const InternMap = Module.InternMap;
-const PtrTypeMap = Module.PtrTypeMap;
-
-const CodeGen = @This();
-
-pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
- return comptime &.initMany(&.{
- .expand_intcast_safe,
- .expand_int_from_float_safe,
- .expand_int_from_float_optimized_safe,
- .expand_add_safe,
- .expand_sub_safe,
- .expand_mul_safe,
- });
-}
-
-pub const zig_call_abi_ver = 3;
-
-const ControlFlow = union(enum) {
- const Structured = struct {
- /// This type indicates the way that a block is terminated. The
- /// state of a particular block is used to track how a jump from
- /// inside the block must reach the outside.
- const Block = union(enum) {
- const Incoming = struct {
- src_label: Id,
- /// Instruction that returns an u32 value of the
- /// `Air.Inst.Index` that control flow should jump to.
- next_block: Id,
- };
-
- const SelectionMerge = struct {
- /// Incoming block from the `then` label.
- /// Note that hte incoming block from the `else` label is
- /// either given by the next element in the stack.
- incoming: Incoming,
- /// The label id of the cond_br's merge block.
- /// For the top-most element in the stack, this
- /// value is undefined.
- merge_block: Id,
- };
-
- /// For a `selection` type block, we cannot use early exits, and we
- /// must generate a 'merge ladder' of OpSelection instructions. To that end,
- /// we keep a stack of the merges that still must be closed at the end of
- /// a block.
- ///
- /// This entire structure basically just resembles a tree like
- /// a x
- /// \ /
- /// b o merge
- /// \ /
- /// c o merge
- /// \ /
- /// o merge
- /// /
- /// o jump to next block
- selection: struct {
- /// In order to know which merges we still need to do, we need to keep
- /// a stack of those.
- merge_stack: std.ArrayList(SelectionMerge) = .empty,
- },
- /// For a `loop` type block, we can early-exit the block by
- /// jumping to the loop exit node, and we don't need to generate
- /// an entire stack of merges.
- loop: struct {
- /// The next block to jump to can be determined from any number
- /// of conditions that jump to the loop exit.
- merges: std.ArrayList(Incoming) = .empty,
- /// The label id of the loop's merge block.
- merge_block: Id,
- },
-
- fn deinit(block: *Structured.Block, gpa: Allocator) void {
- switch (block.*) {
- .selection => |*merge| merge.merge_stack.deinit(gpa),
- .loop => |*merge| merge.merges.deinit(gpa),
- }
- block.* = undefined;
- }
- };
- /// This determines how exits from the current block must be handled.
- block_stack: std.ArrayList(*Structured.Block) = .empty,
- block_results: std.AutoHashMapUnmanaged(Air.Inst.Index, Id) = .empty,
- };
-
- const Unstructured = struct {
- const Incoming = struct {
- src_label: Id,
- break_value_id: Id,
- };
-
- const Block = struct {
- label: ?Id = null,
- incoming_blocks: std.ArrayList(Incoming) = .empty,
- };
-
- /// We need to keep track of result ids for block labels, as well as the 'incoming'
- /// blocks for a block.
- blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *Block) = .empty,
- };
-
- structured: Structured,
- unstructured: Unstructured,
-
- pub fn deinit(cg: *ControlFlow, gpa: Allocator) void {
- switch (cg.*) {
- .structured => |*cf| {
- cf.block_stack.deinit(gpa);
- cf.block_results.deinit(gpa);
- },
- .unstructured => |*cf| {
- cf.blocks.deinit(gpa);
- },
- }
- cg.* = undefined;
- }
-};
-
+// Compilation
pt: Zcu.PerThread,
+zcu: *Zcu,
+gpa: Allocator,
+arena: Allocator,
air: Air,
liveness: Air.Liveness,
owner_nav: InternPool.Nav.Index,
-module: *Module,
-control_flow: ControlFlow,
base_line: u32,
-block_label: Id = .none,
-next_arg_index: u32 = 0,
+
+// Module-level output (accumulated across the nav's codegen)
+next_result_id: Word = 1,
+decls: std.ArrayList(Decl) = .empty,
+decl_deps: std.ArrayList(Decl.Index) = .empty,
+nav_link: std.AutoHashMapUnmanaged(InternPool.Nav.Index, Decl.Index) = .empty,
+uav_link: std.AutoHashMapUnmanaged(struct { InternPool.Index, spec.StorageClass }, Decl.Index) = .empty,
+entry_points: std.array_hash_map.Auto(Id, EntryPoint) = .empty,
+error_buffer: ?Decl.Index = null,
+struct_types: std.array_hash_map.Custom(StructType, Id, StructType.HashContext, true) = .empty,
+builtins: std.AutoHashMapUnmanaged(struct { spec.BuiltIn, spec.StorageClass }, Decl.Index) = .empty,
+sections: struct {
+ // Module layout, according to SPIR-V Spec section 2.4, "Logical Layout of a Module".
+ extended_instruction_set: Section = .{},
+ memory_model: Section = .{},
+ execution_modes: Section = .{},
+ debug_strings: Section = .{},
+ debug_names: Section = .{},
+ annotations: Section = .{},
+ globals: Section = .{},
+ functions: Section = .{},
+} = .{},
+
+// Per-function state (reset between top-level genNav calls)
+prologue: Section = .{},
+body: Section = .{},
args: std.ArrayList(Id) = .empty,
+next_arg_index: u32 = 0,
+block_stack: std.ArrayList(*Block) = .empty,
+block_label: Id = .none,
+/// Whether the current block has been terminated by a terminator
+/// instruction (e.g. OpKill from inline assembly). When true, no further
+/// branch instructions should be emitted for the current block.
+block_terminated: bool = false,
+block_results: std.AutoHashMapUnmanaged(Air.Inst.Index, Id) = .empty,
inst_results: std.AutoHashMapUnmanaged(Air.Inst.Index, Id) = .empty,
+tracked_allocas: std.AutoHashMapUnmanaged(Id, ?Id) = .empty,
+loop_switches: std.AutoHashMapUnmanaged(Air.Inst.Index, LoopSwitch) = .empty,
id_scratch: std.ArrayList(Id) = .empty,
-prologue: Section = .{},
-body: Section = .{},
+
+const big_int_bits = @bitSizeOf(u32);
+
+/// Data can be lowered into in two basic representations: indirect, which is when
+/// a type is stored in memory, and direct, which is how a type is stored when its
+/// a direct SPIR-V value.
+pub const Repr = enum {
+ /// A SPIR-V value as it would be used in operations.
+ direct,
+ /// A SPIR-V value as it is stored in memory.
+ indirect,
+};
+
+/// A function or global, tracked here so the linker can order globals and build
+/// per-entry-point interface lists.
+pub const Decl = struct {
+ pub const Index = enum(u32) { _ };
+ pub const Kind = enum { func, global, invocation_global };
+
+ kind: Kind,
+ /// Result-id of the associated OpFunction / OpVariable / InvocationGlobal.
+ result_id: Id,
+ /// Range into `decl_deps` for this decl's dependencies.
+ begin_dep: usize = 0,
+ end_dep: usize = 0,
+ /// Whether an extern-function stub has been emitted.
+ has_extern_stub: bool = false,
+};
+
+pub const EntryPoint = struct {
+ decl_index: Decl.Index,
+ name: []const u8,
+ cc: std.builtin.CallingConvention,
+};
+
+const StructType = struct {
+ fields: []const Id,
+ ip_index: InternPool.Index,
+
+ const HashContext = struct {
+ pub fn hash(_: @This(), ty: StructType) u32 {
+ var hasher = std.hash.Wyhash.init(0);
+ hasher.update(std.mem.sliceAsBytes(ty.fields));
+ hasher.update(std.mem.asBytes(&ty.ip_index));
+ return @truncate(hasher.final());
+ }
+
+ pub fn eql(_: @This(), a: StructType, b: StructType, _: usize) bool {
+ return a.ip_index == b.ip_index and std.mem.eql(Id, a.fields, b.fields);
+ }
+ };
+};
+
+pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
+ return comptime &.initMany(&.{
+ .expand_int_cast_safe,
+ .expand_int_from_float_safe,
+ .expand_int_from_float_optimized_safe,
+ .expand_add_safe,
+ .expand_sub_safe,
+ .expand_mul_safe,
+ });
+}
+
+const LoopSwitch = struct { cond_var: Id, continue_label: Id };
+
+/// Pointer-typed AIR refs should resolve through `resolvePtr` to handle the
+/// `tracked_allocas` case explicitly at every use site.
+const Ptr = union(enum) {
+ id: Id,
+ /// Function-local pointer whose value lives in `tracked_allocas` rather
+ /// than a real OpVariable. `slot` is the current pointee value.
+ tracked: struct { id: Id, slot: *?Id },
+};
+
+/// Tracks how control flow leaves a Zig `block` under SPIR-V's structured
+/// control flow rules.
+const Block = union(enum) {
+ const Incoming = struct {
+ src_label: Id,
+ /// Block index (u32) that control flow should jump to next.
+ next_block: Id,
+ };
+
+ const SelectionMerge = struct {
+ incoming: Incoming,
+ /// Label of the cond_br's merge block (undefined for top-of-stack).
+ merge_block: Id,
+ };
+
+ /// Selection blocks can't use early exits. Closing requires a "merge ladder"
+ /// of nested OpSelectionMerge instructions, one per pending merge.
+ selection: struct {
+ merge_stack: std.ArrayList(SelectionMerge) = .empty,
+ },
+ /// Loop blocks early-exit by jumping to the loop merge label.
+ loop: struct {
+ merges: std.ArrayList(Incoming) = .empty,
+ merge_block: Id,
+ },
+
+ fn deinit(block: *Block, gpa: Allocator) void {
+ switch (block.*) {
+ .selection => |*merge| merge.merge_stack.deinit(gpa),
+ .loop => |*merge| merge.merges.deinit(gpa),
+ }
+ block.* = undefined;
+ }
+};
pub fn deinit(cg: *CodeGen) void {
- const gpa = cg.module.gpa;
- cg.control_flow.deinit(gpa);
+ const gpa = cg.gpa;
+ cg.block_stack.deinit(gpa);
+ cg.block_results.deinit(gpa);
cg.args.deinit(gpa);
+ cg.tracked_allocas.deinit(gpa);
cg.inst_results.deinit(gpa);
+ cg.loop_switches.deinit(gpa);
cg.id_scratch.deinit(gpa);
cg.prologue.deinit(gpa);
cg.body.deinit(gpa);
+
+ cg.nav_link.deinit(gpa);
+ cg.uav_link.deinit(gpa);
+
+ cg.sections.extended_instruction_set.deinit(gpa);
+ cg.sections.memory_model.deinit(gpa);
+ cg.sections.execution_modes.deinit(gpa);
+ cg.sections.debug_strings.deinit(gpa);
+ cg.sections.debug_names.deinit(gpa);
+ cg.sections.annotations.deinit(gpa);
+ cg.sections.globals.deinit(gpa);
+ cg.sections.functions.deinit(gpa);
+
+ cg.struct_types.deinit(gpa);
+ cg.builtins.deinit(gpa);
+
+ cg.decls.deinit(gpa);
+ cg.decl_deps.deinit(gpa);
+ cg.entry_points.deinit(gpa);
+}
+
+pub fn generate(
+ _: *link.File,
+ pt: Zcu.PerThread,
+ func_index: InternPool.Index,
+ air: *const Air,
+ liveness: *const ?Air.Liveness,
+) codegen.Error!Mir {
+ const zcu = pt.zcu;
+ const gpa = zcu.gpa;
+ const nav = zcu.funcInfo(func_index).owner_nav;
+
+ var arena = std.heap.ArenaAllocator.init(gpa);
+ defer arena.deinit();
+
+ var cg: CodeGen = .{
+ .pt = pt,
+ .gpa = gpa,
+ .arena = arena.allocator(),
+ .zcu = zcu,
+ .air = air.*,
+ .liveness = liveness.*.?,
+ .owner_nav = nav,
+ .base_line = zcu.navSrcLine(nav),
+ };
+ defer cg.deinit();
+
+ cg.genNav(true) catch |err| switch (err) {
+ error.AlreadyReported => return error.AlreadyReported,
+ error.OutOfMemory => return error.OutOfMemory,
+ };
+
+ return cg.serializeToMir(gpa);
+}
+
+pub fn generateNav(
+ pt: Zcu.PerThread,
+ nav_index: InternPool.Nav.Index,
+) codegen.Error!Mir {
+ const zcu = pt.zcu;
+ const gpa = zcu.gpa;
+
+ var arena = std.heap.ArenaAllocator.init(gpa);
+ defer arena.deinit();
+
+ var cg: CodeGen = .{
+ .pt = pt,
+ .gpa = gpa,
+ .arena = arena.allocator(),
+ .zcu = zcu,
+ .air = undefined,
+ .liveness = undefined,
+ .owner_nav = nav_index,
+ .base_line = zcu.navSrcLine(nav_index),
+ };
+ defer cg.deinit();
+
+ cg.genNav(false) catch |err| switch (err) {
+ error.AlreadyReported => return error.AlreadyReported,
+ error.OutOfMemory => return error.OutOfMemory,
+ };
+
+ return cg.serializeToMir(gpa);
+}
+
+fn serializeToMir(cg: *CodeGen, gpa: Allocator) codegen.Error!Mir {
+ const owner_entry = cg.nav_link.get(cg.owner_nav);
+ const owner_decl_index = owner_entry orelse return .{
+ .id_bound = cg.next_result_id,
+ .owner_nav = cg.owner_nav,
+ .kind = .func,
+ .decl_result_id = .none,
+ .extended_instruction_set = &.{},
+ .globals = &.{},
+ .functions = &.{},
+ .annotations = &.{},
+ .debug_names = &.{},
+ .debug_strings = &.{},
+ .execution_modes = &.{},
+ .nav_refs = &.{},
+ .uav_refs = &.{},
+ .decl_deps = &.{},
+ .internal_globals = &.{},
+ .entry_points = &.{},
+ };
+
+ const owner_decl = cg.declPtr(owner_decl_index);
+
+ var nav_refs: std.ArrayList(Mir.NavRef) = .empty;
+ defer nav_refs.deinit(gpa);
+ var nav_it = cg.nav_link.iterator();
+ while (nav_it.next()) |entry| {
+ if (entry.key_ptr.* == cg.owner_nav) continue;
+ const decl = cg.declPtr(entry.value_ptr.*);
+ try nav_refs.append(gpa, .{
+ .local_id = decl.result_id,
+ .nav = entry.key_ptr.*,
+ .kind = decl.kind,
+ });
+ }
+
+ var uav_refs: std.ArrayList(Mir.UavRef) = .empty;
+ defer uav_refs.deinit(gpa);
+ var uav_it = cg.uav_link.iterator();
+ while (uav_it.next()) |entry| {
+ const decl = cg.declPtr(entry.value_ptr.*);
+ try uav_refs.append(gpa, .{
+ .local_id = decl.result_id,
+ .val = entry.key_ptr.*[0],
+ .storage_class = entry.key_ptr.*[1],
+ .kind = decl.kind,
+ });
+ }
+
+ var decl_deps: std.ArrayList(Mir.DeclDep) = .empty;
+ defer decl_deps.deinit(gpa);
+ var internal_globals: std.ArrayList(Id) = .empty;
+ defer internal_globals.deinit(gpa);
+
+ const deps = cg.decl_deps.items[owner_decl.begin_dep..owner_decl.end_dep];
+ for (deps) |dep_index| {
+ const dep_decl = cg.declPtr(dep_index);
+ var found = false;
+ nav_it.index = 0;
+ while (nav_it.next()) |entry| {
+ if (entry.value_ptr.* == dep_index) {
+ try decl_deps.append(gpa, .{
+ .kind = dep_decl.kind,
+ .nav = entry.key_ptr.*,
+ });
+ found = true;
+ break;
+ }
+ }
+ if (!found and dep_decl.kind == .global) {
+ try internal_globals.append(gpa, dep_decl.result_id);
+ }
+ }
+
+ var ep_list: std.ArrayList(Mir.EntryPoint) = .empty;
+ defer ep_list.deinit(gpa);
+ var ep_it = cg.entry_points.iterator();
+ while (ep_it.next()) |entry| {
+ const ep = entry.value_ptr;
+ const ep_decl = cg.declPtr(ep.decl_index);
+ try ep_list.append(gpa, .{
+ .local_id = ep_decl.result_id,
+ .name = try gpa.dupe(u8, ep.name),
+ .cc = ep.cc,
+ });
+ }
+
+ return .{
+ .id_bound = cg.next_result_id,
+ .owner_nav = cg.owner_nav,
+ .kind = owner_decl.kind,
+ .decl_result_id = owner_decl.result_id,
+ .extended_instruction_set = try cg.sections.extended_instruction_set.instructions.toOwnedSlice(gpa),
+ .globals = try cg.sections.globals.instructions.toOwnedSlice(gpa),
+ .functions = try cg.sections.functions.instructions.toOwnedSlice(gpa),
+ .annotations = try cg.sections.annotations.instructions.toOwnedSlice(gpa),
+ .debug_names = try cg.sections.debug_names.instructions.toOwnedSlice(gpa),
+ .debug_strings = try cg.sections.debug_strings.instructions.toOwnedSlice(gpa),
+ .execution_modes = try cg.sections.execution_modes.instructions.toOwnedSlice(gpa),
+ .nav_refs = try nav_refs.toOwnedSlice(gpa),
+ .uav_refs = try uav_refs.toOwnedSlice(gpa),
+ .decl_deps = try decl_deps.toOwnedSlice(gpa),
+ .internal_globals = try internal_globals.toOwnedSlice(gpa),
+ .entry_points = try ep_list.toOwnedSlice(gpa),
+ };
+}
+
+fn typeOf(cg: *CodeGen, inst: Air.Inst.Ref) Type {
+ const zcu = cg.zcu;
+ return cg.air.typeOf(inst, &zcu.intern_pool);
+}
+
+fn typeOfIndex(cg: *CodeGen, inst: Air.Inst.Index) Type {
+ const zcu = cg.zcu;
+ return cg.air.typeOfIndex(inst, &zcu.intern_pool);
+}
+
+/// Does not generate the nav.
+pub fn resolveNav(cg: *CodeGen, ip: *InternPool, nav_index: InternPool.Nav.Index) !Decl.Index {
+ const entry = try cg.nav_link.getOrPut(cg.gpa, nav_index);
+ if (!entry.found_existing) {
+ const nav = ip.getNav(nav_index);
+ // TODO: Extern fn?
+ const kind: Decl.Kind = if (ip.isFunctionType(nav.resolved.?.type))
+ .func
+ else switch (nav.resolved.?.@"addrspace") {
+ .generic => .invocation_global,
+ else => .global,
+ };
+ entry.value_ptr.* = try cg.allocDecl(kind);
+ }
+
+ return entry.value_ptr.*;
+}
+
+pub fn allocIds(cg: *CodeGen, n: u32) spec.IdRange {
+ defer cg.next_result_id += n;
+ return .{ .base = cg.next_result_id, .len = n };
+}
+
+pub fn allocId(cg: *CodeGen) Id {
+ return cg.allocIds(1).at(0);
+}
+
+pub fn idBound(cg: *const CodeGen) Word {
+ return cg.next_result_id;
+}
+
+pub fn addEntryPointDeps(
+ cg: *CodeGen,
+ decl_index: Decl.Index,
+ seen: *std.bit_set.Dynamic,
+ interface: *std.array_list.Managed(Id),
+) !void {
+ const decl = cg.declPtr(decl_index);
+ const deps = cg.decl_deps.items[decl.begin_dep..decl.end_dep];
+
+ if (seen.isSet(@intFromEnum(decl_index))) {
+ return;
+ }
+
+ seen.set(@intFromEnum(decl_index));
+
+ if (decl.kind == .global) {
+ try interface.append(decl.result_id);
+ }
+
+ for (deps) |dep| {
+ try cg.addEntryPointDeps(dep, seen, interface);
+ }
+}
+
+pub fn importInstructionSet(cg: *CodeGen, set: spec.InstructionSet) !Id {
+ assert(set != .core);
+ const result_id = cg.allocId();
+ try cg.sections.extended_instruction_set.emit(cg.gpa, .OpExtInstImport, .{
+ .id_result = result_id,
+ .name = @tagName(set),
+ });
+ return result_id;
+}
+
+pub fn boolType(cg: *CodeGen) !Id {
+ const result_id = cg.allocId();
+ try cg.sections.globals.emit(cg.gpa, .OpTypeBool, .{
+ .id_result = result_id,
+ });
+ return result_id;
+}
+
+pub fn voidType(cg: *CodeGen) !Id {
+ const result_id = cg.allocId();
+ try cg.sections.globals.emit(cg.gpa, .OpTypeVoid, .{
+ .id_result = result_id,
+ });
+ try cg.debugName(result_id, "void");
+ return result_id;
+}
+
+pub fn opaqueType(cg: *CodeGen, name: []const u8) !Id {
+ const result_id = cg.allocId();
+ try cg.sections.globals.emit(cg.gpa, .OpTypeOpaque, .{
+ .id_result = result_id,
+ .literal_string = name,
+ });
+ try cg.debugName(result_id, name);
+ return result_id;
+}
+
+pub fn backingIntBits(cg: *const CodeGen, bits: u16) struct { u16, bool } {
+ assert(bits != 0);
+ const target = cg.zcu.getTarget();
+ const ints = [_]struct { bits: u16, enabled: bool }{
+ .{ .bits = 8, .enabled = target.cpu.has(.spirv, .int8) },
+ .{ .bits = 16, .enabled = target.cpu.has(.spirv, .int16) },
+ .{ .bits = 32, .enabled = true },
+ .{ .bits = 64, .enabled = target.cpu.has(.spirv, .int64) or target.cpu.arch == .spirv64 },
+ };
+
+ for (ints) |int| {
+ if (bits <= int.bits and int.enabled) return .{ int.bits, false };
+ }
+
+ return .{ std.mem.alignForward(u16, bits, big_int_bits), true };
+}
+
+pub fn intType(cg: *CodeGen, signedness: std.lang.Signedness, bits: u16) !Id {
+ assert(bits > 0);
+
+ const target = cg.zcu.getTarget();
+ const actual_signedness = switch (target.os.tag) {
+ // Kernel only supports unsigned ints.
+ .opencl, .amdhsa => .unsigned,
+ else => signedness,
+ };
+ const backing_bits, const big_int = cg.backingIntBits(bits);
+ if (big_int) {
+ const u32_ty = try cg.intType(.unsigned, 32);
+ const len_id = cg.allocId();
+ try cg.sections.globals.emit(cg.gpa, .OpConstant, .{
+ .id_result_type = u32_ty,
+ .id_result = len_id,
+ .value = .{ .uint32 = backing_bits / big_int_bits },
+ });
+ return cg.arrayType(len_id, u32_ty);
+ }
+
+ const result_id = cg.allocId();
+ try cg.sections.globals.emit(cg.gpa, .OpTypeInt, .{
+ .id_result = result_id,
+ .width = backing_bits,
+ .signedness = switch (actual_signedness) {
+ .signed => 1,
+ .unsigned => 0,
+ },
+ });
+ switch (actual_signedness) {
+ .signed => try cg.debugNameFmt(result_id, "i{}", .{backing_bits}),
+ .unsigned => try cg.debugNameFmt(result_id, "u{}", .{backing_bits}),
+ }
+ return result_id;
+}
+
+pub fn floatType(cg: *CodeGen, bits: u16) !Id {
+ assert(bits > 0);
+ const result_id = cg.allocId();
+ try cg.sections.globals.emit(cg.gpa, .OpTypeFloat, .{
+ .id_result = result_id,
+ .width = bits,
+ });
+ try cg.debugNameFmt(result_id, "f{}", .{bits});
+ return result_id;
+}
+
+pub fn vectorType(cg: *CodeGen, len: u32, child_ty_id: Id) !Id {
+ const result_id = cg.allocId();
+ try cg.sections.globals.emit(cg.gpa, .OpTypeVector, .{
+ .id_result = result_id,
+ .component_type = child_ty_id,
+ .component_count = len,
+ });
+ return result_id;
+}
+
+pub fn arrayType(cg: *CodeGen, len_id: Id, child_ty_id: Id) !Id {
+ const result_id = cg.allocId();
+ try cg.sections.globals.emit(cg.gpa, .OpTypeArray, .{
+ .id_result = result_id,
+ .element_type = child_ty_id,
+ .length = len_id,
+ });
+ return result_id;
+}
+
+pub fn ptrType(cg: *CodeGen, child_ty_id: Id, storage_class: spec.StorageClass) !Id {
+ const result_id = cg.allocId();
+ try cg.sections.globals.emit(cg.gpa, .OpTypePointer, .{
+ .id_result = result_id,
+ .storage_class = storage_class,
+ .type = child_ty_id,
+ });
+ return result_id;
+}
+
+pub fn structType(
+ cg: *CodeGen,
+ types: []const Id,
+ maybe_names: ?[]const []const u8,
+ ip_index: InternPool.Index,
+) !Id {
+ const actual_ip_index = if (cg.zcu.comp.config.root_strip) .none else ip_index;
+
+ if (cg.struct_types.get(.{ .fields = types, .ip_index = actual_ip_index })) |id| return id;
+ const result_id = cg.allocId();
+ const types_dup = try cg.arena.dupe(Id, types);
+ try cg.sections.globals.emit(cg.gpa, .OpTypeStruct, .{
+ .id_result = result_id,
+ .id_ref = types_dup,
+ });
+
+ if (maybe_names) |names| {
+ assert(names.len == types.len);
+ for (names, 0..) |name, i| {
+ try cg.memberDebugName(result_id, @intCast(i), name);
+ }
+ }
+
+ try cg.struct_types.put(
+ cg.gpa,
+ .{ .fields = types_dup, .ip_index = actual_ip_index },
+ result_id,
+ );
+ return result_id;
+}
+
+pub fn functionType(cg: *CodeGen, return_ty_id: Id, param_type_ids: []const Id) !Id {
+ const result_id = cg.allocId();
+ try cg.sections.globals.emit(cg.gpa, .OpTypeFunction, .{
+ .id_result = result_id,
+ .return_type = return_ty_id,
+ .id_ref_2 = param_type_ids,
+ });
+ return result_id;
+}
+
+pub fn constUndef(cg: *CodeGen, ty_id: Id) !Id {
+ const result_id = cg.allocId();
+ try cg.sections.globals.emit(cg.gpa, .OpUndef, .{
+ .id_result_type = ty_id,
+ .id_result = result_id,
+ });
+ return result_id;
+}
+
+pub fn constNull(cg: *CodeGen, ty_id: Id) !Id {
+ const result_id = cg.allocId();
+ try cg.sections.globals.emit(cg.gpa, .OpConstantNull, .{
+ .id_result_type = ty_id,
+ .id_result = result_id,
+ });
+ return result_id;
+}
+
+pub fn decorate(
+ cg: *CodeGen,
+ target: Id,
+ decoration: spec.Decoration.Extended,
+) !void {
+ try cg.sections.annotations.emit(cg.gpa, .OpDecorate, .{
+ .target = target,
+ .decoration = decoration,
+ });
+}
+
+pub fn decorateMember(
+ cg: *CodeGen,
+ structure_type: Id,
+ member: u32,
+ decoration: spec.Decoration.Extended,
+) !void {
+ try cg.sections.annotations.emit(cg.gpa, .OpMemberDecorate, .{
+ .structure_type = structure_type,
+ .member = member,
+ .decoration = decoration,
+ });
+}
+
+pub fn allocDecl(cg: *CodeGen, kind: Decl.Kind) !Decl.Index {
+ try cg.decls.append(cg.gpa, .{
+ .kind = kind,
+ .result_id = cg.allocId(),
+ });
+
+ return @as(Decl.Index, @enumFromInt(@as(u32, @intCast(cg.decls.items.len - 1))));
+}
+
+pub fn declPtr(cg: *CodeGen, index: Decl.Index) *Decl {
+ return &cg.decls.items[@intFromEnum(index)];
+}
+
+pub fn debugName(cg: *CodeGen, target: Id, name: []const u8) !void {
+ if (cg.zcu.comp.config.root_strip) return;
+ try cg.sections.debug_names.emit(cg.gpa, .OpName, .{
+ .target = target,
+ .name = name,
+ });
+}
+
+pub fn debugNameFmt(cg: *CodeGen, target: Id, comptime fmt: []const u8, args: anytype) !void {
+ if (cg.zcu.comp.config.root_strip) return;
+ const name = try std.fmt.allocPrint(cg.gpa, fmt, args);
+ defer cg.gpa.free(name);
+ try cg.debugName(target, name);
+}
+
+pub fn memberDebugName(cg: *CodeGen, target: Id, member: u32, name: []const u8) !void {
+ if (cg.zcu.comp.config.root_strip) return;
+ try cg.sections.debug_names.emit(cg.gpa, .OpMemberName, .{
+ .type = target,
+ .member = member,
+ .name = name,
+ });
+}
+
+pub fn storageClass(cg: *const CodeGen, as: std.lang.AddressSpace) spec.StorageClass {
+ const target = cg.zcu.getTarget();
+ return switch (as) {
+ .generic => .function,
+ .global => switch (target.os.tag) {
+ .opencl, .amdhsa => .cross_workgroup,
+ else => .storage_buffer,
+ },
+ .push_constant => .push_constant,
+ .output => .output,
+ .uniform => .uniform,
+ .storage_buffer => .storage_buffer,
+ .physical_storage_buffer => .physical_storage_buffer,
+ .constant => .uniform_constant,
+ .shared => .workgroup,
+ .local => .function,
+ .input => .input,
+ .gs,
+ .fs,
+ .ss,
+ .far,
+ .param,
+ .flash,
+ .flash1,
+ .flash2,
+ .flash3,
+ .flash4,
+ .flash5,
+ .cog,
+ .lut,
+ .hub,
+ .externref,
+ .funcref,
+ => unreachable,
+ };
}
const Error = error{ AlreadyReported, OutOfMemory };
pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
- const gpa = cg.module.gpa;
- const zcu = cg.module.zcu;
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
const ip = &zcu.intern_pool;
const target = zcu.getTarget();
@@ -179,20 +725,30 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
const val = zcu.navValue(cg.owner_nav);
const ty = val.typeOf(zcu);
- if (!do_codegen and !ty.hasRuntimeBits(zcu)) return;
+ if (!do_codegen and !ty.hasRuntimeBits(zcu)) {
+ const child_ty = if (ty.zigTypeTag(zcu) == .pointer) ty.childType(zcu) else ty;
+ if (child_ty.zigTypeTag(zcu) != .spirv) return;
+ }
- const spv_decl_index = try cg.module.resolveNav(ip, cg.owner_nav);
- const decl = cg.module.declPtr(spv_decl_index);
+ const spv_decl_index = try cg.resolveNav(ip, cg.owner_nav);
+ const decl = cg.declPtr(spv_decl_index);
const result_id = decl.result_id;
- decl.begin_dep = cg.module.decl_deps.items.len;
+ decl.begin_dep = cg.decl_deps.items.len;
switch (decl.kind) {
.func => {
+ if (nav.resolved.?.is_extern_decl) {
+ _ = try cg.resolveType(ty, .direct);
+ try emitExternFnStub(cg, nav, decl, ty);
+ decl.end_dep = cg.decl_deps.items.len;
+ return;
+ }
+
const fn_info = zcu.typeToFunc(ty).?;
const return_ty_id = try cg.resolveFnReturnType(.fromInterned(fn_info.return_type));
const is_test = zcu.test_functions.contains(cg.owner_nav);
- const func_result_id = if (is_test) cg.module.allocId() else result_id;
+ const func_result_id = if (is_test) cg.allocId() else result_id;
const prototype_ty_id = try cg.resolveType(ty, .direct);
try cg.prologue.emit(gpa, .OpFunction, .{
.id_result_type = return_ty_id,
@@ -203,14 +759,13 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
.function_control = .{},
});
- comptime assert(zig_call_abi_ver == 3);
try cg.args.ensureUnusedCapacity(gpa, fn_info.param_types.len);
for (fn_info.param_types.get(ip)) |param_ty_index| {
const param_ty: Type = .fromInterned(param_ty_index);
if (!param_ty.hasRuntimeBits(zcu)) continue;
const param_type_id = try cg.resolveType(param_ty, .direct);
- const arg_result_id = cg.module.allocId();
+ const arg_result_id = cg.allocId();
try cg.prologue.emit(gpa, .OpFunctionParameter, .{
.id_result_type = param_type_id,
.id_result = arg_result_id,
@@ -219,7 +774,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
}
// TODO: This could probably be done in a better way...
- const root_block_id = cg.module.allocId();
+ const root_block_id = cg.allocId();
// The root block of a function declaration should appear before OpVariable instructions,
// so it is generated into the function's prologue.
@@ -229,39 +784,32 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
cg.block_label = root_block_id;
const main_body = cg.air.getMainBody();
- switch (cg.control_flow) {
- .structured => {
- _ = try cg.genStructuredBody(.selection, main_body);
- // We always expect paths to here to end, but we still need the block
- // to act as a dummy merge block.
- try cg.body.emit(gpa, .OpUnreachable, {});
- },
- .unstructured => {
- try cg.genBody(main_body);
- },
- }
+ _ = try cg.genStructuredBody(.selection, main_body);
+ // We always expect paths to here to end, but we still need the block
+ // to act as a dummy merge block.
+ try cg.body.emit(gpa, .OpUnreachable, {});
try cg.body.emit(gpa, .OpFunctionEnd, {});
// Append the actual code into the functions section.
- try cg.module.sections.functions.append(gpa, cg.prologue);
- try cg.module.sections.functions.append(gpa, cg.body);
+ try cg.sections.functions.append(gpa, cg.prologue);
+ try cg.sections.functions.append(gpa, cg.body);
// Temporarily generate a test kernel declaration if this is a test function.
if (is_test) {
try cg.generateTestEntryPoint(nav.fqn.toSlice(ip), spv_decl_index, func_result_id);
}
- try cg.module.debugName(func_result_id, nav.fqn.toSlice(ip));
+ try cg.debugName(func_result_id, nav.fqn.toSlice(ip));
},
.global => {
const key = ip.indexToKey(val.toIntern()).@"extern";
- const storage_class = cg.module.storageClass(nav.resolved.?.@"addrspace");
+ const storage_class = cg.storageClass(nav.resolved.?.@"addrspace");
assert(storage_class != .generic); // These should be instance globals
const ty_id = try cg.resolveType(ty, .indirect);
- const ptr_ty_id = try cg.module.ptrType(ty_id, storage_class);
+ const ptr_ty_id = try cg.ptrType(ty_id, storage_class);
- try cg.module.sections.globals.emit(gpa, .OpVariable, .{
+ try cg.sections.globals.emit(gpa, .OpVariable, .{
.id_result_type = ptr_ty_id,
.id_result = result_id,
.storage_class = storage_class,
@@ -269,35 +817,44 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
switch (target.os.tag) {
.vulkan, .opengl => {
- if (ty.zigTypeTag(zcu) == .@"struct") {
- switch (storage_class) {
- .uniform, .push_constant => try cg.module.decorate(ty_id, .block),
- else => {},
- }
- }
+ switch (storage_class) {
+ .uniform, .push_constant, .storage_buffer, .physical_storage_buffer => {
+ if (ty.zigTypeTag(zcu) == .@"struct" and storage_class != .physical_storage_buffer) {
+ try cg.decorate(ty_id, .block);
+ }
- try cg.module.decorate(ptr_ty_id, .{
- .array_stride = .{ .array_stride = @intCast(ty.abiSize(zcu)) },
- });
+ if (ty.hasRuntimeBits(zcu)) {
+ try cg.decorate(ptr_ty_id, .{
+ .array_stride = .{ .array_stride = @intCast(ty.abiSize(zcu)) },
+ });
+ try cg.decorateLayout(ty, ty_id);
+ }
+ },
+ else => {},
+ }
if (key.decoration) |decoration| switch (decoration) {
.location => |location| {
if (storage_class != .output and storage_class != .input and storage_class != .uniform_constant) {
return cg.fail("storage class must be one of (output, input, uniform_constant) but is {s}", .{@tagName(storage_class)});
}
- try cg.module.decorate(result_id, .{
+ try cg.decorate(result_id, .{
.location = .{ .location = location },
});
},
+ .flat => |location| {
+ try cg.decorate(result_id, .{ .location = .{ .location = location } });
+ try cg.decorate(result_id, .flat);
+ },
.descriptor => |descriptor| {
if (storage_class != .storage_buffer and storage_class != .uniform and storage_class != .uniform_constant) {
return cg.fail("storage class must be one of (storage_buffer, uniform, uniform_constant) but is {s}", .{@tagName(storage_class)});
}
- try cg.module.decorate(result_id, .{
+ try cg.decorate(result_id, .{
.binding = .{ .binding_point = descriptor.binding },
});
- try cg.module.decorate(result_id, .{
+ try cg.decorate(result_id, .{
.descriptor_set = .{ .descriptor_set = descriptor.set },
});
},
@@ -306,21 +863,33 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
else => {},
}
- if (std.meta.stringToEnum(spec.BuiltIn, nav.fqn.toSlice(ip))) |builtin| {
- try cg.module.decorate(result_id, .{ .built_in = .{ .built_in = builtin } });
+ if (std.meta.stringToEnum(spec.BuiltIn, nav.fqn.toSlice(ip))) |built_in| {
+ try cg.decorate(result_id, .{ .built_in = .{ .built_in = built_in } });
}
- try cg.module.debugName(result_id, nav.fqn.toSlice(ip));
+ try cg.debugName(result_id, nav.fqn.toSlice(ip));
},
.invocation_global => {
+ // `@extern()` produces an invocation_global whose value is a
+ // comptime-known pointer to an underlying extern symbol's Nav.
+ // The pointer is inlined at use sites so we don't need a Function-scope wrapper here.
+ if (ip.indexToKey(val.toIntern()) == .ptr) alias: {
+ const ptr_key = ip.indexToKey(val.toIntern()).ptr;
+ if (ptr_key.base_addr != .nav or ptr_key.byte_offset != 0) break :alias;
+ const underlying_nav = ip.getNav(ptr_key.base_addr.nav);
+ if (!underlying_nav.resolved.?.is_extern_decl) break :alias;
+ cg.declPtr(spv_decl_index).end_dep = cg.decl_deps.items.len;
+ return;
+ }
+
const ty_id = try cg.resolveType(ty, .indirect);
- const ptr_ty_id = try cg.module.ptrType(ty_id, .function);
+ const ptr_ty_id = try cg.ptrType(ty_id, .function);
// TODO: Combine with resolveAnonDecl?
const void_ty_id = try cg.resolveType(.void, .direct);
- const initializer_proto_ty_id = try cg.module.functionType(void_ty_id, &.{});
+ const initializer_proto_ty_id = try cg.functionType(void_ty_id, &.{});
- const initializer_id = cg.module.allocId();
+ const initializer_id = cg.allocId();
try cg.prologue.emit(gpa, .OpFunction, .{
.id_result_type = try cg.resolveType(.void, .direct),
.id_result = initializer_id,
@@ -328,7 +897,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
.function_type = initializer_proto_ty_id,
});
- const root_block_id = cg.module.allocId();
+ const root_block_id = cg.allocId();
try cg.prologue.emit(gpa, .OpLabel, .{
.id_result = root_block_id,
});
@@ -342,27 +911,107 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
try cg.body.emit(gpa, .OpReturn, {});
try cg.body.emit(gpa, .OpFunctionEnd, {});
- try cg.module.sections.functions.append(gpa, cg.prologue);
- try cg.module.sections.functions.append(gpa, cg.body);
+ try cg.sections.functions.append(gpa, cg.prologue);
+ try cg.sections.functions.append(gpa, cg.body);
- try cg.module.debugNameFmt(initializer_id, "initializer of {f}", .{nav.fqn.fmt(ip)});
+ try cg.debugNameFmt(initializer_id, "initializer of {f}", .{nav.fqn.fmt(ip)});
+ try cg.debugName(result_id, nav.fqn.toSlice(ip));
- try cg.module.sections.globals.emit(gpa, .OpExtInst, .{
+ try cg.sections.globals.emit(gpa, .OpExtInst, .{
.id_result_type = ptr_ty_id,
.id_result = result_id,
- .set = try cg.module.importInstructionSet(.zig),
+ .set = try cg.importInstructionSet(.zig),
.instruction = .{ .inst = @intFromEnum(spec.Zig.InvocationGlobal) },
.id_ref_4 = &.{initializer_id},
});
},
}
- cg.module.declPtr(spv_decl_index).end_dep = cg.module.decl_deps.items.len;
+ cg.declPtr(spv_decl_index).end_dep = cg.decl_deps.items.len;
+}
+
+fn decorateLayout(cg: *CodeGen, ty: Type, ty_id: spec.Id) Error!void {
+ const zcu = cg.zcu;
+ const ip = &zcu.intern_pool;
+ switch (ty.zigTypeTag(zcu)) {
+ .array => {
+ const elem_ty = ty.childType(zcu);
+ if (!elem_ty.hasRuntimeBits(zcu)) return;
+ try cg.decorate(ty_id, .{
+ .array_stride = .{ .array_stride = @intCast(elem_ty.abiSize(zcu)) },
+ });
+ try cg.decorateLayout(elem_ty, try cg.resolveType(elem_ty, .indirect));
+ },
+ .vector => {
+ const elem_ty = ty.childType(zcu);
+ try cg.decorateLayout(elem_ty, try cg.resolveType(elem_ty, .indirect));
+ if (cg.isSpvVector(ty)) return;
+ try cg.decorate(ty_id, .{
+ .array_stride = .{ .array_stride = @intCast(elem_ty.abiSize(zcu)) },
+ });
+ },
+ .@"struct" => switch (ip.indexToKey(ty.toIntern())) {
+ .struct_type => {
+ const struct_type = ip.loadStructType(ty.toIntern());
+ if (struct_type.layout == .@"packed") return;
+ var it = struct_type.iterateRuntimeOrder(ip);
+ var member: u32 = 0;
+ while (it.next()) |field_index| {
+ const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
+ if (!field_ty.hasRuntimeBits(zcu)) continue;
+ const offset: u32 = @intCast(ty.structFieldOffset(field_index, zcu));
+ try cg.decorateMember(ty_id, member, .{ .offset = .{ .byte_offset = offset } });
+ try cg.decorateLayout(field_ty, try cg.resolveType(field_ty, .indirect));
+ member += 1;
+ }
+ },
+ .tuple_type => |tuple| {
+ for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, field_val| {
+ if (field_val != .none) continue;
+ const ft: Type = .fromInterned(field_ty);
+ if (ft.hasRuntimeBits(zcu)) try cg.decorateLayout(ft, try cg.resolveType(ft, .indirect));
+ }
+ },
+ else => {},
+ },
+ .@"union" => {
+ const union_obj = zcu.typeToUnion(ty).?;
+ if (union_obj.layout == .@"packed") return;
+ const layout = cg.unionLayout(ty);
+ if (layout.tag_size != 0) {
+ const tag_ty: Type = .fromInterned(union_obj.enum_tag_type);
+ try cg.decorateLayout(tag_ty, try cg.resolveType(tag_ty, .indirect));
+ }
+ if (layout.has_payload) {
+ try cg.decorateLayout(layout.payload_ty, try cg.resolveType(layout.payload_ty, .indirect));
+ }
+ const u8_id = try cg.resolveType(.u8, .direct);
+ if (layout.payload_padding_size != 0) {
+ const len_id = try cg.constInt(.u32, layout.payload_padding_size);
+ const arr_id = try cg.arrayType(len_id, u8_id);
+ try cg.decorate(arr_id, .{ .array_stride = .{ .array_stride = 1 } });
+ }
+ if (layout.padding_size != 0) {
+ const len_id = try cg.constInt(.u32, layout.padding_size);
+ const arr_id = try cg.arrayType(len_id, u8_id);
+ try cg.decorate(arr_id, .{ .array_stride = .{ .array_stride = 1 } });
+ }
+ },
+ .optional => {
+ const payload_ty = ty.optionalChild(zcu);
+ if (payload_ty.hasRuntimeBits(zcu)) try cg.decorateLayout(payload_ty, try cg.resolveType(payload_ty, .indirect));
+ },
+ .error_union => {
+ const payload_ty = ty.errorUnionPayload(zcu);
+ if (payload_ty.hasRuntimeBits(zcu)) try cg.decorateLayout(payload_ty, try cg.resolveType(payload_ty, .indirect));
+ },
+ else => {},
+ }
}
pub fn fail(cg: *CodeGen, comptime format: []const u8, args: anytype) Error {
@branchHint(.cold);
- return cg.module.zcu.codegenFail(cg.owner_nav, format, args);
+ return cg.zcu.codegenFail(cg.owner_nav, format, args);
}
pub fn todo(cg: *CodeGen, comptime format: []const u8, args: anytype) Error {
@@ -372,29 +1021,36 @@ pub fn todo(cg: *CodeGen, comptime format: []const u8, args: anytype) Error {
/// This imports the "default" extended instruction set for the target
/// For OpenCL, OpenCL.std.100. For Vulkan and OpenGL, GLSL.std.450.
fn importExtendedSet(cg: *CodeGen) !Id {
- const target = cg.module.zcu.getTarget();
+ const target = cg.zcu.getTarget();
return switch (target.os.tag) {
- .opencl, .amdhsa => try cg.module.importInstructionSet(.@"OpenCL.std"),
- .vulkan, .opengl => try cg.module.importInstructionSet(.@"GLSL.std.450"),
+ .opencl, .amdhsa => try cg.importInstructionSet(.@"OpenCL.std"),
+ .vulkan, .opengl => try cg.importInstructionSet(.@"GLSL.std.450"),
else => unreachable,
};
}
/// Fetch the result-id for a previously generated instruction or constant.
fn resolve(cg: *CodeGen, inst: Air.Inst.Ref) !Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ip = &zcu.intern_pool;
if (inst.toInterned()) |val_ip_index| {
const ty = cg.typeOf(inst);
if (ty.zigTypeTag(zcu) == .@"fn") {
- const fn_nav = switch (zcu.intern_pool.indexToKey(val_ip_index)) {
+ const val_key = zcu.intern_pool.indexToKey(val_ip_index);
+ const fn_nav = switch (val_key) {
.@"extern" => |@"extern"| @"extern".owner_nav,
.func => |func| func.owner_nav,
else => unreachable,
};
- const spv_decl_index = try cg.module.resolveNav(ip, fn_nav);
- try cg.module.decl_deps.append(cg.module.gpa, spv_decl_index);
- return cg.module.declPtr(spv_decl_index).result_id;
+ const spv_decl_index = try cg.resolveNav(ip, fn_nav);
+ try cg.decl_deps.append(cg.gpa, spv_decl_index);
+ const decl = cg.declPtr(spv_decl_index);
+ if (val_key == .@"extern") {
+ const nav = ip.getNav(fn_nav);
+ const nav_ty: Type = .fromInterned(nav.resolved.?.type);
+ try emitExternFnStub(cg, nav, decl, nav_ty);
+ }
+ return decl.result_id;
}
return try cg.constant(ty, .fromInterned(val_ip_index), .direct);
@@ -404,22 +1060,22 @@ fn resolve(cg: *CodeGen, inst: Air.Inst.Ref) !Id {
}
fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id {
- const gpa = cg.module.gpa;
+ const gpa = cg.gpa;
// TODO: This cannot be a function at this point, but it should probably be handled anyway.
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ty: Type = .fromInterned(zcu.intern_pool.typeOf(val));
const ty_id = try cg.resolveType(ty, .indirect);
const spv_decl_index = blk: {
- const entry = try cg.module.uav_link.getOrPut(gpa, .{ val, .function });
+ const entry = try cg.uav_link.getOrPut(gpa, .{ val, .function });
if (entry.found_existing) {
try cg.addFunctionDep(entry.value_ptr.*, .function);
- return cg.module.declPtr(entry.value_ptr.*).result_id;
+ return cg.declPtr(entry.value_ptr.*).result_id;
}
- const spv_decl_index = try cg.module.allocDecl(.invocation_global);
+ const spv_decl_index = try cg.allocDecl(.invocation_global);
try cg.addFunctionDep(spv_decl_index, .function);
entry.value_ptr.* = spv_decl_index;
break :blk spv_decl_index;
@@ -431,7 +1087,7 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id {
// constant lowering of this value will need to be deferred to an initializer similar to
// other globals.
- const result_id = cg.module.declPtr(spv_decl_index).result_id;
+ const result_id = cg.declPtr(spv_decl_index).result_id;
{
// Save the current state so that we can temporarily generate into a different function.
@@ -453,16 +1109,16 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id {
}
const void_ty_id = try cg.resolveType(.void, .direct);
- const initializer_proto_ty_id = try cg.module.functionType(void_ty_id, &.{});
+ const initializer_proto_ty_id = try cg.functionType(void_ty_id, &.{});
- const initializer_id = cg.module.allocId();
+ const initializer_id = cg.allocId();
try cg.prologue.emit(gpa, .OpFunction, .{
.id_result_type = try cg.resolveType(.void, .direct),
.id_result = initializer_id,
.function_control = .{},
.function_type = initializer_proto_ty_id,
});
- const root_block_id = cg.module.allocId();
+ const root_block_id = cg.allocId();
try cg.prologue.emit(gpa, .OpLabel, .{
.id_result = root_block_id,
});
@@ -477,16 +1133,16 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id {
try cg.body.emit(gpa, .OpReturn, {});
try cg.body.emit(gpa, .OpFunctionEnd, {});
- try cg.module.sections.functions.append(gpa, cg.prologue);
- try cg.module.sections.functions.append(gpa, cg.body);
+ try cg.sections.functions.append(gpa, cg.prologue);
+ try cg.sections.functions.append(gpa, cg.body);
- try cg.module.debugNameFmt(initializer_id, "initializer of __anon_{d}", .{@intFromEnum(val)});
+ try cg.debugNameFmt(initializer_id, "initializer of __anon_{d}", .{@intFromEnum(val)});
- const fn_decl_ptr_ty_id = try cg.module.ptrType(ty_id, .function);
- try cg.module.sections.globals.emit(gpa, .OpExtInst, .{
+ const fn_decl_ptr_ty_id = try cg.ptrType(ty_id, .function);
+ try cg.sections.globals.emit(gpa, .OpExtInst, .{
.id_result_type = fn_decl_ptr_ty_id,
.id_result = result_id,
- .set = try cg.module.importInstructionSet(.zig),
+ .set = try cg.importInstructionSet(.zig),
.instruction = .{ .inst = @intFromEnum(spec.Zig.InvocationGlobal) },
.id_ref_4 = &.{initializer_id},
});
@@ -495,15 +1151,21 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id {
return result_id;
}
-fn addFunctionDep(cg: *CodeGen, decl_index: Module.Decl.Index, storage_class: StorageClass) !void {
- const gpa = cg.module.gpa;
- const target = cg.module.zcu.getTarget();
+fn resolvePtr(cg: *CodeGen, ref: Air.Inst.Ref) !Ptr {
+ const id = try cg.resolve(ref);
+ if (cg.tracked_allocas.getPtr(id)) |slot| return .{ .tracked = .{ .id = id, .slot = slot } };
+ return .{ .id = id };
+}
+
+fn addFunctionDep(cg: *CodeGen, decl_index: Decl.Index, storage_class: StorageClass) !void {
+ const gpa = cg.gpa;
+ const target = cg.zcu.getTarget();
if (target.cpu.has(.spirv, .v1_4)) {
- try cg.module.decl_deps.append(gpa, decl_index);
+ try cg.decl_deps.append(gpa, decl_index);
} else {
// Before version 1.4, the interface’s storage classes are limited to the Input and Output
if (storage_class == .input or storage_class == .output) {
- try cg.module.decl_deps.append(gpa, decl_index);
+ try cg.decl_deps.append(gpa, decl_index);
}
}
}
@@ -513,22 +1175,9 @@ fn addFunctionDep(cg: *CodeGen, decl_index: Module.Decl.Index, storage_class: St
/// Note that there is no such thing as nested blocks like in ZIR or AIR, so we don't need to
/// keep track of the previous block.
fn beginSpvBlock(cg: *CodeGen, label: Id) !void {
- try cg.body.emit(cg.module.gpa, .OpLabel, .{ .id_result = label });
+ try cg.body.emit(cg.gpa, .OpLabel, .{ .id_result = label });
cg.block_label = label;
-}
-
-/// Return the amount of bits in the largest supported integer type. This is either 32 (always supported), or 64 (if
-/// the Int64 capability is enabled).
-/// Note: The extension SPV_INTEL_arbitrary_precision_integers allows any integer size (at least up to 32 bits).
-/// In theory that could also be used, but since the spec says that it only guarantees support up to 32-bit ints there
-/// is no way of knowing whether those are actually supported.
-/// TODO: Maybe this should be cached?
-fn largestSupportedIntBits(cg: *CodeGen) u16 {
- const target = cg.module.zcu.getTarget();
- if (target.cpu.has(.spirv, .int64) or target.cpu.arch == .spirv64) {
- return 64;
- }
- return 32;
+ cg.block_terminated = false;
}
const ArithmeticTypeInfo = struct {
@@ -568,8 +1217,8 @@ const ArithmeticTypeInfo = struct {
};
fn arithmeticTypeInfo(cg: *CodeGen, ty: Type) ArithmeticTypeInfo {
- const zcu = cg.module.zcu;
- const target = cg.module.zcu.getTarget();
+ const zcu = cg.zcu;
+ const target = cg.zcu.getTarget();
var scalar_ty = ty.scalarType(zcu);
if (scalar_ty.zigTypeTag(zcu) == .@"enum") {
scalar_ty = scalar_ty.intTagType(zcu);
@@ -578,7 +1227,7 @@ fn arithmeticTypeInfo(cg: *CodeGen, ty: Type) ArithmeticTypeInfo {
return switch (scalar_ty.zigTypeTag(zcu)) {
.bool => .{
.bits = 1, // Doesn't matter for this class.
- .backing_bits = cg.module.backingIntBits(1).@"0",
+ .backing_bits = cg.backingIntBits(1).@"0",
.vector_len = vector_len,
.signedness = .unsigned, // Technically, but doesn't matter for this class.
.class = .bool,
@@ -593,7 +1242,7 @@ fn arithmeticTypeInfo(cg: *CodeGen, ty: Type) ArithmeticTypeInfo {
.int => blk: {
const int_info = scalar_ty.intInfo(zcu);
// TODO: Maybe it's useful to also return this value.
- const backing_bits, const big_int = cg.module.backingIntBits(int_info.bits);
+ const backing_bits, const big_int = cg.backingIntBits(int_info.bits);
break :blk .{
.bits = int_info.bits,
.backing_bits = backing_bits,
@@ -613,8 +1262,8 @@ fn arithmeticTypeInfo(cg: *CodeGen, ty: Type) ArithmeticTypeInfo {
/// Checks whether the type can be directly translated to SPIR-V vectors
fn isSpvVector(cg: *CodeGen, ty: Type) bool {
- const zcu = cg.module.zcu;
- const target = cg.module.zcu.getTarget();
+ const zcu = cg.zcu;
+ const target = cg.zcu.getTarget();
if (ty.zigTypeTag(zcu) != .vector) return false;
// TODO: This check must be expanded for types that can be represented
@@ -642,22 +1291,34 @@ fn isSpvVector(cg: *CodeGen, ty: Type) bool {
/// Emits a bool constant in a particular representation.
fn constBool(cg: *CodeGen, value: bool, repr: Repr) !Id {
- return switch (repr) {
- .indirect => cg.constInt(.u1, @intFromBool(value)),
- .direct => cg.module.constBool(value),
- };
+ switch (repr) {
+ .indirect => return cg.constInt(.u1, @intFromBool(value)),
+ .direct => {
+ const result_ty_id = try cg.boolType();
+ const result_id = cg.allocId();
+ switch (value) {
+ inline else => |value_ct| try cg.sections.globals.emit(
+ cg.gpa,
+ if (value_ct) .OpConstantTrue else .OpConstantFalse,
+ .{ .id_result_type = result_ty_id, .id_result = result_id },
+ ),
+ }
+ return result_id;
+ },
+ }
}
/// Emits an integer constant.
-/// This function, unlike Module.constInt, takes care to bitcast
+/// This function, unlike cg.constInt, takes care to bitcast
/// the value to an unsigned int first for Kernels.
fn constInt(cg: *CodeGen, ty: Type, value: anytype) !Id {
- const zcu = cg.module.zcu;
- const target = cg.module.zcu.getTarget();
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
+ const target = cg.zcu.getTarget();
const scalar_ty = ty.scalarType(zcu);
const int_info = scalar_ty.intInfo(zcu);
// Use backing bits so that negatives are sign extended
- const backing_bits, const big_int = cg.module.backingIntBits(int_info.bits);
+ const backing_bits, const big_int = cg.backingIntBits(int_info.bits);
assert(backing_bits != 0); // u0 is comptime
const result_ty_id = try cg.resolveType(scalar_ty, .indirect);
@@ -671,11 +1332,18 @@ fn constInt(cg: *CodeGen, ty: Type, value: anytype) !Id {
.signed => @bitCast(@as(i64, @intCast(value))),
.unsigned => @as(u64, @intCast(value)),
};
- assert(backing_bits == 64);
- return cg.constructComposite(result_ty_id, &.{
- try cg.constInt(.u32, @as(u32, @truncate(value64))),
- try cg.constInt(.u32, @as(u32, @truncate(value64 << 32))),
- });
+ const n_limbs = backing_bits / big_int_bits;
+ const fill: u32 = if (signedness == .signed and value < 0) 0xFFFFFFFF else 0;
+ const scratch_top = cg.id_scratch.items.len;
+ defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
+ const constituents = try cg.id_scratch.addManyAsSlice(gpa, n_limbs);
+ for (constituents, 0..) |*c, i| {
+ c.* = try cg.constInt(
+ .u32,
+ if (i < 2) @as(u32, @truncate(value64 >> @intCast(i * 32))) else fill,
+ );
+ }
+ return cg.constructComposite(result_ty_id, constituents);
}
const final_value: spec.LiteralContextDependentNumber = switch (target.os.tag) {
@@ -704,15 +1372,54 @@ fn constInt(cg: *CodeGen, ty: Type, value: anytype) !Id {
},
};
- const result_id = try cg.module.constant(result_ty_id, final_value);
+ const result_id = cg.allocId();
+ try cg.sections.globals.emit(cg.gpa, .OpConstant, .{
+ .id_result_type = result_ty_id,
+ .id_result = result_id,
+ .value = final_value,
+ });
if (!ty.isVector(zcu)) return result_id;
return cg.constructCompositeSplat(ty, result_id);
}
+/// Construct a composite value from its constituents.
+/// In logical addressing mode (Vulkan/OpenGL), OpCompositeConstruct cannot accept
+/// pointer operands, so for struct types we use alloc, store for each field and load instead.
pub fn constructComposite(cg: *CodeGen, result_ty_id: Id, constituents: []const Id) !Id {
- const gpa = cg.module.gpa;
- const result_id = cg.module.allocId();
+ const gpa = cg.gpa;
+
+ const maybe_fields: ?[]const Id = for (cg.struct_types.keys(), cg.struct_types.values()) |key, val| {
+ if (val == result_ty_id) break key.fields;
+ } else null;
+ if (maybe_fields) |fields| {
+ assert(fields.len == constituents.len);
+ const u32_ty_id = try cg.intType(.unsigned, 32);
+ const var_id = try cg.alloc(result_ty_id, null);
+ for (fields, constituents, 0..) |field_ty_id, constituent, i| {
+ const field_ptr_ty_id = try cg.ptrType(field_ty_id, .function);
+ const index_id = cg.allocId();
+ try cg.sections.globals.emit(gpa, .OpConstant, .{
+ .id_result_type = u32_ty_id,
+ .id_result = index_id,
+ .value = .{ .uint32 = @intCast(i) },
+ });
+ const field_ptr = try cg.accessChainId(field_ptr_ty_id, var_id, &.{index_id});
+ try cg.body.emit(gpa, .OpStore, .{
+ .pointer = field_ptr,
+ .object = constituent,
+ });
+ }
+ const result_id = cg.allocId();
+ try cg.body.emit(gpa, .OpLoad, .{
+ .id_result_type = result_ty_id,
+ .id_result = result_id,
+ .pointer = var_id,
+ });
+ return result_id;
+ }
+
+ const result_id = cg.allocId();
try cg.body.emit(gpa, .OpCompositeConstruct, .{
.id_result_type = result_ty_id,
.id_result = result_id,
@@ -724,8 +1431,8 @@ pub fn constructComposite(cg: *CodeGen, result_ty_id: Id, constituents: []const
/// Construct a composite at runtime with all lanes set to the same value.
/// ty must be an aggregate type.
fn constructCompositeSplat(cg: *CodeGen, ty: Type, constituent: Id) !Id {
- const gpa = cg.module.gpa;
- const zcu = cg.module.zcu;
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
const n: usize = @intCast(ty.arrayLen(zcu));
const scratch_top = cg.id_scratch.items.len;
@@ -745,24 +1452,17 @@ fn constructCompositeSplat(cg: *CodeGen, ty: Type, constituent: Id) !Id {
//
/// This function should only be called during function code generation.
fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id {
- const gpa = cg.module.gpa;
-
- // Note: Using intern_map can only be used with constants that DO NOT generate any runtime code!!
- // Ideally that should be all constants in the future, or it should be cleaned up somehow. For
- // now, only use the intern_map on case-by-case basis by breaking to :cache.
- if (cg.module.intern_map.get(.{ val.toIntern(), repr })) |id| {
- return id;
- }
+ const gpa = cg.gpa;
const pt = cg.pt;
- const zcu = cg.module.zcu;
- const target = cg.module.zcu.getTarget();
+ const zcu = cg.zcu;
+ const target = cg.zcu.getTarget();
const result_ty_id = try cg.resolveType(ty, repr);
const ip = &zcu.intern_pool;
log.debug("lowering constant: ty = {f}, val = {f}, key = {s}", .{ ty.fmt(pt), val.fmtValue(pt), @tagName(ip.indexToKey(val.toIntern())) });
if (val.isUndef(zcu)) {
- return cg.module.constUndef(result_ty_id);
+ return cg.constUndef(result_ty_id);
}
const cacheable_id = cache: {
@@ -779,6 +1479,7 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id {
.tuple_type,
.union_type,
.opaque_type,
+ .spirv_type,
.enum_type,
.func_type,
.error_set_type,
@@ -801,6 +1502,27 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id {
.false, .true => break :cache try cg.constBool(val.toBool(), repr),
},
.int => {
+ const int_info = ty.intInfo(zcu);
+ const backing_bits, const is_big_int = cg.backingIntBits(int_info.bits);
+ if (is_big_int) {
+ const n_limbs = backing_bits / big_int_bits;
+ const big_result_ty_id = try cg.resolveType(ty, .indirect);
+ var bigint_space: Value.BigIntSpace = undefined;
+ const bigint = val.toBigInt(&bigint_space, zcu);
+ const limb_values = try gpa.alloc(u32, n_limbs);
+ defer gpa.free(limb_values);
+ bigint.writeTwosComplement(std.mem.sliceAsBytes(limb_values), .little);
+ if (builtin.cpu.arch.endian() == .big) {
+ for (limb_values) |*limb| limb.* = @byteSwap(limb.*);
+ }
+ const scratch_top = cg.id_scratch.items.len;
+ defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
+ const constituents = try cg.id_scratch.addManyAsSlice(gpa, n_limbs);
+ for (constituents, 0..) |*c, i| {
+ c.* = try cg.constInt(.u32, limb_values[i]);
+ }
+ break :cache try cg.constructComposite(big_result_ty_id, constituents);
+ }
if (ty.isSignedInt(zcu)) {
break :cache try cg.constInt(ty, val.toSignedInt(zcu));
} else {
@@ -815,7 +1537,13 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id {
80, 128 => unreachable, // TODO
else => unreachable,
};
- break :cache try cg.module.constant(result_ty_id, lit);
+ const lit_id = cg.allocId();
+ try cg.sections.globals.emit(gpa, .OpConstant, .{
+ .id_result_type = result_ty_id,
+ .id_result = lit_id,
+ .value = lit,
+ });
+ break :cache lit_id;
},
.err => |err| {
const value = try pt.getErrorValue(err.name);
@@ -882,7 +1610,7 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id {
if (maybe_payload_val) |payload_val| {
return try cg.constant(payload_ty, payload_val, .indirect);
} else {
- break :cache try cg.module.constNull(result_ty_id);
+ break :cache try cg.constNull(result_ty_id);
}
}
@@ -893,7 +1621,7 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id {
const payload_id = if (maybe_payload_val) |payload_val|
try cg.constant(payload_ty, payload_val, .indirect)
else
- try cg.module.constUndef(try cg.resolveType(payload_ty, .indirect));
+ try cg.constUndef(try cg.resolveType(payload_ty, .indirect));
const comp_ty_id = try cg.resolveType(ty, .direct);
return try cg.constructComposite(comp_ty_id, &.{ payload_id, has_pl_id });
@@ -962,7 +1690,23 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id {
const comp_ty_id = try cg.resolveType(ty, .direct);
return try cg.constructComposite(comp_ty_id, constituents.items);
},
- .tuple_type => return cg.todo("implement tuple types", .{}),
+ .tuple_type => |tuple| {
+ var constituents: std.ArrayList(Id) = .empty;
+ defer constituents.deinit(gpa);
+
+ for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| {
+ if (field_val != .none) continue;
+ const ft: Type = .fromInterned(field_ty);
+ if (!ft.hasRuntimeBits(zcu)) continue;
+
+ const fv = try val.fieldValue(pt, i);
+ const field_id = try cg.constant(ft, fv, .indirect);
+ try constituents.append(gpa, field_id);
+ }
+
+ const comp_ty_id = try cg.resolveType(ty, .direct);
+ return try cg.constructComposite(comp_ty_id, constituents.items);
+ },
else => unreachable,
},
.un => |un| {
@@ -987,21 +1731,18 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id {
.memoized_call => unreachable,
}
};
-
- try cg.module.intern_map.putNoClobber(gpa, .{ val.toIntern(), repr }, cacheable_id);
-
return cacheable_id;
}
fn constantPtr(cg: *CodeGen, ptr_val: Value) !Id {
const pt = cg.pt;
- const zcu = cg.module.zcu;
- const gpa = cg.module.gpa;
+ const zcu = cg.zcu;
+ const gpa = cg.gpa;
if (ptr_val.isUndef(zcu)) {
const result_ty = ptr_val.typeOf(zcu);
const result_ty_id = try cg.resolveType(result_ty, .direct);
- return cg.module.constUndef(result_ty_id);
+ return cg.constUndef(result_ty_id);
}
var arena = std.heap.ArenaAllocator.init(gpa);
@@ -1012,9 +1753,9 @@ fn constantPtr(cg: *CodeGen, ptr_val: Value) !Id {
}
fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id {
- const gpa = cg.module.gpa;
+ const gpa = cg.gpa;
const pt = cg.pt;
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const target = zcu.getTarget();
switch (derivation) {
.comptime_alloc_ptr, .comptime_field_ptr => unreachable,
@@ -1031,7 +1772,7 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id {
// TODO: This can probably be an OpSpecConstantOp Bitcast, but
// that is not implemented by Mesa yet. Therefore, just generate it
// as a runtime operation.
- const result_ptr_id = cg.module.allocId();
+ const result_ptr_id = cg.allocId();
const value_id = try cg.constInt(.usize, int.addr);
try cg.body.emit(gpa, .OpConvertUToPtr, .{
.id_result_type = result_ty_id,
@@ -1040,13 +1781,87 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id {
});
return result_ptr_id;
},
- .nav_ptr => |nav| {
- const result_ptr_ty = try pt.navPtrType(nav);
- return cg.constantNavRef(result_ptr_ty, nav);
+ .nav_ptr => |nav_index| {
+ const ip = &zcu.intern_pool;
+ const result_ptr_ty = try pt.navPtrType(nav_index);
+ const ty_id = try cg.resolveType(result_ptr_ty, .direct);
+ const nav = ip.getNav(nav_index);
+ const nav_ty: Type = .fromInterned(nav.resolved.?.type);
+
+ switch (nav.resolved.?.value) {
+ .none => {},
+ else => |value| switch (ip.indexToKey(value)) {
+ // TODO: Properly lower function pointers; for now substitute undef.
+ .func => return try cg.constUndef(ty_id),
+ .@"extern" => if (ip.isFunctionType(nav_ty.toIntern())) {
+ const spv_decl_index = try cg.resolveNav(ip, nav_index);
+ const decl = cg.declPtr(spv_decl_index);
+ try emitExternFnStub(cg, nav, decl, nav_ty);
+ return decl.result_id;
+ },
+ else => {},
+ },
+ }
+
+ if (!nav_ty.hasRuntimeBits(zcu) and nav_ty.zigTypeTag(zcu) != .spirv) {
+ return cg.constUndef(ty_id);
+ }
+
+ const spv_decl_index = try cg.resolveNav(ip, nav_index);
+ const spv_decl = cg.declPtr(spv_decl_index);
+ assert(spv_decl.kind != .func);
+ const storage_class = cg.storageClass(nav.resolved.?.@"addrspace");
+ try cg.addFunctionDep(spv_decl_index, storage_class);
+
+ const nav_ty_id = try cg.resolveType(nav_ty, .indirect);
+ const decl_ptr_ty_id = try cg.ptrType(nav_ty_id, storage_class);
+ if (decl_ptr_ty_id == ty_id) return spv_decl.result_id;
+ switch (target.os.tag) {
+ .vulkan, .opengl => return spv_decl.result_id,
+ else => {},
+ }
+ const casted_ptr_id = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = ty_id,
+ .id_result = casted_ptr_id,
+ .operand = spv_decl.result_id,
+ });
+ return casted_ptr_id;
},
.uav_ptr => |uav| {
+ const ip = &zcu.intern_pool;
const result_ptr_ty: Type = .fromInterned(uav.orig_ty);
- return cg.constantUavRef(result_ptr_ty, uav);
+ const ty_id = try cg.resolveType(result_ptr_ty, .direct);
+ const uav_ty: Type = .fromInterned(ip.typeOf(uav.val));
+
+ switch (ip.indexToKey(uav.val)) {
+ .func => unreachable, // TODO
+ .@"extern" => assert(!ip.isFunctionType(uav_ty.toIntern())),
+ else => {},
+ }
+
+ if (!uav_ty.hasRuntimeBits(zcu) and uav_ty.zigTypeTag(zcu) != .spirv) {
+ return cg.constUndef(ty_id);
+ }
+
+ // Uav refs are always generic.
+ assert(result_ptr_ty.ptrAddressSpace(zcu) == .generic);
+ const uav_ty_id = try cg.resolveType(uav_ty, .indirect);
+ const decl_ptr_ty_id = try cg.ptrType(uav_ty_id, .function);
+ const ptr_id = try cg.resolveUav(uav.val);
+
+ if (decl_ptr_ty_id == ty_id) return ptr_id;
+ switch (target.os.tag) {
+ .vulkan, .opengl => return ptr_id,
+ else => {},
+ }
+ const casted_ptr_id = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = ty_id,
+ .id_result = casted_ptr_id,
+ .operand = ptr_id,
+ });
+ return casted_ptr_id;
},
.eu_payload_ptr => @panic("TODO"),
.opt_payload_ptr => @panic("TODO"),
@@ -1065,28 +1880,47 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id {
const parent_ptr_id = try cg.derivePtr(oac.parent.*);
const parent_ptr_ty = try oac.parent.ptrType(pt);
const result_ty_id = try cg.resolveType(oac.new_ptr_ty, .direct);
- const child_size = oac.new_ptr_ty.childType(zcu).abiSize(zcu);
- if (parent_ptr_ty.childType(zcu).isVector(zcu) and oac.byte_offset % child_size == 0) {
+ if (parent_ptr_ty.childType(zcu).isVector(zcu)) {
// Vector element ptr accesses are derived as offset_and_cast.
// We can just use OpAccessChain.
- return cg.accessChain(
- result_ty_id,
- parent_ptr_id,
- &.{@intCast(@divExact(oac.byte_offset, child_size))},
- );
+ const child_size = oac.new_ptr_ty.childType(zcu).abiSize(zcu);
+ if (oac.byte_offset % child_size == 0) {
+ return cg.accessChain(
+ result_ty_id,
+ parent_ptr_id,
+ &.{@intCast(@divExact(oac.byte_offset, child_size))},
+ );
+ }
}
if (oac.byte_offset == 0) {
- // Allow changing the pointer type child only to restructure arrays.
- // e.g. [3][2]T to T is fine, as is [2]T -> [2][1]T.
- const result_ptr_id = cg.module.allocId();
- try cg.body.emit(gpa, .OpBitcast, .{
- .id_result_type = result_ty_id,
- .id_result = result_ptr_id,
- .operand = parent_ptr_id,
- });
- return result_ptr_id;
+ var depth: u32 = 0;
+ var cur = parent_ptr_ty.childType(zcu);
+ const dst_child = oac.new_ptr_ty.childType(zcu);
+ while (cur.toIntern() != dst_child.toIntern()) {
+ if (cur.zigTypeTag(zcu) == .array) {
+ cur = cur.childType(zcu);
+ depth += 1;
+ } else break;
+ }
+ if (depth > 0 and cur.toIntern() == dst_child.toIntern()) {
+ const scratch_top = cg.id_scratch.items.len;
+ defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
+ const zero = try cg.constInt(.u32, 0);
+ const ids = try cg.id_scratch.addManyAsSlice(gpa, depth);
+ @memset(ids, zero);
+ return cg.accessChainId(result_ty_id, parent_ptr_id, ids);
+ }
+ if (target.os.tag == .opencl) {
+ const result_ptr_id = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = result_ty_id,
+ .id_result = result_ptr_id,
+ .operand = parent_ptr_id,
+ });
+ return result_ptr_id;
+ }
}
return cg.fail("cannot perform pointer cast: '{f}' to '{f}'", .{
@@ -1097,103 +1931,53 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id {
}
}
-fn constantUavRef(
- cg: *CodeGen,
- ty: Type,
- uav: InternPool.Key.Ptr.BaseAddr.Uav,
-) !Id {
- // TODO: Merge this function with constantDeclRef.
-
- const zcu = cg.module.zcu;
+/// Emit a stub OpFunction/OpFunctionEnd + Import linkage decoration for an
+/// extern function so the module is structurally valid. The stub will be
+/// replaced by the real definition at link time.
+fn emitExternFnStub(cg: *CodeGen, nav: InternPool.Nav, decl: *Decl, fn_ty: Type) !void {
+ if (decl.has_extern_stub) return;
+ decl.has_extern_stub = true;
+
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
const ip = &zcu.intern_pool;
- const ty_id = try cg.resolveType(ty, .direct);
- const uav_ty: Type = .fromInterned(ip.typeOf(uav.val));
-
- switch (ip.indexToKey(uav.val)) {
- .func => unreachable, // TODO
- .@"extern" => assert(!ip.isFunctionType(uav_ty.toIntern())),
- else => {},
- }
-
- // const is_fn_body = decl_ty.zigTypeTag(zcu) == .@"fn";
- if (!uav_ty.hasRuntimeBits(zcu)) {
- // Pointer to nothing - return undefined
- return cg.module.constUndef(ty_id);
- }
-
- // Uav refs are always generic.
- assert(ty.ptrAddressSpace(zcu) == .generic);
- const uav_ty_id = try cg.resolveType(uav_ty, .indirect);
- const decl_ptr_ty_id = try cg.module.ptrType(uav_ty_id, .function);
- const ptr_id = try cg.resolveUav(uav.val);
-
- if (decl_ptr_ty_id != ty_id) {
- // Differing pointer types, insert a cast.
- const casted_ptr_id = cg.module.allocId();
- try cg.body.emit(cg.module.gpa, .OpBitcast, .{
- .id_result_type = ty_id,
- .id_result = casted_ptr_id,
- .operand = ptr_id,
+ const fn_info = zcu.typeToFunc(fn_ty).?;
+ const return_ty_id = try cg.resolveFnReturnType(.fromInterned(fn_info.return_type));
+ const prototype_ty_id = try cg.resolveType(fn_ty, .direct);
+
+ var stub: Section = .{};
+ defer stub.deinit(gpa);
+ try stub.emit(gpa, .OpFunction, .{
+ .id_result_type = return_ty_id,
+ .id_result = decl.result_id,
+ .function_type = prototype_ty_id,
+ .function_control = .{},
+ });
+ for (fn_info.param_types.get(ip)) |param_ty_index| {
+ const param_ty: Type = .fromInterned(param_ty_index);
+ if (!param_ty.hasRuntimeBits(zcu)) continue;
+ const param_type_id = try cg.resolveType(param_ty, .direct);
+ try stub.emit(gpa, .OpFunctionParameter, .{
+ .id_result_type = param_type_id,
+ .id_result = cg.allocId(),
});
- return casted_ptr_id;
- } else {
- return ptr_id;
}
+ try stub.emit(gpa, .OpFunctionEnd, {});
+ try cg.sections.functions.append(gpa, stub);
+
+ const extern_name = nav.getExtern(ip).?.name.toSlice(ip);
+ try cg.sections.annotations.emit(gpa, .OpDecorate, .{
+ .target = decl.result_id,
+ .decoration = .{ .linkage_attributes = .{
+ .name = extern_name,
+ .linkage_type = .import,
+ } },
+ });
+ try cg.debugName(decl.result_id, extern_name);
}
-fn constantNavRef(cg: *CodeGen, ty: Type, nav_index: InternPool.Nav.Index) !Id {
- const zcu = cg.module.zcu;
- const ip = &zcu.intern_pool;
- const ty_id = try cg.resolveType(ty, .direct);
- const nav = ip.getNav(nav_index);
- const nav_ty: Type = .fromInterned(nav.resolved.?.type);
-
- switch (nav.resolved.?.value) {
- .none => {}, // this is not a function or extern
- else => |value| switch (ip.indexToKey(value)) {
- .func => {
- // TODO: Properly lower function pointers. For now we are going to hack around it and
- // just generate an empty pointer. Function pointers are represented by a pointer to usize.
- return try cg.module.constUndef(ty_id);
- },
- .@"extern" => if (ip.isFunctionType(nav_ty.toIntern())) @panic("TODO"),
- else => {},
- },
- }
-
- if (!nav_ty.hasRuntimeBits(zcu)) {
- // Pointer to nothing - return undefined.
- return cg.module.constUndef(ty_id);
- }
-
- const spv_decl_index = try cg.module.resolveNav(ip, nav_index);
- const spv_decl = cg.module.declPtr(spv_decl_index);
- const spv_decl_result_id = spv_decl.result_id;
- assert(spv_decl.kind != .func);
-
- const storage_class = cg.module.storageClass(nav.resolved.?.@"addrspace");
- try cg.addFunctionDep(spv_decl_index, storage_class);
-
- const nav_ty_id = try cg.resolveType(nav_ty, .indirect);
- const decl_ptr_ty_id = try cg.module.ptrType(nav_ty_id, storage_class);
-
- if (decl_ptr_ty_id != ty_id) {
- // Differing pointer types, insert a cast.
- const casted_ptr_id = cg.module.allocId();
- try cg.body.emit(cg.module.gpa, .OpBitcast, .{
- .id_result_type = ty_id,
- .id_result = casted_ptr_id,
- .operand = spv_decl_result_id,
- });
- return casted_ptr_id;
- }
-
- return spv_decl_result_id;
-}
-
-// Turn a Zig type's name into a cache reference.
fn resolveTypeName(cg: *CodeGen, ty: Type) ![]const u8 {
- const gpa = cg.module.gpa;
+ const gpa = cg.gpa;
var aw: std.Io.Writer.Allocating = .init(gpa);
defer aw.deinit();
ty.print(&aw.writer, cg.pt, null) catch |err| switch (err) {
@@ -1220,68 +2004,8 @@ fn resolveTypeName(cg: *CodeGen, ty: Type) ![]const u8 {
/// padding: [padding_size]u8,
/// }
/// If any of the fields' size is 0, it will be omitted.
-fn resolveUnionType(cg: *CodeGen, ty: Type) !Id {
- const gpa = cg.module.gpa;
- const zcu = cg.module.zcu;
- const union_obj = zcu.typeToUnion(ty).?;
-
- if (union_obj.layout == .@"packed") {
- return try cg.module.intType(.unsigned, @intCast(ty.bitSize(zcu)));
- }
-
- const layout = cg.unionLayout(ty);
- if (!layout.has_payload) {
- // No payload, so represent this as just the tag type.
- return try cg.resolveType(.fromInterned(union_obj.enum_tag_type), .indirect);
- }
-
- var member_types: [4]Id = undefined;
- var member_names: [4][]const u8 = undefined;
-
- const u8_ty_id = try cg.resolveType(.u8, .direct);
-
- if (layout.tag_size != 0) {
- const tag_ty_id = try cg.resolveType(.fromInterned(union_obj.enum_tag_type), .indirect);
- member_types[layout.tag_index] = tag_ty_id;
- member_names[layout.tag_index] = "(tag)";
- }
-
- if (layout.payload_size != 0) {
- const payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect);
- member_types[layout.payload_index] = payload_ty_id;
- member_names[layout.payload_index] = "(payload)";
- }
-
- if (layout.payload_padding_size != 0) {
- const len_id = try cg.constInt(.u32, layout.payload_padding_size);
- const payload_padding_ty_id = try cg.module.arrayType(len_id, u8_ty_id);
- member_types[layout.payload_padding_index] = payload_padding_ty_id;
- member_names[layout.payload_padding_index] = "(payload padding)";
- }
-
- if (layout.padding_size != 0) {
- const len_id = try cg.constInt(.u32, layout.padding_size);
- const padding_ty_id = try cg.module.arrayType(len_id, u8_ty_id);
- member_types[layout.padding_index] = padding_ty_id;
- member_names[layout.padding_index] = "(padding)";
- }
-
- const result_id = try cg.module.structType(
- member_types[0..layout.total_fields],
- member_names[0..layout.total_fields],
- null,
- .none,
- );
-
- const type_name = try cg.resolveTypeName(ty);
- defer gpa.free(type_name);
- try cg.module.debugName(result_id, type_name);
-
- return result_id;
-}
-
fn resolveFnReturnType(cg: *CodeGen, ret_ty: Type) !Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
if (!ret_ty.hasRuntimeBits(zcu)) {
// If the return type is an error set or an error union, then we make this
// anyerror return type instead, so that it can be coerced into a function
@@ -1297,38 +2021,38 @@ fn resolveFnReturnType(cg: *CodeGen, ret_ty: Type) !Id {
}
fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
- const gpa = cg.module.gpa;
+ const gpa = cg.gpa;
const pt = cg.pt;
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ip = &zcu.intern_pool;
- const target = cg.module.zcu.getTarget();
+ const target = cg.zcu.getTarget();
log.debug("resolveType: ty = {f}", .{ty.fmt(pt)});
switch (ty.zigTypeTag(zcu)) {
.noreturn => {
assert(repr == .direct);
- return try cg.module.voidType();
+ return try cg.voidType();
},
.void => switch (repr) {
- .direct => return try cg.module.voidType(),
+ .direct => return try cg.voidType(),
.indirect => {
if (target.os.tag != .opencl) return cg.fail("cannot generate opaque type", .{});
- return try cg.module.opaqueType("void");
+ return try cg.opaqueType("void");
},
},
.bool => switch (repr) {
- .direct => return try cg.module.boolType(),
+ .direct => return try cg.boolType(),
.indirect => return try cg.resolveType(.u1, .indirect),
},
.int => {
if (ty.toIntern() == .u0_type) {
assert(repr == .indirect);
if (target.os.tag != .opencl) return cg.fail("cannot generate opaque type", .{});
- return try cg.module.opaqueType("u0");
+ return try cg.opaqueType("u0");
}
const int_info = ty.intInfo(zcu);
- return try cg.module.intType(int_info.signedness, int_info.bits);
+ return try cg.intType(int_info.signedness, int_info.bits);
},
.@"enum" => return try cg.resolveType(ty.intTagType(zcu), repr),
.float => {
@@ -1347,7 +2071,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
);
}
- return try cg.module.floatType(bits);
+ return try cg.floatType(bits);
},
.array => {
const elem_ty = ty.childType(zcu);
@@ -1359,7 +2083,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
if (!elem_ty.hasRuntimeBits(zcu)) {
assert(repr == .indirect);
if (target.os.tag != .opencl) return cg.fail("cannot generate opaque type", .{});
- return try cg.module.opaqueType("zero-sized-array");
+ return try cg.opaqueType("zero-sized-array");
} else if (total_len == 0) {
// The size of the array would be 0, but that is not allowed in SPIR-V.
// This path can be reached for example when there is a slicing of a pointer
@@ -1370,36 +2094,24 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
// generate an array of 1 element instead, so that ptr_elem_ptr instructions
// can be lowered to ptrAccessChain instead of manually performing the math.
const len_id = try cg.constInt(.u32, 1);
- return try cg.module.arrayType(len_id, elem_ty_id);
+ return try cg.arrayType(len_id, elem_ty_id);
} else {
const total_len_id = try cg.constInt(.u32, total_len);
- const result_id = try cg.module.arrayType(total_len_id, elem_ty_id);
- switch (target.os.tag) {
- .vulkan, .opengl => {
- try cg.module.decorate(result_id, .{
- .array_stride = .{
- .array_stride = @intCast(elem_ty.abiSize(zcu)),
- },
- });
- },
- else => {},
- }
- return result_id;
+ return try cg.arrayType(total_len_id, elem_ty_id);
}
},
.vector => {
const elem_ty = ty.childType(zcu);
const elem_ty_id = try cg.resolveType(elem_ty, repr);
const len = ty.vectorLen(zcu);
- if (cg.isSpvVector(ty)) return try cg.module.vectorType(len, elem_ty_id);
+ if (cg.isSpvVector(ty)) return try cg.vectorType(len, elem_ty_id);
const len_id = try cg.constInt(.u32, len);
- return try cg.module.arrayType(len_id, elem_ty_id);
+ return try cg.arrayType(len_id, elem_ty_id);
},
.@"fn" => switch (repr) {
.direct => {
const fn_info = zcu.typeToFunc(ty).?;
- comptime assert(zig_call_abi_ver == 3);
assert(!fn_info.is_var_args);
switch (fn_info.cc) {
.auto,
@@ -1407,6 +2119,8 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
.spirv_fragment,
.spirv_vertex,
.spirv_device,
+ .spirv_task,
+ .spirv_mesh,
=> {},
else => unreachable,
}
@@ -1426,7 +2140,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
param_index += 1;
}
- return try cg.module.functionType(return_ty_id, param_ty_ids[0..param_index]);
+ return try cg.functionType(return_ty_id, param_ty_ids[0..param_index]);
},
.indirect => {
// TODO: Represent function pointers properly.
@@ -1437,20 +2151,29 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
.pointer => {
const ptr_info = ty.ptrInfo(zcu);
- const child_ty: Type = .fromInterned(ptr_info.child);
+ const child_ty: Type = switch (ptr_info.packed_offset.host_size) {
+ 0 => .fromInterned(ptr_info.child),
+ else => switch (ptr_info.flags.vector_index) {
+ // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate these usages of `pt`.
+ .none => try pt.intType(.unsigned, ptr_info.packed_offset.host_size * 8),
+ else => try pt.vectorType(.{
+ .child = ptr_info.child,
+ .len = ptr_info.packed_offset.host_size,
+ }),
+ },
+ };
const child_ty_id = try cg.resolveType(child_ty, .indirect);
- const storage_class = cg.module.storageClass(ptr_info.flags.address_space);
- const ptr_ty_id = try cg.module.ptrType(child_ty_id, storage_class);
+ const storage_class = cg.storageClass(ptr_info.flags.address_space);
+ const ptr_ty_id = try cg.ptrType(child_ty_id, storage_class);
if (ptr_info.flags.size != .slice) {
return ptr_ty_id;
}
const size_ty_id = try cg.resolveType(.usize, .direct);
- return try cg.module.structType(
+ return try cg.structType(
&.{ ptr_ty_id, size_ty_id },
&.{ "ptr", "len" },
- null,
.none,
);
},
@@ -1469,15 +2192,14 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
member_index += 1;
}
- const result_id = try cg.module.structType(
+ const result_id = try cg.structType(
member_types[0..member_index],
null,
- null,
.none,
);
const type_name = try cg.resolveTypeName(ty);
defer gpa.free(type_name);
- try cg.module.debugName(result_id, type_name);
+ try cg.debugName(result_id, type_name);
return result_id;
},
.struct_type => ip.loadStructType(ty.toIntern()),
@@ -1494,9 +2216,6 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
var member_names = std.array_list.Managed([]const u8).init(gpa);
defer member_names.deinit();
- var member_offsets = std.array_list.Managed(u32).init(gpa);
- defer member_offsets.deinit();
-
var it = struct_type.iterateRuntimeOrder(ip);
while (it.next()) |field_index| {
const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
@@ -1505,19 +2224,17 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
const field_name = struct_type.field_names.get(ip)[field_index];
try member_types.append(try cg.resolveType(field_ty, .indirect));
try member_names.append(field_name.toSlice(ip));
- try member_offsets.append(@intCast(ty.structFieldOffset(field_index, zcu)));
}
- const result_id = try cg.module.structType(
+ const result_id = try cg.structType(
member_types.items,
member_names.items,
- member_offsets.items,
ty.toIntern(),
);
const type_name = try cg.resolveTypeName(ty);
defer gpa.free(type_name);
- try cg.module.debugName(result_id, type_name);
+ try cg.debugName(result_id, type_name);
return result_id;
},
@@ -1538,14 +2255,52 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
const bool_ty_id = try cg.resolveType(.bool, .indirect);
- return try cg.module.structType(
+ return try cg.structType(
&.{ payload_ty_id, bool_ty_id },
&.{ "payload", "valid" },
- null,
.none,
);
},
- .@"union" => return try cg.resolveUnionType(ty),
+ .@"union" => {
+ const union_obj = zcu.typeToUnion(ty).?;
+ if (union_obj.layout == .@"packed") {
+ return try cg.intType(.unsigned, @intCast(ty.bitSize(zcu)));
+ }
+ const layout = cg.unionLayout(ty);
+ if (!layout.has_payload) {
+ return try cg.resolveType(.fromInterned(union_obj.enum_tag_type), .indirect);
+ }
+ var member_types: [4]Id = undefined;
+ var member_names: [4][]const u8 = undefined;
+ const u8_ty_id = try cg.resolveType(.u8, .direct);
+ if (layout.tag_size != 0) {
+ member_types[layout.tag_index] = try cg.resolveType(.fromInterned(union_obj.enum_tag_type), .indirect);
+ member_names[layout.tag_index] = "(tag)";
+ }
+ if (layout.payload_size != 0) {
+ member_types[layout.payload_index] = try cg.resolveType(layout.payload_ty, .indirect);
+ member_names[layout.payload_index] = "(payload)";
+ }
+ if (layout.payload_padding_size != 0) {
+ const len_id = try cg.constInt(.u32, layout.payload_padding_size);
+ member_types[layout.payload_padding_index] = try cg.arrayType(len_id, u8_ty_id);
+ member_names[layout.payload_padding_index] = "(payload padding)";
+ }
+ if (layout.padding_size != 0) {
+ const len_id = try cg.constInt(.u32, layout.padding_size);
+ member_types[layout.padding_index] = try cg.arrayType(len_id, u8_ty_id);
+ member_names[layout.padding_index] = "(padding)";
+ }
+ const result_id = try cg.structType(
+ member_types[0..layout.total_fields],
+ member_names[0..layout.total_fields],
+ .none,
+ );
+ const type_name = try cg.resolveTypeName(ty);
+ defer gpa.free(type_name);
+ try cg.debugName(result_id, type_name);
+ return result_id;
+ },
.error_set => {
const err_int_ty = try pt.errorIntType();
return try cg.resolveType(err_int_ty, repr);
@@ -1576,13 +2331,88 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
// TODO: ABI padding?
}
- return try cg.module.structType(&member_types, &member_names, null, .none);
+ return try cg.structType(&member_types, &member_names, .none);
},
.@"opaque" => {
if (target.os.tag != .opencl) return cg.fail("cannot generate opaque type", .{});
const type_name = try cg.resolveTypeName(ty);
defer gpa.free(type_name);
- return try cg.module.opaqueType(type_name);
+ return try cg.opaqueType(type_name);
+ },
+ .spirv => {
+ const spirv_type = ip.loadSpirvType(ty.toIntern());
+ const result_id = cg.allocId();
+ switch (spirv_type.flags.tag) {
+ .sampler => try cg.sections.globals.emit(gpa, .OpTypeSampler, .{ .id_result = result_id }),
+ .image => {
+ const sampled_type_id = try cg.resolveType(.fromInterned(spirv_type.ty), .direct);
+ try cg.sections.globals.emit(gpa, .OpTypeImage, .{
+ .id_result = result_id,
+ .sampled_type = sampled_type_id,
+ .dim = switch (spirv_type.flags.dim) {
+ .@"1d" => .@"1d",
+ .@"2d" => .@"2d",
+ .@"3d" => .@"3d",
+ .cube => .cube,
+ },
+ .depth = switch (spirv_type.flags.depth) {
+ .not_depth => 0,
+ .depth => 1,
+ .unknown => 2,
+ },
+ .arrayed = @intFromBool(spirv_type.flags.is_arrayed),
+ .ms = @intFromBool(spirv_type.flags.is_multisampled),
+ .sampled = switch (spirv_type.flags.usage) {
+ .unknown => 0,
+ .sampled => 1,
+ .storage => 2,
+ },
+ .image_format = switch (spirv_type.flags.format) {
+ .unknown => .unknown,
+ .rgba32f => .rgba32f,
+ .rgba32i => .rgba32i,
+ .rgba32u => .rgba32ui,
+ .rgba16f => .rgba16f,
+ .rgba16i => .rgba16i,
+ .rgba16u => .rgba16ui,
+ .rgba8unorm => .rgba8,
+ .rgba8snorm => .rgba8snorm,
+ .rgba8i => .rgba8i,
+ .rgba8u => .rgba8ui,
+ .r32f => .r32f,
+ .r32i => .r32i,
+ .r32u => .r32ui,
+ },
+ .access_qualifier = switch (spirv_type.flags.access) {
+ .unknown => null,
+ .read_only => .read_only,
+ .write_only => .write_only,
+ .read_write => .read_write,
+ },
+ });
+ },
+ .sampled_image => {
+ const image_ty_id = try cg.resolveType(.fromInterned(spirv_type.ty), .indirect);
+ try cg.sections.globals.emit(gpa, .OpTypeSampledImage, .{
+ .id_result = result_id,
+ .image_type = image_ty_id,
+ });
+ },
+ .runtime_array => {
+ const elem_ty: Type = .fromInterned(spirv_type.ty);
+ const elem_ty_id = try cg.resolveType(elem_ty, .indirect);
+ try cg.sections.globals.emit(gpa, .OpTypeRuntimeArray, .{
+ .id_result = result_id,
+ .element_type = elem_ty_id,
+ });
+ if (elem_ty.hasRuntimeBits(zcu)) {
+ try cg.decorate(result_id, .{ .array_stride = .{
+ .array_stride = @intCast(elem_ty.abiSize(zcu)),
+ } });
+ }
+ },
+ }
+ return result_id;
},
.null,
@@ -1613,7 +2443,7 @@ const ErrorUnionLayout = struct {
};
fn errorUnionLayout(cg: *CodeGen, payload_ty: Type) ErrorUnionLayout {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const error_align = Type.abiAlignment(.anyerror, zcu);
const payload_align = payload_ty.abiAlignment(zcu);
@@ -1644,7 +2474,7 @@ const UnionLayout = struct {
};
fn unionLayout(cg: *CodeGen, ty: Type) UnionLayout {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ip = &zcu.intern_pool;
const layout = ty.unionGetLayout(zcu);
const union_obj = zcu.typeToUnion(ty).?;
@@ -1734,8 +2564,8 @@ const Temporary = struct {
}
fn materialize(temp: Temporary, cg: *CodeGen) !Id {
- const gpa = cg.module.gpa;
- const zcu = cg.module.zcu;
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
switch (temp.value) {
.singleton => |id| return id,
.exploded_vector => |range| {
@@ -1769,7 +2599,7 @@ const Temporary = struct {
/// 'Explode' a temporary into separate elements. This turns a vector
/// into a bag of elements.
fn explode(temp: Temporary, cg: *CodeGen) !IdRange {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
// If the value is a scalar, then this is a no-op.
if (!temp.ty.isVector(zcu)) {
@@ -1781,7 +2611,7 @@ const Temporary = struct {
const ty_id = try cg.resolveType(temp.ty.scalarType(zcu), .direct);
const n = temp.ty.vectorLen(zcu);
- const results = cg.module.allocIds(n);
+ const results = cg.allocIds(n);
const id = switch (temp.value) {
.singleton => |id| id,
@@ -1790,7 +2620,7 @@ const Temporary = struct {
for (0..n) |i| {
const indexes = [_]u32{@intCast(i)};
- try cg.body.emit(cg.module.gpa, .OpCompositeExtract, .{
+ try cg.body.emit(cg.gpa, .OpCompositeExtract, .{
.id_result_type = ty_id,
.id_result = results.at(i),
.composite = id,
@@ -1802,6 +2632,715 @@ const Temporary = struct {
}
};
+/// composite integers are represented as [N]u32 arrays
+const CompositeInt = struct {
+ cg: *CodeGen,
+ limbs: []Id,
+ n_limbs: u16,
+ info: ArithmeticTypeInfo,
+
+ fn init(cg: *CodeGen, composite_id: Id, info: ArithmeticTypeInfo) !CompositeInt {
+ const n_limbs: u16 = info.backing_bits / big_int_bits;
+ const gpa = cg.gpa;
+ const u32_ty_id = try cg.resolveType(.u32, .direct);
+ const limbs = try cg.id_scratch.addManyAsSlice(gpa, n_limbs);
+ for (limbs, 0..) |*limb, i| {
+ const result_id = cg.allocId();
+ try cg.body.emit(gpa, .OpCompositeExtract, .{
+ .id_result_type = u32_ty_id,
+ .id_result = result_id,
+ .composite = composite_id,
+ .indexes = &.{@as(u32, @intCast(i))},
+ });
+ limb.* = result_id;
+ }
+ return .{ .cg = cg, .limbs = limbs, .n_limbs = n_limbs, .info = info };
+ }
+
+ fn fromLimbs(cg: *CodeGen, limbs: []Id, info: ArithmeticTypeInfo) CompositeInt {
+ return .{
+ .cg = cg,
+ .limbs = limbs,
+ .n_limbs = @intCast(limbs.len),
+ .info = info,
+ };
+ }
+
+ fn zero(cg: *CodeGen, info: ArithmeticTypeInfo) !CompositeInt {
+ const n_limbs: u16 = info.backing_bits / big_int_bits;
+ const limbs = try cg.id_scratch.addManyAsSlice(cg.gpa, n_limbs);
+ const zero_id = try cg.constInt(.u32, @as(u32, 0));
+ for (limbs) |*limb| limb.* = zero_id;
+ return .{ .cg = cg, .limbs = limbs, .n_limbs = n_limbs, .info = info };
+ }
+
+ fn materialize(ci: CompositeInt, ty: Type) !Id {
+ const result_ty_id = try ci.cg.resolveType(ty, .indirect);
+ return ci.cg.constructComposite(result_ty_id, ci.limbs);
+ }
+
+ fn limbBinOp(ci: CompositeInt, opcode: Opcode, lhs: Id, rhs: Id) !Id {
+ const cg = ci.cg;
+ const gpa = cg.gpa;
+ const u32_ty_id = try cg.resolveType(.u32, .direct);
+ const result_id = cg.allocId();
+ try cg.body.emitRaw(gpa, opcode, 4);
+ cg.body.writeOperand(Id, u32_ty_id);
+ cg.body.writeOperand(Id, result_id);
+ cg.body.writeOperand(Id, lhs);
+ cg.body.writeOperand(Id, rhs);
+ return result_id;
+ }
+
+ fn limbUnOp(ci: CompositeInt, opcode: Opcode, operand: Id) !Id {
+ const cg = ci.cg;
+ const gpa = cg.gpa;
+ const u32_ty_id = try cg.resolveType(.u32, .direct);
+ const result_id = cg.allocId();
+ try cg.body.emitRaw(gpa, opcode, 3);
+ cg.body.writeOperand(Id, u32_ty_id);
+ cg.body.writeOperand(Id, result_id);
+ cg.body.writeOperand(Id, operand);
+ return result_id;
+ }
+
+ fn bitwiseOp(ci: CompositeInt, other: CompositeInt, opcode: Opcode) !CompositeInt {
+ const cg = ci.cg;
+ const gpa = cg.gpa;
+ const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs);
+ for (result_limbs, 0..) |*r, i| {
+ r.* = try ci.limbBinOp(opcode, ci.limbs[i], other.limbs[i]);
+ }
+ return .fromLimbs(cg, result_limbs, ci.info);
+ }
+
+ fn bitwiseNot(ci: CompositeInt) !CompositeInt {
+ const cg = ci.cg;
+ const gpa = cg.gpa;
+ const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs);
+ for (result_limbs, 0..) |*r, i| {
+ r.* = try ci.limbUnOp(.OpNot, ci.limbs[i]);
+ }
+ return .fromLimbs(cg, result_limbs, ci.info);
+ }
+
+ fn cmp(ci: CompositeInt, other: CompositeInt, op: std.math.CompareOperator) !Id {
+ const cg = ci.cg;
+ const gpa = cg.gpa;
+ const bool_ty_id = try cg.resolveType(.bool, .direct);
+
+ switch (op) {
+ .eq, .neq => {
+ var result = blk: {
+ const r = cg.allocId();
+ try cg.body.emit(gpa, .OpIEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = r,
+ .operand_1 = ci.limbs[0],
+ .operand_2 = other.limbs[0],
+ });
+ break :blk r;
+ };
+ for (1..ci.n_limbs) |i| {
+ const limb_eq = cg.allocId();
+ try cg.body.emit(gpa, .OpIEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = limb_eq,
+ .operand_1 = ci.limbs[i],
+ .operand_2 = other.limbs[i],
+ });
+ const combined = cg.allocId();
+ try cg.body.emit(gpa, .OpLogicalAnd, .{
+ .id_result_type = bool_ty_id,
+ .id_result = combined,
+ .operand_1 = result,
+ .operand_2 = limb_eq,
+ });
+ result = combined;
+ }
+ if (op == .neq) {
+ const negated = cg.allocId();
+ try cg.body.emit(gpa, .OpLogicalNot, .{
+ .id_result_type = bool_ty_id,
+ .id_result = negated,
+ .operand = result,
+ });
+ result = negated;
+ }
+ return result;
+ },
+ .lt, .lte, .gt, .gte => {
+ const is_lt = (op == .lt or op == .lte);
+ const is_strict = (op == .lt or op == .gt);
+ var result = try cg.constBool(!is_strict, .direct);
+
+ for (0..ci.n_limbs) |i| {
+ const l = ci.limbs[i];
+ const r = other.limbs[i];
+ const limb_ne = cg.allocId();
+ try cg.body.emit(gpa, .OpINotEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = limb_ne,
+ .operand_1 = l,
+ .operand_2 = r,
+ });
+
+ const is_top = (i == ci.n_limbs - 1);
+ const use_signed = is_top and ci.info.signedness == .signed;
+ var cmp_l = l;
+ var cmp_r = r;
+ if (use_signed) {
+ const i32_ty_id = try cg.resolveType(.i32, .direct);
+ const sl = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = i32_ty_id,
+ .id_result = sl,
+ .operand = l,
+ });
+ const sr = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = i32_ty_id,
+ .id_result = sr,
+ .operand = r,
+ });
+ cmp_l = sl;
+ cmp_r = sr;
+ }
+
+ const cmp_opcode: Opcode = if (is_lt)
+ (if (use_signed) .OpSLessThan else .OpULessThan)
+ else
+ (if (use_signed) .OpSGreaterThan else .OpUGreaterThan);
+
+ const limb_cmp = cg.allocId();
+ try cg.body.emitRaw(gpa, cmp_opcode, 4);
+ cg.body.writeOperand(Id, bool_ty_id);
+ cg.body.writeOperand(Id, limb_cmp);
+ cg.body.writeOperand(Id, cmp_l);
+ cg.body.writeOperand(Id, cmp_r);
+
+ const selected = cg.allocId();
+ try cg.body.emit(gpa, .OpSelect, .{
+ .id_result_type = bool_ty_id,
+ .id_result = selected,
+ .condition = limb_ne,
+ .object_1 = limb_cmp,
+ .object_2 = result,
+ });
+ result = selected;
+ }
+ return result;
+ },
+ }
+ }
+
+ fn addSub(ci: CompositeInt, other: CompositeInt, comptime is_add: bool) !CompositeInt {
+ const cg = ci.cg;
+ const gpa = cg.gpa;
+ const pt = cg.pt;
+ const zcu = cg.zcu;
+ const ip = &zcu.intern_pool;
+ const comp = zcu.comp;
+ const io = comp.io;
+
+ const u32_zig = try pt.intType(.unsigned, 32);
+ const u32_ty_id = try cg.resolveType(.u32, .direct);
+ const carry_struct_ty: Type = .fromInterned(try ip.getTupleType(gpa, io, pt.tid, .{
+ .types = &.{ u32_zig.toIntern(), u32_zig.toIntern() },
+ .values = &.{ .none, .none },
+ }));
+ const carry_struct_ty_id = try cg.resolveType(carry_struct_ty, .direct);
+
+ const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs);
+ var carry_id = try cg.constInt(.u32, @as(u32, 0));
+
+ const opcode: Opcode = if (is_add) .OpIAddCarry else .OpISubBorrow;
+
+ for (0..ci.n_limbs) |i| {
+ const op1 = cg.allocId();
+ try cg.body.emitRaw(gpa, opcode, 4);
+ cg.body.writeOperand(Id, carry_struct_ty_id);
+ cg.body.writeOperand(Id, op1);
+ cg.body.writeOperand(Id, ci.limbs[i]);
+ cg.body.writeOperand(Id, other.limbs[i]);
+
+ const sum1 = cg.allocId();
+ try cg.body.emit(gpa, .OpCompositeExtract, .{
+ .id_result_type = u32_ty_id,
+ .id_result = sum1,
+ .composite = op1,
+ .indexes = &.{0},
+ });
+ const carry1 = cg.allocId();
+ try cg.body.emit(gpa, .OpCompositeExtract, .{
+ .id_result_type = u32_ty_id,
+ .id_result = carry1,
+ .composite = op1,
+ .indexes = &.{1},
+ });
+
+ const op2 = cg.allocId();
+ try cg.body.emitRaw(gpa, opcode, 4);
+ cg.body.writeOperand(Id, carry_struct_ty_id);
+ cg.body.writeOperand(Id, op2);
+ cg.body.writeOperand(Id, sum1);
+ cg.body.writeOperand(Id, carry_id);
+
+ result_limbs[i] = cg.allocId();
+ try cg.body.emit(gpa, .OpCompositeExtract, .{
+ .id_result_type = u32_ty_id,
+ .id_result = result_limbs[i],
+ .composite = op2,
+ .indexes = &.{0},
+ });
+ const carry2 = cg.allocId();
+ try cg.body.emit(gpa, .OpCompositeExtract, .{
+ .id_result_type = u32_ty_id,
+ .id_result = carry2,
+ .composite = op2,
+ .indexes = &.{1},
+ });
+
+ carry_id = try ci.limbBinOp(.OpBitwiseOr, carry1, carry2);
+ }
+
+ return .fromLimbs(cg, result_limbs, ci.info);
+ }
+
+ fn shl(ci: CompositeInt, shift_amt_id: Id) !CompositeInt {
+ const cg = ci.cg;
+ const gpa = cg.gpa;
+ const u32_ty_id = try cg.resolveType(.u32, .direct);
+ const bool_ty_id = try cg.resolveType(.bool, .direct);
+ const zero_id = try cg.constInt(.u32, @as(u32, 0));
+ const five_id = try cg.constInt(.u32, @as(u32, 5));
+ const thirty_one_id = try cg.constInt(.u32, @as(u32, 31));
+ const thirty_two_id = try cg.constInt(.u32, @as(u32, 32));
+
+ const whole = try ci.limbBinOp(.OpShiftRightLogical, shift_amt_id, five_id);
+ const frac = try ci.limbBinOp(.OpBitwiseAnd, shift_amt_id, thirty_one_id);
+ const comp_frac = try ci.limbBinOp(.OpISub, thirty_two_id, frac);
+ const frac_is_zero = blk: {
+ const r = cg.allocId();
+ try cg.body.emit(gpa, .OpIEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = r,
+ .operand_1 = frac,
+ .operand_2 = zero_id,
+ });
+ break :blk r;
+ };
+
+ const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs);
+
+ for (0..ci.n_limbs) |i| {
+ const i_id = try cg.constInt(.u32, @as(u32, @intCast(i)));
+ var main_val = zero_id;
+ var carry_val = zero_id;
+
+ for (0..ci.n_limbs) |j| {
+ const j_id = try cg.constInt(.u32, @as(u32, @intCast(j)));
+ const j_plus_whole = try ci.limbBinOp(.OpIAdd, j_id, whole);
+
+ const is_main = blk: {
+ const r = cg.allocId();
+ try cg.body.emit(gpa, .OpIEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = r,
+ .operand_1 = j_plus_whole,
+ .operand_2 = i_id,
+ });
+ break :blk r;
+ };
+ const shifted = try ci.limbBinOp(.OpShiftLeftLogical, ci.limbs[j], frac);
+ main_val = blk: {
+ const r = cg.allocId();
+ try cg.body.emit(gpa, .OpSelect, .{
+ .id_result_type = u32_ty_id,
+ .id_result = r,
+ .condition = is_main,
+ .object_1 = shifted,
+ .object_2 = main_val,
+ });
+ break :blk r;
+ };
+
+ const one_id = try cg.constInt(.u32, @as(u32, 1));
+ const j_plus_whole_plus_1 = try ci.limbBinOp(.OpIAdd, j_plus_whole, one_id);
+ const is_carry = blk: {
+ const r = cg.allocId();
+ try cg.body.emit(gpa, .OpIEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = r,
+ .operand_1 = j_plus_whole_plus_1,
+ .operand_2 = i_id,
+ });
+ break :blk r;
+ };
+ const carry_shifted = try ci.limbBinOp(.OpShiftRightLogical, ci.limbs[j], comp_frac);
+ const guarded_carry = blk: {
+ const r = cg.allocId();
+ try cg.body.emit(gpa, .OpSelect, .{
+ .id_result_type = u32_ty_id,
+ .id_result = r,
+ .condition = frac_is_zero,
+ .object_1 = zero_id,
+ .object_2 = carry_shifted,
+ });
+ break :blk r;
+ };
+ carry_val = blk: {
+ const r = cg.allocId();
+ try cg.body.emit(gpa, .OpSelect, .{
+ .id_result_type = u32_ty_id,
+ .id_result = r,
+ .condition = is_carry,
+ .object_1 = guarded_carry,
+ .object_2 = carry_val,
+ });
+ break :blk r;
+ };
+ }
+
+ result_limbs[i] = try ci.limbBinOp(.OpBitwiseOr, main_val, carry_val);
+ }
+
+ return .fromLimbs(cg, result_limbs, ci.info);
+ }
+
+ fn shr(ci: CompositeInt, shift_amt_id: Id, comptime is_arithmetic: bool) !CompositeInt {
+ const cg = ci.cg;
+ const gpa = cg.gpa;
+ const u32_ty_id = try cg.resolveType(.u32, .direct);
+ const bool_ty_id = try cg.resolveType(.bool, .direct);
+ const zero_id = try cg.constInt(.u32, @as(u32, 0));
+ const five_id = try cg.constInt(.u32, @as(u32, 5));
+ const thirty_one_id = try cg.constInt(.u32, @as(u32, 31));
+ const thirty_two_id = try cg.constInt(.u32, @as(u32, 32));
+
+ const whole = try ci.limbBinOp(.OpShiftRightLogical, shift_amt_id, five_id);
+ const frac = try ci.limbBinOp(.OpBitwiseAnd, shift_amt_id, thirty_one_id);
+ const comp_frac = try ci.limbBinOp(.OpISub, thirty_two_id, frac);
+ const frac_is_zero = blk: {
+ const r = cg.allocId();
+ try cg.body.emit(gpa, .OpIEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = r,
+ .operand_1 = frac,
+ .operand_2 = zero_id,
+ });
+ break :blk r;
+ };
+
+ const fill_id = if (is_arithmetic) blk: {
+ const i32_ty_id = try cg.resolveType(.i32, .direct);
+ const msb_signed = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = i32_ty_id,
+ .id_result = msb_signed,
+ .operand = ci.limbs[ci.n_limbs - 1],
+ });
+ const shift31 = try cg.constInt(.i32, @as(i32, 31));
+ const sign_ext = cg.allocId();
+ try cg.body.emit(gpa, .OpShiftRightArithmetic, .{
+ .id_result_type = i32_ty_id,
+ .id_result = sign_ext,
+ .base = msb_signed,
+ .shift = shift31,
+ });
+ const back = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = u32_ty_id,
+ .id_result = back,
+ .operand = sign_ext,
+ });
+ break :blk back;
+ } else zero_id;
+
+ const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs);
+
+ const arith_carry_init = if (is_arithmetic) blk: {
+ const shifted_fill = try ci.limbBinOp(.OpShiftLeftLogical, fill_id, comp_frac);
+ const guarded = cg.allocId();
+ try cg.body.emit(gpa, .OpSelect, .{
+ .id_result_type = u32_ty_id,
+ .id_result = guarded,
+ .condition = frac_is_zero,
+ .object_1 = zero_id,
+ .object_2 = shifted_fill,
+ });
+ break :blk guarded;
+ } else zero_id;
+
+ for (0..ci.n_limbs) |i| {
+ const i_id = try cg.constInt(.u32, @as(u32, @intCast(i)));
+ var main_val = fill_id;
+ var carry_val = arith_carry_init;
+
+ for (0..ci.n_limbs) |j| {
+ const j_id = try cg.constInt(.u32, @as(u32, @intCast(j)));
+ const i_plus_whole = try ci.limbBinOp(.OpIAdd, i_id, whole);
+ const is_main = blk: {
+ const r = cg.allocId();
+ try cg.body.emit(gpa, .OpIEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = r,
+ .operand_1 = j_id,
+ .operand_2 = i_plus_whole,
+ });
+ break :blk r;
+ };
+ const shifted = try ci.limbBinOp(.OpShiftRightLogical, ci.limbs[j], frac);
+ main_val = blk: {
+ const r = cg.allocId();
+ try cg.body.emit(gpa, .OpSelect, .{
+ .id_result_type = u32_ty_id,
+ .id_result = r,
+ .condition = is_main,
+ .object_1 = shifted,
+ .object_2 = main_val,
+ });
+ break :blk r;
+ };
+
+ const one_id = try cg.constInt(.u32, @as(u32, 1));
+ const i_plus_whole_plus_1 = try ci.limbBinOp(.OpIAdd, i_plus_whole, one_id);
+ const is_carry = blk: {
+ const r = cg.allocId();
+ try cg.body.emit(gpa, .OpIEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = r,
+ .operand_1 = j_id,
+ .operand_2 = i_plus_whole_plus_1,
+ });
+ break :blk r;
+ };
+ const carry_shifted = try ci.limbBinOp(.OpShiftLeftLogical, ci.limbs[j], comp_frac);
+ const guarded_carry = blk: {
+ const r = cg.allocId();
+ try cg.body.emit(gpa, .OpSelect, .{
+ .id_result_type = u32_ty_id,
+ .id_result = r,
+ .condition = frac_is_zero,
+ .object_1 = zero_id,
+ .object_2 = carry_shifted,
+ });
+ break :blk r;
+ };
+ carry_val = blk: {
+ const r = cg.allocId();
+ try cg.body.emit(gpa, .OpSelect, .{
+ .id_result_type = u32_ty_id,
+ .id_result = r,
+ .condition = is_carry,
+ .object_1 = guarded_carry,
+ .object_2 = carry_val,
+ });
+ break :blk r;
+ };
+ }
+
+ result_limbs[i] = try ci.limbBinOp(.OpBitwiseOr, main_val, carry_val);
+ }
+
+ return .fromLimbs(cg, result_limbs, ci.info);
+ }
+
+ fn mul(ci: CompositeInt, other: CompositeInt, comptime wide: bool) ![]Id {
+ const cg = ci.cg;
+ const gpa = cg.gpa;
+ const pt = cg.pt;
+ const zcu = cg.zcu;
+ const ip = &zcu.intern_pool;
+ const comp = zcu.comp;
+ const io = comp.io;
+ const target = zcu.getTarget();
+
+ const n: usize = ci.n_limbs;
+ const total: usize = if (wide) 2 * n else n;
+ const u32_zig = try pt.intType(.unsigned, 32);
+ const u32_ty_id = try cg.resolveType(.u32, .direct);
+
+ const pair_struct_ty: Type = .fromInterned(try ip.getTupleType(gpa, io, pt.tid, .{
+ .types = &.{ u32_zig.toIntern(), u32_zig.toIntern() },
+ .values = &.{ .none, .none },
+ }));
+ const pair_struct_ty_id = try cg.resolveType(pair_struct_ty, .direct);
+
+ const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, total);
+ const zero_id = try cg.constInt(.u32, @as(u32, 0));
+ for (result_limbs) |*r| r.* = zero_id;
+
+ for (0..n) |i| {
+ var carry_id = zero_id;
+ for (0..n) |j| {
+ const k = i + j;
+ if (k >= total) break;
+
+ var lo: Id = undefined;
+ var hi: Id = undefined;
+ switch (target.os.tag) {
+ .opencl => {
+ lo = cg.allocId();
+ try cg.body.emit(gpa, .OpIMul, .{
+ .id_result_type = u32_ty_id,
+ .id_result = lo,
+ .operand_1 = ci.limbs[i],
+ .operand_2 = other.limbs[j],
+ });
+
+ const set = try cg.importExtendedSet();
+ hi = cg.allocId();
+ try cg.body.emit(gpa, .OpExtInst, .{
+ .id_result_type = u32_ty_id,
+ .id_result = hi,
+ .set = set,
+ .instruction = .{ .inst = @intFromEnum(spec.OpenClOpcode.u_mul_hi) },
+ .id_ref_4 = &.{ ci.limbs[i], other.limbs[j] },
+ });
+ },
+ else => {
+ const mul_result = cg.allocId();
+ try cg.body.emit(gpa, .OpUMulExtended, .{
+ .id_result_type = pair_struct_ty_id,
+ .id_result = mul_result,
+ .operand_1 = ci.limbs[i],
+ .operand_2 = other.limbs[j],
+ });
+
+ lo = cg.allocId();
+ try cg.body.emit(gpa, .OpCompositeExtract, .{
+ .id_result_type = u32_ty_id,
+ .id_result = lo,
+ .composite = mul_result,
+ .indexes = &.{0},
+ });
+ hi = cg.allocId();
+ try cg.body.emit(gpa, .OpCompositeExtract, .{
+ .id_result_type = u32_ty_id,
+ .id_result = hi,
+ .composite = mul_result,
+ .indexes = &.{1},
+ });
+ },
+ }
+
+ const add1 = cg.allocId();
+ try cg.body.emit(gpa, .OpIAddCarry, .{
+ .id_result_type = pair_struct_ty_id,
+ .id_result = add1,
+ .operand_1 = result_limbs[k],
+ .operand_2 = lo,
+ });
+
+ const sum1 = cg.allocId();
+ try cg.body.emit(gpa, .OpCompositeExtract, .{
+ .id_result_type = u32_ty_id,
+ .id_result = sum1,
+ .composite = add1,
+ .indexes = &.{0},
+ });
+ const c1 = cg.allocId();
+ try cg.body.emit(gpa, .OpCompositeExtract, .{
+ .id_result_type = u32_ty_id,
+ .id_result = c1,
+ .composite = add1,
+ .indexes = &.{1},
+ });
+
+ const add2 = cg.allocId();
+ try cg.body.emit(gpa, .OpIAddCarry, .{
+ .id_result_type = pair_struct_ty_id,
+ .id_result = add2,
+ .operand_1 = sum1,
+ .operand_2 = carry_id,
+ });
+
+ result_limbs[k] = cg.allocId();
+ try cg.body.emit(gpa, .OpCompositeExtract, .{
+ .id_result_type = u32_ty_id,
+ .id_result = result_limbs[k],
+ .composite = add2,
+ .indexes = &.{0},
+ });
+ const c2 = cg.allocId();
+ try cg.body.emit(gpa, .OpCompositeExtract, .{
+ .id_result_type = u32_ty_id,
+ .id_result = c2,
+ .composite = add2,
+ .indexes = &.{1},
+ });
+
+ const hi_plus_c1 = try ci.limbBinOp(.OpIAdd, hi, c1);
+ carry_id = try ci.limbBinOp(.OpIAdd, hi_plus_c1, c2);
+ }
+ if (wide and i + n < 2 * n) {
+ result_limbs[i + n] = try ci.limbBinOp(.OpIAdd, result_limbs[i + n], carry_id);
+ }
+ }
+
+ return result_limbs;
+ }
+
+ fn normalize(ci: CompositeInt) !CompositeInt {
+ if (ci.info.bits == ci.info.backing_bits) return ci;
+ const cg = ci.cg;
+ const gpa = cg.gpa;
+ const top_bits: u16 = ci.info.bits % big_int_bits;
+ assert(top_bits != 0);
+
+ const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs);
+ for (0..ci.n_limbs - 1) |i| {
+ result_limbs[i] = ci.limbs[i];
+ }
+
+ const top_limb = ci.limbs[ci.n_limbs - 1];
+ switch (ci.info.signedness) {
+ .unsigned => {
+ const mask_val: u32 = (@as(u32, 1) << @as(u5, @intCast(top_bits))) - 1;
+ const mask_id = try cg.constInt(.u32, mask_val);
+ result_limbs[ci.n_limbs - 1] = try ci.limbBinOp(.OpBitwiseAnd, top_limb, mask_id);
+ },
+ .signed => {
+ const u32_ty_id = try cg.resolveType(.u32, .direct);
+ const i32_ty_id = try cg.resolveType(.i32, .direct);
+ const shift_amt: u32 = 32 - top_bits;
+ const shift_id = try cg.constInt(.u32, shift_amt);
+
+ const as_signed = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = i32_ty_id,
+ .id_result = as_signed,
+ .operand = top_limb,
+ });
+ const shifted_left = cg.allocId();
+ try cg.body.emit(gpa, .OpShiftLeftLogical, .{
+ .id_result_type = i32_ty_id,
+ .id_result = shifted_left,
+ .base = as_signed,
+ .shift = shift_id,
+ });
+ const shifted_right = cg.allocId();
+ try cg.body.emit(gpa, .OpShiftRightArithmetic, .{
+ .id_result_type = i32_ty_id,
+ .id_result = shifted_right,
+ .base = shifted_left,
+ .shift = shift_id,
+ });
+ const back = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = u32_ty_id,
+ .id_result = back,
+ .operand = shifted_right,
+ });
+ result_limbs[ci.n_limbs - 1] = back;
+ },
+ }
+
+ return .fromLimbs(cg, result_limbs, ci.info);
+ }
+};
+
/// Initialize a `Temporary` from an AIR value.
fn temporary(cg: *CodeGen, inst: Air.Inst.Ref) !Temporary {
return .{
@@ -1823,7 +3362,7 @@ const Vectorization = union(enum) {
/// Derive a vectorization from a particular type
fn fromType(ty: Type, cg: *CodeGen) Vectorization {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
if (!ty.isVector(zcu)) return .scalar;
return .{ .unrolled = ty.vectorLen(zcu) };
}
@@ -1857,7 +3396,7 @@ const Vectorization = union(enum) {
/// `ty` may be a scalar or vector, it doesn't matter.
fn resultType(vec: Vectorization, cg: *CodeGen, ty: Type) !Type {
const pt = cg.pt;
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const scalar_ty = ty.scalarType(zcu);
return switch (vec) {
.scalar => scalar_ty,
@@ -1869,7 +3408,7 @@ const Vectorization = union(enum) {
/// this setup, and returns a new type that holds the relevant information on how to access
/// elements of the input.
fn prepare(vec: Vectorization, cg: *CodeGen, tmp: Temporary) !PreparedOperand {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const is_vector = tmp.ty.isVector(zcu);
const value: PreparedOperand.Value = switch (tmp.value) {
.singleton => |id| switch (vec) {
@@ -1969,26 +3508,28 @@ fn vectorization(cg: *CodeGen, args: anytype) Vectorization {
/// This function builds an OpSConvert of OpUConvert depending on the
/// signedness of the types.
fn buildConvert(cg: *CodeGen, dst_ty: Type, src: Temporary) !Temporary {
- const zcu = cg.module.zcu;
-
- const dst_ty_id = try cg.resolveType(dst_ty.scalarType(zcu), .direct);
- const src_ty_id = try cg.resolveType(src.ty.scalarType(zcu), .direct);
+ const zcu = cg.zcu;
const v = cg.vectorization(.{ dst_ty, src });
const result_ty = try v.resultType(cg, dst_ty);
- // We can directly compare integers, because those type-IDs are cached.
- if (dst_ty_id == src_ty_id) {
- // Nothing to do, type-pun to the right value.
- // Note, Caller guarantees that the types fit (or caller will normalize after),
- // so we don't have to normalize here.
- // Note, dst_ty may be a scalar type even if we expect a vector, so we have to
- // convert to the right type here.
+ const dst_scalar = dst_ty.scalarType(zcu);
+ const src_scalar = src.ty.scalarType(zcu);
+ if (dst_scalar.toIntern() == src_scalar.toIntern()) {
return src.pun(result_ty);
}
+ if (dst_scalar.isInt(zcu) and src_scalar.isInt(zcu)) {
+ const dst_info = dst_scalar.intInfo(zcu);
+ const src_info = src_scalar.intInfo(zcu);
+ if (cg.backingIntBits(dst_info.bits).@"0" == cg.backingIntBits(src_info.bits).@"0" and
+ dst_info.signedness == src_info.signedness)
+ {
+ return src.pun(result_ty);
+ }
+ }
const ops = v.components();
- const results = cg.module.allocIds(ops);
+ const results = cg.allocIds(ops);
const op_result_ty = dst_ty.scalarType(zcu);
const op_result_ty_id = try cg.resolveType(op_result_ty, .direct);
@@ -2002,7 +3543,7 @@ fn buildConvert(cg: *CodeGen, dst_ty: Type, src: Temporary) !Temporary {
const op_src = try v.prepare(cg, src);
for (0..ops) |i| {
- try cg.body.emitRaw(cg.module.gpa, opcode, 3);
+ try cg.body.emitRaw(cg.gpa, opcode, 3);
cg.body.writeOperand(Id, op_result_ty_id);
cg.body.writeOperand(Id, results.at(i));
cg.body.writeOperand(Id, op_src.at(i));
@@ -2011,51 +3552,12 @@ fn buildConvert(cg: *CodeGen, dst_ty: Type, src: Temporary) !Temporary {
return v.finalize(result_ty, results);
}
-fn buildFma(cg: *CodeGen, a: Temporary, b: Temporary, c: Temporary) !Temporary {
- const zcu = cg.module.zcu;
- const target = cg.module.zcu.getTarget();
-
- const v = cg.vectorization(.{ a, b, c });
- const ops = v.components();
- const results = cg.module.allocIds(ops);
-
- const op_result_ty = a.ty.scalarType(zcu);
- const op_result_ty_id = try cg.resolveType(op_result_ty, .direct);
- const result_ty = try v.resultType(cg, a.ty);
-
- const op_a = try v.prepare(cg, a);
- const op_b = try v.prepare(cg, b);
- const op_c = try v.prepare(cg, c);
-
- const set = try cg.importExtendedSet();
- const opcode: u32 = switch (target.os.tag) {
- .opencl => @intFromEnum(spec.OpenClOpcode.fma),
- // NOTE: Vulkan's FMA instruction does *NOT* produce the right values!
- // its precision guarantees do NOT match zigs and it does NOT match OpenCLs!
- // it needs to be emulated!
- .vulkan, .opengl => @intFromEnum(spec.GlslOpcode.Fma),
- else => unreachable,
- };
-
- for (0..ops) |i| {
- try cg.body.emit(cg.module.gpa, .OpExtInst, .{
- .id_result_type = op_result_ty_id,
- .id_result = results.at(i),
- .set = set,
- .instruction = .{ .inst = opcode },
- .id_ref_4 = &.{ op_a.at(i), op_b.at(i), op_c.at(i) },
- });
- }
-
- return v.finalize(result_ty, results);
-}
-
fn buildSelect(cg: *CodeGen, condition: Temporary, lhs: Temporary, rhs: Temporary) !Temporary {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const v = cg.vectorization(.{ condition, lhs, rhs });
const ops = v.components();
- const results = cg.module.allocIds(ops);
+ const results = cg.allocIds(ops);
const op_result_ty = lhs.ty.scalarType(zcu);
const op_result_ty_id = try cg.resolveType(op_result_ty, .direct);
@@ -2068,7 +3570,7 @@ fn buildSelect(cg: *CodeGen, condition: Temporary, lhs: Temporary, rhs: Temporar
const object_2 = try v.prepare(cg, rhs);
for (0..ops) |i| {
- try cg.body.emit(cg.module.gpa, .OpSelect, .{
+ try cg.body.emit(cg.gpa, .OpSelect, .{
.id_result_type = op_result_ty_id,
.id_result = results.at(i),
.condition = cond.at(i),
@@ -2083,7 +3585,7 @@ fn buildSelect(cg: *CodeGen, condition: Temporary, lhs: Temporary, rhs: Temporar
fn buildCmp(cg: *CodeGen, opcode: Opcode, lhs: Temporary, rhs: Temporary) !Temporary {
const v = cg.vectorization(.{ lhs, rhs });
const ops = v.components();
- const results = cg.module.allocIds(ops);
+ const results = cg.allocIds(ops);
const op_result_ty: Type = .bool;
const op_result_ty_id = try cg.resolveType(op_result_ty, .direct);
@@ -2093,7 +3595,7 @@ fn buildCmp(cg: *CodeGen, opcode: Opcode, lhs: Temporary, rhs: Temporary) !Tempo
const op_rhs = try v.prepare(cg, rhs);
for (0..ops) |i| {
- try cg.body.emitRaw(cg.module.gpa, opcode, 4);
+ try cg.body.emitRaw(cg.gpa, opcode, 4);
cg.body.writeOperand(Id, op_result_ty_id);
cg.body.writeOperand(Id, results.at(i));
cg.body.writeOperand(Id, op_lhs.at(i));
@@ -2174,11 +3676,11 @@ const UnaryOp = enum {
};
fn buildUnary(cg: *CodeGen, op: UnaryOp, operand: Temporary) !Temporary {
- const zcu = cg.module.zcu;
- const target = cg.module.zcu.getTarget();
+ const zcu = cg.zcu;
+ const target = cg.zcu.getTarget();
const v = cg.vectorization(.{operand});
const ops = v.components();
- const results = cg.module.allocIds(ops);
+ const results = cg.allocIds(ops);
const op_result_ty = operand.ty.scalarType(zcu);
const op_result_ty_id = try cg.resolveType(op_result_ty, .direct);
const result_ty = try v.resultType(cg, operand.ty);
@@ -2187,7 +3689,7 @@ fn buildUnary(cg: *CodeGen, op: UnaryOp, operand: Temporary) !Temporary {
if (op.extInstOpcode(target)) |opcode| {
const set = try cg.importExtendedSet();
for (0..ops) |i| {
- try cg.body.emit(cg.module.gpa, .OpExtInst, .{
+ try cg.body.emit(cg.gpa, .OpExtInst, .{
.id_result_type = op_result_ty_id,
.id_result = results.at(i),
.set = set,
@@ -2207,7 +3709,7 @@ fn buildUnary(cg: *CodeGen, op: UnaryOp, operand: Temporary) !Temporary {
),
};
for (0..ops) |i| {
- try cg.body.emitRaw(cg.module.gpa, opcode, 3);
+ try cg.body.emitRaw(cg.gpa, opcode, 3);
cg.body.writeOperand(Id, op_result_ty_id);
cg.body.writeOperand(Id, results.at(i));
cg.body.writeOperand(Id, op_operand.at(i));
@@ -2218,11 +3720,11 @@ fn buildUnary(cg: *CodeGen, op: UnaryOp, operand: Temporary) !Temporary {
}
fn buildBinary(cg: *CodeGen, opcode: Opcode, lhs: Temporary, rhs: Temporary) !Temporary {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const v = cg.vectorization(.{ lhs, rhs });
const ops = v.components();
- const results = cg.module.allocIds(ops);
+ const results = cg.allocIds(ops);
const op_result_ty = lhs.ty.scalarType(zcu);
const op_result_ty_id = try cg.resolveType(op_result_ty, .direct);
@@ -2232,7 +3734,7 @@ fn buildBinary(cg: *CodeGen, opcode: Opcode, lhs: Temporary, rhs: Temporary) !Te
const op_rhs = try v.prepare(cg, rhs);
for (0..ops) |i| {
- try cg.body.emitRaw(cg.module.gpa, opcode, 4);
+ try cg.body.emitRaw(cg.gpa, opcode, 4);
cg.body.writeOperand(Id, op_result_ty_id);
cg.body.writeOperand(Id, results.at(i));
cg.body.writeOperand(Id, op_lhs.at(i));
@@ -2251,11 +3753,11 @@ fn buildWideMul(
rhs: Temporary,
) !struct { Temporary, Temporary } {
const pt = cg.pt;
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const comp = zcu.comp;
const gpa = comp.gpa;
const io = comp.io;
- const target = cg.module.zcu.getTarget();
+ const target = cg.zcu.getTarget();
const ip = &zcu.intern_pool;
const v = lhs.vectorization(cg).unify(rhs.vectorization(cg));
@@ -2267,8 +3769,8 @@ fn buildWideMul(
const lhs_op = try v.prepare(cg, lhs);
const rhs_op = try v.prepare(cg, rhs);
- const value_results = cg.module.allocIds(ops);
- const overflow_results = cg.module.allocIds(ops);
+ const value_results = cg.allocIds(ops);
+ const overflow_results = cg.allocIds(ops);
switch (target.os.tag) {
.opencl => {
@@ -2313,7 +3815,7 @@ fn buildWideMul(
};
for (0..ops) |i| {
- const op_result = cg.module.allocId();
+ const op_result = cg.allocId();
try cg.body.emitRaw(gpa, opcode, 4);
cg.body.writeOperand(Id, op_result_ty_id);
@@ -2373,12 +3875,12 @@ fn buildWideMul(
fn generateTestEntryPoint(
cg: *CodeGen,
name: []const u8,
- spv_decl_index: Module.Decl.Index,
+ spv_decl_index: Decl.Index,
test_id: Id,
) !void {
- const gpa = cg.module.gpa;
- const zcu = cg.module.zcu;
- const target = cg.module.zcu.getTarget();
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
+ const target = cg.zcu.getTarget();
const anyerror_ty_id = try cg.resolveType(.anyerror, .direct);
const ptr_anyerror_ty = try cg.pt.ptrType(.{
@@ -2387,15 +3889,15 @@ fn generateTestEntryPoint(
});
const ptr_anyerror_ty_id = try cg.resolveType(ptr_anyerror_ty, .direct);
- const kernel_id = cg.module.declPtr(spv_decl_index).result_id;
+ const kernel_id = cg.declPtr(spv_decl_index).result_id;
- const section = &cg.module.sections.functions;
+ const section = &cg.sections.functions;
- const p_error_id = cg.module.allocId();
+ const p_error_id = cg.allocId();
switch (target.os.tag) {
.opencl, .amdhsa => {
const void_ty_id = try cg.resolveType(.void, .direct);
- const kernel_proto_ty_id = try cg.module.functionType(void_ty_id, &.{ptr_anyerror_ty_id});
+ const kernel_proto_ty_id = try cg.functionType(void_ty_id, &.{ptr_anyerror_ty_id});
try section.emit(gpa, .OpFunction, .{
.id_result_type = try cg.resolveType(.void, .direct),
@@ -2410,52 +3912,43 @@ fn generateTestEntryPoint(
});
try section.emit(gpa, .OpLabel, .{
- .id_result = cg.module.allocId(),
+ .id_result = cg.allocId(),
});
},
.vulkan, .opengl => {
- if (cg.module.error_buffer == null) {
- const spv_err_decl_index = try cg.module.allocDecl(.global);
- const err_buf_result_id = cg.module.declPtr(spv_err_decl_index).result_id;
+ if (cg.error_buffer == null) {
+ const spv_err_decl_index = try cg.allocDecl(.global);
+ const err_buf_result_id = cg.declPtr(spv_err_decl_index).result_id;
- const buffer_struct_ty_id = try cg.module.structType(
- &.{anyerror_ty_id},
- &.{"error_out"},
- null,
- .none,
- );
- try cg.module.decorate(buffer_struct_ty_id, .block);
- try cg.module.decorateMember(buffer_struct_ty_id, 0, .{ .offset = .{ .byte_offset = 0 } });
+ const buffer_struct_ty_id = cg.allocId();
+ try cg.sections.globals.emit(gpa, .OpTypeStruct, .{
+ .id_result = buffer_struct_ty_id,
+ .id_ref = &.{anyerror_ty_id},
+ });
+ try cg.memberDebugName(buffer_struct_ty_id, 0, "error_out");
+ try cg.decorate(buffer_struct_ty_id, .block);
+ try cg.decorateMember(buffer_struct_ty_id, 0, .{ .offset = .{ .byte_offset = 0 } });
- const ptr_buffer_struct_ty_id = cg.module.allocId();
- try cg.module.sections.globals.emit(gpa, .OpTypePointer, .{
+ const ptr_buffer_struct_ty_id = cg.allocId();
+ try cg.sections.globals.emit(gpa, .OpTypePointer, .{
.id_result = ptr_buffer_struct_ty_id,
- .storage_class = cg.module.storageClass(.global),
+ .storage_class = cg.storageClass(.global),
.type = buffer_struct_ty_id,
});
- try cg.module.sections.globals.emit(gpa, .OpVariable, .{
+ try cg.sections.globals.emit(gpa, .OpVariable, .{
.id_result_type = ptr_buffer_struct_ty_id,
.id_result = err_buf_result_id,
- .storage_class = cg.module.storageClass(.global),
+ .storage_class = cg.storageClass(.global),
});
- try cg.module.decorate(err_buf_result_id, .{ .descriptor_set = .{ .descriptor_set = 0 } });
- try cg.module.decorate(err_buf_result_id, .{ .binding = .{ .binding_point = 0 } });
+ try cg.decorate(err_buf_result_id, .{ .descriptor_set = .{ .descriptor_set = 0 } });
+ try cg.decorate(err_buf_result_id, .{ .binding = .{ .binding_point = 0 } });
- cg.module.error_buffer = spv_err_decl_index;
+ cg.error_buffer = spv_err_decl_index;
}
- try cg.module.sections.execution_modes.emit(gpa, .OpExecutionMode, .{
- .entry_point = kernel_id,
- .mode = .{ .local_size = .{
- .x_size = 1,
- .y_size = 1,
- .z_size = 1,
- } },
- });
-
const void_ty_id = try cg.resolveType(.void, .direct);
- const kernel_proto_ty_id = try cg.module.functionType(void_ty_id, &.{});
+ const kernel_proto_ty_id = try cg.functionType(void_ty_id, &.{});
try section.emit(gpa, .OpFunction, .{
.id_result_type = try cg.resolveType(.void, .direct),
.id_result = kernel_id,
@@ -2463,12 +3956,12 @@ fn generateTestEntryPoint(
.function_type = kernel_proto_ty_id,
});
try section.emit(gpa, .OpLabel, .{
- .id_result = cg.module.allocId(),
+ .id_result = cg.allocId(),
});
- const spv_err_decl_index = cg.module.error_buffer.?;
- const buffer_id = cg.module.declPtr(spv_err_decl_index).result_id;
- try cg.module.decl_deps.append(gpa, spv_err_decl_index);
+ const spv_err_decl_index = cg.error_buffer.?;
+ const buffer_id = cg.declPtr(spv_err_decl_index).result_id;
+ try cg.decl_deps.append(gpa, spv_err_decl_index);
const zero_id = try cg.constInt(.u32, 0);
try section.emit(gpa, .OpInBoundsAccessChain, .{
@@ -2481,7 +3974,7 @@ fn generateTestEntryPoint(
else => unreachable,
}
- const error_id = cg.module.allocId();
+ const error_id = cg.allocId();
try section.emit(gpa, .OpFunctionCall, .{
.id_result_type = anyerror_ty_id,
.id_result = error_id,
@@ -2500,15 +3993,14 @@ fn generateTestEntryPoint(
// Just generate a quick other name because the intel runtime crashes when the entry-
// point name is the same as a different OpName.
- const test_name = try std.fmt.allocPrint(cg.module.arena, "test {s}", .{name});
+ const test_name = try std.fmt.allocPrint(cg.arena, "test {s}", .{name});
- const execution_mode: spec.ExecutionModel = switch (target.os.tag) {
- .vulkan, .opengl => .gl_compute,
- .opencl, .amdhsa => .kernel,
- else => unreachable,
+ const ep_gop = try cg.entry_points.getOrPut(cg.gpa, cg.declPtr(spv_decl_index).result_id);
+ ep_gop.value_ptr.* = .{
+ .decl_index = spv_decl_index,
+ .name = test_name,
+ .cc = .{ .spirv_kernel = .{ .x = 1, .y = 1, .z = 1 } },
};
-
- try cg.module.declareEntryPoint(spv_decl_index, test_name, execution_mode, null);
}
fn intFromBool(cg: *CodeGen, value: Temporary, result_ty: Type) !Temporary {
@@ -2526,7 +4018,7 @@ fn intFromBool(cg: *CodeGen, value: Temporary, result_ty: Type) !Temporary {
/// This converts the argument type from resolveType(ty, .indirect) to resolveType(ty, .direct).
fn convertToDirect(cg: *CodeGen, ty: Type, operand_id: Id) !Id {
const pt = cg.pt;
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
switch (ty.scalarType(zcu).zigTypeTag(zcu)) {
.bool => {
const false_id = try cg.constBool(false, .indirect);
@@ -2552,7 +4044,7 @@ fn convertToDirect(cg: *CodeGen, ty: Type, operand_id: Id) !Id {
/// Convert representation from direct (in 'register) to direct (in memory)
/// This converts the argument type from resolveType(ty, .direct) to resolveType(ty, .indirect).
fn convertToIndirect(cg: *CodeGen, ty: Type, operand_id: Id) !Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
switch (ty.scalarType(zcu).zigTypeTag(zcu)) {
.bool => {
const result = try cg.intFromBool(.init(ty, operand_id), .u1);
@@ -2564,9 +4056,9 @@ fn convertToIndirect(cg: *CodeGen, ty: Type, operand_id: Id) !Id {
fn extractField(cg: *CodeGen, result_ty: Type, object: Id, field: u32) !Id {
const result_ty_id = try cg.resolveType(result_ty, .indirect);
- const result_id = cg.module.allocId();
+ const result_id = cg.allocId();
const indexes = [_]u32{field};
- try cg.body.emit(cg.module.gpa, .OpCompositeExtract, .{
+ try cg.body.emit(cg.gpa, .OpCompositeExtract, .{
.id_result_type = result_ty_id,
.id_result = result_id,
.composite = object,
@@ -2578,9 +4070,9 @@ fn extractField(cg: *CodeGen, result_ty: Type, object: Id, field: u32) !Id {
fn extractVectorComponent(cg: *CodeGen, result_ty: Type, vector_id: Id, field: u32) !Id {
const result_ty_id = try cg.resolveType(result_ty, .direct);
- const result_id = cg.module.allocId();
+ const result_id = cg.allocId();
const indexes = [_]u32{field};
- try cg.body.emit(cg.module.gpa, .OpCompositeExtract, .{
+ try cg.body.emit(cg.gpa, .OpCompositeExtract, .{
.id_result_type = result_ty_id,
.id_result = result_id,
.composite = vector_id,
@@ -2595,15 +4087,15 @@ const MemoryOptions = struct {
};
fn load(cg: *CodeGen, value_ty: Type, ptr_id: Id, options: MemoryOptions) !Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const alignment: u32 = @intCast(value_ty.abiAlignment(zcu).toByteUnits().?);
const indirect_value_ty_id = try cg.resolveType(value_ty, .indirect);
- const result_id = cg.module.allocId();
+ const result_id = cg.allocId();
const access: spec.MemoryAccess.Extended = .{
.@"volatile" = options.is_volatile,
.aligned = .{ .literal_integer = alignment },
};
- try cg.body.emit(cg.module.gpa, .OpLoad, .{
+ try cg.body.emit(cg.gpa, .OpLoad, .{
.id_result_type = indirect_value_ty_id,
.id_result = result_id,
.pointer = ptr_id,
@@ -2615,7 +4107,7 @@ fn load(cg: *CodeGen, value_ty: Type, ptr_id: Id, options: MemoryOptions) !Id {
fn store(cg: *CodeGen, value_ty: Type, ptr_id: Id, value_id: Id, options: MemoryOptions) !void {
const indirect_value_id = try cg.convertToIndirect(value_ty, value_id);
const access: spec.MemoryAccess.Extended = .{ .@"volatile" = options.is_volatile };
- try cg.body.emit(cg.module.gpa, .OpStore, .{
+ try cg.body.emit(cg.gpa, .OpStore, .{
.pointer = ptr_id,
.object = indirect_value_id,
.memory_access = access,
@@ -2629,8 +4121,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) !void {
}
fn genInst(cg: *CodeGen, inst: Air.Inst.Index) Error!void {
- const gpa = cg.module.gpa;
- const zcu = cg.module.zcu;
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
const ip = &zcu.intern_pool;
if (cg.liveness.isUnused(inst) and !cg.air.mustLower(inst, ip))
return;
@@ -2685,9 +4177,9 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) Error!void {
.ptr_add => try cg.airPtrAdd(inst),
.ptr_sub => try cg.airPtrSub(inst),
- .bit_and => try cg.airBinOpSimple(inst, .OpBitwiseAnd),
- .bit_or => try cg.airBinOpSimple(inst, .OpBitwiseOr),
- .xor => try cg.airBinOpSimple(inst, .OpBitwiseXor),
+ .bit_and => try cg.airBitwiseOp(inst, .bit_and),
+ .bit_or => try cg.airBitwiseOp(inst, .bit_or),
+ .xor => try cg.airBitwiseOp(inst, .xor),
.shl, .shl_exact => try cg.airShift(inst, .OpShiftLeftLogical, .OpShiftLeftLogical),
.shr, .shr_exact => try cg.airShift(inst, .OpShiftRightLogical, .OpShiftRightArithmetic),
@@ -2695,12 +4187,19 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) Error!void {
.min => try cg.airMinMax(inst, .min),
.max => try cg.airMinMax(inst, .max),
- .bitcast => try cg.airBitCast(inst),
- .intcast, .trunc => try cg.airIntCast(inst),
- .float_from_int => try cg.airFloatFromInt(inst),
- .int_from_float => try cg.airIntFromFloat(inst),
- .fpext, .fptrunc => try cg.airFloatCast(inst),
- .not => try cg.airNot(inst),
+ .bit_cast => try cg.airBitCast(inst),
+ .ptr_cast => try cg.airBitCast(inst),
+ .ptr_from_int => try cg.airBitCast(inst),
+ .int_from_ptr => try cg.airBitCast(inst),
+ .error_cast => try cg.airBitCast(inst),
+ .error_from_int => try cg.airBitCast(inst),
+ .int_from_error => try cg.airBitCast(inst),
+ .union_from_enum => try cg.airBitCast(inst),
+ .int_cast, .trunc => try cg.airIntCast(inst),
+ .float_from_int => try cg.airFloatFromInt(inst),
+ .int_from_float => try cg.airIntFromFloat(inst),
+ .fpext, .fptrunc => try cg.airFloatCast(inst),
+ .not => try cg.airNot(inst),
.array_to_slice => try cg.airArrayToSlice(inst),
.slice => try cg.airSlice(inst),
@@ -2708,13 +4207,16 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) Error!void {
.memcpy => return cg.airMemcpy(inst),
.memmove => return cg.airMemmove(inst),
- .slice_ptr => try cg.airSliceField(inst, 0),
- .slice_len => try cg.airSliceField(inst, 1),
- .slice_elem_ptr => try cg.airSliceElemPtr(inst),
- .slice_elem_val => try cg.airSliceElemVal(inst),
- .ptr_elem_ptr => try cg.airPtrElemPtr(inst),
- .ptr_elem_val => try cg.airPtrElemVal(inst),
- .array_elem_val => try cg.airArrayElemVal(inst),
+ .slice_ptr => try cg.airSliceField(inst, 0),
+ .slice_len => try cg.airSliceField(inst, 1),
+ .ptr_slice_ptr_ptr => try cg.airStructFieldPtrIndex(inst, 0),
+ .ptr_slice_len_ptr => try cg.airStructFieldPtrIndex(inst, 1),
+ .spirv_runtime_array_len => try cg.airSpirvRuntimeArrayLen(inst),
+ .slice_elem_ptr => try cg.airSliceElemPtr(inst),
+ .slice_elem_val => try cg.airSliceElemVal(inst),
+ .ptr_elem_ptr => try cg.airPtrElemPtr(inst),
+ .ptr_elem_val => try cg.airPtrElemVal(inst),
+ .array_elem_val => try cg.airArrayElemVal(inst),
.set_union_tag => return cg.airSetUnionTag(inst),
.get_union_tag => try cg.airGetUnionTag(inst),
@@ -2747,19 +4249,21 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) Error!void {
.load => try cg.airLoad(inst),
.store, .store_safe => return cg.airStore(inst),
- .br => return cg.airBr(inst),
+ .br => return cg.airBr(inst),
// For now just ignore this instruction. This effectively falls back on the old implementation,
// this doesn't change anything for us.
- .repeat => return,
- .breakpoint => return,
- .cond_br => return cg.airCondBr(inst),
- .loop => return cg.airLoop(inst),
- .ret => return cg.airRet(inst),
- .ret_safe => return cg.airRet(inst), // TODO
- .ret_load => return cg.airRetLoad(inst),
- .@"try" => try cg.airTry(inst),
- .switch_br => return cg.airSwitchBr(inst),
- .unreach, .trap => return cg.airUnreach(),
+ .repeat => return,
+ .breakpoint => return,
+ .cond_br => return cg.airCondBr(inst),
+ .loop => return cg.airLoop(inst),
+ .ret => return cg.airRet(inst),
+ .ret_safe => return cg.airRet(inst), // TODO
+ .ret_load => return cg.airRetLoad(inst),
+ .@"try" => try cg.airTry(inst),
+ .switch_br => return cg.airSwitchBr(inst),
+ .loop_switch_br => return cg.airLoopSwitchBr(inst),
+ .switch_dispatch => return cg.airSwitchDispatch(inst),
+ .unreach, .trap => return cg.airUnreach(),
.dbg_empty_stmt => return,
.dbg_stmt => return cg.airDbgStmt(inst),
@@ -2811,8 +4315,50 @@ fn airBinOpSimple(cg: *CodeGen, inst: Air.Inst.Index, op: Opcode) !?Id {
return try result.materialize(cg);
}
+const BitwiseOp = enum { bit_and, bit_or, xor };
+
+fn airBitwiseOp(cg: *CodeGen, inst: Air.Inst.Index, op: BitwiseOp) !?Id {
+ const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
+ const lhs = try cg.temporary(bin_op.lhs);
+ const rhs = try cg.temporary(bin_op.rhs);
+ const info = cg.arithmeticTypeInfo(lhs.ty);
+
+ // SPIR-V requires logical opcodes for booleans, bitwise opcodes for integers.
+ const opcode: Opcode = switch (info.class) {
+ .bool => switch (op) {
+ .bit_and => .OpLogicalAnd,
+ .bit_or => .OpLogicalOr,
+ .xor => .OpLogicalNotEqual,
+ },
+ .integer, .strange_integer => switch (op) {
+ .bit_and => .OpBitwiseAnd,
+ .bit_or => .OpBitwiseOr,
+ .xor => .OpBitwiseXor,
+ },
+ .float => unreachable,
+ .composite_integer => {
+ const spv_opcode: Opcode = switch (op) {
+ .bit_and => .OpBitwiseAnd,
+ .bit_or => .OpBitwiseOr,
+ .xor => .OpBitwiseXor,
+ };
+ const lhs_id = try lhs.materialize(cg);
+ const rhs_id = try rhs.materialize(cg);
+ const scratch_top = cg.id_scratch.items.len;
+ defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
+ const ci_lhs = try CompositeInt.init(cg, lhs_id, info);
+ const ci_rhs = try CompositeInt.init(cg, rhs_id, info);
+ const ci_result = try ci_lhs.bitwiseOp(ci_rhs, spv_opcode);
+ return try ci_result.materialize(lhs.ty);
+ },
+ };
+
+ const result = try cg.buildBinary(opcode, lhs, rhs);
+ return try result.materialize(cg);
+}
+
fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
if (cg.typeOf(bin_op.lhs).isVector(zcu) and !cg.typeOf(bin_op.rhs).isVector(zcu)) {
@@ -2826,7 +4372,39 @@ fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode
const info = cg.arithmeticTypeInfo(result_ty);
switch (info.class) {
- .composite_integer => return cg.todo("shift ops for composite integers", .{}),
+ .composite_integer => {
+ const shift_info = cg.arithmeticTypeInfo(shift.ty);
+ const shift_amt_id = switch (shift_info.class) {
+ .composite_integer => blk: {
+ const shift_id = try shift.materialize(cg);
+ const u32_ty_id = try cg.resolveType(.u32, .direct);
+ const result_id = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpCompositeExtract, .{
+ .id_result_type = u32_ty_id,
+ .id_result = result_id,
+ .composite = shift_id,
+ .indexes = &.{@as(u32, 0)},
+ });
+ break :blk result_id;
+ },
+ else => blk: {
+ const converted = try cg.buildConvert(.u32, shift);
+ break :blk try converted.materialize(cg);
+ },
+ };
+ const base_id = try base.materialize(cg);
+ const scratch_top = cg.id_scratch.items.len;
+ defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
+ const ci = try CompositeInt.init(cg, base_id, info);
+ const ci_result = if (unsigned == .OpShiftLeftLogical)
+ try ci.shl(shift_amt_id)
+ else switch (info.signedness) {
+ .unsigned => try ci.shr(shift_amt_id, false),
+ .signed => try ci.shr(shift_amt_id, true),
+ };
+ const normalized = try ci_result.normalize();
+ return try normalized.materialize(result_ty);
+ },
.integer, .strange_integer => {},
.float, .bool => unreachable,
}
@@ -2908,13 +4486,13 @@ fn airMinMax(cg: *CodeGen, inst: Air.Inst.Index, op: MinMax) !?Id {
}
fn minMax(cg: *CodeGen, lhs: Temporary, rhs: Temporary, op: MinMax) !Temporary {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const target = zcu.getTarget();
const info = cg.arithmeticTypeInfo(lhs.ty);
const v = cg.vectorization(.{ lhs, rhs });
const ops = v.components();
- const results = cg.module.allocIds(ops);
+ const results = cg.allocIds(ops);
const op_result_ty = lhs.ty.scalarType(zcu);
const op_result_ty_id = try cg.resolveType(op_result_ty, .direct);
@@ -2926,7 +4504,7 @@ fn minMax(cg: *CodeGen, lhs: Temporary, rhs: Temporary, op: MinMax) !Temporary {
const set = try cg.importExtendedSet();
const opcode = op.extInstOpcode(target, info);
for (0..ops) |i| {
- try cg.body.emit(cg.module.gpa, .OpExtInst, .{
+ try cg.body.emit(cg.gpa, .OpExtInst, .{
.id_result_type = op_result_ty_id,
.id_result = results.at(i),
.set = set,
@@ -2947,10 +4525,19 @@ fn minMax(cg: *CodeGen, lhs: Temporary, rhs: Temporary, op: MinMax) !Temporary {
/// All other values are returned unmodified (this makes strange integer
/// wrapping easier to use in generic operations).
fn normalize(cg: *CodeGen, value: Temporary, info: ArithmeticTypeInfo) !Temporary {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ty = value.ty;
switch (info.class) {
- .composite_integer, .integer, .bool, .float => return value,
+ .integer, .bool, .float => return value,
+ .composite_integer => {
+ if (info.bits == info.backing_bits) return value;
+ const val_id = try value.materialize(cg);
+ const scratch_top = cg.id_scratch.items.len;
+ defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
+ const ci = try CompositeInt.init(cg, val_id, info);
+ const normalized = try ci.normalize();
+ return .init(ty, try normalized.materialize(ty));
+ },
.strange_integer => switch (info.signedness) {
.unsigned => {
const mask_value = @as(u64, std.math.maxInt(u64)) >> @as(u6, @intCast(64 - info.bits));
@@ -2976,7 +4563,7 @@ fn airDivFloor(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const info = cg.arithmeticTypeInfo(lhs.ty);
switch (info.class) {
- .composite_integer => unreachable, // TODO
+ .composite_integer => return cg.todo("div_floor for composite integers", .{}),
.integer, .strange_integer => {
switch (info.signedness) {
.unsigned => {
@@ -3015,7 +4602,7 @@ fn airDivTrunc(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const rhs = try cg.temporary(bin_op.rhs);
const info = cg.arithmeticTypeInfo(lhs.ty);
switch (info.class) {
- .composite_integer => unreachable, // TODO
+ .composite_integer => return cg.todo("div_trunc for composite integers", .{}),
.integer, .strange_integer => switch (info.signedness) {
.unsigned => {
const result = try cg.buildBinary(.OpUDiv, lhs, rhs);
@@ -3054,10 +4641,28 @@ fn airArithOp(
const rhs = try cg.temporary(bin_op.rhs);
const info = cg.arithmeticTypeInfo(lhs.ty);
const result = switch (info.class) {
- .composite_integer => unreachable, // TODO
- .integer, .strange_integer => switch (info.signedness) {
- .signed => try cg.buildBinary(sop, lhs, rhs),
- .unsigned => try cg.buildBinary(uop, lhs, rhs),
+ .composite_integer => res: {
+ const lhs_id = try lhs.materialize(cg);
+ const rhs_id = try rhs.materialize(cg);
+ const scratch_top = cg.id_scratch.items.len;
+ defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
+ const ci_lhs = try CompositeInt.init(cg, lhs_id, info);
+ const ci_rhs = try CompositeInt.init(cg, rhs_id, info);
+ const ci_result = switch (uop) {
+ .OpIAdd => try ci_lhs.addSub(ci_rhs, true),
+ .OpISub => try ci_lhs.addSub(ci_rhs, false),
+ .OpIMul => CompositeInt.fromLimbs(cg, try ci_lhs.mul(ci_rhs, false), info),
+ else => return cg.todo("arith op for composite integers", .{}),
+ };
+ const normalized = try ci_result.normalize();
+ break :res Temporary.init(lhs.ty, try normalized.materialize(lhs.ty));
+ },
+ .integer, .strange_integer => res: {
+ const raw = switch (info.signedness) {
+ .signed => try cg.buildBinary(sop, lhs, rhs),
+ .unsigned => try cg.buildBinary(uop, lhs, rhs),
+ };
+ break :res try cg.normalize(raw, info);
},
.float => try cg.buildBinary(fop, lhs, rhs),
.bool => unreachable,
@@ -3066,35 +4671,63 @@ fn airArithOp(
}
fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
+ const zcu = cg.zcu;
+ const target = zcu.getTarget();
const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
- const operand = try cg.temporary(ty_op.operand);
- // Note: operand_ty may be signed, while ty is always unsigned!
+ const value = try cg.temporary(ty_op.operand);
+ // Note: operand_ty may be signed, while ty is always unsigned.
const result_ty = cg.typeOfIndex(inst);
- const result = try cg.abs(result_ty, operand);
- return try result.materialize(cg);
-}
-
-fn abs(cg: *CodeGen, result_ty: Type, value: Temporary) !Temporary {
- const zcu = cg.module.zcu;
- const target = cg.module.zcu.getTarget();
const operand_info = cg.arithmeticTypeInfo(value.ty);
- switch (operand_info.class) {
- .float => return try cg.buildUnary(.f_abs, value),
- .integer, .strange_integer => {
- const abs_value = try cg.buildUnary(.i_abs, value);
+ const result: Temporary = switch (operand_info.class) {
+ .float => try cg.buildUnary(.f_abs, value),
+ .integer, .strange_integer => abs: {
+ var abs_value = try cg.buildUnary(.i_abs, value);
switch (target.os.tag) {
.vulkan, .opengl => {
if (value.ty.intInfo(zcu).signedness == .signed) {
- return cg.todo("perform bitcast after @abs", .{});
+ const abs_id = try abs_value.materialize(cg);
+ const dst_ty_id = try cg.resolveType(result_ty, .direct);
+ const cast_id = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpBitcast, .{
+ .id_result_type = dst_ty_id,
+ .id_result = cast_id,
+ .operand = abs_id,
+ });
+ abs_value = .init(result_ty, cast_id);
}
},
else => {},
}
- return try cg.normalize(abs_value, cg.arithmeticTypeInfo(result_ty));
+ break :abs try cg.normalize(abs_value, cg.arithmeticTypeInfo(result_ty));
+ },
+ .composite_integer => abs: {
+ const val_id = try value.materialize(cg);
+ const scratch_top = cg.id_scratch.items.len;
+ defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
+ const ci = try CompositeInt.init(cg, val_id, operand_info);
+ const ci_z = try CompositeInt.zero(cg, operand_info);
+ const is_neg = try ci.cmp(ci_z, .lt);
+ const ci_neg = try ci_z.addSub(ci, false);
+ const result_info = cg.arithmeticTypeInfo(result_ty);
+ const u32_ty_id = try cg.resolveType(.u32, .direct);
+ const result_limbs = try cg.id_scratch.addManyAsSlice(cg.gpa, ci.n_limbs);
+ for (0..ci.n_limbs) |i| {
+ result_limbs[i] = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpSelect, .{
+ .id_result_type = u32_ty_id,
+ .id_result = result_limbs[i],
+ .condition = is_neg,
+ .object_1 = ci_neg.limbs[i],
+ .object_2 = ci.limbs[i],
+ });
+ }
+ const ci_result = CompositeInt.fromLimbs(cg, result_limbs, result_info);
+ const normalized = try ci_result.normalize();
+ break :abs .init(result_ty, try normalized.materialize(result_ty));
},
- .composite_integer => unreachable, // TODO
.bool => unreachable,
- }
+ };
+ return try result.materialize(cg);
}
fn airAddSubOverflow(
@@ -3120,7 +4753,73 @@ fn airAddSubOverflow(
const info = cg.arithmeticTypeInfo(lhs.ty);
switch (info.class) {
- .composite_integer => unreachable, // TODO
+ .composite_integer => {
+ const lhs_id = try lhs.materialize(cg);
+ const rhs_id = try rhs.materialize(cg);
+ const scratch_top = cg.id_scratch.items.len;
+ defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
+ const ci_lhs = try CompositeInt.init(cg, lhs_id, info);
+ const ci_rhs = try CompositeInt.init(cg, rhs_id, info);
+ const ci_sum = if (add == .OpIAdd) try ci_lhs.addSub(ci_rhs, true) else try ci_lhs.addSub(ci_rhs, false);
+ const ci_result = try ci_sum.normalize();
+ const result_val_id = try ci_result.materialize(lhs.ty);
+
+ const ov_bool = switch (info.signedness) {
+ .unsigned => blk: {
+ const ci_res2 = try CompositeInt.init(cg, result_val_id, info);
+ const ci_lhs2 = try CompositeInt.init(cg, lhs_id, info);
+ break :blk if (add == .OpIAdd)
+ try ci_res2.cmp(ci_lhs2, .lt)
+ else
+ try ci_res2.cmp(ci_lhs2, .gt);
+ },
+ .signed => blk: {
+ const ci_res2 = try CompositeInt.init(cg, result_val_id, info);
+ const ci_lhs2 = try CompositeInt.init(cg, lhs_id, info);
+ const ci_rhs2 = try CompositeInt.init(cg, rhs_id, info);
+ const ci_z = try CompositeInt.zero(cg, info);
+ const lhs_neg = try ci_lhs2.cmp(ci_z, .lt);
+ const rhs_neg = try ci_rhs2.cmp(ci_z, .lt);
+ const res_neg = try ci_res2.cmp(ci_z, .lt);
+
+ const bool_ty_id = try cg.resolveType(.bool, .direct);
+ const signs_match = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpLogicalEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = signs_match,
+ .operand_1 = lhs_neg,
+ .operand_2 = rhs_neg,
+ });
+ const res_sign_diff = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpLogicalNotEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = res_sign_diff,
+ .operand_1 = lhs_neg,
+ .operand_2 = res_neg,
+ });
+ const ov_cond = if (add == .OpIAdd) signs_match else blk2: {
+ const not_match = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpLogicalNot, .{
+ .id_result_type = bool_ty_id,
+ .id_result = not_match,
+ .operand = signs_match,
+ });
+ break :blk2 not_match;
+ };
+ const ov_result = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpLogicalAnd, .{
+ .id_result_type = bool_ty_id,
+ .id_result = ov_result,
+ .operand_1 = ov_cond,
+ .operand_2 = res_sign_diff,
+ });
+ break :blk ov_result;
+ },
+ };
+ const ov = try cg.intFromBool(.init(.bool, ov_bool), .u1);
+ const result_ty_id = try cg.resolveType(result_ty, .direct);
+ return try cg.constructComposite(result_ty_id, &.{ result_val_id, try ov.materialize(cg) });
+ },
.strange_integer, .integer => {},
.float, .bool => unreachable,
}
@@ -3162,6 +4861,7 @@ fn airAddSubOverflow(
fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const pt = cg.pt;
+ const gpa = cg.gpa;
const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const extra = cg.air.extraData(Air.Bin, ty_pl.payload).data;
const lhs = try cg.temporary(extra.lhs);
@@ -3170,7 +4870,168 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const info = cg.arithmeticTypeInfo(lhs.ty);
switch (info.class) {
- .composite_integer => unreachable, // TODO
+ .composite_integer => {
+ const lhs_id = try lhs.materialize(cg);
+ const rhs_id = try rhs.materialize(cg);
+ const scratch_top = cg.id_scratch.items.len;
+ defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
+ const ci_lhs = try CompositeInt.init(cg, lhs_id, info);
+ const ci_rhs = try CompositeInt.init(cg, rhs_id, info);
+
+ const low_limbs = try ci_lhs.mul(ci_rhs, false);
+ const ci_result = try CompositeInt.fromLimbs(cg, low_limbs, info).normalize();
+ const result_val_id = try ci_result.materialize(lhs.ty);
+
+ const ci_lhs2 = try CompositeInt.init(cg, lhs_id, info);
+ const ci_rhs2 = try CompositeInt.init(cg, rhs_id, info);
+ const wide_limbs = try ci_lhs2.mul(ci_rhs2, true);
+ const high_limbs = wide_limbs[ci_lhs2.n_limbs..];
+
+ const bool_ty_id = try cg.resolveType(.bool, .direct);
+ const u32_ty_id = try cg.resolveType(.u32, .direct);
+ const n: usize = info.backing_bits / big_int_bits;
+
+ const ov_bool = switch (info.signedness) {
+ .unsigned => blk: {
+ const zero_id = try cg.constInt(.u32, @as(u32, 0));
+ var any_nonzero = cg.allocId();
+ try cg.body.emit(gpa, .OpINotEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = any_nonzero,
+ .operand_1 = high_limbs[0],
+ .operand_2 = zero_id,
+ });
+
+ for (1..n) |i| {
+ const limb_nz = cg.allocId();
+ try cg.body.emit(gpa, .OpINotEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = limb_nz,
+ .operand_1 = high_limbs[i],
+ .operand_2 = zero_id,
+ });
+
+ const combined = cg.allocId();
+ try cg.body.emit(gpa, .OpLogicalOr, .{
+ .id_result_type = bool_ty_id,
+ .id_result = combined,
+ .operand_1 = any_nonzero,
+ .operand_2 = limb_nz,
+ });
+ any_nonzero = combined;
+ }
+
+ break :blk any_nonzero;
+ },
+ .signed => blk: {
+ const ci_res = try CompositeInt.init(cg, result_val_id, info);
+ const top_limb = ci_res.limbs[n - 1];
+ const i32_ty_id = try cg.resolveType(.i32, .direct);
+
+ const top_bits: u16 = if (info.bits % big_int_bits == 0)
+ big_int_bits
+ else
+ info.bits % big_int_bits;
+
+ const shift_amt: u32 = top_bits - 1;
+ const shift_id = try cg.constInt(.u32, shift_amt);
+
+ const as_signed = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = i32_ty_id,
+ .id_result = as_signed,
+ .operand = top_limb,
+ });
+ const sign_ext = cg.allocId();
+ try cg.body.emit(gpa, .OpShiftRightArithmetic, .{
+ .id_result_type = i32_ty_id,
+ .id_result = sign_ext,
+ .base = as_signed,
+ .shift = shift_id,
+ });
+ const expected = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = u32_ty_id,
+ .id_result = expected,
+ .operand = sign_ext,
+ });
+
+ var any_mismatch = cg.allocId();
+ try cg.body.emit(gpa, .OpINotEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = any_mismatch,
+ .operand_1 = high_limbs[0],
+ .operand_2 = expected,
+ });
+
+ for (1..n) |i| {
+ const limb_ne = cg.allocId();
+ try cg.body.emit(gpa, .OpINotEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = limb_ne,
+ .operand_1 = high_limbs[i],
+ .operand_2 = expected,
+ });
+
+ const combined = cg.allocId();
+ try cg.body.emit(gpa, .OpLogicalOr, .{
+ .id_result_type = bool_ty_id,
+ .id_result = combined,
+ .operand_1 = any_mismatch,
+ .operand_2 = limb_ne,
+ });
+ any_mismatch = combined;
+ }
+
+ if (info.bits != info.backing_bits) {
+ const top_bits_s: u16 = info.bits % big_int_bits;
+ const s_shift_id = try cg.constInt(.u32, top_bits_s - 1);
+
+ const top_as_signed = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = i32_ty_id,
+ .id_result = top_as_signed,
+ .operand = top_limb,
+ });
+ const top_sign_ext = cg.allocId();
+ try cg.body.emit(gpa, .OpShiftRightArithmetic, .{
+ .id_result_type = i32_ty_id,
+ .id_result = top_sign_ext,
+ .base = top_as_signed,
+ .shift = s_shift_id,
+ });
+ const top_expected = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = u32_ty_id,
+ .id_result = top_expected,
+ .operand = top_sign_ext,
+ });
+ const top_mismatch = cg.allocId();
+ try cg.body.emit(gpa, .OpINotEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = top_mismatch,
+ .operand_1 = top_limb,
+ .operand_2 = top_expected,
+ });
+
+ const combined = cg.allocId();
+ try cg.body.emit(gpa, .OpLogicalOr, .{
+ .id_result_type = bool_ty_id,
+ .id_result = combined,
+ .operand_1 = any_mismatch,
+ .operand_2 = top_mismatch,
+ });
+ any_mismatch = combined;
+ }
+
+ break :blk any_mismatch;
+ },
+ };
+
+ const ov = try cg.intFromBool(.init(.bool, ov_bool), .u1);
+ const result_ty_id = try cg.resolveType(result_ty, .direct);
+ return try cg.constructComposite(result_ty_id, &.{ result_val_id, try ov.materialize(cg) });
+ },
.strange_integer, .integer => {},
.float, .bool => unreachable,
}
@@ -3181,7 +5042,8 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
// - Additionally, if info.bits != 32, we'll have to check the high bits
// of the result too.
- const largest_int_bits = cg.largestSupportedIntBits();
+ const target = cg.zcu.getTarget();
+ const largest_int_bits: u16 = if (target.cpu.has(.spirv, .int64) or target.cpu.arch == .spirv64) 64 else 32;
// If non-null, the number of bits that the multiplication should be performed in. If
// null, we have to use wide multiplication.
const maybe_op_ty_bits: ?u16 = switch (info.bits) {
@@ -3189,7 +5051,7 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
1...16 => 32,
17...32 => if (largest_int_bits > 32) 64 else null, // Upcast if we can.
33...64 => null, // Always use wide multiplication.
- else => unreachable, // TODO: Composite integers
+ else => unreachable,
};
const result, const overflowed = switch (info.signedness) {
@@ -3325,7 +5187,7 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn airShlOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const extra = cg.air.extraData(Air.Bin, ty_pl.payload).data;
@@ -3341,7 +5203,7 @@ fn airShlOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const info = cg.arithmeticTypeInfo(base.ty);
switch (info.class) {
- .composite_integer => unreachable, // TODO
+ .composite_integer => return cg.todo("shl-with-overflow for composite integers", .{}),
.integer, .strange_integer => {},
.float, .bool => unreachable,
}
@@ -3377,14 +5239,48 @@ fn airMulAdd(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const info = cg.arithmeticTypeInfo(result_ty);
assert(info.class == .float); // .mul_add is only emitted for floats
- const result = try cg.buildFma(a, b, c);
+ const zcu = cg.zcu;
+ const target = zcu.getTarget();
+
+ const v = cg.vectorization(.{ a, b, c });
+ const ops = v.components();
+ const results = cg.allocIds(ops);
+
+ const op_result_ty = a.ty.scalarType(zcu);
+ const op_result_ty_id = try cg.resolveType(op_result_ty, .direct);
+ const result_temp_ty = try v.resultType(cg, a.ty);
+
+ const op_a = try v.prepare(cg, a);
+ const op_b = try v.prepare(cg, b);
+ const op_c = try v.prepare(cg, c);
+
+ const set = try cg.importExtendedSet();
+ const opcode: u32 = switch (target.os.tag) {
+ .opencl => @intFromEnum(spec.OpenClOpcode.fma),
+ // NOTE: Vulkan's FMA does not meet Zig's nor OpenCL's precision guarantees and needs
+ // to be emulated.
+ .vulkan, .opengl => @intFromEnum(spec.GlslOpcode.Fma),
+ else => unreachable,
+ };
+
+ for (0..ops) |i| {
+ try cg.body.emit(cg.gpa, .OpExtInst, .{
+ .id_result_type = op_result_ty_id,
+ .id_result = results.at(i),
+ .set = set,
+ .instruction = .{ .inst = opcode },
+ .id_ref_4 = &.{ op_a.at(i), op_b.at(i), op_c.at(i) },
+ });
+ }
+
+ const result = v.finalize(result_temp_ty, results);
return try result.materialize(cg);
}
fn airClzCtz(cg: *CodeGen, inst: Air.Inst.Index, op: UnaryOp) !?Id {
if (cg.liveness.isUnused(inst)) return null;
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const operand = try cg.temporary(ty_op.operand);
@@ -3392,7 +5288,7 @@ fn airClzCtz(cg: *CodeGen, inst: Air.Inst.Index, op: UnaryOp) !?Id {
const info = cg.arithmeticTypeInfo(operand.ty);
switch (info.class) {
- .composite_integer => unreachable, // TODO
+ .composite_integer => return cg.todo("@clz/@ctz for composite integers", .{}),
.integer, .strange_integer => {},
.float, .bool => unreachable,
}
@@ -3427,12 +5323,11 @@ fn airSplat(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn airReduce(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const reduce = cg.air.instructions.items(.data)[@intFromEnum(inst)].reduce;
const operand = try cg.resolve(reduce.operand);
const operand_ty = cg.typeOf(reduce.operand);
const scalar_ty = operand_ty.scalarType(zcu);
- const scalar_ty_id = try cg.resolveType(scalar_ty, .direct);
const info = cg.arithmeticTypeInfo(operand_ty);
const len = operand_ty.vectorLen(zcu);
const first = try cg.extractVectorComponent(scalar_ty, operand, 0);
@@ -3458,8 +5353,6 @@ fn airReduce(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
else => {},
}
- var result_id = first;
-
const opcode: Opcode = switch (info.class) {
.bool => switch (reduce.operation) {
.And => .OpLogicalAnd,
@@ -3480,26 +5373,25 @@ fn airReduce(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
.Mul => .OpFMul,
else => unreachable,
},
- .composite_integer => unreachable, // TODO
+ .composite_integer => return cg.todo("@reduce for composite integers", .{}),
};
+ const needs_normalize = info.class == .strange_integer and
+ (reduce.operation == .Add or reduce.operation == .Mul);
+
+ var result: Temporary = .init(scalar_ty, first);
for (1..len) |i| {
- const lhs = result_id;
- const rhs = try cg.extractVectorComponent(scalar_ty, operand, @intCast(i));
- result_id = cg.module.allocId();
-
- try cg.body.emitRaw(cg.module.gpa, opcode, 4);
- cg.body.writeOperand(Id, scalar_ty_id);
- cg.body.writeOperand(Id, result_id);
- cg.body.writeOperand(Id, lhs);
- cg.body.writeOperand(Id, rhs);
+ const rhs_id = try cg.extractVectorComponent(scalar_ty, operand, @intCast(i));
+ const rhs: Temporary = .init(scalar_ty, rhs_id);
+ const stepped = try cg.buildBinary(opcode, result, rhs);
+ result = if (needs_normalize) try cg.normalize(stepped, info) else stepped;
}
- return result_id;
+ return try result.materialize(cg);
}
fn airShuffleOne(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const gpa = zcu.gpa;
const unwrapped = cg.air.unwrapShuffleOne(zcu, inst);
@@ -3524,7 +5416,7 @@ fn airShuffleOne(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn airShuffleTwo(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const gpa = zcu.gpa;
const unwrapped = cg.air.unwrapShuffleTwo(zcu, inst);
@@ -3543,7 +5435,7 @@ fn airShuffleTwo(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
id.* = switch (mask_elem.unwrap()) {
.a_elem => |idx| try cg.extractVectorComponent(elem_ty, operand_a, idx),
.b_elem => |idx| try cg.extractVectorComponent(elem_ty, operand_b, idx),
- .undef => try cg.module.constUndef(elem_ty_id),
+ .undef => try cg.constUndef(elem_ty_id),
};
}
@@ -3557,8 +5449,8 @@ fn accessChainId(
base: Id,
indices: []const Id,
) !Id {
- const result_id = cg.module.allocId();
- try cg.body.emit(cg.module.gpa, .OpInBoundsAccessChain, .{
+ const result_id = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpInBoundsAccessChain, .{
.id_result_type = result_ty_id,
.id_result = result_id,
.base = base,
@@ -3577,7 +5469,7 @@ fn accessChain(
base: Id,
indices: []const u32,
) !Id {
- const gpa = cg.module.gpa;
+ const gpa = cg.gpa;
const scratch_top = cg.id_scratch.items.len;
defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
const ids = try cg.id_scratch.addManyAsSlice(gpa, indices.len);
@@ -3594,8 +5486,8 @@ fn ptrAccessChain(
element: Id,
indices: []const u32,
) !Id {
- const gpa = cg.module.gpa;
- const target = cg.module.zcu.getTarget();
+ const gpa = cg.gpa;
+ const target = cg.zcu.getTarget();
const scratch_top = cg.id_scratch.items.len;
defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
@@ -3604,7 +5496,7 @@ fn ptrAccessChain(
id.* = try cg.constInt(.u32, index);
}
- const result_id = cg.module.allocId();
+ const result_id = cg.allocId();
switch (target.os.tag) {
.opencl, .amdhsa => {
try cg.body.emit(gpa, .OpInBoundsPtrAccessChain, .{
@@ -3630,7 +5522,7 @@ fn ptrAccessChain(
}
fn ptrAdd(cg: *CodeGen, result_ty: Type, ptr_ty: Type, ptr_id: Id, offset_id: Id) !Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const result_ty_id = try cg.resolveType(result_ty, .direct);
switch (ptr_ty.ptrSize(zcu)) {
@@ -3671,8 +5563,8 @@ fn airPtrSub(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const offset_ty_id = try cg.resolveType(offset_ty, .direct);
const result_ty = cg.typeOfIndex(inst);
- const negative_offset_id = cg.module.allocId();
- try cg.body.emit(cg.module.gpa, .OpSNegate, .{
+ const negative_offset_id = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpSNegate, .{
.id_result_type = offset_ty_id,
.id_result = negative_offset_id,
.operand = offset_id,
@@ -3686,9 +5578,9 @@ fn cmp(
lhs: Temporary,
rhs: Temporary,
) !Temporary {
- const gpa = cg.module.gpa;
+ const gpa = cg.gpa;
const pt = cg.pt;
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const scalar_ty = lhs.ty.scalarType(zcu);
const is_vector = lhs.ty.isVector(zcu);
@@ -3717,14 +5609,14 @@ fn cmp(
const usize_ty_id = try cg.resolveType(.usize, .direct);
- const lhs_int_id = cg.module.allocId();
+ const lhs_int_id = cg.allocId();
try cg.body.emit(gpa, .OpConvertPtrToU, .{
.id_result_type = usize_ty_id,
.id_result = lhs_int_id,
.pointer = try lhs.materialize(cg),
});
- const rhs_int_id = cg.module.allocId();
+ const rhs_int_id = cg.allocId();
try cg.body.emit(gpa, .OpConvertPtrToU, .{
.id_result_type = usize_ty_id,
.id_result = rhs_int_id,
@@ -3816,7 +5708,16 @@ fn cmp(
const info = cg.arithmeticTypeInfo(scalar_ty);
const pred: Opcode = switch (info.class) {
- .composite_integer => unreachable, // TODO
+ .composite_integer => {
+ const lhs_id = try lhs.materialize(cg);
+ const rhs_id = try rhs.materialize(cg);
+ const scratch_top = cg.id_scratch.items.len;
+ defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
+ const ci_lhs = try CompositeInt.init(cg, lhs_id, info);
+ const ci_rhs = try CompositeInt.init(cg, rhs_id, info);
+ const result_id = try ci_lhs.cmp(ci_rhs, op);
+ return .init(.bool, result_id);
+ },
.float => switch (op) {
.eq => .OpFOrdEqual,
.neq => .OpFUnordNotEqual,
@@ -3884,14 +5785,29 @@ fn bitCast(
src_ty: Type,
src_id: Id,
) !Id {
- const gpa = cg.module.gpa;
- const zcu = cg.module.zcu;
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
const target = zcu.getTarget();
- const src_ty_id = try cg.resolveType(src_ty, .direct);
+
+ if (src_ty.toIntern() == dst_ty.toIntern()) return src_id;
+ if (src_ty.isPtrAtRuntime(zcu) and dst_ty.isPtrAtRuntime(zcu)) switch (target.os.tag) {
+ .vulkan, .opengl => if (src_ty.ptrAddressSpace(zcu) != .physical_storage_buffer) return src_id,
+ else => {},
+ };
+
const dst_ty_id = try cg.resolveType(dst_ty, .direct);
-
const result_id = blk: {
- if (src_ty_id == dst_ty_id) break :blk src_id;
+ // Big-int ↔ big-int bitcast: the indirect representation is an array,
+ // which OpBitcast cannot operate on. The arrays are bitwise identical
+ // apart from the top limb's padding; the normalize pass below fixes
+ // the padding.
+ if (src_ty.isInt(zcu) and dst_ty.isInt(zcu)) {
+ const src_info = src_ty.intInfo(zcu);
+ const dst_info = dst_ty.intInfo(zcu);
+ const src_backing, const src_big = cg.backingIntBits(src_info.bits);
+ const dst_backing, const dst_big = cg.backingIntBits(dst_info.bits);
+ if (src_backing == dst_backing and src_big and dst_big) break :blk src_id;
+ }
// TODO: Some more cases are missing here
// See fn bitCast in llvm.zig
@@ -3906,7 +5822,7 @@ fn bitCast(
}
}
- const result_id = cg.module.allocId();
+ const result_id = cg.allocId();
try cg.body.emit(gpa, .OpConvertUToPtr, .{
.id_result_type = dst_ty_id,
.id_result = result_id,
@@ -3920,7 +5836,7 @@ fn bitCast(
// otherwise use a temporary and perform a pointer cast.
const can_bitcast = (src_ty.isNumeric(zcu) and dst_ty.isNumeric(zcu)) or (src_ty.isPtrAtRuntime(zcu) and dst_ty.isPtrAtRuntime(zcu));
if (can_bitcast) {
- const result_id = cg.module.allocId();
+ const result_id = cg.allocId();
try cg.body.emit(gpa, .OpBitcast, .{
.id_result_type = dst_ty_id,
.id_result = result_id,
@@ -3930,12 +5846,24 @@ fn bitCast(
break :blk result_id;
}
- const dst_ptr_ty_id = try cg.module.ptrType(dst_ty_id, .function);
+ switch (target.os.tag) {
+ .vulkan, .opengl => {
+ // Logical addressing forbids OpBitcast on pointers. Allocate
+ // the temp with dst_ty so the load reads through a slot of the right type.
+ const dst_ty_indirect_id = try cg.resolveType(dst_ty, .indirect);
+ const tmp_id = try cg.alloc(dst_ty_indirect_id, null);
+ try cg.store(dst_ty, tmp_id, src_id, .{});
+ break :blk try cg.load(dst_ty, tmp_id, .{});
+ },
+ else => {},
+ }
+
+ const dst_ptr_ty_id = try cg.ptrType(dst_ty_id, .function);
const src_ty_indirect_id = try cg.resolveType(src_ty, .indirect);
const tmp_id = try cg.alloc(src_ty_indirect_id, null);
try cg.store(src_ty, tmp_id, src_id, .{});
- const casted_ptr_id = cg.module.allocId();
+ const casted_ptr_id = cg.allocId();
try cg.body.emit(gpa, .OpBitcast, .{
.id_result_type = dst_ptr_ty_id,
.id_result = casted_ptr_id,
@@ -3966,6 +5894,12 @@ fn airBitCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const result = try cg.intFromBool(operand, .u1);
return try result.materialize(cg);
}
+ if (operand_ty.zigTypeTag(cg.zcu) == .pointer) {
+ switch (try cg.resolvePtr(ty_op.operand)) {
+ .tracked => |t| return t.id, // TODO
+ .id => |operand_id| return try cg.bitCast(result_ty, operand_ty, operand_id),
+ }
+ }
const operand_id = try cg.resolve(ty_op.operand);
return try cg.bitCast(result_ty, operand_ty, operand_id);
}
@@ -3978,8 +5912,207 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const src_info = cg.arithmeticTypeInfo(src.ty);
const dst_info = cg.arithmeticTypeInfo(dst_ty);
+ const src_composite = src_info.class == .composite_integer;
+ const dst_composite = dst_info.class == .composite_integer;
+
+ if (src_composite or dst_composite) {
+ const gpa = cg.gpa;
+ const scratch_top = cg.id_scratch.items.len;
+ defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
+
+ if (src_composite and dst_composite) {
+ const src_id = try src.materialize(cg);
+ const src_n: u16 = src_info.backing_bits / big_int_bits;
+ const dst_n: u16 = dst_info.backing_bits / big_int_bits;
+ const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, dst_n);
+ const min_n = @min(src_n, dst_n);
+ const u32_ty_id = try cg.resolveType(.u32, .direct);
+ for (0..min_n) |i| {
+ result_limbs[i] = cg.allocId();
+ try cg.body.emit(gpa, .OpCompositeExtract, .{
+ .id_result_type = u32_ty_id,
+ .id_result = result_limbs[i],
+ .composite = src_id,
+ .indexes = &.{@as(u32, @intCast(i))},
+ });
+ }
+ if (dst_n > src_n) {
+ const fill = if (src_info.signedness == .signed) blk: {
+ const i32_ty_id = try cg.resolveType(.i32, .direct);
+ const msb = result_limbs[src_n - 1];
+ const msb_signed = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = i32_ty_id,
+ .id_result = msb_signed,
+ .operand = msb,
+ });
+ const shift31 = try cg.constInt(.i32, @as(i32, 31));
+ const sign_ext = cg.allocId();
+ try cg.body.emit(gpa, .OpShiftRightArithmetic, .{
+ .id_result_type = i32_ty_id,
+ .id_result = sign_ext,
+ .base = msb_signed,
+ .shift = shift31,
+ });
+ const back = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = u32_ty_id,
+ .id_result = back,
+ .operand = sign_ext,
+ });
+ break :blk back;
+ } else try cg.constInt(.u32, @as(u32, 0));
+ for (min_n..dst_n) |i| {
+ result_limbs[i] = fill;
+ }
+ }
+ const ci = CompositeInt.fromLimbs(cg, result_limbs, dst_info);
+ const normalized = try ci.normalize();
+ return try normalized.materialize(dst_ty);
+ } else if (src_composite and !dst_composite) {
+ const src_id = try src.materialize(cg);
+ const u32_ty_id = try cg.resolveType(.u32, .direct);
+ if (dst_info.backing_bits <= 32) {
+ const limb0 = cg.allocId();
+ try cg.body.emit(gpa, .OpCompositeExtract, .{
+ .id_result_type = u32_ty_id,
+ .id_result = limb0,
+ .composite = src_id,
+ .indexes = &.{@as(u32, 0)},
+ });
+ const tmp: Temporary = .init(.u32, limb0);
+ const converted = try cg.buildConvert(dst_ty, tmp);
+ const result = if (dst_info.bits < src_info.bits)
+ try cg.normalize(converted, dst_info)
+ else
+ converted;
+ return try result.materialize(cg);
+ } else {
+ const limb0 = cg.allocId();
+ try cg.body.emit(gpa, .OpCompositeExtract, .{
+ .id_result_type = u32_ty_id,
+ .id_result = limb0,
+ .composite = src_id,
+ .indexes = &.{@as(u32, 0)},
+ });
+ const limb1 = cg.allocId();
+ try cg.body.emit(gpa, .OpCompositeExtract, .{
+ .id_result_type = u32_ty_id,
+ .id_result = limb1,
+ .composite = src_id,
+ .indexes = &.{@as(u32, 1)},
+ });
+ const u64_ty_id = try cg.resolveType(.u64, .direct);
+ const lo = cg.allocId();
+ try cg.body.emit(gpa, .OpUConvert, .{
+ .id_result_type = u64_ty_id,
+ .id_result = lo,
+ .unsigned_value = limb0,
+ });
+ const hi = cg.allocId();
+ try cg.body.emit(gpa, .OpUConvert, .{
+ .id_result_type = u64_ty_id,
+ .id_result = hi,
+ .unsigned_value = limb1,
+ });
+ const shift32 = try cg.constInt(.u64, @as(u64, 32));
+ const hi_shifted = cg.allocId();
+ try cg.body.emit(gpa, .OpShiftLeftLogical, .{
+ .id_result_type = u64_ty_id,
+ .id_result = hi_shifted,
+ .base = hi,
+ .shift = shift32,
+ });
+ const combined = cg.allocId();
+ try cg.body.emit(gpa, .OpBitwiseOr, .{
+ .id_result_type = u64_ty_id,
+ .id_result = combined,
+ .operand_1 = lo,
+ .operand_2 = hi_shifted,
+ });
+ const tmp: Temporary = .init(.u64, combined);
+ const converted = try cg.buildConvert(dst_ty, tmp);
+ const result = if (dst_info.bits < src_info.bits)
+ try cg.normalize(converted, dst_info)
+ else
+ converted;
+ return try result.materialize(cg);
+ }
+ } else {
+ const dst_n: u16 = dst_info.backing_bits / big_int_bits;
+ const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, dst_n);
+ const u32_ty_id = try cg.resolveType(.u32, .direct);
+
+ if (src_info.backing_bits <= 32) {
+ const converted = try cg.buildConvert(.u32, src);
+ result_limbs[0] = try converted.materialize(cg);
+ } else {
+ const src_as_u64 = try cg.buildConvert(.u64, src);
+ const src_id = try src_as_u64.materialize(cg);
+ result_limbs[0] = cg.allocId();
+ try cg.body.emit(gpa, .OpUConvert, .{
+ .id_result_type = u32_ty_id,
+ .id_result = result_limbs[0],
+ .unsigned_value = src_id,
+ });
+ const u64_ty_id = try cg.resolveType(.u64, .direct);
+ const shift32 = try cg.constInt(.u64, @as(u64, 32));
+ const hi = cg.allocId();
+ try cg.body.emit(gpa, .OpShiftRightLogical, .{
+ .id_result_type = u64_ty_id,
+ .id_result = hi,
+ .base = src_id,
+ .shift = shift32,
+ });
+ result_limbs[1] = cg.allocId();
+ try cg.body.emit(gpa, .OpUConvert, .{
+ .id_result_type = u32_ty_id,
+ .id_result = result_limbs[1],
+ .unsigned_value = hi,
+ });
+ }
+ // Sign/zero-extend remaining limbs.
+ const fill_start: u16 = if (src_info.backing_bits <= 32) 1 else 2;
+ const fill = if (src_info.signedness == .signed) blk: {
+ const i32_ty_id = try cg.resolveType(.i32, .direct);
+ const msb = result_limbs[fill_start - 1];
+ const msb_signed = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = i32_ty_id,
+ .id_result = msb_signed,
+ .operand = msb,
+ });
+ const shift31 = try cg.constInt(.i32, @as(i32, 31));
+ const sign_ext = cg.allocId();
+ try cg.body.emit(gpa, .OpShiftRightArithmetic, .{
+ .id_result_type = i32_ty_id,
+ .id_result = sign_ext,
+ .base = msb_signed,
+ .shift = shift31,
+ });
+ const back = cg.allocId();
+ try cg.body.emit(gpa, .OpBitcast, .{
+ .id_result_type = u32_ty_id,
+ .id_result = back,
+ .operand = sign_ext,
+ });
+ break :blk back;
+ } else try cg.constInt(.u32, @as(u32, 0));
+ for (fill_start..dst_n) |i| {
+ result_limbs[i] = fill;
+ }
+ const ci = CompositeInt.fromLimbs(cg, result_limbs, dst_info);
+ const normalized = try ci.normalize();
+ return try normalized.materialize(dst_ty);
+ }
+ }
+
if (src_info.backing_bits == dst_info.backing_bits) {
- return try src.materialize(cg);
+ const result = if (dst_info.bits < src_info.bits)
+ try cg.normalize(src.pun(dst_ty), dst_info)
+ else
+ src.pun(dst_ty);
+ return try result.materialize(cg);
}
const converted = try cg.buildConvert(dst_ty, src);
@@ -3998,8 +6131,8 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
fn intFromPtr(cg: *CodeGen, operand_id: Id) !Id {
const result_type_id = try cg.resolveType(.usize, .direct);
- const result_id = cg.module.allocId();
- try cg.body.emit(cg.module.gpa, .OpConvertPtrToU, .{
+ const result_id = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpConvertPtrToU, .{
.id_result_type = result_type_id,
.id_result = result_id,
.pointer = operand_id,
@@ -4008,17 +6141,13 @@ fn intFromPtr(cg: *CodeGen, operand_id: Id) !Id {
}
fn airFloatFromInt(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
+ const gpa = cg.gpa;
const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const operand_ty = cg.typeOf(ty_op.operand);
const operand_id = try cg.resolve(ty_op.operand);
const result_ty = cg.typeOfIndex(inst);
- return try cg.floatFromInt(result_ty, operand_ty, operand_id);
-}
-
-fn floatFromInt(cg: *CodeGen, result_ty: Type, operand_ty: Type, operand_id: Id) !Id {
- const gpa = cg.module.gpa;
const operand_info = cg.arithmeticTypeInfo(operand_ty);
- const result_id = cg.module.allocId();
+ const result_id = cg.allocId();
const result_ty_id = try cg.resolveType(result_ty, .direct);
switch (operand_info.signedness) {
.signed => try cg.body.emit(gpa, .OpConvertSToF, .{
@@ -4036,17 +6165,13 @@ fn floatFromInt(cg: *CodeGen, result_ty: Type, operand_ty: Type, operand_id: Id)
}
fn airIntFromFloat(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
+ const gpa = cg.gpa;
const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const operand_id = try cg.resolve(ty_op.operand);
const result_ty = cg.typeOfIndex(inst);
- return try cg.intFromFloat(result_ty, operand_id);
-}
-
-fn intFromFloat(cg: *CodeGen, result_ty: Type, operand_id: Id) !Id {
- const gpa = cg.module.gpa;
const result_info = cg.arithmeticTypeInfo(result_ty);
const result_ty_id = try cg.resolveType(result_ty, .direct);
- const result_id = cg.module.allocId();
+ const result_id = cg.allocId();
switch (result_info.signedness) {
.signed => try cg.body.emit(gpa, .OpConvertFToS, .{
.id_result_type = result_ty_id,
@@ -4079,7 +6204,15 @@ fn airNot(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const result = switch (info.class) {
.bool => try cg.buildUnary(.l_not, operand),
.float => unreachable,
- .composite_integer => unreachable, // TODO
+ .composite_integer => blk: {
+ const op_id = try operand.materialize(cg);
+ const scratch_top = cg.id_scratch.items.len;
+ defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
+ const ci = try CompositeInt.init(cg, op_id, info);
+ const notted = try ci.bitwiseNot();
+ const normalized = try notted.normalize();
+ break :blk Temporary.init(result_ty, try normalized.materialize(result_ty));
+ },
.strange_integer, .integer => blk: {
const complement = try cg.buildUnary(.bit_not, operand);
break :blk try cg.normalize(complement, info);
@@ -4090,7 +6223,7 @@ fn airNot(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn airArrayToSlice(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const array_ptr_ty = cg.typeOf(ty_op.operand);
const array_ty = array_ptr_ty.childType(zcu);
@@ -4124,11 +6257,11 @@ fn airSlice(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const gpa = cg.module.gpa;
+ const gpa = cg.gpa;
const pt = cg.pt;
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ip = &zcu.intern_pool;
- const target = cg.module.zcu.getTarget();
+ const target = cg.zcu.getTarget();
const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const result_ty = cg.typeOfIndex(inst);
const len: usize = @intCast(result_ty.arrayLen(zcu));
@@ -4253,23 +6386,8 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
}
-fn sliceOrArrayLen(cg: *CodeGen, operand_id: Id, ty: Type) !Id {
- const zcu = cg.module.zcu;
- switch (ty.ptrSize(zcu)) {
- .slice => return cg.extractField(.usize, operand_id, 1),
- .one => {
- const array_ty = ty.childType(zcu);
- const elem_ty = array_ty.childType(zcu);
- const abi_size = elem_ty.abiSize(zcu);
- const size = array_ty.arrayLenIncludingSentinel(zcu) * abi_size;
- return try cg.constInt(.usize, size);
- },
- .many, .c => unreachable,
- }
-}
-
fn sliceOrArrayPtr(cg: *CodeGen, operand_id: Id, ty: Type) !Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
if (ty.isSlice(zcu)) {
const ptr_ty = ty.slicePtrFieldType(zcu);
return cg.extractField(ptr_ty, operand_id, 0);
@@ -4285,8 +6403,17 @@ fn airMemcpy(cg: *CodeGen, inst: Air.Inst.Index) !void {
const src_ty = cg.typeOf(bin_op.rhs);
const dest_ptr = try cg.sliceOrArrayPtr(dest_slice, dest_ty);
const src_ptr = try cg.sliceOrArrayPtr(src_slice, src_ty);
- const len = try cg.sliceOrArrayLen(dest_slice, dest_ty);
- try cg.body.emit(cg.module.gpa, .OpCopyMemorySized, .{
+ const len = switch (dest_ty.ptrSize(cg.zcu)) {
+ .slice => try cg.extractField(.usize, dest_slice, 1),
+ .one => len: {
+ const array_ty = dest_ty.childType(cg.zcu);
+ const elem_ty = array_ty.childType(cg.zcu);
+ const size = array_ty.arrayLenIncludingSentinel(cg.zcu) * elem_ty.abiSize(cg.zcu);
+ break :len try cg.constInt(.usize, size);
+ },
+ .many, .c => unreachable,
+ };
+ try cg.body.emit(cg.gpa, .OpCopyMemorySized, .{
.target = dest_ptr,
.source = src_ptr,
.size = len,
@@ -4305,8 +6432,24 @@ fn airSliceField(cg: *CodeGen, inst: Air.Inst.Index, field: u32) !?Id {
return try cg.extractField(field_ty, operand_id, field);
}
+fn airSpirvRuntimeArrayLen(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
+ const gpa = cg.gpa;
+ const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
+ const extra = cg.air.extraData(Air.StructField, ty_pl.payload).data;
+ const struct_ptr_id = try cg.resolve(extra.struct_operand);
+ const u32_ty_id = try cg.intType(.unsigned, 32);
+ const result_id = cg.allocId();
+ try cg.body.emit(gpa, .OpArrayLength, .{
+ .id_result_type = u32_ty_id,
+ .id_result = result_id,
+ .structure = struct_ptr_id,
+ .array_member = extra.field_index,
+ });
+ return result_id;
+}
+
fn airSliceElemPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const bin_op = cg.air.extraData(Air.Bin, ty_pl.payload).data;
const slice_ty = cg.typeOf(bin_op.lhs);
@@ -4323,7 +6466,7 @@ fn airSliceElemPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn airSliceElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
const slice_ty = cg.typeOf(bin_op.lhs);
if (!slice_ty.isVolatilePtr(zcu) and cg.liveness.isUnused(inst)) return null;
@@ -4340,11 +6483,11 @@ fn airSliceElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn ptrElemPtr(cg: *CodeGen, ptr_ty: Type, ptr_id: Id, index_id: Id) !Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
// Construct new pointer type for the resulting pointer
const elem_ty = ptr_ty.indexableElem(zcu);
const elem_ty_id = try cg.resolveType(elem_ty, .indirect);
- const elem_ptr_ty_id = try cg.module.ptrType(elem_ty_id, cg.module.storageClass(ptr_ty.ptrAddressSpace(zcu)));
+ const elem_ptr_ty_id = try cg.ptrType(elem_ty_id, cg.storageClass(ptr_ty.ptrAddressSpace(zcu)));
if (ptr_ty.isSinglePointer(zcu)) {
// Pointer-to-array. In this case, the resulting pointer is not of the same type
// as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain.
@@ -4356,7 +6499,7 @@ fn ptrElemPtr(cg: *CodeGen, ptr_ty: Type, ptr_id: Id, index_id: Id) !Id {
}
fn airPtrElemPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const bin_op = cg.air.extraData(Air.Bin, ty_pl.payload).data;
const src_ptr_ty = cg.typeOf(bin_op.lhs);
@@ -4370,8 +6513,8 @@ fn airPtrElemPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const gpa = cg.module.gpa;
- const zcu = cg.module.zcu;
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
const array_ty = cg.typeOf(bin_op.lhs);
const elem_ty = array_ty.childType(zcu);
@@ -4386,10 +6529,10 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const elem_repr: Repr = if (is_vector) .direct else .indirect;
const array_ty_id = try cg.resolveType(array_ty, .direct);
const elem_ty_id = try cg.resolveType(elem_ty, elem_repr);
- const ptr_array_ty_id = try cg.module.ptrType(array_ty_id, .function);
- const ptr_elem_ty_id = try cg.module.ptrType(elem_ty_id, .function);
+ const ptr_array_ty_id = try cg.ptrType(array_ty_id, .function);
+ const ptr_elem_ty_id = try cg.ptrType(elem_ty_id, .function);
- const tmp_id = cg.module.allocId();
+ const tmp_id = cg.allocId();
try cg.prologue.emit(gpa, .OpVariable, .{
.id_result_type = ptr_array_ty_id,
.id_result = tmp_id,
@@ -4403,7 +6546,7 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const elem_ptr_id = try cg.accessChainId(ptr_elem_ty_id, tmp_id, &.{index_id});
- const result_id = cg.module.allocId();
+ const result_id = cg.allocId();
try cg.body.emit(gpa, .OpLoad, .{
.id_result_type = try cg.resolveType(elem_ty, elem_repr),
.id_result = result_id,
@@ -4422,7 +6565,7 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn airPtrElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
const ptr_ty = cg.typeOf(bin_op.lhs);
const elem_ty = cg.typeOfIndex(inst);
@@ -4433,7 +6576,7 @@ fn airPtrElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn airSetUnionTag(cg: *CodeGen, inst: Air.Inst.Index) !void {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
const un_ptr_ty = cg.typeOf(bin_op.lhs);
const un_ty = un_ptr_ty.childType(zcu);
@@ -4443,7 +6586,7 @@ fn airSetUnionTag(cg: *CodeGen, inst: Air.Inst.Index) !void {
const tag_ty = un_ty.unionTagTypeRuntime(zcu).?;
const tag_ty_id = try cg.resolveType(tag_ty, .indirect);
- const tag_ptr_ty_id = try cg.module.ptrType(tag_ty_id, cg.module.storageClass(un_ptr_ty.ptrAddressSpace(zcu)));
+ const tag_ptr_ty_id = try cg.ptrType(tag_ty_id, cg.storageClass(un_ptr_ty.ptrAddressSpace(zcu)));
const union_ptr_id = try cg.resolve(bin_op.lhs);
const new_tag_id = try cg.resolve(bin_op.rhs);
@@ -4460,7 +6603,7 @@ fn airGetUnionTag(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const un_ty = cg.typeOf(ty_op.operand);
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const layout = cg.unionLayout(un_ty);
if (layout.tag_size == 0) return null;
@@ -4484,7 +6627,7 @@ fn unionInit(
// Note: The result here is not cached, because it generates runtime code.
const pt = cg.pt;
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ip = &zcu.intern_pool;
const union_ty = zcu.typeToUnion(ty).?;
const tag_ty: Type = .fromInterned(union_ty.enum_tag_type);
@@ -4509,7 +6652,7 @@ fn unionInit(
if (layout.tag_size != 0) {
const tag_ty_id = try cg.resolveType(tag_ty, .indirect);
- const tag_ptr_ty_id = try cg.module.ptrType(tag_ty_id, .function);
+ const tag_ptr_ty_id = try cg.ptrType(tag_ty_id, .function);
const ptr_id = try cg.accessChain(tag_ptr_ty_id, tmp_id, &.{@as(u32, @intCast(layout.tag_index))});
const tag_id = try cg.constInt(tag_ty, tag_int);
try cg.store(tag_ty, ptr_id, tag_id, .{});
@@ -4517,13 +6660,13 @@ fn unionInit(
if (payload_ty.hasRuntimeBits(zcu)) {
const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect);
- const pl_ptr_ty_id = try cg.module.ptrType(layout_payload_ty_id, .function);
+ const pl_ptr_ty_id = try cg.ptrType(layout_payload_ty_id, .function);
const pl_ptr_id = try cg.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index});
- const active_pl_ptr_id = if (!layout.payload_ty.eql(payload_ty, zcu)) blk: {
+ const active_pl_ptr_id = if (!layout.payload_ty.eql(payload_ty)) blk: {
const payload_ty_id = try cg.resolveType(payload_ty, .indirect);
- const active_pl_ptr_ty_id = try cg.module.ptrType(payload_ty_id, .function);
- const active_pl_ptr_id = cg.module.allocId();
- try cg.body.emit(cg.module.gpa, .OpBitcast, .{
+ const active_pl_ptr_ty_id = try cg.ptrType(payload_ty_id, .function);
+ const active_pl_ptr_id = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpBitcast, .{
.id_result_type = active_pl_ptr_ty_id,
.id_result = active_pl_ptr_id,
.operand = pl_ptr_id,
@@ -4543,7 +6686,7 @@ fn unionInit(
}
fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ip = &zcu.intern_pool;
const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const extra = cg.air.extraData(Air.UnionInit, ty_pl.payload).data;
@@ -4560,7 +6703,7 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const pt = cg.pt;
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const struct_field = cg.air.extraData(Air.StructField, ty_pl.payload).data;
@@ -4575,7 +6718,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
.@"struct" => switch (object_ty.containerLayout(zcu)) {
.@"packed" => {
const struct_ty = zcu.typeToPackedStruct(object_ty).?;
- const struct_backing_int_bits = cg.module.backingIntBits(@intCast(object_ty.bitSize(zcu))).@"0";
+ const struct_backing_int_bits = cg.backingIntBits(@intCast(object_ty.bitSize(zcu))).@"0";
const bit_offset = zcu.structPackedFieldBitOffset(struct_ty, field_index);
// We use the same int type the packed struct is backed by, because even though it would
// be valid SPIR-V to use an smaller type like u16, some implementations like PoCL will complain.
@@ -4588,7 +6731,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const mask_id = try cg.constInt(object_ty, (@as(u64, 1) << @as(u6, @intCast(field_bit_size))) - 1);
const masked = try cg.buildBinary(.OpBitwiseAnd, shift, .{ .ty = object_ty, .value = .{ .singleton = mask_id } });
const result_id = blk: {
- if (cg.module.backingIntBits(field_bit_size).@"0" == struct_backing_int_bits)
+ if (cg.backingIntBits(field_bit_size).@"0" == struct_backing_int_bits)
break :blk try cg.bitCast(field_int_ty, object_ty, try masked.materialize(cg));
const trunc = try cg.buildConvert(field_int_ty, masked);
break :blk try trunc.materialize(cg);
@@ -4612,7 +6755,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
.{ .ty = backing_int_ty, .value = .{ .singleton = mask_id } },
);
const result_id = blk: {
- if (cg.module.backingIntBits(field_bit_size).@"0" == cg.module.backingIntBits(@intCast(backing_int_ty.bitSize(zcu))).@"0")
+ if (cg.backingIntBits(field_bit_size).@"0" == cg.backingIntBits(@intCast(backing_int_ty.bitSize(zcu))).@"0")
break :blk try cg.bitCast(int_ty, backing_int_ty, try masked.materialize(cg));
const trunc = try cg.buildConvert(int_ty, masked);
break :blk try trunc.materialize(cg);
@@ -4631,13 +6774,13 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
try cg.store(object_ty, tmp_id, object_id, .{});
const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect);
- const pl_ptr_ty_id = try cg.module.ptrType(layout_payload_ty_id, .function);
+ const pl_ptr_ty_id = try cg.ptrType(layout_payload_ty_id, .function);
const pl_ptr_id = try cg.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index});
const field_ty_id = try cg.resolveType(field_ty, .indirect);
- const active_pl_ptr_ty_id = try cg.module.ptrType(field_ty_id, .function);
- const active_pl_ptr_id = cg.module.allocId();
- try cg.body.emit(cg.module.gpa, .OpBitcast, .{
+ const active_pl_ptr_ty_id = try cg.ptrType(field_ty_id, .function);
+ const active_pl_ptr_id = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpBitcast, .{
.id_result_type = active_pl_ptr_ty_id,
.id_result = active_pl_ptr_id,
.operand = pl_ptr_id,
@@ -4650,7 +6793,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn airFieldParentPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const target = zcu.getTarget();
const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const extra = cg.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
@@ -4683,8 +6826,8 @@ fn airFieldParentPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
}
- const base_ptr = cg.module.allocId();
- try cg.body.emit(cg.module.gpa, .OpConvertUToPtr, .{
+ const base_ptr = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpConvertUToPtr, .{
.id_result_type = result_ty_id,
.id_result = base_ptr,
.integer_value = base_ptr_int,
@@ -4702,7 +6845,7 @@ fn structFieldPtr(
) !Id {
const result_ty_id = try cg.resolveType(result_ptr_ty, .direct);
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const object_ty = object_ptr_ty.childType(zcu);
switch (object_ty.zigTypeTag(zcu)) {
.pointer => {
@@ -4710,7 +6853,27 @@ fn structFieldPtr(
return cg.accessChain(result_ty_id, object_ptr, &.{field_index});
},
.@"struct" => switch (object_ty.containerLayout(zcu)) {
- .@"packed" => return cg.todo("implement field access for packed structs", .{}),
+ .@"packed" => {
+ const byte_offset = codegen.fieldOffset(object_ptr_ty, result_ptr_ty, field_index, zcu);
+ if (byte_offset == 0) return object_ptr;
+ const usize_ty_id = try cg.resolveType(.usize, .direct);
+ const base_int = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpConvertPtrToU, .{
+ .id_result_type = usize_ty_id,
+ .id_result = base_int,
+ .pointer = object_ptr,
+ });
+ const offset_id = try cg.constInt(.usize, byte_offset);
+ const adjusted = try cg.buildBinary(.OpIAdd, .{ .ty = .usize, .value = .{ .singleton = base_int } }, .{ .ty = .usize, .value = .{ .singleton = offset_id } });
+ const adjusted_id = try adjusted.materialize(cg);
+ const result_id = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpConvertUToPtr, .{
+ .id_result_type = result_ty_id,
+ .id_result = result_id,
+ .integer_value = adjusted_id,
+ });
+ return result_id;
+ },
.auto, .@"extern" => {
return try cg.accessChain(result_ty_id, object_ptr, &.{field_index});
},
@@ -4722,19 +6885,19 @@ fn structFieldPtr(
if (!layout.has_payload) {
// Asked to get a pointer to a zero-sized field. Just lower this
// to undefined, there is no reason to make it be a valid pointer.
- return try cg.module.constUndef(result_ty_id);
+ return try cg.constUndef(result_ty_id);
}
- const storage_class = cg.module.storageClass(object_ptr_ty.ptrAddressSpace(zcu));
+ const storage_class = cg.storageClass(object_ptr_ty.ptrAddressSpace(zcu));
const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect);
- const pl_ptr_ty_id = try cg.module.ptrType(layout_payload_ty_id, storage_class);
+ const pl_ptr_ty_id = try cg.ptrType(layout_payload_ty_id, storage_class);
const pl_ptr_id = blk: {
if (object_ty.containerLayout(zcu) == .@"packed") break :blk object_ptr;
break :blk try cg.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index});
};
- const active_pl_ptr_id = cg.module.allocId();
- try cg.body.emit(cg.module.gpa, .OpBitcast, .{
+ const active_pl_ptr_id = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpBitcast, .{
.id_result_type = result_ty_id,
.id_result = active_pl_ptr_id,
.operand = pl_ptr_id,
@@ -4764,9 +6927,9 @@ fn airStructFieldPtrIndex(cg: *CodeGen, inst: Air.Inst.Index, field_index: u32)
}
fn alloc(cg: *CodeGen, ty_id: Id, initializer: ?Id) !Id {
- const ptr_ty_id = try cg.module.ptrType(ty_id, .function);
- const result_id = cg.module.allocId();
- try cg.prologue.emit(cg.module.gpa, .OpVariable, .{
+ const ptr_ty_id = try cg.ptrType(ty_id, .function);
+ const result_id = cg.allocId();
+ try cg.prologue.emit(cg.gpa, .OpVariable, .{
.id_result_type = ptr_ty_id,
.id_result = result_id,
.storage_class = .function,
@@ -4776,16 +6939,31 @@ fn alloc(cg: *CodeGen, ty_id: Id, initializer: ?Id) !Id {
}
fn airAlloc(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const target = zcu.getTarget();
const ptr_ty = cg.typeOfIndex(inst);
const child_ty = ptr_ty.childType(zcu);
+
+ switch (target.os.tag) {
+ .vulkan, .opengl => {
+ if (child_ty.zigTypeTag(zcu) == .pointer and !child_ty.isSlice(zcu)) {
+ const as = child_ty.ptrAddressSpace(zcu);
+ if (cg.storageClass(as) == .function) {
+ const result_id = cg.allocId();
+ try cg.tracked_allocas.put(cg.gpa, result_id, null);
+ return result_id;
+ }
+ }
+ },
+ else => {},
+ }
+
const child_ty_id = try cg.resolveType(child_ty, .indirect);
const ptr_align = ptr_ty.ptrAlignment(zcu);
const result_id = try cg.alloc(child_ty_id, null);
if (ptr_align != child_ty.abiAlignment(zcu)) {
if (target.os.tag != .opencl) return cg.fail("cannot apply alignment to variables", .{});
- try cg.module.decorate(result_id, .{
+ try cg.decorate(result_id, .{
.alignment = .{ .alignment = @intCast(ptr_align.toByteUnits().?) },
});
}
@@ -4801,12 +6979,10 @@ fn airArg(cg: *CodeGen) Id {
/// block to jump to. This function emits instructions, so it should be emitted
/// inside the merge block of the block.
/// This function should only be called with structured control flow generation.
-fn structuredNextBlock(cg: *CodeGen, incoming: []const ControlFlow.Structured.Block.Incoming) !Id {
- assert(cg.control_flow == .structured);
-
- const result_id = cg.module.allocId();
+fn structuredNextBlock(cg: *CodeGen, incoming: []const Block.Incoming) !Id {
+ const result_id = cg.allocId();
const block_id_ty_id = try cg.resolveType(.u32, .direct);
- try cg.body.emitRaw(cg.module.gpa, .OpPhi, @intCast(2 + incoming.len * 2)); // result type + result + variable/parent...
+ try cg.body.emitRaw(cg.gpa, .OpPhi, @intCast(2 + incoming.len * 2)); // result type + result + variable/parent...
cg.body.writeOperand(Id, block_id_ty_id);
cg.body.writeOperand(Id, result_id);
@@ -4821,13 +6997,13 @@ fn structuredNextBlock(cg: *CodeGen, incoming: []const ControlFlow.Structured.Bl
/// terminating a body, there should be no instructions after it.
/// This function should only be called with structured control flow generation.
fn structuredBreak(cg: *CodeGen, target_block: Id) !void {
- assert(cg.control_flow == .structured);
+ if (cg.block_terminated) return;
- const gpa = cg.module.gpa;
- const sblock = cg.control_flow.structured.block_stack.getLast().?;
+ const gpa = cg.gpa;
+ const sblock = cg.block_stack.getLast().?;
const merge_block = switch (sblock.*) {
.selection => |*merge| blk: {
- const merge_label = cg.module.allocId();
+ const merge_label = cg.allocId();
try merge.merge_stack.append(gpa, .{
.incoming = .{
.src_label = cg.block_label,
@@ -4867,11 +7043,9 @@ fn genStructuredBody(
},
body: []const Air.Inst.Index,
) !Id {
- assert(cg.control_flow == .structured);
+ const gpa = cg.gpa;
- const gpa = cg.module.gpa;
-
- var sblock: ControlFlow.Structured.Block = switch (block_merge_type) {
+ var sblock: Block = switch (block_merge_type) {
.loop => |merge| .{ .loop = .{
.merge_block = merge.merge_label,
} },
@@ -4880,8 +7054,8 @@ fn genStructuredBody(
defer sblock.deinit(gpa);
{
- try cg.control_flow.structured.block_stack.append(gpa, &sblock);
- defer _ = cg.control_flow.structured.block_stack.pop();
+ try cg.block_stack.append(gpa, &sblock);
+ defer _ = cg.block_stack.pop();
try cg.genBody(body);
}
@@ -4907,9 +7081,9 @@ fn genStructuredBody(
// Make sure that we are still in a block when exiting the function.
// TODO: Can we get rid of that?
- try cg.beginSpvBlock(cg.module.allocId());
+ try cg.beginSpvBlock(cg.allocId());
const block_id_ty_id = try cg.resolveType(.u32, .direct);
- return try cg.module.constUndef(block_id_ty_id);
+ return try cg.constUndef(block_id_ty_id);
}
// The top-most merge actually only has a single source, the
@@ -4919,7 +7093,7 @@ fn genStructuredBody(
try cg.beginSpvBlock(merge_stack[merge_stack.len - 1].merge_block);
// Now generate a merge ladder for the remaining merges in the stack.
- var incoming: ControlFlow.Structured.Block.Incoming = .{
+ var incoming: Block.Incoming = .{
.src_label = cg.block_label,
.next_block = merge_stack[merge_stack.len - 1].incoming.next_block,
};
@@ -4963,74 +7137,28 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index)
// of the block, then a label, and then generate the rest of the current
// ir.Block in a different SPIR-V block.
- const gpa = cg.module.gpa;
- const zcu = cg.module.zcu;
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
const ty = cg.typeOfIndex(inst);
const have_block_result = ty.hasRuntimeBits(zcu);
- const cf = switch (cg.control_flow) {
- .structured => |*cf| cf,
- .unstructured => |*cf| {
- var block: ControlFlow.Unstructured.Block = .{};
- defer block.incoming_blocks.deinit(gpa);
-
- // 4 chosen as arbitrary initial capacity.
- try block.incoming_blocks.ensureUnusedCapacity(gpa, 4);
-
- try cf.blocks.putNoClobber(gpa, inst, &block);
- defer assert(cf.blocks.remove(inst));
-
- try cg.genBody(body);
-
- // Only begin a new block if there were actually any breaks towards it.
- if (block.label) |label| {
- try cg.beginSpvBlock(label);
- }
-
- if (!have_block_result)
- return null;
-
- assert(block.label != null);
- const result_id = cg.module.allocId();
- const result_type_id = try cg.resolveType(ty, .direct);
-
- try cg.body.emitRaw(
- gpa,
- .OpPhi,
- // result type + result + variable/parent...
- 2 + @as(u16, @intCast(block.incoming_blocks.items.len * 2)),
- );
- cg.body.writeOperand(Id, result_type_id);
- cg.body.writeOperand(Id, result_id);
-
- for (block.incoming_blocks.items) |incoming| {
- cg.body.writeOperand(
- spec.PairIdRefIdRef,
- .{ incoming.break_value_id, incoming.src_label },
- );
- }
-
- return result_id;
- },
- };
-
const maybe_block_result_var_id = if (have_block_result) blk: {
const ty_id = try cg.resolveType(ty, .indirect);
const block_result_var_id = try cg.alloc(ty_id, null);
- try cf.block_results.putNoClobber(gpa, inst, block_result_var_id);
+ try cg.block_results.putNoClobber(gpa, inst, block_result_var_id);
break :blk block_result_var_id;
} else null;
- defer if (have_block_result) assert(cf.block_results.remove(inst));
+ defer if (have_block_result) assert(cg.block_results.remove(inst));
const next_block = try cg.genStructuredBody(.selection, body);
// When encountering a block instruction, we are always at least in the function's scope,
// so there always has to be another entry.
- assert(cf.block_stack.items.len > 0);
+ assert(cg.block_stack.items.len > 0);
// Check if the target of the branch was this current block.
const this_block = try cg.constInt(.u32, @intFromEnum(inst));
- const jump_to_this_block_id = cg.module.allocId();
+ const jump_to_this_block_id = cg.allocId();
const bool_ty_id = try cg.resolveType(.bool, .direct);
try cg.body.emit(gpa, .OpIEqual, .{
.id_result_type = bool_ty_id,
@@ -5039,7 +7167,7 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index)
.operand_2 = this_block,
});
- const sblock = cf.block_stack.getLast().?;
+ const sblock = cg.block_stack.getLast().?;
if (ty.isNoReturn(zcu)) {
// If this block is noreturn, this instruction is the last of a block,
@@ -5050,8 +7178,8 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index)
.selection => |*merge| {
// To jump out of a selection block, push a new entry onto its merge stack and
// generate a conditional branch to there and to the instructions following this block.
- const merge_label = cg.module.allocId();
- const then_label = cg.module.allocId();
+ const merge_label = cg.allocId();
+ const then_label = cg.allocId();
try cg.body.emit(gpa, .OpSelectionMerge, .{
.merge_block = merge_label,
.selection_control = .{},
@@ -5074,7 +7202,7 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index)
.loop => |*merge| {
// To jump out of a loop block, generate a conditional that exits the block
// to the loop merge if the target ID is not the one of this block.
- const continue_label = cg.module.allocId();
+ const continue_label = cg.allocId();
try cg.body.emit(gpa, .OpBranchConditional, .{
.condition = jump_to_this_block_id,
.true_label = continue_label,
@@ -5097,180 +7225,237 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index)
}
fn airBr(cg: *CodeGen, inst: Air.Inst.Index) !void {
- const gpa = cg.module.gpa;
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const br = cg.air.instructions.items(.data)[@intFromEnum(inst)].br;
const operand_ty = cg.typeOf(br.operand);
- switch (cg.control_flow) {
- .structured => |*cf| {
- if (operand_ty.hasRuntimeBits(zcu)) {
- const operand_id = try cg.resolve(br.operand);
- const block_result_var_id = cf.block_results.get(br.block_inst).?;
- try cg.store(operand_ty, block_result_var_id, operand_id, .{});
- }
-
- const next_block = try cg.constInt(.u32, @intFromEnum(br.block_inst));
- try cg.structuredBreak(next_block);
- },
- .unstructured => |cf| {
- const block = cf.blocks.get(br.block_inst).?;
- if (operand_ty.hasRuntimeBits(zcu)) {
- const operand_id = try cg.resolve(br.operand);
- // block_label should not be undefined here, lest there
- // is a br or br_void in the function's body.
- try block.incoming_blocks.append(gpa, .{
- .src_label = cg.block_label,
- .break_value_id = operand_id,
- });
- }
-
- if (block.label == null) {
- block.label = cg.module.allocId();
- }
-
- try cg.body.emit(gpa, .OpBranch, .{ .target_label = block.label.? });
- },
+ if (operand_ty.hasRuntimeBits(zcu)) {
+ const operand_id = try cg.resolve(br.operand);
+ const block_result_var_id = cg.block_results.get(br.block_inst).?;
+ try cg.store(operand_ty, block_result_var_id, operand_id, .{});
}
+
+ const next_block = try cg.constInt(.u32, @intFromEnum(br.block_inst));
+ try cg.structuredBreak(next_block);
}
fn airCondBr(cg: *CodeGen, inst: Air.Inst.Index) !void {
- const gpa = cg.module.gpa;
+ const gpa = cg.gpa;
const cond_br = cg.air.unwrapCondBr(inst);
const then_body = cond_br.then_body;
const else_body = cond_br.else_body;
const condition_id = try cg.resolve(cond_br.condition);
- const then_label = cg.module.allocId();
- const else_label = cg.module.allocId();
-
- switch (cg.control_flow) {
- .structured => {
- const merge_label = cg.module.allocId();
-
- try cg.body.emit(gpa, .OpSelectionMerge, .{
- .merge_block = merge_label,
- .selection_control = .{},
- });
- try cg.body.emit(gpa, .OpBranchConditional, .{
- .condition = condition_id,
- .true_label = then_label,
- .false_label = else_label,
- });
-
- try cg.beginSpvBlock(then_label);
- const then_next = try cg.genStructuredBody(.selection, then_body);
- const then_incoming: ControlFlow.Structured.Block.Incoming = .{
- .src_label = cg.block_label,
- .next_block = then_next,
- };
-
- try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label });
-
- try cg.beginSpvBlock(else_label);
- const else_next = try cg.genStructuredBody(.selection, else_body);
- const else_incoming: ControlFlow.Structured.Block.Incoming = .{
- .src_label = cg.block_label,
- .next_block = else_next,
- };
-
- try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label });
-
- try cg.beginSpvBlock(merge_label);
- const next_block = try cg.structuredNextBlock(&.{ then_incoming, else_incoming });
-
- try cg.structuredBreak(next_block);
- },
- .unstructured => {
- try cg.body.emit(gpa, .OpBranchConditional, .{
- .condition = condition_id,
- .true_label = then_label,
- .false_label = else_label,
- });
-
- try cg.beginSpvBlock(then_label);
- try cg.genBody(then_body);
- try cg.beginSpvBlock(else_label);
- try cg.genBody(else_body);
- },
+ const then_label = cg.allocId();
+ const else_label = cg.allocId();
+
+ const merge_label = cg.allocId();
+
+ try cg.body.emit(gpa, .OpSelectionMerge, .{
+ .merge_block = merge_label,
+ .selection_control = .{},
+ });
+ try cg.body.emit(gpa, .OpBranchConditional, .{
+ .condition = condition_id,
+ .true_label = then_label,
+ .false_label = else_label,
+ });
+
+ try cg.beginSpvBlock(then_label);
+ const then_next = try cg.genStructuredBody(.selection, then_body);
+ const then_incoming: Block.Incoming = .{
+ .src_label = cg.block_label,
+ .next_block = then_next,
+ };
+
+ if (!cg.block_terminated) {
+ try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label });
}
+
+ try cg.beginSpvBlock(else_label);
+ const else_next = try cg.genStructuredBody(.selection, else_body);
+ const else_incoming: Block.Incoming = .{
+ .src_label = cg.block_label,
+ .next_block = else_next,
+ };
+
+ if (!cg.block_terminated) {
+ try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label });
+ }
+
+ try cg.beginSpvBlock(merge_label);
+ const next_block = try cg.structuredNextBlock(&.{ then_incoming, else_incoming });
+
+ try cg.structuredBreak(next_block);
}
fn airLoop(cg: *CodeGen, inst: Air.Inst.Index) !void {
- const gpa = cg.module.gpa;
+ const gpa = cg.gpa;
const block = cg.air.unwrapBlock(inst);
- const body_label = cg.module.allocId();
-
- switch (cg.control_flow) {
- .structured => {
- const header_label = cg.module.allocId();
- const merge_label = cg.module.allocId();
- const continue_label = cg.module.allocId();
-
- // The back-edge must point to the loop header, so generate a separate block for the
- // loop header so that we don't accidentally include some instructions from there
- // in the loop.
-
- try cg.body.emit(gpa, .OpBranch, .{ .target_label = header_label });
- try cg.beginSpvBlock(header_label);
-
- // Emit loop header and jump to loop body
- try cg.body.emit(gpa, .OpLoopMerge, .{
- .merge_block = merge_label,
- .continue_target = continue_label,
- .loop_control = .{},
- });
-
- try cg.body.emit(gpa, .OpBranch, .{ .target_label = body_label });
-
- try cg.beginSpvBlock(body_label);
-
- const next_block = try cg.genStructuredBody(.{ .loop = .{
- .merge_label = merge_label,
- .continue_label = continue_label,
- } }, block.body);
- try cg.structuredBreak(next_block);
-
- try cg.beginSpvBlock(continue_label);
-
- try cg.body.emit(gpa, .OpBranch, .{ .target_label = header_label });
- },
- .unstructured => {
- try cg.body.emit(gpa, .OpBranch, .{ .target_label = body_label });
- try cg.beginSpvBlock(body_label);
- try cg.genBody(block.body);
-
- try cg.body.emit(gpa, .OpBranch, .{ .target_label = body_label });
- },
- }
+ const body_label = cg.allocId();
+
+ const header_label = cg.allocId();
+ const merge_label = cg.allocId();
+ const continue_label = cg.allocId();
+
+ // The back-edge must point to the loop header, so generate a separate block for the
+ // loop header so that we don't accidentally include some instructions from there
+ // in the loop.
+
+ try cg.body.emit(gpa, .OpBranch, .{ .target_label = header_label });
+ try cg.beginSpvBlock(header_label);
+
+ // Emit loop header and jump to loop body
+ try cg.body.emit(gpa, .OpLoopMerge, .{
+ .merge_block = merge_label,
+ .continue_target = continue_label,
+ .loop_control = .{},
+ });
+
+ try cg.body.emit(gpa, .OpBranch, .{ .target_label = body_label });
+
+ try cg.beginSpvBlock(body_label);
+
+ const next_block = try cg.genStructuredBody(.{ .loop = .{
+ .merge_label = merge_label,
+ .continue_label = continue_label,
+ } }, block.body);
+ try cg.structuredBreak(next_block);
+
+ try cg.beginSpvBlock(continue_label);
+
+ try cg.body.emit(gpa, .OpBranch, .{ .target_label = header_label });
}
fn airLoad(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
+ const pt = cg.pt;
const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const ptr_ty = cg.typeOf(ty_op.operand);
+ const ptr_info = ptr_ty.ptrInfo(zcu);
const elem_ty = cg.typeOfIndex(inst);
- const operand = try cg.resolve(ty_op.operand);
- if (!ptr_ty.isVolatilePtr(zcu) and cg.liveness.isUnused(inst)) return null;
+ const ptr = try cg.resolvePtr(ty_op.operand);
+ assert(ptr_info.child == elem_ty.toIntern());
- return try cg.load(elem_ty, operand, .{ .is_volatile = ptr_ty.isVolatilePtr(zcu) });
+ const operand_ptr_id = switch (ptr) {
+ .tracked => |t| return t.slot.*.?,
+ .id => |id| id,
+ };
+
+ if (ptr_info.packed_offset.host_size != 0 and
+ ptr_info.flags.vector_index == .none)
+ {
+ const host_bits: u16 = ptr_info.packed_offset.host_size * 8;
+ const elem_bit_size: u16 = @intCast(elem_ty.bitSize(zcu));
+ const host_int_ty = try pt.intType(.unsigned, host_bits);
+ const host_val = try cg.load(host_int_ty, operand_ptr_id, .{ .is_volatile = ptr_info.flags.is_volatile });
+ const signedness: Signedness = if (elem_ty.isInt(zcu)) elem_ty.intInfo(zcu).signedness else .unsigned;
+ const field_int_ty = try pt.intType(signedness, elem_bit_size);
+ const narrowed = if (ptr_info.packed_offset.bit_offset > 0) blk: {
+ const bit_offset_id = try cg.constInt(host_int_ty, ptr_info.packed_offset.bit_offset);
+ const shifted = try cg.buildBinary(.OpShiftRightLogical, .{ .ty = host_int_ty, .value = .{ .singleton = host_val } }, .{ .ty = host_int_ty, .value = .{ .singleton = bit_offset_id } });
+ break :blk try shifted.materialize(cg);
+ } else host_val;
+ const result_id = blk: {
+ if (cg.backingIntBits(elem_bit_size).@"0" == cg.backingIntBits(host_bits).@"0")
+ break :blk try cg.bitCast(field_int_ty, host_int_ty, narrowed);
+ const trunc = try cg.buildConvert(field_int_ty, .{ .ty = host_int_ty, .value = .{ .singleton = narrowed } });
+ break :blk try trunc.materialize(cg);
+ };
+ if (elem_ty.ip_index == .bool_type) return try cg.convertToDirect(.bool, result_id);
+ if (elem_ty.isInt(zcu)) return result_id;
+ return try cg.bitCast(elem_ty, field_int_ty, result_id);
+ }
+
+ const ptr_id = switch (ptr_info.flags.vector_index) {
+ .none => operand_ptr_id,
+ else => |index| ptr_id: {
+ const elem_ptr_ty_id = try cg.ptrType(
+ try cg.resolveType(elem_ty, .indirect),
+ cg.storageClass(ptr_info.flags.address_space),
+ );
+ break :ptr_id try cg.accessChain(elem_ptr_ty_id, operand_ptr_id, &.{@intFromEnum(index)});
+ },
+ };
+ return try cg.load(elem_ty, ptr_id, .{ .is_volatile = ptr_info.flags.is_volatile });
}
fn airStore(cg: *CodeGen, inst: Air.Inst.Index) !void {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
+ const pt = cg.pt;
const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
const ptr_ty = cg.typeOf(bin_op.lhs);
- const elem_ty = ptr_ty.childType(zcu);
- const ptr = try cg.resolve(bin_op.lhs);
- const value = try cg.resolve(bin_op.rhs);
+ const ptr_info = ptr_ty.ptrInfo(zcu);
+ const elem_ty: Type = .fromInterned(ptr_info.child);
+ const value_id = try cg.resolve(bin_op.rhs);
+ const operand_ptr_id = switch (try cg.resolvePtr(bin_op.lhs)) {
+ .tracked => |t| {
+ t.slot.* = value_id;
+ return;
+ },
+ .id => |id| id,
+ };
- try cg.store(elem_ty, ptr, value, .{ .is_volatile = ptr_ty.isVolatilePtr(zcu) });
+ if (ptr_info.packed_offset.host_size != 0 and
+ ptr_info.flags.vector_index == .none)
+ {
+ const host_bits: u16 = ptr_info.packed_offset.host_size * 8;
+ const host_int_ty = try pt.intType(.unsigned, host_bits);
+ const host_val = try cg.load(host_int_ty, operand_ptr_id, .{ .is_volatile = ptr_info.flags.is_volatile });
+ const elem_bit_size: u16 = @intCast(elem_ty.bitSize(zcu));
+ const signedness: Signedness = if (elem_ty.isInt(zcu)) elem_ty.intInfo(zcu).signedness else .unsigned;
+ const field_int_ty = try pt.intType(signedness, elem_bit_size);
+
+ var value_as_int: Id = undefined;
+ if (elem_ty.ip_index == .bool_type) {
+ value_as_int = try cg.convertToIndirect(.bool, value_id);
+ value_as_int = try cg.bitCast(field_int_ty, .u1, value_as_int);
+ } else if (elem_ty.isInt(zcu)) {
+ value_as_int = value_id;
+ } else {
+ value_as_int = try cg.bitCast(field_int_ty, elem_ty, value_id);
+ }
+
+ const extended = blk: {
+ if (cg.backingIntBits(elem_bit_size).@"0" == cg.backingIntBits(host_bits).@"0")
+ break :blk try cg.bitCast(host_int_ty, field_int_ty, value_as_int);
+ const conv = try cg.buildConvert(host_int_ty, .{ .ty = field_int_ty, .value = .{ .singleton = value_as_int } });
+ break :blk try conv.materialize(cg);
+ };
+
+ const bit_offset = ptr_info.packed_offset.bit_offset;
+ const field_mask = (@as(u64, 1) << @as(u6, @intCast(elem_bit_size))) - 1;
+ const host_mask = if (host_bits == 64) @as(u64, std.math.maxInt(u64)) else (@as(u64, 1) << @as(u6, @intCast(host_bits))) - 1;
+ const clear_mask = ~(field_mask << @as(u6, @intCast(bit_offset))) & host_mask;
+ const clear_mask_id = try cg.constInt(host_int_ty, clear_mask);
+ const cleared = try cg.buildBinary(.OpBitwiseAnd, .{ .ty = host_int_ty, .value = .{ .singleton = host_val } }, .{ .ty = host_int_ty, .value = .{ .singleton = clear_mask_id } });
+ const bit_offset_id = try cg.constInt(host_int_ty, bit_offset);
+ const shifted_val = try cg.buildBinary(.OpShiftLeftLogical, .{ .ty = host_int_ty, .value = .{ .singleton = extended } }, .{ .ty = host_int_ty, .value = .{ .singleton = bit_offset_id } });
+ const combined = try cg.buildBinary(.OpBitwiseOr, cleared, shifted_val);
+ const combined_id = try combined.materialize(cg);
+
+ try cg.store(host_int_ty, operand_ptr_id, combined_id, .{ .is_volatile = ptr_info.flags.is_volatile });
+ return;
+ }
+
+ const ptr_id = switch (ptr_info.flags.vector_index) {
+ .none => operand_ptr_id,
+ else => |index| ptr_id: {
+ const elem_ptr_ty_id = try cg.ptrType(
+ try cg.resolveType(elem_ty, .indirect),
+ cg.storageClass(ptr_info.flags.address_space),
+ );
+ break :ptr_id try cg.accessChain(elem_ptr_ty_id, operand_ptr_id, &.{@intFromEnum(index)});
+ },
+ };
+
+ try cg.store(elem_ty, ptr_id, value_id, .{ .is_volatile = ptr_info.flags.is_volatile });
}
fn airRet(cg: *CodeGen, inst: Air.Inst.Index) !void {
- const gpa = cg.module.gpa;
- const zcu = cg.module.zcu;
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
const operand = cg.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
const ret_ty = cg.typeOf(operand);
if (!ret_ty.hasRuntimeBits(zcu)) {
@@ -5291,8 +7476,8 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) !void {
}
fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) !void {
- const gpa = cg.module.gpa;
- const zcu = cg.module.zcu;
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
const un_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
const ptr_ty = cg.typeOf(un_op);
const ret_ty = ptr_ty.childType(zcu);
@@ -5310,16 +7495,18 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) !void {
}
}
- const ptr = try cg.resolve(un_op);
- const value = try cg.load(ret_ty, ptr, .{ .is_volatile = ptr_ty.isVolatilePtr(zcu) });
+ const value = switch (try cg.resolvePtr(un_op)) {
+ .tracked => |t| t.slot.*.?,
+ .id => |ptr| try cg.load(ret_ty, ptr, .{ .is_volatile = ptr_ty.isVolatilePtr(zcu) }),
+ };
try cg.body.emit(gpa, .OpReturnValue, .{
.value = value,
});
}
fn airTry(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const gpa = cg.module.gpa;
- const zcu = cg.module.zcu;
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
const unwrapped_try = cg.air.unwrapTry(inst);
const body = unwrapped_try.else_body;
@@ -5338,7 +7525,7 @@ fn airTry(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
err_union_id;
const zero_id = try cg.constInt(.anyerror, 0);
- const is_err_id = cg.module.allocId();
+ const is_err_id = cg.allocId();
try cg.body.emit(gpa, .OpINotEqual, .{
.id_result_type = bool_ty_id,
.id_result = is_err_id,
@@ -5350,22 +7537,16 @@ fn airTry(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
// with the current body.
// Just generate a new block here, then generate a new block inline for the remainder of the body.
- const err_block = cg.module.allocId();
- const ok_block = cg.module.allocId();
+ const err_block = cg.allocId();
+ const ok_block = cg.allocId();
- switch (cg.control_flow) {
- .structured => {
- // According to AIR documentation, this block is guaranteed
- // to not break and end in a return instruction. Thus,
- // for structured control flow, we can just naively use
- // the ok block as the merge block here.
- try cg.body.emit(gpa, .OpSelectionMerge, .{
- .merge_block = ok_block,
- .selection_control = .{},
- });
- },
- .unstructured => {},
- }
+ // According to AIR documentation, this block is guaranteed
+ // to not break and end in a return instruction. Thus,
+ // we can just naively use the ok block as the merge block here.
+ try cg.body.emit(gpa, .OpSelectionMerge, .{
+ .merge_block = ok_block,
+ .selection_control = .{},
+ });
try cg.body.emit(gpa, .OpBranchConditional, .{
.condition = is_err_id,
@@ -5388,7 +7569,7 @@ fn airTry(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn airErrUnionErr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const operand_id = try cg.resolve(ty_op.operand);
const err_union_ty = cg.typeOf(ty_op.operand);
@@ -5396,7 +7577,7 @@ fn airErrUnionErr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
if (err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) {
// No error possible, so just return undefined.
- return try cg.module.constUndef(err_ty_id);
+ return try cg.constUndef(err_ty_id);
}
const payload_ty = err_union_ty.errorUnionPayload(zcu);
@@ -5424,7 +7605,7 @@ fn airErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn airWrapErrUnionErr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const err_union_ty = cg.typeOfIndex(inst);
const payload_ty = err_union_ty.errorUnionPayload(zcu);
@@ -5439,7 +7620,7 @@ fn airWrapErrUnionErr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
var members: [2]Id = undefined;
members[eu_layout.errorFieldIndex()] = operand_id;
- members[eu_layout.payloadFieldIndex()] = try cg.module.constUndef(payload_ty_id);
+ members[eu_layout.payloadFieldIndex()] = try cg.constUndef(payload_ty_id);
var types: [2]Type = undefined;
types[eu_layout.errorFieldIndex()] = .anyerror;
@@ -5473,7 +7654,7 @@ fn airWrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn airIsNull(cg: *CodeGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { is_null, is_non_null }) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const un_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
const operand_id = try cg.resolve(un_op);
const operand_ty = cg.typeOf(un_op);
@@ -5500,7 +7681,7 @@ fn airIsNull(cg: *CodeGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum {
loaded_id;
const ptr_ty_id = try cg.resolveType(ptr_ty, .direct);
- const null_id = try cg.module.constNull(ptr_ty_id);
+ const null_id = try cg.constNull(ptr_ty_id);
const null_tmp: Temporary = .init(ptr_ty, null_id);
const ptr: Temporary = .init(ptr_ty, ptr_id);
@@ -5515,9 +7696,9 @@ fn airIsNull(cg: *CodeGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum {
const is_non_null_id = blk: {
if (is_pointer) {
if (payload_ty.hasRuntimeBits(zcu)) {
- const storage_class = cg.module.storageClass(operand_ty.ptrAddressSpace(zcu));
+ const storage_class = cg.storageClass(operand_ty.ptrAddressSpace(zcu));
const bool_indirect_ty_id = try cg.resolveType(.bool, .indirect);
- const bool_ptr_ty_id = try cg.module.ptrType(bool_indirect_ty_id, storage_class);
+ const bool_ptr_ty_id = try cg.ptrType(bool_indirect_ty_id, storage_class);
const tag_ptr_id = try cg.accessChain(bool_ptr_ty_id, operand_id, &.{1});
break :blk try cg.load(.bool, tag_ptr_id, .{});
}
@@ -5537,8 +7718,8 @@ fn airIsNull(cg: *CodeGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum {
return switch (pred) {
.is_null => blk: {
// Invert condition
- const result_id = cg.module.allocId();
- try cg.body.emit(cg.module.gpa, .OpLogicalNot, .{
+ const result_id = cg.allocId();
+ try cg.body.emit(cg.gpa, .OpLogicalNot, .{
.id_result_type = bool_ty_id,
.id_result = result_id,
.operand = is_non_null_id,
@@ -5550,7 +7731,7 @@ fn airIsNull(cg: *CodeGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum {
}
fn airIsErr(cg: *CodeGen, inst: Air.Inst.Index, pred: enum { is_err, is_non_err }) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const un_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
const operand_id = try cg.resolve(un_op);
const err_union_ty = cg.typeOf(un_op);
@@ -5568,10 +7749,10 @@ fn airIsErr(cg: *CodeGen, inst: Air.Inst.Index, pred: enum { is_err, is_non_err
else
try cg.extractField(.anyerror, operand_id, eu_layout.errorFieldIndex());
- const result_id = cg.module.allocId();
+ const result_id = cg.allocId();
switch (pred) {
inline else => |pred_ct| try cg.body.emit(
- cg.module.gpa,
+ cg.gpa,
switch (pred_ct) {
.is_err => .OpINotEqual,
.is_non_err => .OpIEqual,
@@ -5588,7 +7769,7 @@ fn airIsErr(cg: *CodeGen, inst: Air.Inst.Index, pred: enum { is_err, is_non_err
}
fn airUnwrapOptional(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const operand_id = try cg.resolve(ty_op.operand);
const optional_ty = cg.typeOf(ty_op.operand);
@@ -5604,7 +7785,7 @@ fn airUnwrapOptional(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn airUnwrapOptionalPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const operand_id = try cg.resolve(ty_op.operand);
const operand_ty = cg.typeOf(ty_op.operand);
@@ -5628,7 +7809,7 @@ fn airUnwrapOptionalPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const payload_ty = cg.typeOf(ty_op.operand);
@@ -5648,9 +7829,9 @@ fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
}
fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void {
- const gpa = cg.module.gpa;
- const zcu = cg.module.zcu;
- const target = cg.module.zcu.getTarget();
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
+ const target = cg.zcu.getTarget();
const switch_br = cg.air.unwrapSwitch(inst);
const cond_ty = cg.typeOf(switch_br.operand);
const cond = try cg.resolve(switch_br.operand);
@@ -5660,14 +7841,14 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void {
.bool, .error_set => 1,
.int => blk: {
const bits = cond_ty.intInfo(zcu).bits;
- const backing_bits, const big_int = cg.module.backingIntBits(bits);
+ const backing_bits, const big_int = cg.backingIntBits(bits);
if (big_int) return cg.todo("implement composite int switch", .{});
break :blk if (backing_bits <= 32) 1 else 2;
},
.@"enum" => blk: {
const int_ty = cond_ty.intTagType(zcu);
const int_info = int_ty.intInfo(zcu);
- const backing_bits, const big_int = cg.module.backingIntBits(int_info.bits);
+ const backing_bits, const big_int = cg.backingIntBits(int_info.bits);
if (big_int) return cg.todo("implement composite int switch", .{});
break :blk if (backing_bits <= 32) 1 else 2;
},
@@ -5681,54 +7862,51 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void {
const num_cases = switch_br.cases_len;
- // Compute the total number of arms that we need.
- // Zig switches are grouped by condition, so we need to loop through all of them
- const num_conditions = blk: {
- var num_conditions: u32 = 0;
+ // compute the total number of scalar arms and find the last range case
+ var num_conditions: u32 = 0;
+ var last_range_case: ?u32 = null;
+ {
var it = switch_br.iterateCases();
while (it.next()) |case| {
- if (case.ranges.len > 0) return cg.todo("switch with ranges", .{});
- num_conditions += @intCast(case.items.len);
+ if (case.ranges.len > 0) {
+ last_range_case = case.idx;
+ } else {
+ num_conditions += @intCast(case.items.len);
+ }
}
- break :blk num_conditions;
- };
+ }
// First, pre-allocate the labels for the cases.
- const case_labels = cg.module.allocIds(num_cases);
+ const case_labels = cg.allocIds(num_cases);
// We always need the default case - if zig has none, we will generate unreachable there.
- const default = cg.module.allocId();
+ const default_label = cg.allocId();
+ const switch_default = if (last_range_case != null) cg.allocId() else default_label;
- const merge_label = switch (cg.control_flow) {
- .structured => cg.module.allocId(),
- .unstructured => null,
- };
+ const merge_label = cg.allocId();
- if (cg.control_flow == .structured) {
- try cg.body.emit(gpa, .OpSelectionMerge, .{
- .merge_block = merge_label.?,
- .selection_control = .{},
- });
- }
+ try cg.body.emit(gpa, .OpSelectionMerge, .{
+ .merge_block = merge_label,
+ .selection_control = .{},
+ });
// Emit the instruction before generating the blocks.
try cg.body.emitRaw(gpa, .OpSwitch, 2 + (cond_words + 1) * num_conditions);
cg.body.writeOperand(Id, cond_indirect);
- cg.body.writeOperand(Id, default);
+ cg.body.writeOperand(Id, switch_default);
- // Emit each of the cases
+ // Emit the non-range cases into the OpSwitch.
+ // Cases with ranges are handled by the conditional chain below.
{
var it = switch_br.iterateCases();
while (it.next()) |case| {
- // SPIR-V needs a literal here, which' width depends on the case condition.
+ if (case.ranges.len > 0) continue;
const label = case_labels.at(case.idx);
for (case.items) |item| {
const value: Value = .fromInterned(item.toInterned().?);
const int_val: u64 = switch (cond_ty.zigTypeTag(zcu)) {
.bool, .int => if (cond_ty.isSignedInt(zcu)) @bitCast(value.toSignedInt(zcu)) else value.toUnsignedInt(zcu),
- .@"enum" => blk: {
- break :blk value.intFromEnum(zcu).toUnsignedInt(zcu); // TODO: composite integer constants
- },
+ .@"enum" => value.intFromEnum(zcu).toUnsignedInt(zcu),
.error_set => value.getErrorInt(zcu),
.pointer => value.toUnsignedInt(zcu),
else => unreachable,
@@ -5744,84 +7922,427 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void {
}
}
- var incoming_structured_blocks: std.ArrayList(ControlFlow.Structured.Block.Incoming) = .empty;
+ var incoming_structured_blocks: std.ArrayList(Block.Incoming) = .empty;
defer incoming_structured_blocks.deinit(gpa);
+ try incoming_structured_blocks.ensureUnusedCapacity(gpa, num_cases + 1);
- if (cg.control_flow == .structured) {
- try incoming_structured_blocks.ensureUnusedCapacity(gpa, num_cases + 1);
+ // emit the range-checking chain as nested if-else inside the switch's default branch.
+ // each range case becomes:
+ // - check condition,
+ // - if true emit case body and branch to merge,
+ // - else continue to next check or default
+ if (last_range_case != null) {
+ const cond_tmp: Temporary = .init(cond_ty, cond);
+ const bool_ty_id = try cg.resolveType(.bool, .direct);
+
+ try cg.beginSpvBlock(switch_default);
+
+ var it_range = switch_br.iterateCases();
+ while (it_range.next()) |case| {
+ if (case.ranges.len == 0) continue;
+
+ var case_cond: ?Id = null;
+
+ for (case.items) |item| {
+ const item_tmp: Temporary = try cg.temporary(item);
+ const eq = try (try cg.cmp(.eq, cond_tmp, item_tmp)).materialize(cg);
+ case_cond = if (case_cond) |prev| blk: {
+ const combined = cg.allocId();
+ try cg.body.emit(gpa, .OpLogicalOr, .{
+ .id_result_type = bool_ty_id,
+ .id_result = combined,
+ .operand_1 = prev,
+ .operand_2 = eq,
+ });
+ break :blk combined;
+ } else eq;
+ }
+
+ for (case.ranges) |range| {
+ const lo_tmp: Temporary = try cg.temporary(range[0]);
+ const hi_tmp: Temporary = try cg.temporary(range[1]);
+ const ge = try (try cg.cmp(.gte, cond_tmp, lo_tmp)).materialize(cg);
+ const le = try (try cg.cmp(.lte, cond_tmp, hi_tmp)).materialize(cg);
+ const in_range = cg.allocId();
+ try cg.body.emit(gpa, .OpLogicalAnd, .{
+ .id_result_type = bool_ty_id,
+ .id_result = in_range,
+ .operand_1 = ge,
+ .operand_2 = le,
+ });
+ case_cond = if (case_cond) |prev| blk: {
+ const combined = cg.allocId();
+ try cg.body.emit(gpa, .OpLogicalOr, .{
+ .id_result_type = bool_ty_id,
+ .id_result = combined,
+ .operand_1 = prev,
+ .operand_2 = in_range,
+ });
+ break :blk combined;
+ } else in_range;
+ }
+
+ const case_label = case_labels.at(case.idx);
+ const is_last = case.idx == last_range_case.?;
+ const next_check = if (is_last) default_label else cg.allocId();
+
+ try cg.body.emit(gpa, .OpSelectionMerge, .{
+ .merge_block = next_check,
+ .selection_control = .{},
+ });
+
+ try cg.body.emit(gpa, .OpBranchConditional, .{
+ .condition = case_cond.?,
+ .true_label = case_label,
+ .false_label = next_check,
+ });
+
+ if (!is_last) {
+ try cg.beginSpvBlock(next_check);
+ }
+ }
}
- // Now, finally, we can start emitting each of the cases.
+ // emit bodies
var it = switch_br.iterateCases();
while (it.next()) |case| {
const label = case_labels.at(case.idx);
try cg.beginSpvBlock(label);
- switch (cg.control_flow) {
- .structured => {
- const next_block = try cg.genStructuredBody(.selection, case.body);
- incoming_structured_blocks.appendAssumeCapacity(.{
- .src_label = cg.block_label,
- .next_block = next_block,
- });
+ const next_block = try cg.genStructuredBody(.selection, case.body);
+ incoming_structured_blocks.appendAssumeCapacity(.{
+ .src_label = cg.block_label,
+ .next_block = next_block,
+ });
- try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label.? });
- },
- .unstructured => {
- try cg.genBody(case.body);
- },
- }
+ try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label });
}
- const else_body = it.elseBody();
- try cg.beginSpvBlock(default);
+ const else_body = blk: {
+ var it_else = switch_br.iterateCases();
+ while (it_else.next()) |_| {}
+ break :blk it_else.elseBody();
+ };
+ try cg.beginSpvBlock(default_label);
if (else_body.len != 0) {
- switch (cg.control_flow) {
- .structured => {
- const next_block = try cg.genStructuredBody(.selection, else_body);
- incoming_structured_blocks.appendAssumeCapacity(.{
- .src_label = cg.block_label,
- .next_block = next_block,
+ const next_block = try cg.genStructuredBody(.selection, else_body);
+ incoming_structured_blocks.appendAssumeCapacity(.{
+ .src_label = cg.block_label,
+ .next_block = next_block,
+ });
+
+ try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label });
+ } else {
+ try cg.body.emit(gpa, .OpUnreachable, {});
+ }
+
+ try cg.beginSpvBlock(merge_label);
+ const next_block = try cg.structuredNextBlock(incoming_structured_blocks.items);
+ try cg.structuredBreak(next_block);
+}
+
+fn airLoopSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void {
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
+ const target = cg.zcu.getTarget();
+ const switch_br = cg.air.unwrapSwitch(inst);
+ const cond_ty = cg.typeOf(switch_br.operand);
+ const initial_cond = try cg.resolve(switch_br.operand);
+ var initial_cond_indirect = try cg.convertToIndirect(cond_ty, initial_cond);
+
+ const cond_words: u32 = switch (cond_ty.zigTypeTag(zcu)) {
+ .bool, .error_set => 1,
+ .int => blk: {
+ const bits = cond_ty.intInfo(zcu).bits;
+ const backing_bits, const big_int = cg.backingIntBits(bits);
+ if (big_int) return cg.todo("implement composite int loop switch", .{});
+ break :blk if (backing_bits <= 32) 1 else 2;
+ },
+ .@"enum" => blk: {
+ const int_ty = cond_ty.intTagType(zcu);
+ const int_info = int_ty.intInfo(zcu);
+ const backing_bits, const big_int = cg.backingIntBits(int_info.bits);
+ if (big_int) return cg.todo("implement composite int loop switch", .{});
+ break :blk if (backing_bits <= 32) 1 else 2;
+ },
+ .pointer => blk: {
+ initial_cond_indirect = try cg.intFromPtr(initial_cond_indirect);
+ break :blk target.ptrBitWidth() / 32;
+ },
+ else => return cg.todo("implement loop switch for type {s}", .{@tagName(cond_ty.zigTypeTag(zcu))}),
+ };
+
+ const cond_ty_id = try cg.resolveType(cond_ty, .indirect);
+ const cond_var = try cg.alloc(cond_ty_id, null);
+ try cg.store(cond_ty, cond_var, initial_cond_indirect, .{});
+
+ const num_cases = switch_br.cases_len;
+
+ var num_conditions: u32 = 0;
+ var last_range_case: ?u32 = null;
+ {
+ var it = switch_br.iterateCases();
+ while (it.next()) |case| {
+ if (case.ranges.len > 0) {
+ last_range_case = case.idx;
+ } else {
+ num_conditions += @intCast(case.items.len);
+ }
+ }
+ }
+
+ const case_labels = cg.allocIds(num_cases);
+ const default_label = cg.allocId();
+ const switch_default = if (last_range_case != null) cg.allocId() else default_label;
+
+ const header_label = cg.allocId();
+ const loop_merge = cg.allocId();
+ const continue_label = cg.allocId();
+ const switch_merge = cg.allocId();
+ const body_label = cg.allocId();
+
+ // switch_dispatch signals "continue the loop" by using this sentinel as the
+ // next_block in structuredBreak. at switch_merge, a phi + comparison distinguishes
+ // dispatch (continue) from break (exit)
+ const dispatch_sentinel = try cg.constInt(.u32, @intFromEnum(inst));
+
+ try cg.loop_switches.putNoClobber(gpa, inst, .{
+ .cond_var = cond_var,
+ .continue_label = dispatch_sentinel,
+ });
+ defer assert(cg.loop_switches.remove(inst));
+
+ try cg.body.emit(gpa, .OpBranch, .{ .target_label = header_label });
+ try cg.beginSpvBlock(header_label);
+
+ try cg.body.emit(gpa, .OpLoopMerge, .{
+ .merge_block = loop_merge,
+ .continue_target = continue_label,
+ .loop_control = .{},
+ });
+
+ try cg.body.emit(gpa, .OpBranch, .{ .target_label = body_label });
+ try cg.beginSpvBlock(body_label);
+
+ const cond = try cg.load(cond_ty, cond_var, .{});
+ const cond_indirect = try cg.convertToIndirect(cond_ty, cond);
+
+ try cg.body.emit(gpa, .OpSelectionMerge, .{
+ .merge_block = switch_merge,
+ .selection_control = .{},
+ });
+
+ try cg.body.emitRaw(gpa, .OpSwitch, 2 + (cond_words + 1) * num_conditions);
+ cg.body.writeOperand(Id, cond_indirect);
+ cg.body.writeOperand(Id, switch_default);
+
+ {
+ var it = switch_br.iterateCases();
+ while (it.next()) |case| {
+ if (case.ranges.len > 0) continue;
+ const label = case_labels.at(case.idx);
+ for (case.items) |item| {
+ const value: Value = .fromInterned(item.toInterned().?);
+ const int_val: u64 = switch (cond_ty.zigTypeTag(zcu)) {
+ .bool, .int => if (cond_ty.isSignedInt(zcu)) @bitCast(value.toSignedInt(zcu)) else value.toUnsignedInt(zcu),
+ .@"enum" => value.intFromEnum(zcu).toUnsignedInt(zcu),
+ .error_set => value.getErrorInt(zcu),
+ .pointer => value.toUnsignedInt(zcu),
+ else => unreachable,
+ };
+ const int_lit: spec.LiteralContextDependentNumber = switch (cond_words) {
+ 1 => .{ .uint32 = @intCast(int_val) },
+ 2 => .{ .uint64 = int_val },
+ else => unreachable,
+ };
+ cg.body.writeOperand(spec.LiteralContextDependentNumber, int_lit);
+ cg.body.writeOperand(Id, label);
+ }
+ }
+ }
+
+ var incoming_structured_blocks: std.ArrayList(Block.Incoming) = .empty;
+ defer incoming_structured_blocks.deinit(gpa);
+ try incoming_structured_blocks.ensureUnusedCapacity(gpa, num_cases + 1);
+
+ if (last_range_case != null) {
+ const cond_tmp: Temporary = .init(cond_ty, cond);
+ const bool_ty_id = try cg.resolveType(.bool, .direct);
+
+ try cg.beginSpvBlock(switch_default);
+
+ var it_range = switch_br.iterateCases();
+ while (it_range.next()) |case| {
+ if (case.ranges.len == 0) continue;
+
+ var case_cond: ?Id = null;
+
+ for (case.items) |item| {
+ const item_tmp: Temporary = try cg.temporary(item);
+ const eq = try (try cg.cmp(.eq, cond_tmp, item_tmp)).materialize(cg);
+ case_cond = if (case_cond) |prev| blk: {
+ const combined = cg.allocId();
+ try cg.body.emit(gpa, .OpLogicalOr, .{
+ .id_result_type = bool_ty_id,
+ .id_result = combined,
+ .operand_1 = prev,
+ .operand_2 = eq,
+ });
+ break :blk combined;
+ } else eq;
+ }
+
+ for (case.ranges) |range| {
+ const lo_tmp: Temporary = try cg.temporary(range[0]);
+ const hi_tmp: Temporary = try cg.temporary(range[1]);
+ const ge = try (try cg.cmp(.gte, cond_tmp, lo_tmp)).materialize(cg);
+ const le = try (try cg.cmp(.lte, cond_tmp, hi_tmp)).materialize(cg);
+ const in_range = cg.allocId();
+ try cg.body.emit(gpa, .OpLogicalAnd, .{
+ .id_result_type = bool_ty_id,
+ .id_result = in_range,
+ .operand_1 = ge,
+ .operand_2 = le,
});
+ case_cond = if (case_cond) |prev| blk: {
+ const combined = cg.allocId();
+ try cg.body.emit(gpa, .OpLogicalOr, .{
+ .id_result_type = bool_ty_id,
+ .id_result = combined,
+ .operand_1 = prev,
+ .operand_2 = in_range,
+ });
+ break :blk combined;
+ } else in_range;
+ }
+
+ const case_label = case_labels.at(case.idx);
+ const is_last = case.idx == last_range_case.?;
+ const next_check = if (is_last) default_label else cg.allocId();
+
+ try cg.body.emit(gpa, .OpSelectionMerge, .{
+ .merge_block = next_check,
+ .selection_control = .{},
+ });
+
+ try cg.body.emit(gpa, .OpBranchConditional, .{
+ .condition = case_cond.?,
+ .true_label = case_label,
+ .false_label = next_check,
+ });
+
+ if (!is_last) {
+ try cg.beginSpvBlock(next_check);
+ }
+ }
+ }
- try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label.? });
- },
- .unstructured => {
- try cg.genBody(else_body);
- },
+ {
+ var it = switch_br.iterateCases();
+ while (it.next()) |case| {
+ const label = case_labels.at(case.idx);
+ try cg.beginSpvBlock(label);
+
+ const next_block = try cg.genStructuredBody(.selection, case.body);
+ incoming_structured_blocks.appendAssumeCapacity(.{
+ .src_label = cg.block_label,
+ .next_block = next_block,
+ });
+ try cg.body.emit(gpa, .OpBranch, .{ .target_label = switch_merge });
}
+ }
+
+ const else_body = blk: {
+ var it_else = switch_br.iterateCases();
+ while (it_else.next()) |_| {}
+ break :blk it_else.elseBody();
+ };
+ try cg.beginSpvBlock(default_label);
+ if (else_body.len != 0) {
+ const next_block = try cg.genStructuredBody(.selection, else_body);
+ incoming_structured_blocks.appendAssumeCapacity(.{
+ .src_label = cg.block_label,
+ .next_block = next_block,
+ });
+ try cg.body.emit(gpa, .OpBranch, .{ .target_label = switch_merge });
} else {
try cg.body.emit(gpa, .OpUnreachable, {});
}
- if (cg.control_flow == .structured) {
- try cg.beginSpvBlock(merge_label.?);
- const next_block = try cg.structuredNextBlock(incoming_structured_blocks.items);
- try cg.structuredBreak(next_block);
- }
+ try cg.beginSpvBlock(switch_merge);
+ const next_block = try cg.structuredNextBlock(incoming_structured_blocks.items);
+
+ const is_dispatch = cg.allocId();
+ const bool_ty_id = try cg.resolveType(.bool, .direct);
+ try cg.body.emit(gpa, .OpIEqual, .{
+ .id_result_type = bool_ty_id,
+ .id_result = is_dispatch,
+ .operand_1 = next_block,
+ .operand_2 = dispatch_sentinel,
+ });
+
+ const dispatch_check_merge = cg.allocId();
+ try cg.body.emit(gpa, .OpSelectionMerge, .{
+ .merge_block = dispatch_check_merge,
+ .selection_control = .{},
+ });
+ const exit_block = cg.allocId();
+ try cg.body.emit(gpa, .OpBranchConditional, .{
+ .condition = is_dispatch,
+ .true_label = dispatch_check_merge,
+ .false_label = exit_block,
+ });
+
+ try cg.beginSpvBlock(exit_block);
+ try cg.body.emit(gpa, .OpBranch, .{ .target_label = loop_merge });
+
+ try cg.beginSpvBlock(dispatch_check_merge);
+ try cg.body.emit(gpa, .OpBranch, .{ .target_label = continue_label });
+
+ try cg.beginSpvBlock(continue_label);
+ try cg.body.emit(gpa, .OpBranch, .{ .target_label = header_label });
+
+ try cg.beginSpvBlock(loop_merge);
+ try cg.structuredBreak(next_block);
+}
+
+fn airSwitchDispatch(cg: *CodeGen, inst: Air.Inst.Index) !void {
+ const br = cg.air.instructions.items(.data)[@intFromEnum(inst)].br;
+ const loop_switch = cg.loop_switches.get(br.block_inst).?;
+ const cond_ty = cg.typeOf(br.operand);
+ const operand = try cg.resolve(br.operand);
+ const operand_indirect = try cg.convertToIndirect(cond_ty, operand);
+
+ try cg.store(cond_ty, loop_switch.cond_var, operand_indirect, .{});
+ try cg.structuredBreak(loop_switch.continue_label);
}
fn airUnreach(cg: *CodeGen) !void {
- try cg.body.emit(cg.module.gpa, .OpUnreachable, {});
+ try cg.body.emit(cg.gpa, .OpUnreachable, {});
}
fn airDbgStmt(cg: *CodeGen, inst: Air.Inst.Index) !void {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const dbg_stmt = cg.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
const path = zcu.navFileScope(cg.owner_nav).sub_file_path;
if (zcu.comp.config.root_strip) return;
- try cg.body.emit(cg.module.gpa, .OpLine, .{
- .file = try cg.module.debugString(path),
+ const path_id = cg.allocId();
+ try cg.sections.debug_strings.emit(cg.gpa, .OpString, .{
+ .id_result = path_id,
+ .string = path,
+ });
+ try cg.body.emit(cg.gpa, .OpLine, .{
+ .file = path_id,
.line = cg.base_line + dbg_stmt.line + 1,
.column = dbg_stmt.column + 1,
});
}
fn airDbgInlineBlock(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const zcu = cg.module.zcu;
+ const zcu = cg.zcu;
const block = cg.air.unwrapDbgBlock(inst);
const old_base_line = cg.base_line;
defer cg.base_line = old_base_line;
@@ -5831,14 +8352,17 @@ fn airDbgInlineBlock(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
fn airDbgVar(cg: *CodeGen, inst: Air.Inst.Index) !void {
const pl_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
- const target_id = try cg.resolve(pl_op.operand);
+ const target_id = switch (try cg.resolvePtr(pl_op.operand)) {
+ .tracked => return,
+ .id => |id| id,
+ };
const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
- try cg.module.debugName(target_id, name.toSlice(cg.air));
+ try cg.debugName(target_id, name.toSlice(cg.air));
}
fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
- const gpa = cg.module.gpa;
- const zcu = cg.module.zcu;
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
const unwrapped_asm = cg.air.unwrapAsm(inst);
const is_volatile = unwrapped_asm.is_volatile;
@@ -5870,7 +8394,6 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
return cg.fail("assembly inputs with 'c' constraint have to be compile-time known", .{});
});
- // TODO: This entire function should be handled a bit better...
const ip = &zcu.intern_pool;
switch (ip.indexToKey(val.toIntern())) {
.int_type,
@@ -5884,6 +8407,7 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
.struct_type,
.union_type,
.opaque_type,
+ .spirv_type,
.enum_type,
.func_type,
.error_set_type,
@@ -5975,8 +8499,8 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) !?Id {
_ = modifier;
- const gpa = cg.module.gpa;
- const zcu = cg.module.zcu;
+ const gpa = cg.gpa;
+ const zcu = cg.zcu;
const air_call = cg.air.unwrapCall(inst);
const args = air_call.args;
const callee_ty = cg.typeOf(air_call.callee);
@@ -5989,11 +8513,9 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier)
const return_type = fn_info.return_type;
const result_type_id = try cg.resolveFnReturnType(.fromInterned(return_type));
- const result_id = cg.module.allocId();
+ const result_id = cg.allocId();
const callee_id = try cg.resolve(air_call.callee);
- comptime assert(zig_call_abi_ver == 3);
-
const scratch_top = cg.id_scratch.items.len;
defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
const params = try cg.id_scratch.addManyAsSlice(gpa, args.len);
@@ -6005,9 +8527,20 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier)
// temporary params buffer.
const arg_ty = cg.typeOf(arg);
if (!arg_ty.hasRuntimeBits(zcu)) continue;
- const arg_id = try cg.resolve(arg);
- params[n_params] = arg_id;
+ if (arg_ty.zigTypeTag(zcu) == .pointer and !arg_ty.isSlice(zcu) and
+ !arg_ty.childType(zcu).hasRuntimeBits(zcu) and
+ cg.storageClass(arg_ty.ptrAddressSpace(zcu)) == .function)
+ {
+ // in logical addressing, pointer arguments to function calls
+ // must be memory object declarations (OpVariable). for pointers to
+ // zero-sized types, the source value may not be a variable, so just
+ // allocate a dummy one.
+ const child_ty_id = try cg.resolveType(arg_ty.childType(zcu), .indirect);
+ params[n_params] = try cg.alloc(child_ty_id, null);
+ } else {
+ params[n_params] = try cg.resolve(arg);
+ }
n_params += 1;
}
@@ -6028,19 +8561,30 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier)
fn builtin3D(
cg: *CodeGen,
result_ty: Type,
- builtin: spec.BuiltIn,
+ built_in: spec.BuiltIn,
dimension: u32,
out_of_range_value: anytype,
) !Id {
- const gpa = cg.module.gpa;
+ const gpa = cg.gpa;
if (dimension >= 3) return try cg.constInt(result_ty, out_of_range_value);
- const u32_ty_id = try cg.module.intType(.unsigned, 32);
- const vec_ty_id = try cg.module.vectorType(3, u32_ty_id);
- const ptr_ty_id = try cg.module.ptrType(vec_ty_id, .input);
- const spv_decl_index = try cg.module.builtin(ptr_ty_id, builtin, .input);
- try cg.module.decl_deps.append(gpa, spv_decl_index);
- const ptr_id = cg.module.declPtr(spv_decl_index).result_id;
- const vec_id = cg.module.allocId();
+ const u32_ty_id = try cg.intType(.unsigned, 32);
+ const vec_ty_id = try cg.vectorType(3, u32_ty_id);
+ const ptr_ty_id = try cg.ptrType(vec_ty_id, .input);
+ const builtins_gop = try cg.builtins.getOrPut(gpa, .{ built_in, .input });
+ if (!builtins_gop.found_existing) {
+ builtins_gop.value_ptr.* = try cg.allocDecl(.global);
+ const decl = cg.declPtr(builtins_gop.value_ptr.*);
+ try cg.sections.globals.emit(gpa, .OpVariable, .{
+ .id_result_type = ptr_ty_id,
+ .id_result = decl.result_id,
+ .storage_class = .input,
+ });
+ try cg.decorate(decl.result_id, .{ .built_in = .{ .built_in = built_in } });
+ }
+ const spv_decl_index = builtins_gop.value_ptr.*;
+ try cg.decl_deps.append(gpa, spv_decl_index);
+ const ptr_id = cg.declPtr(spv_decl_index).result_id;
+ const vec_id = cg.allocId();
try cg.body.emit(gpa, .OpLoad, .{
.id_result_type = vec_ty_id,
.id_result = vec_id,
@@ -6071,12 +8615,30 @@ fn airWorkGroupId(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
return try cg.builtin3D(.u32, .workgroup_id, dimension, 0);
}
-fn typeOf(cg: *CodeGen, inst: Air.Inst.Ref) Type {
- const zcu = cg.module.zcu;
- return cg.air.typeOf(inst, &zcu.intern_pool);
-}
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const Target = std.Target;
+const Signedness = std.lang.Signedness;
+const assert = std.debug.assert;
+const log = std.log.scoped(.codegen);
-fn typeOfIndex(cg: *CodeGen, inst: Air.Inst.Index) Type {
- const zcu = cg.module.zcu;
- return cg.air.typeOfIndex(inst, &zcu.intern_pool);
-}
+const builtin = @import("builtin");
+const link = @import("../../link.zig");
+const codegen = @import("../../codegen.zig");
+const Zcu = @import("../../Zcu.zig");
+const Type = @import("../../Type.zig");
+const Value = @import("../../Value.zig");
+const Air = @import("../../Air.zig");
+const InternPool = @import("../../InternPool.zig");
+const Section = @import("Section.zig");
+const Assembler = @import("Assembler.zig");
+const Mir = @import("Mir.zig");
+
+const spec = @import("spec.zig");
+const Opcode = spec.Opcode;
+const Word = spec.Word;
+const Id = spec.Id;
+const IdRange = spec.IdRange;
+const StorageClass = spec.StorageClass;
+
+const CodeGen = @This();
diff --git a/src/codegen/spirv/Mir.zig b/src/codegen/spirv/Mir.zig
new file mode 100644
index 0000000000000000000000000000000000000000..c91c362426f83d8b458bce82e2b872e9d24722ff
--- /dev/null
+++ b/src/codegen/spirv/Mir.zig
@@ -0,0 +1,71 @@
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+
+const spec = @import("spec.zig");
+const Word = spec.Word;
+const Id = spec.Id;
+
+const InternPool = @import("../../InternPool.zig");
+const CodeGen = @import("CodeGen.zig");
+
+const Mir = @This();
+
+id_bound: Word,
+owner_nav: InternPool.Nav.Index,
+kind: CodeGen.Decl.Kind,
+decl_result_id: Id,
+extended_instruction_set: []const Word,
+globals: []const Word,
+functions: []const Word,
+annotations: []const Word,
+debug_names: []const Word,
+debug_strings: []const Word,
+execution_modes: []const Word,
+nav_refs: []const NavRef,
+uav_refs: []const UavRef,
+decl_deps: []const DeclDep,
+internal_globals: []const Id,
+entry_points: []const EntryPoint,
+
+pub const NavRef = struct {
+ local_id: Id,
+ nav: InternPool.Nav.Index,
+ kind: CodeGen.Decl.Kind,
+};
+
+pub const UavRef = struct {
+ local_id: Id,
+ val: InternPool.Index,
+ storage_class: spec.StorageClass,
+ kind: CodeGen.Decl.Kind,
+};
+
+pub const DeclDep = struct {
+ kind: CodeGen.Decl.Kind,
+ nav: InternPool.Nav.Index,
+};
+
+pub const EntryPoint = struct {
+ local_id: Id,
+ name: []const u8,
+ cc: std.builtin.CallingConvention,
+};
+
+pub fn deinit(mir: *Mir, gpa: Allocator) void {
+ gpa.free(mir.extended_instruction_set);
+ gpa.free(mir.globals);
+ gpa.free(mir.functions);
+ gpa.free(mir.annotations);
+ gpa.free(mir.debug_names);
+ gpa.free(mir.debug_strings);
+ gpa.free(mir.execution_modes);
+ gpa.free(mir.nav_refs);
+ gpa.free(mir.uav_refs);
+ gpa.free(mir.decl_deps);
+ gpa.free(mir.internal_globals);
+ for (mir.entry_points) |ep| {
+ gpa.free(ep.name);
+ }
+ gpa.free(mir.entry_points);
+ mir.* = undefined;
+}
diff --git a/src/codegen/spirv/Module.zig b/src/codegen/spirv/Module.zig
deleted file mode 100644
index f2fe02873c914723f2cb847470556133df4631b5..0000000000000000000000000000000000000000
--- a/src/codegen/spirv/Module.zig
+++ /dev/null
@@ -1,954 +0,0 @@
-//! This structure represents a SPIR-V (sections) module being compiled, and keeps
-//! track of all relevant information. That includes the actual instructions, the
-//! current result-id bound, and data structures for querying result-id's of data
-//! which needs to be persistent over different calls to Decl code generation.
-//!
-//! A SPIR-V binary module supports both little- and big endian layout. The layout
-//! is detected by the magic word in the header. Therefore, we can ignore any byte
-//! order throughout the implementation, and just use the host byte order, and make
-//! this a problem for the consumer.
-const std = @import("std");
-const Allocator = std.mem.Allocator;
-const assert = std.debug.assert;
-
-const Zcu = @import("../../Zcu.zig");
-const InternPool = @import("../../InternPool.zig");
-const Section = @import("Section.zig");
-const spec = @import("spec.zig");
-const Word = spec.Word;
-const Id = spec.Id;
-
-const Module = @This();
-
-gpa: Allocator,
-arena: Allocator,
-zcu: *Zcu,
-nav_link: std.AutoHashMapUnmanaged(InternPool.Nav.Index, Decl.Index) = .empty,
-uav_link: std.AutoHashMapUnmanaged(struct { InternPool.Index, spec.StorageClass }, Decl.Index) = .empty,
-intern_map: std.AutoHashMapUnmanaged(struct { InternPool.Index, Repr }, Id) = .empty,
-decls: std.ArrayList(Decl) = .empty,
-decl_deps: std.ArrayList(Decl.Index) = .empty,
-entry_points: std.AutoArrayHashMapUnmanaged(Id, EntryPoint) = .empty,
-/// This map serves a dual purpose:
-/// - It keeps track of pointers that are currently being emitted, so that we can tell
-/// if they are recursive and need an OpTypeForwardPointer.
-/// - It caches pointers by child-type. This is required because sometimes we rely on
-/// ID-equality for pointers, and pointers constructed via `ptrType()` aren't interned
-/// via the usual `intern_map` mechanism.
-ptr_types: std.AutoHashMapUnmanaged(struct { Id, spec.StorageClass }, Id) = .{},
-/// For test declarations compiled for Vulkan target, we have to add a buffer.
-/// We only need to generate this once, this holds the link information related to that.
-error_buffer: ?Decl.Index = null,
-/// SPIR-V instructions return result-ids.
-/// This variable holds the module-wide counter for these.
-next_result_id: Word = 1,
-/// Some types shouldn't be emitted more than one time, but cannot be caught by
-/// the `intern_map` during codegen. Sometimes, IDs are compared to check if
-/// types are the same, so we can't delay until the dedup pass. Therefore,
-/// this is an ad-hoc structure to cache types where required.
-/// According to the SPIR-V specification, section 2.8, this includes all non-aggregate
-/// non-pointer types.
-/// Additionally, this is used for other values which can be cached, for example,
-/// built-in variables.
-cache: struct {
- bool_type: ?Id = null,
- void_type: ?Id = null,
- opaque_types: std.StringHashMapUnmanaged(Id) = .empty,
- int_types: std.AutoHashMapUnmanaged(std.lang.Type.Int, Id) = .empty,
- float_types: std.AutoHashMapUnmanaged(std.lang.Type.Float, Id) = .empty,
- vector_types: std.AutoHashMapUnmanaged(struct { Id, u32 }, Id) = .empty,
- array_types: std.AutoHashMapUnmanaged(struct { Id, Id }, Id) = .empty,
- struct_types: std.ArrayHashMapUnmanaged(StructType, Id, StructType.HashContext, true) = .empty,
- fn_types: std.ArrayHashMapUnmanaged(FnType, Id, FnType.HashContext, true) = .empty,
-
- capabilities: std.AutoHashMapUnmanaged(spec.Capability, void) = .empty,
- extensions: std.StringHashMapUnmanaged(void) = .empty,
- extended_instruction_set: std.AutoHashMapUnmanaged(spec.InstructionSet, Id) = .empty,
- decorations: std.AutoHashMapUnmanaged(struct { Id, spec.Decoration }, void) = .empty,
- builtins: std.AutoHashMapUnmanaged(struct { spec.BuiltIn, spec.StorageClass }, Decl.Index) = .empty,
- strings: std.StringArrayHashMapUnmanaged(Id) = .empty,
-
- bool_const: [2]?Id = .{ null, null },
- constants: std.ArrayHashMapUnmanaged(Constant, Id, Constant.HashContext, true) = .empty,
-} = .{},
-/// Module layout, according to SPIR-V Spec section 2.4, "Logical Layout of a Module".
-sections: struct {
- capabilities: Section = .{},
- extensions: Section = .{},
- extended_instruction_set: Section = .{},
- memory_model: Section = .{},
- execution_modes: Section = .{},
- debug_strings: Section = .{},
- debug_names: Section = .{},
- annotations: Section = .{},
- globals: Section = .{},
- functions: Section = .{},
-} = .{},
-
-pub const big_int_bits = 32;
-
-/// Data can be lowered into in two basic representations: indirect, which is when
-/// a type is stored in memory, and direct, which is how a type is stored when its
-/// a direct SPIR-V value.
-pub const Repr = enum {
- /// A SPIR-V value as it would be used in operations.
- direct,
- /// A SPIR-V value as it is stored in memory.
- indirect,
-};
-
-/// Declarations, both functions and globals, can have dependencies. These are used for 2 things:
-/// - Globals must be declared before they are used, also between globals. The compiler processes
-/// globals unordered, so we must use the dependencies here to figure out how to order the globals
-/// in the final module. The Globals structure is also used for that.
-/// - Entry points must declare the complete list of OpVariable instructions that they access.
-/// For these we use the same dependency structure.
-/// In this mechanism, globals will only depend on other globals, while functions may depend on
-/// globals or other functions.
-pub const Decl = struct {
- /// Index to refer to a Decl by.
- pub const Index = enum(u32) { _ };
-
- /// Useful to tell what kind of decl this is, and hold the result-id or field index
- /// to be used for this decl.
- pub const Kind = enum {
- func,
- global,
- invocation_global,
- };
-
- /// See comment on Kind
- kind: Kind,
- /// The result-id associated to this decl. The specific meaning of this depends on `kind`:
- /// - For `func`, this is the result-id of the associated OpFunction instruction.
- /// - For `global`, this is the result-id of the associated OpVariable instruction.
- /// - For `invocation_global`, this is the result-id of the associated InvocationGlobal instruction.
- result_id: Id,
- /// The offset of the first dependency of this decl in the `decl_deps` array.
- begin_dep: usize = 0,
- /// The past-end offset of the dependencies of this decl in the `decl_deps` array.
- end_dep: usize = 0,
-};
-
-/// This models a kernel entry point.
-pub const EntryPoint = struct {
- /// The declaration that should be exported.
- decl_index: Decl.Index,
- /// The name of the kernel to be exported.
- name: []const u8,
- /// Calling Convention
- exec_model: spec.ExecutionModel,
- exec_mode: ?spec.ExecutionMode = null,
-};
-
-const StructType = struct {
- fields: []const Id,
- ip_index: InternPool.Index,
-
- const HashContext = struct {
- pub fn hash(_: @This(), ty: StructType) u32 {
- var hasher = std.hash.Wyhash.init(0);
- hasher.update(std.mem.sliceAsBytes(ty.fields));
- hasher.update(std.mem.asBytes(&ty.ip_index));
- return @truncate(hasher.final());
- }
-
- pub fn eql(_: @This(), a: StructType, b: StructType, _: usize) bool {
- return a.ip_index == b.ip_index and std.mem.eql(Id, a.fields, b.fields);
- }
- };
-};
-
-const FnType = struct {
- return_ty: Id,
- params: []const Id,
-
- const HashContext = struct {
- pub fn hash(_: @This(), ty: FnType) u32 {
- var hasher = std.hash.Wyhash.init(0);
- hasher.update(std.mem.asBytes(&ty.return_ty));
- hasher.update(std.mem.sliceAsBytes(ty.params));
- return @truncate(hasher.final());
- }
-
- pub fn eql(_: @This(), a: FnType, b: FnType, _: usize) bool {
- return a.return_ty == b.return_ty and
- std.mem.eql(Id, a.params, b.params);
- }
- };
-};
-
-const Constant = struct {
- ty: Id,
- value: spec.LiteralContextDependentNumber,
-
- const HashContext = struct {
- pub fn hash(_: @This(), value: Constant) u32 {
- const Tag = @typeInfo(spec.LiteralContextDependentNumber).@"union".tag_type.?;
- var hasher = std.hash.Wyhash.init(0);
- hasher.update(std.mem.asBytes(&value.ty));
- hasher.update(std.mem.asBytes(&@as(Tag, value.value)));
- switch (value.value) {
- inline else => |v| hasher.update(std.mem.asBytes(&v)),
- }
- return @truncate(hasher.final());
- }
-
- pub fn eql(_: @This(), a: Constant, b: Constant, _: usize) bool {
- if (a.ty != b.ty) return false;
- const Tag = @typeInfo(spec.LiteralContextDependentNumber).@"union".tag_type.?;
- if (@as(Tag, a.value) != @as(Tag, b.value)) return false;
- return switch (a.value) {
- inline else => |v, tag| v == @field(b.value, @tagName(tag)),
- };
- }
- };
-};
-
-pub fn deinit(module: *Module) void {
- module.nav_link.deinit(module.gpa);
- module.uav_link.deinit(module.gpa);
- module.intern_map.deinit(module.gpa);
- module.ptr_types.deinit(module.gpa);
-
- module.sections.capabilities.deinit(module.gpa);
- module.sections.extensions.deinit(module.gpa);
- module.sections.extended_instruction_set.deinit(module.gpa);
- module.sections.memory_model.deinit(module.gpa);
- module.sections.execution_modes.deinit(module.gpa);
- module.sections.debug_strings.deinit(module.gpa);
- module.sections.debug_names.deinit(module.gpa);
- module.sections.annotations.deinit(module.gpa);
- module.sections.globals.deinit(module.gpa);
- module.sections.functions.deinit(module.gpa);
-
- module.cache.opaque_types.deinit(module.gpa);
- module.cache.int_types.deinit(module.gpa);
- module.cache.float_types.deinit(module.gpa);
- module.cache.vector_types.deinit(module.gpa);
- module.cache.array_types.deinit(module.gpa);
- module.cache.struct_types.deinit(module.gpa);
- module.cache.fn_types.deinit(module.gpa);
- module.cache.capabilities.deinit(module.gpa);
- module.cache.extensions.deinit(module.gpa);
- module.cache.extended_instruction_set.deinit(module.gpa);
- module.cache.decorations.deinit(module.gpa);
- module.cache.builtins.deinit(module.gpa);
- module.cache.strings.deinit(module.gpa);
-
- module.cache.constants.deinit(module.gpa);
-
- module.decls.deinit(module.gpa);
- module.decl_deps.deinit(module.gpa);
- module.entry_points.deinit(module.gpa);
-
- module.* = undefined;
-}
-
-/// Fetch or allocate a result id for nav index. This function also marks the nav as alive.
-/// Note: Function does not actually generate the nav, it just allocates an index.
-pub fn resolveNav(module: *Module, ip: *InternPool, nav_index: InternPool.Nav.Index) !Decl.Index {
- const entry = try module.nav_link.getOrPut(module.gpa, nav_index);
- if (!entry.found_existing) {
- const nav = ip.getNav(nav_index);
- // TODO: Extern fn?
- const kind: Decl.Kind = if (ip.isFunctionType(nav.resolved.?.type))
- .func
- else switch (nav.resolved.?.@"addrspace") {
- .generic => .invocation_global,
- else => .global,
- };
- entry.value_ptr.* = try module.allocDecl(kind);
- }
-
- return entry.value_ptr.*;
-}
-
-pub fn allocIds(module: *Module, n: u32) spec.IdRange {
- defer module.next_result_id += n;
- return .{ .base = module.next_result_id, .len = n };
-}
-
-pub fn allocId(module: *Module) Id {
- return module.allocIds(1).at(0);
-}
-
-pub fn idBound(module: Module) Word {
- return module.next_result_id;
-}
-
-pub fn addEntryPointDeps(
- module: *Module,
- decl_index: Decl.Index,
- seen: *std.bit_set.Dynamic,
- interface: *std.array_list.Managed(Id),
-) !void {
- const decl = module.declPtr(decl_index);
- const deps = module.decl_deps.items[decl.begin_dep..decl.end_dep];
-
- if (seen.isSet(@intFromEnum(decl_index))) {
- return;
- }
-
- seen.set(@intFromEnum(decl_index));
-
- if (decl.kind == .global) {
- try interface.append(decl.result_id);
- }
-
- for (deps) |dep| {
- try module.addEntryPointDeps(dep, seen, interface);
- }
-}
-
-fn entryPoints(module: *Module) !Section {
- const target = module.zcu.getTarget();
-
- var entry_points = Section{};
- errdefer entry_points.deinit(module.gpa);
-
- var interface = std.array_list.Managed(Id).init(module.gpa);
- defer interface.deinit();
-
- var seen: std.bit_set.Dynamic = try .initEmpty(module.gpa, module.decls.items.len);
- defer seen.deinit(module.gpa);
-
- for (module.entry_points.keys(), module.entry_points.values()) |entry_point_id, entry_point| {
- interface.items.len = 0;
- seen.setRangeValue(.{ .start = 0, .end = module.decls.items.len }, false);
-
- try module.addEntryPointDeps(entry_point.decl_index, &seen, &interface);
- try entry_points.emit(module.gpa, .OpEntryPoint, .{
- .execution_model = entry_point.exec_model,
- .entry_point = entry_point_id,
- .name = entry_point.name,
- .interface = interface.items,
- });
-
- if (entry_point.exec_mode == null and entry_point.exec_model == .fragment) {
- switch (target.os.tag) {
- .vulkan, .opengl => |tag| {
- try module.sections.execution_modes.emit(module.gpa, .OpExecutionMode, .{
- .entry_point = entry_point_id,
- .mode = if (tag == .vulkan) .origin_upper_left else .origin_lower_left,
- });
- },
- .opencl => {},
- else => unreachable,
- }
- }
- }
-
- return entry_points;
-}
-
-pub fn finalize(module: *Module, gpa: Allocator) ![]Word {
- const target = module.zcu.getTarget();
-
- // Emit capabilities and extensions
- switch (target.os.tag) {
- .opengl => {
- try module.addCapability(.shader);
- try module.addCapability(.matrix);
- },
- .vulkan => {
- try module.addCapability(.shader);
- try module.addCapability(.matrix);
- if (target.cpu.arch == .spirv64) {
- try module.addExtension("SPV_KHR_physical_storage_buffer");
- try module.addCapability(.physical_storage_buffer_addresses);
- }
- },
- .opencl, .amdhsa => {
- try module.addCapability(.kernel);
- try module.addCapability(.addresses);
- },
- else => unreachable,
- }
- if (target.cpu.arch == .spirv64) try module.addCapability(.int64);
- if (target.cpu.has(.spirv, .int64)) try module.addCapability(.int64);
- if (target.cpu.has(.spirv, .float16)) {
- if (target.os.tag == .opencl) try module.addExtension("cl_khr_fp16");
- try module.addCapability(.float16);
- }
- if (target.cpu.has(.spirv, .float64)) try module.addCapability(.float64);
- if (target.cpu.has(.spirv, .generic_pointer)) try module.addCapability(.generic_pointer);
- if (target.cpu.has(.spirv, .vector16)) try module.addCapability(.vector16);
- if (target.cpu.has(.spirv, .storage_push_constant16)) {
- try module.addExtension("SPV_KHR_16bit_storage");
- try module.addCapability(.storage_push_constant16);
- }
- if (target.cpu.has(.spirv, .arbitrary_precision_integers)) {
- try module.addExtension("SPV_INTEL_arbitrary_precision_integers");
- try module.addCapability(.arbitrary_precision_integers_intel);
- }
- if (target.cpu.has(.spirv, .variable_pointers)) {
- try module.addExtension("SPV_KHR_variable_pointers");
- try module.addCapability(.variable_pointers_storage_buffer);
- try module.addCapability(.variable_pointers);
- }
- // These are well supported
- try module.addCapability(.int8);
- try module.addCapability(.int16);
-
- // Emit memory model
- const addressing_model: spec.AddressingModel = switch (target.os.tag) {
- .opengl => .logical,
- .vulkan => if (target.cpu.arch == .spirv32) .logical else .physical_storage_buffer64,
- .opencl => if (target.cpu.arch == .spirv32) .physical32 else .physical64,
- .amdhsa => .physical64,
- else => unreachable,
- };
- try module.sections.memory_model.emit(module.gpa, .OpMemoryModel, .{
- .addressing_model = addressing_model,
- .memory_model = switch (target.os.tag) {
- .opencl => .open_cl,
- .vulkan, .opengl => .glsl450,
- else => unreachable,
- },
- });
-
- var entry_points = try module.entryPoints();
- defer entry_points.deinit(module.gpa);
-
- const version: spec.Version = .{
- .major = 1,
- .minor = blk: {
- // Prefer higher versions
- if (target.cpu.has(.spirv, .v1_6)) break :blk 6;
- if (target.cpu.has(.spirv, .v1_5)) break :blk 5;
- if (target.cpu.has(.spirv, .v1_4)) break :blk 4;
- if (target.cpu.has(.spirv, .v1_3)) break :blk 3;
- if (target.cpu.has(.spirv, .v1_2)) break :blk 2;
- if (target.cpu.has(.spirv, .v1_1)) break :blk 1;
- break :blk 0;
- },
- };
-
- const zig_version = @import("builtin").zig_version;
- const zig_spirv_compiler_version = comptime (zig_version.major << 12) | (zig_version.minor << 7) | zig_version.patch;
-
- // A SPIR-V Generator Magic Number is a 32 bit word: The high order 16
- // bits are a tool ID, which should be unique across all SPIR-V
- // generators. The low order 16 bits are reserved for use as a tool
- // version number, or any other purpose the tool supplier chooses.
- // Only the tool IDs are reserved with Khronos.
- // See https://github.com/KhronosGroup/SPIRV-Headers/blob/f2e4bd213104fe323a01e935df56557328d37ac8/include/spirv/spir-v.xml#L17C5-L21C54
- const generator_id: u32 = (spec.zig_generator_id << 16) | zig_spirv_compiler_version;
-
- const header = [_]Word{
- spec.magic_number,
- version.toWord(),
- generator_id,
- module.idBound(),
- 0, // Schema (currently reserved for future use)
- };
-
- var source = Section{};
- defer source.deinit(module.gpa);
- try module.sections.debug_strings.emit(module.gpa, .OpSource, .{
- .source_language = .zig,
- .version = zig_spirv_compiler_version,
- // We cannot emit these because the Khronos translator does not parse this instruction
- // correctly.
- // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/2188
- .file = null,
- .source = null,
- });
-
- // Note: needs to be kept in order according to section 2.3!
- const buffers = &[_][]const Word{
- &header,
- module.sections.capabilities.toWords(),
- module.sections.extensions.toWords(),
- module.sections.extended_instruction_set.toWords(),
- module.sections.memory_model.toWords(),
- entry_points.toWords(),
- module.sections.execution_modes.toWords(),
- source.toWords(),
- module.sections.debug_strings.toWords(),
- module.sections.debug_names.toWords(),
- module.sections.annotations.toWords(),
- module.sections.globals.toWords(),
- module.sections.functions.toWords(),
- };
-
- var total_result_size: usize = 0;
- for (buffers) |buffer| {
- total_result_size += buffer.len;
- }
- const result = try gpa.alloc(Word, total_result_size);
- errdefer comptime unreachable;
-
- var offset: usize = 0;
- for (buffers) |buffer| {
- @memcpy(result[offset..][0..buffer.len], buffer);
- offset += buffer.len;
- }
-
- return result;
-}
-
-pub fn addCapability(module: *Module, cap: spec.Capability) !void {
- const entry = try module.cache.capabilities.getOrPut(module.gpa, cap);
- if (entry.found_existing) return;
- try module.sections.capabilities.emit(module.gpa, .OpCapability, .{ .capability = cap });
-}
-
-pub fn addExtension(module: *Module, ext: []const u8) !void {
- const entry = try module.cache.extensions.getOrPut(module.gpa, ext);
- if (entry.found_existing) return;
- try module.sections.extensions.emit(module.gpa, .OpExtension, .{ .name = ext });
-}
-
-/// Imports or returns the existing id of an extended instruction set
-pub fn importInstructionSet(module: *Module, set: spec.InstructionSet) !Id {
- assert(set != .core);
-
- const gop = try module.cache.extended_instruction_set.getOrPut(module.gpa, set);
- if (gop.found_existing) return gop.value_ptr.*;
-
- const result_id = module.allocId();
- try module.sections.extended_instruction_set.emit(module.gpa, .OpExtInstImport, .{
- .id_result = result_id,
- .name = @tagName(set),
- });
- gop.value_ptr.* = result_id;
-
- return result_id;
-}
-
-pub fn boolType(module: *Module) !Id {
- if (module.cache.bool_type) |id| return id;
-
- const result_id = module.allocId();
- try module.sections.globals.emit(module.gpa, .OpTypeBool, .{
- .id_result = result_id,
- });
- module.cache.bool_type = result_id;
- return result_id;
-}
-
-pub fn voidType(module: *Module) !Id {
- if (module.cache.void_type) |id| return id;
-
- const result_id = module.allocId();
- try module.sections.globals.emit(module.gpa, .OpTypeVoid, .{
- .id_result = result_id,
- });
- module.cache.void_type = result_id;
- try module.debugName(result_id, "void");
- return result_id;
-}
-
-pub fn opaqueType(module: *Module, name: []const u8) !Id {
- if (module.cache.opaque_types.get(name)) |id| return id;
- const result_id = module.allocId();
- const name_dup = try module.arena.dupe(u8, name);
- try module.sections.globals.emit(module.gpa, .OpTypeOpaque, .{
- .id_result = result_id,
- .literal_string = name_dup,
- });
- try module.debugName(result_id, name_dup);
- try module.cache.opaque_types.put(module.gpa, name_dup, result_id);
- return result_id;
-}
-
-pub fn backingIntBits(module: *Module, bits: u16) struct { u16, bool } {
- assert(bits != 0);
- const target = module.zcu.getTarget();
-
- if (target.cpu.has(.spirv, .arbitrary_precision_integers) and bits <= 32) {
- return .{ bits, false };
- }
-
- // We require Int8 and Int16 capabilities and benefit Int64 when available.
- // 32-bit integers are always supported (see spec, 2.16.1, Data rules).
- const ints = [_]struct { bits: u16, enabled: bool }{
- .{ .bits = 8, .enabled = true },
- .{ .bits = 16, .enabled = true },
- .{ .bits = 32, .enabled = true },
- .{
- .bits = 64,
- .enabled = target.cpu.has(.spirv, .int64) or target.cpu.arch == .spirv64,
- },
- };
-
- for (ints) |int| {
- if (bits <= int.bits and int.enabled) return .{ int.bits, false };
- }
-
- // Big int
- return .{ std.mem.alignForward(u16, bits, big_int_bits), true };
-}
-
-pub fn intType(module: *Module, signedness: std.lang.Signedness, bits: u16) !Id {
- assert(bits > 0);
-
- const target = module.zcu.getTarget();
- const actual_signedness = switch (target.os.tag) {
- // Kernel only supports unsigned ints.
- .opencl, .amdhsa => .unsigned,
- else => signedness,
- };
- const backing_bits, const big_int = module.backingIntBits(bits);
- if (big_int) {
- // TODO: support composite integers larger than 64 bit
- assert(backing_bits <= 64);
- const u32_ty = try module.intType(.unsigned, 32);
- const len_id = try module.constant(u32_ty, .{ .uint32 = backing_bits / big_int_bits });
- return module.arrayType(len_id, u32_ty);
- }
-
- const entry = try module.cache.int_types.getOrPut(module.gpa, .{ .signedness = actual_signedness, .bits = backing_bits });
- if (!entry.found_existing) {
- const result_id = module.allocId();
- entry.value_ptr.* = result_id;
- try module.sections.globals.emit(module.gpa, .OpTypeInt, .{
- .id_result = result_id,
- .width = backing_bits,
- .signedness = switch (actual_signedness) {
- .signed => 1,
- .unsigned => 0,
- },
- });
-
- switch (actual_signedness) {
- .signed => try module.debugNameFmt(result_id, "i{}", .{backing_bits}),
- .unsigned => try module.debugNameFmt(result_id, "u{}", .{backing_bits}),
- }
- }
- return entry.value_ptr.*;
-}
-
-pub fn floatType(module: *Module, bits: u16) !Id {
- assert(bits > 0);
- const entry = try module.cache.float_types.getOrPut(module.gpa, .{ .bits = bits });
- if (!entry.found_existing) {
- const result_id = module.allocId();
- entry.value_ptr.* = result_id;
- try module.sections.globals.emit(module.gpa, .OpTypeFloat, .{
- .id_result = result_id,
- .width = bits,
- });
- try module.debugNameFmt(result_id, "f{}", .{bits});
- }
- return entry.value_ptr.*;
-}
-
-pub fn vectorType(module: *Module, len: u32, child_ty_id: Id) !Id {
- const entry = try module.cache.vector_types.getOrPut(module.gpa, .{ child_ty_id, len });
- if (!entry.found_existing) {
- const result_id = module.allocId();
- entry.value_ptr.* = result_id;
- try module.sections.globals.emit(module.gpa, .OpTypeVector, .{
- .id_result = result_id,
- .component_type = child_ty_id,
- .component_count = len,
- });
- }
- return entry.value_ptr.*;
-}
-
-pub fn arrayType(module: *Module, len_id: Id, child_ty_id: Id) !Id {
- const entry = try module.cache.array_types.getOrPut(module.gpa, .{ child_ty_id, len_id });
- if (!entry.found_existing) {
- const result_id = module.allocId();
- entry.value_ptr.* = result_id;
- try module.sections.globals.emit(module.gpa, .OpTypeArray, .{
- .id_result = result_id,
- .element_type = child_ty_id,
- .length = len_id,
- });
- }
- return entry.value_ptr.*;
-}
-
-pub fn ptrType(module: *Module, child_ty_id: Id, storage_class: spec.StorageClass) !Id {
- const key = .{ child_ty_id, storage_class };
- const gop = try module.ptr_types.getOrPut(module.gpa, key);
- if (!gop.found_existing) {
- gop.value_ptr.* = module.allocId();
- try module.sections.globals.emit(module.gpa, .OpTypePointer, .{
- .id_result = gop.value_ptr.*,
- .storage_class = storage_class,
- .type = child_ty_id,
- });
- return gop.value_ptr.*;
- }
- return gop.value_ptr.*;
-}
-
-pub fn structType(
- module: *Module,
- types: []const Id,
- maybe_names: ?[]const []const u8,
- maybe_offsets: ?[]const u32,
- ip_index: InternPool.Index,
-) !Id {
- const target = module.zcu.getTarget();
- const actual_ip_index = if (module.zcu.comp.config.root_strip) .none else ip_index;
-
- if (module.cache.struct_types.get(.{ .fields = types, .ip_index = actual_ip_index })) |id| return id;
- const result_id = module.allocId();
- const types_dup = try module.arena.dupe(Id, types);
- try module.sections.globals.emit(module.gpa, .OpTypeStruct, .{
- .id_result = result_id,
- .id_ref = types_dup,
- });
-
- if (maybe_names) |names| {
- assert(names.len == types.len);
- for (names, 0..) |name, i| {
- try module.memberDebugName(result_id, @intCast(i), name);
- }
- }
-
- switch (target.os.tag) {
- .vulkan, .opengl => {
- if (maybe_offsets) |offsets| {
- assert(offsets.len == types.len);
- for (offsets, 0..) |offset, i| {
- try module.decorateMember(
- result_id,
- @intCast(i),
- .{ .offset = .{ .byte_offset = offset } },
- );
- }
- }
- },
- else => {},
- }
-
- try module.cache.struct_types.put(
- module.gpa,
- .{ .fields = types_dup, .ip_index = actual_ip_index },
- result_id,
- );
- return result_id;
-}
-
-pub fn functionType(module: *Module, return_ty_id: Id, param_type_ids: []const Id) !Id {
- if (module.cache.fn_types.get(.{
- .return_ty = return_ty_id,
- .params = param_type_ids,
- })) |id| return id;
- const result_id = module.allocId();
- const params_dup = try module.arena.dupe(Id, param_type_ids);
- try module.sections.globals.emit(module.gpa, .OpTypeFunction, .{
- .id_result = result_id,
- .return_type = return_ty_id,
- .id_ref_2 = params_dup,
- });
- try module.cache.fn_types.put(module.gpa, .{
- .return_ty = return_ty_id,
- .params = params_dup,
- }, result_id);
- return result_id;
-}
-
-pub fn constant(module: *Module, ty_id: Id, value: spec.LiteralContextDependentNumber) !Id {
- const gop = try module.cache.constants.getOrPut(module.gpa, .{ .ty = ty_id, .value = value });
- if (!gop.found_existing) {
- gop.value_ptr.* = module.allocId();
- try module.sections.globals.emit(module.gpa, .OpConstant, .{
- .id_result_type = ty_id,
- .id_result = gop.value_ptr.*,
- .value = value,
- });
- }
- return gop.value_ptr.*;
-}
-
-pub fn constBool(module: *Module, value: bool) !Id {
- if (module.cache.bool_const[@intFromBool(value)]) |b| return b;
-
- const result_ty_id = try module.boolType();
- const result_id = module.allocId();
- module.cache.bool_const[@intFromBool(value)] = result_id;
-
- switch (value) {
- inline else => |value_ct| try module.sections.globals.emit(
- module.gpa,
- if (value_ct) .OpConstantTrue else .OpConstantFalse,
- .{
- .id_result_type = result_ty_id,
- .id_result = result_id,
- },
- ),
- }
-
- return result_id;
-}
-
-pub fn builtin(
- module: *Module,
- result_ty_id: Id,
- spirv_builtin: spec.BuiltIn,
- storage_class: spec.StorageClass,
-) !Decl.Index {
- const gop = try module.cache.builtins.getOrPut(module.gpa, .{ spirv_builtin, storage_class });
- if (!gop.found_existing) {
- const decl_index = try module.allocDecl(.global);
- const decl = module.declPtr(decl_index);
-
- gop.value_ptr.* = decl_index;
- try module.sections.globals.emit(module.gpa, .OpVariable, .{
- .id_result_type = result_ty_id,
- .id_result = decl.result_id,
- .storage_class = storage_class,
- });
- try module.decorate(decl.result_id, .{ .built_in = .{ .built_in = spirv_builtin } });
- }
- return gop.value_ptr.*;
-}
-
-pub fn constUndef(module: *Module, ty_id: Id) !Id {
- const result_id = module.allocId();
- try module.sections.globals.emit(module.gpa, .OpUndef, .{
- .id_result_type = ty_id,
- .id_result = result_id,
- });
- return result_id;
-}
-
-pub fn constNull(module: *Module, ty_id: Id) !Id {
- const result_id = module.allocId();
- try module.sections.globals.emit(module.gpa, .OpConstantNull, .{
- .id_result_type = ty_id,
- .id_result = result_id,
- });
- return result_id;
-}
-
-/// Decorate a result-id.
-pub fn decorate(
- module: *Module,
- target: Id,
- decoration: spec.Decoration.Extended,
-) !void {
- const gop = try module.cache.decorations.getOrPut(module.gpa, .{ target, decoration });
- if (!gop.found_existing) {
- try module.sections.annotations.emit(module.gpa, .OpDecorate, .{
- .target = target,
- .decoration = decoration,
- });
- }
-}
-
-/// Decorate a result-id which is a member of some struct.
-/// We really don't have to and shouldn't need to cache this.
-pub fn decorateMember(
- module: *Module,
- structure_type: Id,
- member: u32,
- decoration: spec.Decoration.Extended,
-) !void {
- try module.sections.annotations.emit(module.gpa, .OpMemberDecorate, .{
- .structure_type = structure_type,
- .member = member,
- .decoration = decoration,
- });
-}
-
-pub fn allocDecl(module: *Module, kind: Decl.Kind) !Decl.Index {
- try module.decls.append(module.gpa, .{
- .kind = kind,
- .result_id = module.allocId(),
- });
-
- return @as(Decl.Index, @enumFromInt(@as(u32, @intCast(module.decls.items.len - 1))));
-}
-
-pub fn declPtr(module: *Module, index: Decl.Index) *Decl {
- return &module.decls.items[@intFromEnum(index)];
-}
-
-/// Declare a SPIR-V function as an entry point. This causes an extra wrapper
-/// function to be generated, which is then exported as the real entry point. The purpose of this
-/// wrapper is to allocate and initialize the structure holding the instance globals.
-pub fn declareEntryPoint(
- module: *Module,
- decl_index: Decl.Index,
- name: []const u8,
- exec_model: spec.ExecutionModel,
- exec_mode: ?spec.ExecutionMode,
-) !void {
- const gop = try module.entry_points.getOrPut(module.gpa, module.declPtr(decl_index).result_id);
- gop.value_ptr.decl_index = decl_index;
- gop.value_ptr.name = name;
- gop.value_ptr.exec_model = exec_model;
- // Might've been set by assembler
- if (!gop.found_existing) gop.value_ptr.exec_mode = exec_mode;
-}
-
-pub fn debugName(module: *Module, target: Id, name: []const u8) !void {
- if (module.zcu.comp.config.root_strip) return;
- try module.sections.debug_names.emit(module.gpa, .OpName, .{
- .target = target,
- .name = name,
- });
-}
-
-pub fn debugNameFmt(module: *Module, target: Id, comptime fmt: []const u8, args: anytype) !void {
- if (module.zcu.comp.config.root_strip) return;
- const name = try std.fmt.allocPrint(module.gpa, fmt, args);
- defer module.gpa.free(name);
- try module.debugName(target, name);
-}
-
-pub fn memberDebugName(module: *Module, target: Id, member: u32, name: []const u8) !void {
- if (module.zcu.comp.config.root_strip) return;
- try module.sections.debug_names.emit(module.gpa, .OpMemberName, .{
- .type = target,
- .member = member,
- .name = name,
- });
-}
-
-pub fn debugString(module: *Module, string: []const u8) !Id {
- const entry = try module.cache.strings.getOrPut(module.gpa, string);
- if (!entry.found_existing) {
- entry.value_ptr.* = module.allocId();
- try module.sections.debug_strings.emit(module.gpa, .OpString, .{
- .id_result = entry.value_ptr.*,
- .string = string,
- });
- }
- return entry.value_ptr.*;
-}
-
-pub fn storageClass(module: *Module, as: std.lang.AddressSpace) spec.StorageClass {
- const target = module.zcu.getTarget();
- return switch (as) {
- .generic => .function,
- .global => switch (target.os.tag) {
- .opencl, .amdhsa => .cross_workgroup,
- else => .storage_buffer,
- },
- .push_constant => .push_constant,
- .output => .output,
- .uniform => .uniform,
- .storage_buffer => .storage_buffer,
- .physical_storage_buffer => .physical_storage_buffer,
- .constant => .uniform_constant,
- .shared => .workgroup,
- .local => .function,
- .input => .input,
- .gs,
- .fs,
- .ss,
- .far,
- .param,
- .flash,
- .flash1,
- .flash2,
- .flash3,
- .flash4,
- .flash5,
- .cog,
- .lut,
- .hub,
- => unreachable,
- };
-}
diff --git a/src/codegen/spirv/spec.zig b/src/codegen/spirv/spec.zig
index df5292e3e2da826e0e816ef5421ccabc4432d2bf..415a2ae706c2ab2fecdb92b132930a92271961d3 100644
--- a/src/codegen/spirv/spec.zig
+++ b/src/codegen/spirv/spec.zig
@@ -313,16 +313,16 @@ pub const OperandKind = enum {
.{ .name = "IterationMultiple", .value = 0x0040, .parameters = &.{.literal_integer} },
.{ .name = "PeelCount", .value = 0x0080, .parameters = &.{.literal_integer} },
.{ .name = "PartialCount", .value = 0x0100, .parameters = &.{.literal_integer} },
- .{ .name = "InitiationIntervalINTEL", .value = 0x10000, .parameters = &.{.literal_integer} },
- .{ .name = "MaxConcurrencyINTEL", .value = 0x20000, .parameters = &.{.literal_integer} },
- .{ .name = "DependencyArrayINTEL", .value = 0x40000, .parameters = &.{.literal_integer} },
- .{ .name = "PipelineEnableINTEL", .value = 0x80000, .parameters = &.{.literal_integer} },
- .{ .name = "LoopCoalesceINTEL", .value = 0x100000, .parameters = &.{.literal_integer} },
- .{ .name = "MaxInterleavingINTEL", .value = 0x200000, .parameters = &.{.literal_integer} },
- .{ .name = "SpeculatedIterationsINTEL", .value = 0x400000, .parameters = &.{.literal_integer} },
- .{ .name = "NoFusionINTEL", .value = 0x800000, .parameters = &.{} },
- .{ .name = "LoopCountINTEL", .value = 0x1000000, .parameters = &.{.literal_integer} },
- .{ .name = "MaxReinvocationDelayINTEL", .value = 0x2000000, .parameters = &.{.literal_integer} },
+ .{ .name = "InitiationIntervalALTERA", .value = 0x10000, .parameters = &.{.literal_integer} },
+ .{ .name = "MaxConcurrencyALTERA", .value = 0x20000, .parameters = &.{.literal_integer} },
+ .{ .name = "DependencyArrayALTERA", .value = 0x40000, .parameters = &.{.literal_integer} },
+ .{ .name = "PipelineEnableALTERA", .value = 0x80000, .parameters = &.{.literal_integer} },
+ .{ .name = "LoopCoalesceALTERA", .value = 0x100000, .parameters = &.{.literal_integer} },
+ .{ .name = "MaxInterleavingALTERA", .value = 0x200000, .parameters = &.{.literal_integer} },
+ .{ .name = "SpeculatedIterationsALTERA", .value = 0x400000, .parameters = &.{.literal_integer} },
+ .{ .name = "NoFusionALTERA", .value = 0x800000, .parameters = &.{} },
+ .{ .name = "LoopCountALTERA", .value = 0x1000000, .parameters = &.{.literal_integer} },
+ .{ .name = "MaxReinvocationDelayALTERA", .value = 0x2000000, .parameters = &.{.literal_integer} },
},
.function_control => &.{
.{ .name = "Inline", .value = 0x0001, .parameters = &.{} },
@@ -500,6 +500,7 @@ pub const OperandKind = enum {
.{ .name = "QuadDerivativesKHR", .value = 5088, .parameters = &.{} },
.{ .name = "RequireFullQuadsKHR", .value = 5089, .parameters = &.{} },
.{ .name = "SharesInputWithAMDX", .value = 5102, .parameters = &.{ .id_ref, .id_ref } },
+ .{ .name = "ArithmeticPoisonKHR", .value = 5157, .parameters = &.{} },
.{ .name = "OutputLinesEXT", .value = 5269, .parameters = &.{} },
.{ .name = "OutputPrimitivesEXT", .value = 5270, .parameters = &.{.literal_integer} },
.{ .name = "DerivativeGroupQuadsKHR", .value = 5289, .parameters = &.{} },
@@ -511,6 +512,7 @@ pub const OperandKind = enum {
.{ .name = "SampleInterlockUnorderedEXT", .value = 5369, .parameters = &.{} },
.{ .name = "ShadingRateInterlockOrderedEXT", .value = 5370, .parameters = &.{} },
.{ .name = "ShadingRateInterlockUnorderedEXT", .value = 5371, .parameters = &.{} },
+ .{ .name = "Shader64BitIndexingEXT", .value = 5427, .parameters = &.{} },
.{ .name = "SharedLocalMemorySizeINTEL", .value = 5618, .parameters = &.{.literal_integer} },
.{ .name = "RoundingModeRTPINTEL", .value = 5620, .parameters = &.{.literal_integer} },
.{ .name = "RoundingModeRTNINTEL", .value = 5621, .parameters = &.{.literal_integer} },
@@ -556,9 +558,10 @@ pub const OperandKind = enum {
.{ .name = "PhysicalStorageBuffer", .value = 5349, .parameters = &.{} },
.{ .name = "HitObjectAttributeNV", .value = 5385, .parameters = &.{} },
.{ .name = "TaskPayloadWorkgroupEXT", .value = 5402, .parameters = &.{} },
+ .{ .name = "HitObjectAttributeEXT", .value = 5411, .parameters = &.{} },
.{ .name = "CodeSectionINTEL", .value = 5605, .parameters = &.{} },
- .{ .name = "DeviceOnlyINTEL", .value = 5936, .parameters = &.{} },
- .{ .name = "HostOnlyINTEL", .value = 5937, .parameters = &.{} },
+ .{ .name = "DeviceOnlyALTERA", .value = 5936, .parameters = &.{} },
+ .{ .name = "HostOnlyALTERA", .value = 5937, .parameters = &.{} },
},
.dim => &.{
.{ .name = "1D", .value = 0, .parameters = &.{} },
@@ -730,7 +733,7 @@ pub const OperandKind = enum {
.{ .name = "NoCapture", .value = 5, .parameters = &.{} },
.{ .name = "NoWrite", .value = 6, .parameters = &.{} },
.{ .name = "NoReadWrite", .value = 7, .parameters = &.{} },
- .{ .name = "RuntimeAlignedINTEL", .value = 5940, .parameters = &.{} },
+ .{ .name = "RuntimeAlignedALTERA", .value = 5940, .parameters = &.{} },
},
.decoration => &.{
.{ .name = "RelaxedPrecision", .value = 0, .parameters = &.{} },
@@ -795,6 +798,9 @@ pub const OperandKind = enum {
.{ .name = "PayloadNodeSparseArrayAMDX", .value = 5099, .parameters = &.{} },
.{ .name = "PayloadNodeArraySizeAMDX", .value = 5100, .parameters = &.{.id_ref} },
.{ .name = "PayloadDispatchIndirectAMDX", .value = 5105, .parameters = &.{} },
+ .{ .name = "ArrayStrideIdEXT", .value = 5124, .parameters = &.{.id_ref} },
+ .{ .name = "OffsetIdEXT", .value = 5125, .parameters = &.{.id_ref} },
+ .{ .name = "UTFEncodedKHR", .value = 5145, .parameters = &.{} },
.{ .name = "OverrideCoverageNV", .value = 5248, .parameters = &.{} },
.{ .name = "PassthroughNV", .value = 5250, .parameters = &.{} },
.{ .name = "ViewportRelativeNV", .value = 5252, .parameters = &.{} },
@@ -806,7 +812,10 @@ pub const OperandKind = enum {
.{ .name = "NonUniform", .value = 5300, .parameters = &.{} },
.{ .name = "RestrictPointer", .value = 5355, .parameters = &.{} },
.{ .name = "AliasedPointer", .value = 5356, .parameters = &.{} },
+ .{ .name = "MemberOffsetNV", .value = 5358, .parameters = &.{.literal_integer} },
.{ .name = "HitObjectShaderRecordBufferNV", .value = 5386, .parameters = &.{} },
+ .{ .name = "HitObjectShaderRecordBufferEXT", .value = 5389, .parameters = &.{} },
+ .{ .name = "BankNV", .value = 5397, .parameters = &.{.literal_integer} },
.{ .name = "BindlessSamplerNV", .value = 5398, .parameters = &.{} },
.{ .name = "BindlessImageNV", .value = 5399, .parameters = &.{} },
.{ .name = "BoundSamplerNV", .value = 5400, .parameters = &.{} },
@@ -825,55 +834,56 @@ pub const OperandKind = enum {
.{ .name = "UserTypeGOOGLE", .value = 5636, .parameters = &.{.literal_string} },
.{ .name = "FunctionRoundingModeINTEL", .value = 5822, .parameters = &.{ .literal_integer, .fp_rounding_mode } },
.{ .name = "FunctionDenormModeINTEL", .value = 5823, .parameters = &.{ .literal_integer, .fp_denorm_mode } },
- .{ .name = "RegisterINTEL", .value = 5825, .parameters = &.{} },
- .{ .name = "MemoryINTEL", .value = 5826, .parameters = &.{.literal_string} },
- .{ .name = "NumbanksINTEL", .value = 5827, .parameters = &.{.literal_integer} },
- .{ .name = "BankwidthINTEL", .value = 5828, .parameters = &.{.literal_integer} },
- .{ .name = "MaxPrivateCopiesINTEL", .value = 5829, .parameters = &.{.literal_integer} },
- .{ .name = "SinglepumpINTEL", .value = 5830, .parameters = &.{} },
- .{ .name = "DoublepumpINTEL", .value = 5831, .parameters = &.{} },
- .{ .name = "MaxReplicatesINTEL", .value = 5832, .parameters = &.{.literal_integer} },
- .{ .name = "SimpleDualPortINTEL", .value = 5833, .parameters = &.{} },
- .{ .name = "MergeINTEL", .value = 5834, .parameters = &.{ .literal_string, .literal_string } },
- .{ .name = "BankBitsINTEL", .value = 5835, .parameters = &.{.literal_integer} },
- .{ .name = "ForcePow2DepthINTEL", .value = 5836, .parameters = &.{.literal_integer} },
- .{ .name = "StridesizeINTEL", .value = 5883, .parameters = &.{.literal_integer} },
- .{ .name = "WordsizeINTEL", .value = 5884, .parameters = &.{.literal_integer} },
- .{ .name = "TrueDualPortINTEL", .value = 5885, .parameters = &.{} },
- .{ .name = "BurstCoalesceINTEL", .value = 5899, .parameters = &.{} },
- .{ .name = "CacheSizeINTEL", .value = 5900, .parameters = &.{.literal_integer} },
- .{ .name = "DontStaticallyCoalesceINTEL", .value = 5901, .parameters = &.{} },
- .{ .name = "PrefetchINTEL", .value = 5902, .parameters = &.{.literal_integer} },
- .{ .name = "StallEnableINTEL", .value = 5905, .parameters = &.{} },
- .{ .name = "FuseLoopsInFunctionINTEL", .value = 5907, .parameters = &.{} },
- .{ .name = "MathOpDSPModeINTEL", .value = 5909, .parameters = &.{ .literal_integer, .literal_integer } },
+ .{ .name = "RegisterALTERA", .value = 5825, .parameters = &.{} },
+ .{ .name = "MemoryALTERA", .value = 5826, .parameters = &.{.literal_string} },
+ .{ .name = "NumbanksALTERA", .value = 5827, .parameters = &.{.literal_integer} },
+ .{ .name = "BankwidthALTERA", .value = 5828, .parameters = &.{.literal_integer} },
+ .{ .name = "MaxPrivateCopiesALTERA", .value = 5829, .parameters = &.{.literal_integer} },
+ .{ .name = "SinglepumpALTERA", .value = 5830, .parameters = &.{} },
+ .{ .name = "DoublepumpALTERA", .value = 5831, .parameters = &.{} },
+ .{ .name = "MaxReplicatesALTERA", .value = 5832, .parameters = &.{.literal_integer} },
+ .{ .name = "SimpleDualPortALTERA", .value = 5833, .parameters = &.{} },
+ .{ .name = "MergeALTERA", .value = 5834, .parameters = &.{ .literal_string, .literal_string } },
+ .{ .name = "BankBitsALTERA", .value = 5835, .parameters = &.{.literal_integer} },
+ .{ .name = "ForcePow2DepthALTERA", .value = 5836, .parameters = &.{.literal_integer} },
+ .{ .name = "StridesizeALTERA", .value = 5883, .parameters = &.{.literal_integer} },
+ .{ .name = "WordsizeALTERA", .value = 5884, .parameters = &.{.literal_integer} },
+ .{ .name = "TrueDualPortALTERA", .value = 5885, .parameters = &.{} },
+ .{ .name = "BurstCoalesceALTERA", .value = 5899, .parameters = &.{} },
+ .{ .name = "CacheSizeALTERA", .value = 5900, .parameters = &.{.literal_integer} },
+ .{ .name = "DontStaticallyCoalesceALTERA", .value = 5901, .parameters = &.{} },
+ .{ .name = "PrefetchALTERA", .value = 5902, .parameters = &.{.literal_integer} },
+ .{ .name = "StallEnableALTERA", .value = 5905, .parameters = &.{} },
+ .{ .name = "FuseLoopsInFunctionALTERA", .value = 5907, .parameters = &.{} },
+ .{ .name = "MathOpDSPModeALTERA", .value = 5909, .parameters = &.{ .literal_integer, .literal_integer } },
.{ .name = "AliasScopeINTEL", .value = 5914, .parameters = &.{.id_ref} },
.{ .name = "NoAliasINTEL", .value = 5915, .parameters = &.{.id_ref} },
- .{ .name = "InitiationIntervalINTEL", .value = 5917, .parameters = &.{.literal_integer} },
- .{ .name = "MaxConcurrencyINTEL", .value = 5918, .parameters = &.{.literal_integer} },
- .{ .name = "PipelineEnableINTEL", .value = 5919, .parameters = &.{.literal_integer} },
- .{ .name = "BufferLocationINTEL", .value = 5921, .parameters = &.{.literal_integer} },
- .{ .name = "IOPipeStorageINTEL", .value = 5944, .parameters = &.{.literal_integer} },
+ .{ .name = "InitiationIntervalALTERA", .value = 5917, .parameters = &.{.literal_integer} },
+ .{ .name = "MaxConcurrencyALTERA", .value = 5918, .parameters = &.{.literal_integer} },
+ .{ .name = "PipelineEnableALTERA", .value = 5919, .parameters = &.{.literal_integer} },
+ .{ .name = "BufferLocationALTERA", .value = 5921, .parameters = &.{.literal_integer} },
+ .{ .name = "IOPipeStorageALTERA", .value = 5944, .parameters = &.{.literal_integer} },
.{ .name = "FunctionFloatingPointModeINTEL", .value = 6080, .parameters = &.{ .literal_integer, .fp_operation_mode } },
.{ .name = "SingleElementVectorINTEL", .value = 6085, .parameters = &.{} },
.{ .name = "VectorComputeCallableFunctionINTEL", .value = 6087, .parameters = &.{} },
.{ .name = "MediaBlockIOINTEL", .value = 6140, .parameters = &.{} },
- .{ .name = "StallFreeINTEL", .value = 6151, .parameters = &.{} },
+ .{ .name = "StallFreeALTERA", .value = 6151, .parameters = &.{} },
.{ .name = "FPMaxErrorDecorationINTEL", .value = 6170, .parameters = &.{.literal_float} },
- .{ .name = "LatencyControlLabelINTEL", .value = 6172, .parameters = &.{.literal_integer} },
- .{ .name = "LatencyControlConstraintINTEL", .value = 6173, .parameters = &.{ .literal_integer, .literal_integer, .literal_integer } },
- .{ .name = "ConduitKernelArgumentINTEL", .value = 6175, .parameters = &.{} },
- .{ .name = "RegisterMapKernelArgumentINTEL", .value = 6176, .parameters = &.{} },
- .{ .name = "MMHostInterfaceAddressWidthINTEL", .value = 6177, .parameters = &.{.literal_integer} },
- .{ .name = "MMHostInterfaceDataWidthINTEL", .value = 6178, .parameters = &.{.literal_integer} },
- .{ .name = "MMHostInterfaceLatencyINTEL", .value = 6179, .parameters = &.{.literal_integer} },
- .{ .name = "MMHostInterfaceReadWriteModeINTEL", .value = 6180, .parameters = &.{.access_qualifier} },
- .{ .name = "MMHostInterfaceMaxBurstINTEL", .value = 6181, .parameters = &.{.literal_integer} },
- .{ .name = "MMHostInterfaceWaitRequestINTEL", .value = 6182, .parameters = &.{.literal_integer} },
- .{ .name = "StableKernelArgumentINTEL", .value = 6183, .parameters = &.{} },
+ .{ .name = "LatencyControlLabelALTERA", .value = 6172, .parameters = &.{.literal_integer} },
+ .{ .name = "LatencyControlConstraintALTERA", .value = 6173, .parameters = &.{ .literal_integer, .literal_integer, .literal_integer } },
+ .{ .name = "ConduitKernelArgumentALTERA", .value = 6175, .parameters = &.{} },
+ .{ .name = "RegisterMapKernelArgumentALTERA", .value = 6176, .parameters = &.{} },
+ .{ .name = "MMHostInterfaceAddressWidthALTERA", .value = 6177, .parameters = &.{.literal_integer} },
+ .{ .name = "MMHostInterfaceDataWidthALTERA", .value = 6178, .parameters = &.{.literal_integer} },
+ .{ .name = "MMHostInterfaceLatencyALTERA", .value = 6179, .parameters = &.{.literal_integer} },
+ .{ .name = "MMHostInterfaceReadWriteModeALTERA", .value = 6180, .parameters = &.{.access_qualifier} },
+ .{ .name = "MMHostInterfaceMaxBurstALTERA", .value = 6181, .parameters = &.{.literal_integer} },
+ .{ .name = "MMHostInterfaceWaitRequestALTERA", .value = 6182, .parameters = &.{.literal_integer} },
+ .{ .name = "StableKernelArgumentALTERA", .value = 6183, .parameters = &.{} },
.{ .name = "HostAccessINTEL", .value = 6188, .parameters = &.{ .host_access_qualifier, .literal_string } },
- .{ .name = "InitModeINTEL", .value = 6190, .parameters = &.{.initialization_mode_qualifier} },
- .{ .name = "ImplementInRegisterMapINTEL", .value = 6191, .parameters = &.{.literal_integer} },
+ .{ .name = "InitModeALTERA", .value = 6190, .parameters = &.{.initialization_mode_qualifier} },
+ .{ .name = "ImplementInRegisterMapALTERA", .value = 6191, .parameters = &.{.literal_integer} },
+ .{ .name = "ConditionalINTEL", .value = 6247, .parameters = &.{.id_ref} },
.{ .name = "CacheControlLoadINTEL", .value = 6442, .parameters = &.{ .literal_integer, .load_cache_control } },
.{ .name = "CacheControlStoreINTEL", .value = 6443, .parameters = &.{ .literal_integer, .store_cache_control } },
},
@@ -949,6 +959,8 @@ pub const OperandKind = enum {
.{ .name = "FragStencilRefEXT", .value = 5014, .parameters = &.{} },
.{ .name = "RemainingRecursionLevelsAMDX", .value = 5021, .parameters = &.{} },
.{ .name = "ShaderIndexAMDX", .value = 5073, .parameters = &.{} },
+ .{ .name = "SamplerHeapEXT", .value = 5122, .parameters = &.{} },
+ .{ .name = "ResourceHeapEXT", .value = 5123, .parameters = &.{} },
.{ .name = "ViewportMaskNV", .value = 5253, .parameters = &.{} },
.{ .name = "SecondaryPositionNV", .value = 5257, .parameters = &.{} },
.{ .name = "SecondaryViewportMaskNV", .value = 5258, .parameters = &.{} },
@@ -1019,9 +1031,9 @@ pub const OperandKind = enum {
.{ .name = "InclusiveScan", .value = 1, .parameters = &.{} },
.{ .name = "ExclusiveScan", .value = 2, .parameters = &.{} },
.{ .name = "ClusteredReduce", .value = 3, .parameters = &.{} },
- .{ .name = "PartitionedReduceNV", .value = 6, .parameters = &.{} },
- .{ .name = "PartitionedInclusiveScanNV", .value = 7, .parameters = &.{} },
- .{ .name = "PartitionedExclusiveScanNV", .value = 8, .parameters = &.{} },
+ .{ .name = "PartitionedReduceEXT", .value = 6, .parameters = &.{} },
+ .{ .name = "PartitionedInclusiveScanEXT", .value = 7, .parameters = &.{} },
+ .{ .name = "PartitionedExclusiveScanEXT", .value = 8, .parameters = &.{} },
},
.kernel_enqueue_flags => &.{
.{ .name = "NoWait", .value = 0, .parameters = &.{} },
@@ -1144,6 +1156,7 @@ pub const OperandKind = enum {
.{ .name = "TextureBoxFilterQCOM", .value = 4485, .parameters = &.{} },
.{ .name = "TextureBlockMatchQCOM", .value = 4486, .parameters = &.{} },
.{ .name = "TileShadingQCOM", .value = 4495, .parameters = &.{} },
+ .{ .name = "CooperativeMatrixConversionQCOM", .value = 4496, .parameters = &.{} },
.{ .name = "TextureBlockMatch2QCOM", .value = 4498, .parameters = &.{} },
.{ .name = "Float16ImageAMD", .value = 5008, .parameters = &.{} },
.{ .name = "ImageGatherBiasLodAMD", .value = 5009, .parameters = &.{} },
@@ -1159,6 +1172,10 @@ pub const OperandKind = enum {
.{ .name = "BFloat16TypeKHR", .value = 5116, .parameters = &.{} },
.{ .name = "BFloat16DotProductKHR", .value = 5117, .parameters = &.{} },
.{ .name = "BFloat16CooperativeMatrixKHR", .value = 5118, .parameters = &.{} },
+ .{ .name = "AbortKHR", .value = 5120, .parameters = &.{} },
+ .{ .name = "DescriptorHeapEXT", .value = 5128, .parameters = &.{} },
+ .{ .name = "ConstantDataKHR", .value = 5146, .parameters = &.{} },
+ .{ .name = "PoisonFreezeKHR", .value = 5156, .parameters = &.{} },
.{ .name = "SampleMaskOverrideCoverageNV", .value = 5249, .parameters = &.{} },
.{ .name = "GeometryShaderPassthroughNV", .value = 5251, .parameters = &.{} },
.{ .name = "ShaderViewportIndexLayerEXT", .value = 5254, .parameters = &.{} },
@@ -1172,7 +1189,7 @@ pub const OperandKind = enum {
.{ .name = "FragmentBarycentricKHR", .value = 5284, .parameters = &.{} },
.{ .name = "ComputeDerivativeGroupQuadsKHR", .value = 5288, .parameters = &.{} },
.{ .name = "FragmentDensityEXT", .value = 5291, .parameters = &.{} },
- .{ .name = "GroupNonUniformPartitionedNV", .value = 5297, .parameters = &.{} },
+ .{ .name = "GroupNonUniformPartitionedEXT", .value = 5297, .parameters = &.{} },
.{ .name = "ShaderNonUniform", .value = 5301, .parameters = &.{} },
.{ .name = "RuntimeDescriptorArray", .value = 5302, .parameters = &.{} },
.{ .name = "InputAttachmentArrayDynamicIndexing", .value = 5303, .parameters = &.{} },
@@ -1202,6 +1219,7 @@ pub const OperandKind = enum {
.{ .name = "DisplacementMicromapNV", .value = 5380, .parameters = &.{} },
.{ .name = "RayTracingOpacityMicromapEXT", .value = 5381, .parameters = &.{} },
.{ .name = "ShaderInvocationReorderNV", .value = 5383, .parameters = &.{} },
+ .{ .name = "ShaderInvocationReorderEXT", .value = 5388, .parameters = &.{} },
.{ .name = "BindlessTextureNV", .value = 5390, .parameters = &.{} },
.{ .name = "RayQueryPositionFetchKHR", .value = 5391, .parameters = &.{} },
.{ .name = "CooperativeVectorNV", .value = 5394, .parameters = &.{} },
@@ -1210,6 +1228,9 @@ pub const OperandKind = enum {
.{ .name = "RawAccessChainsNV", .value = 5414, .parameters = &.{} },
.{ .name = "RayTracingSpheresGeometryNV", .value = 5418, .parameters = &.{} },
.{ .name = "RayTracingLinearSweptSpheresGeometryNV", .value = 5419, .parameters = &.{} },
+ .{ .name = "PushConstantBanksNV", .value = 5423, .parameters = &.{} },
+ .{ .name = "LongVectorEXT", .value = 5425, .parameters = &.{} },
+ .{ .name = "Shader64BitIndexingEXT", .value = 5426, .parameters = &.{} },
.{ .name = "CooperativeMatrixReductionsNV", .value = 5430, .parameters = &.{} },
.{ .name = "CooperativeMatrixConversionsNV", .value = 5431, .parameters = &.{} },
.{ .name = "CooperativeMatrixPerElementOperationsNV", .value = 5432, .parameters = &.{} },
@@ -1239,27 +1260,27 @@ pub const OperandKind = enum {
.{ .name = "SubgroupAvcMotionEstimationChromaINTEL", .value = 5698, .parameters = &.{} },
.{ .name = "VariableLengthArrayINTEL", .value = 5817, .parameters = &.{} },
.{ .name = "FunctionFloatControlINTEL", .value = 5821, .parameters = &.{} },
- .{ .name = "FPGAMemoryAttributesINTEL", .value = 5824, .parameters = &.{} },
+ .{ .name = "FPGAMemoryAttributesALTERA", .value = 5824, .parameters = &.{} },
.{ .name = "FPFastMathModeINTEL", .value = 5837, .parameters = &.{} },
- .{ .name = "ArbitraryPrecisionIntegersINTEL", .value = 5844, .parameters = &.{} },
- .{ .name = "ArbitraryPrecisionFloatingPointINTEL", .value = 5845, .parameters = &.{} },
+ .{ .name = "ArbitraryPrecisionIntegersALTERA", .value = 5844, .parameters = &.{} },
+ .{ .name = "ArbitraryPrecisionFloatingPointALTERA", .value = 5845, .parameters = &.{} },
.{ .name = "UnstructuredLoopControlsINTEL", .value = 5886, .parameters = &.{} },
- .{ .name = "FPGALoopControlsINTEL", .value = 5888, .parameters = &.{} },
+ .{ .name = "FPGALoopControlsALTERA", .value = 5888, .parameters = &.{} },
.{ .name = "KernelAttributesINTEL", .value = 5892, .parameters = &.{} },
.{ .name = "FPGAKernelAttributesINTEL", .value = 5897, .parameters = &.{} },
- .{ .name = "FPGAMemoryAccessesINTEL", .value = 5898, .parameters = &.{} },
- .{ .name = "FPGAClusterAttributesINTEL", .value = 5904, .parameters = &.{} },
- .{ .name = "LoopFuseINTEL", .value = 5906, .parameters = &.{} },
- .{ .name = "FPGADSPControlINTEL", .value = 5908, .parameters = &.{} },
+ .{ .name = "FPGAMemoryAccessesALTERA", .value = 5898, .parameters = &.{} },
+ .{ .name = "FPGAClusterAttributesALTERA", .value = 5904, .parameters = &.{} },
+ .{ .name = "LoopFuseALTERA", .value = 5906, .parameters = &.{} },
+ .{ .name = "FPGADSPControlALTERA", .value = 5908, .parameters = &.{} },
.{ .name = "MemoryAccessAliasingINTEL", .value = 5910, .parameters = &.{} },
- .{ .name = "FPGAInvocationPipeliningAttributesINTEL", .value = 5916, .parameters = &.{} },
- .{ .name = "FPGABufferLocationINTEL", .value = 5920, .parameters = &.{} },
- .{ .name = "ArbitraryPrecisionFixedPointINTEL", .value = 5922, .parameters = &.{} },
- .{ .name = "USMStorageClassesINTEL", .value = 5935, .parameters = &.{} },
- .{ .name = "RuntimeAlignedAttributeINTEL", .value = 5939, .parameters = &.{} },
- .{ .name = "IOPipesINTEL", .value = 5943, .parameters = &.{} },
- .{ .name = "BlockingPipesINTEL", .value = 5945, .parameters = &.{} },
- .{ .name = "FPGARegINTEL", .value = 5948, .parameters = &.{} },
+ .{ .name = "FPGAInvocationPipeliningAttributesALTERA", .value = 5916, .parameters = &.{} },
+ .{ .name = "FPGABufferLocationALTERA", .value = 5920, .parameters = &.{} },
+ .{ .name = "ArbitraryPrecisionFixedPointALTERA", .value = 5922, .parameters = &.{} },
+ .{ .name = "USMStorageClassesALTERA", .value = 5935, .parameters = &.{} },
+ .{ .name = "RuntimeAlignedAttributeALTERA", .value = 5939, .parameters = &.{} },
+ .{ .name = "IOPipesALTERA", .value = 5943, .parameters = &.{} },
+ .{ .name = "BlockingPipesALTERA", .value = 5945, .parameters = &.{} },
+ .{ .name = "FPGARegALTERA", .value = 5948, .parameters = &.{} },
.{ .name = "DotProductInputAll", .value = 6016, .parameters = &.{} },
.{ .name = "DotProductInput4x8Bit", .value = 6017, .parameters = &.{} },
.{ .name = "DotProductInput4x8BitPacked", .value = 6018, .parameters = &.{} },
@@ -1270,6 +1291,7 @@ pub const OperandKind = enum {
.{ .name = "BitInstructions", .value = 6025, .parameters = &.{} },
.{ .name = "GroupNonUniformRotateKHR", .value = 6026, .parameters = &.{} },
.{ .name = "FloatControls2", .value = 6029, .parameters = &.{} },
+ .{ .name = "FMAKHR", .value = 6030, .parameters = &.{} },
.{ .name = "AtomicFloat32AddEXT", .value = 6033, .parameters = &.{} },
.{ .name = "AtomicFloat64AddEXT", .value = 6034, .parameters = &.{} },
.{ .name = "LongCompositesINTEL", .value = 6089, .parameters = &.{} },
@@ -1279,26 +1301,33 @@ pub const OperandKind = enum {
.{ .name = "BFloat16ConversionINTEL", .value = 6115, .parameters = &.{} },
.{ .name = "SplitBarrierINTEL", .value = 6141, .parameters = &.{} },
.{ .name = "ArithmeticFenceEXT", .value = 6144, .parameters = &.{} },
- .{ .name = "FPGAClusterAttributesV2INTEL", .value = 6150, .parameters = &.{} },
+ .{ .name = "FPGAClusterAttributesV2ALTERA", .value = 6150, .parameters = &.{} },
.{ .name = "FPGAKernelAttributesv2INTEL", .value = 6161, .parameters = &.{} },
- .{ .name = "TaskSequenceINTEL", .value = 6162, .parameters = &.{} },
+ .{ .name = "TaskSequenceALTERA", .value = 6162, .parameters = &.{} },
.{ .name = "FPMaxErrorINTEL", .value = 6169, .parameters = &.{} },
- .{ .name = "FPGALatencyControlINTEL", .value = 6171, .parameters = &.{} },
- .{ .name = "FPGAArgumentInterfacesINTEL", .value = 6174, .parameters = &.{} },
+ .{ .name = "FPGALatencyControlALTERA", .value = 6171, .parameters = &.{} },
+ .{ .name = "FPGAArgumentInterfacesALTERA", .value = 6174, .parameters = &.{} },
.{ .name = "GlobalVariableHostAccessINTEL", .value = 6187, .parameters = &.{} },
- .{ .name = "GlobalVariableFPGADecorationsINTEL", .value = 6189, .parameters = &.{} },
+ .{ .name = "GlobalVariableFPGADecorationsALTERA", .value = 6189, .parameters = &.{} },
.{ .name = "SubgroupBufferPrefetchINTEL", .value = 6220, .parameters = &.{} },
.{ .name = "Subgroup2DBlockIOINTEL", .value = 6228, .parameters = &.{} },
.{ .name = "Subgroup2DBlockTransformINTEL", .value = 6229, .parameters = &.{} },
.{ .name = "Subgroup2DBlockTransposeINTEL", .value = 6230, .parameters = &.{} },
.{ .name = "SubgroupMatrixMultiplyAccumulateINTEL", .value = 6236, .parameters = &.{} },
.{ .name = "TernaryBitwiseFunctionINTEL", .value = 6241, .parameters = &.{} },
+ .{ .name = "UntypedVariableLengthArrayINTEL", .value = 6243, .parameters = &.{} },
+ .{ .name = "SpecConditionalINTEL", .value = 6245, .parameters = &.{} },
+ .{ .name = "FunctionVariantsINTEL", .value = 6246, .parameters = &.{} },
.{ .name = "GroupUniformArithmeticKHR", .value = 6400, .parameters = &.{} },
.{ .name = "TensorFloat32RoundingINTEL", .value = 6425, .parameters = &.{} },
.{ .name = "MaskedGatherScatterINTEL", .value = 6427, .parameters = &.{} },
.{ .name = "CacheControlsINTEL", .value = 6441, .parameters = &.{} },
.{ .name = "RegisterLimitsINTEL", .value = 6460, .parameters = &.{} },
.{ .name = "BindlessImagesINTEL", .value = 6528, .parameters = &.{} },
+ .{ .name = "DotProductFloat16AccFloat32VALVE", .value = 6912, .parameters = &.{} },
+ .{ .name = "DotProductFloat16AccFloat16VALVE", .value = 6913, .parameters = &.{} },
+ .{ .name = "DotProductBFloat16AccVALVE", .value = 6914, .parameters = &.{} },
+ .{ .name = "DotProductFloat8AccFloat32VALVE", .value = 6915, .parameters = &.{} },
},
.ray_query_intersection => &.{
.{ .name = "RayQueryCandidateIntersectionKHR", .value = 0, .parameters = &.{} },
@@ -1352,8 +1381,8 @@ pub const OperandKind = enum {
.{ .name = "DecodeFunc", .value = 0x0002, .parameters = &.{.id_ref} },
},
.initialization_mode_qualifier => &.{
- .{ .name = "InitOnDeviceReprogramINTEL", .value = 0, .parameters = &.{} },
- .{ .name = "InitOnDeviceResetINTEL", .value = 1, .parameters = &.{} },
+ .{ .name = "InitOnDeviceReprogramALTERA", .value = 0, .parameters = &.{} },
+ .{ .name = "InitOnDeviceResetALTERA", .value = 1, .parameters = &.{} },
},
.load_cache_control => &.{
.{ .name = "UncachedINTEL", .value = 0, .parameters = &.{} },
@@ -1811,12 +1840,14 @@ pub const Opcode = enum(u16) {
OpUntypedInBoundsPtrAccessChainKHR = 4424,
OpUntypedArrayLengthKHR = 4425,
OpUntypedPrefetchKHR = 4426,
+ OpFmaKHR = 4427,
OpSubgroupAllKHR = 4428,
OpSubgroupAnyKHR = 4429,
OpSubgroupAllEqualKHR = 4430,
OpGroupNonUniformRotateKHR = 4431,
OpSubgroupReadInvocationKHR = 4432,
OpExtInstWithForwardRefsKHR = 4433,
+ OpUntypedGroupAsyncCopyKHR = 4434,
OpTraceRayKHR = 4445,
OpExecuteCallableKHR = 4446,
OpConvertUToAccelerationStructureKHR = 4447,
@@ -1847,10 +1878,14 @@ pub const Opcode = enum(u16) {
OpImageBoxFilterQCOM = 4481,
OpImageBlockMatchSSDQCOM = 4482,
OpImageBlockMatchSADQCOM = 4483,
+ OpBitCastArrayQCOM = 4497,
OpImageBlockMatchWindowSSDQCOM = 4500,
OpImageBlockMatchWindowSADQCOM = 4501,
OpImageBlockMatchGatherSSDQCOM = 4502,
OpImageBlockMatchGatherSADQCOM = 4503,
+ OpCompositeConstructCoopMatQCOM = 4540,
+ OpCompositeExtractCoopMatQCOM = 4541,
+ OpExtractSubArrayQCOM = 4542,
OpGroupIAddNonUniformAMD = 5000,
OpGroupFAddNonUniformAMD = 5001,
OpGroupFMinNonUniformAMD = 5002,
@@ -1872,6 +1907,16 @@ pub const Opcode = enum(u16) {
OpSpecConstantStringAMDX = 5104,
OpGroupNonUniformQuadAllKHR = 5110,
OpGroupNonUniformQuadAnyKHR = 5111,
+ OpTypeBufferEXT = 5115,
+ OpBufferPointerEXT = 5119,
+ OpAbortKHR = 5121,
+ OpUntypedImageTexelPointerEXT = 5126,
+ OpMemberDecorateIdEXT = 5127,
+ OpConstantSizeOfEXT = 5129,
+ OpConstantDataKHR = 5147,
+ OpSpecConstantDataKHR = 5148,
+ OpPoisonKHR = 5158,
+ OpFreezeKHR = 5159,
OpHitObjectRecordHitMotionNV = 5249,
OpHitObjectRecordHitWithIndexMotionNV = 5250,
OpHitObjectRecordMissMotionNV = 5251,
@@ -1906,7 +1951,7 @@ pub const Opcode = enum(u16) {
OpReorderThreadWithHintNV = 5280,
OpTypeHitObjectNV = 5281,
OpImageSampleFootprintNV = 5283,
- OpTypeCooperativeVectorNV = 5288,
+ OpTypeVectorIdEXT = 5288,
OpCooperativeVectorMatrixMulNV = 5289,
OpCooperativeVectorOuterProductAccumulateNV = 5290,
OpCooperativeVectorReduceSumAccumulateNV = 5291,
@@ -1914,12 +1959,42 @@ pub const Opcode = enum(u16) {
OpCooperativeMatrixConvertNV = 5293,
OpEmitMeshTasksEXT = 5294,
OpSetMeshOutputsEXT = 5295,
- OpGroupNonUniformPartitionNV = 5296,
+ OpGroupNonUniformPartitionEXT = 5296,
OpWritePackedPrimitiveIndices4x8NV = 5299,
OpFetchMicroTriangleVertexPositionNV = 5300,
OpFetchMicroTriangleVertexBarycentricNV = 5301,
OpCooperativeVectorLoadNV = 5302,
OpCooperativeVectorStoreNV = 5303,
+ OpHitObjectRecordFromQueryEXT = 5304,
+ OpHitObjectRecordMissEXT = 5305,
+ OpHitObjectRecordMissMotionEXT = 5306,
+ OpHitObjectGetIntersectionTriangleVertexPositionsEXT = 5307,
+ OpHitObjectGetRayFlagsEXT = 5308,
+ OpHitObjectSetShaderBindingTableRecordIndexEXT = 5309,
+ OpHitObjectReorderExecuteShaderEXT = 5310,
+ OpHitObjectTraceReorderExecuteEXT = 5311,
+ OpHitObjectTraceMotionReorderExecuteEXT = 5312,
+ OpTypeHitObjectEXT = 5313,
+ OpReorderThreadWithHintEXT = 5314,
+ OpReorderThreadWithHitObjectEXT = 5315,
+ OpHitObjectTraceRayEXT = 5316,
+ OpHitObjectTraceRayMotionEXT = 5317,
+ OpHitObjectRecordEmptyEXT = 5318,
+ OpHitObjectExecuteShaderEXT = 5319,
+ OpHitObjectGetCurrentTimeEXT = 5320,
+ OpHitObjectGetAttributesEXT = 5321,
+ OpHitObjectGetHitKindEXT = 5322,
+ OpHitObjectGetPrimitiveIndexEXT = 5323,
+ OpHitObjectGetGeometryIndexEXT = 5324,
+ OpHitObjectGetInstanceIdEXT = 5325,
+ OpHitObjectGetInstanceCustomIndexEXT = 5326,
+ OpHitObjectGetObjectRayOriginEXT = 5327,
+ OpHitObjectGetObjectRayDirectionEXT = 5328,
+ OpHitObjectGetWorldRayDirectionEXT = 5329,
+ OpHitObjectGetWorldRayOriginEXT = 5330,
+ OpHitObjectGetObjectToWorldEXT = 5331,
+ OpHitObjectGetWorldToObjectEXT = 5332,
+ OpHitObjectGetRayTMaxEXT = 5333,
OpReportIntersectionKHR = 5334,
OpIgnoreIntersectionNV = 5335,
OpTerminateRayNV = 5336,
@@ -1929,8 +2004,14 @@ pub const Opcode = enum(u16) {
OpRayQueryGetIntersectionTriangleVertexPositionsKHR = 5340,
OpTypeAccelerationStructureKHR = 5341,
OpExecuteCallableNV = 5344,
- OpRayQueryGetClusterIdNV = 5345,
+ OpRayQueryGetIntersectionClusterIdNV = 5345,
OpHitObjectGetClusterIdNV = 5346,
+ OpHitObjectGetRayTMinEXT = 5347,
+ OpHitObjectGetShaderBindingTableRecordIndexEXT = 5348,
+ OpHitObjectGetShaderRecordBufferHandleEXT = 5349,
+ OpHitObjectIsEmptyEXT = 5350,
+ OpHitObjectIsHitEXT = 5351,
+ OpHitObjectIsMissEXT = 5352,
OpTypeCooperativeMatrixNV = 5358,
OpCooperativeMatrixLoadNV = 5359,
OpCooperativeMatrixStoreNV = 5360,
@@ -2008,10 +2089,10 @@ pub const Opcode = enum(u16) {
OpExpectKHR = 5631,
OpDecorateString = 5632,
OpMemberDecorateString = 5633,
+ OpVariableLengthArrayINTEL = 5818,
+ OpSaveMemoryINTEL = 5819,
+ OpRestoreMemoryINTEL = 5820,
OpLoopControlINTEL = 5887,
- OpReadPipeBlockingINTEL = 5946,
- OpWritePipeBlockingINTEL = 5947,
- OpFPGARegINTEL = 5949,
OpRayQueryGetRayTMinKHR = 6016,
OpRayQueryGetRayFlagsKHR = 6017,
OpRayQueryGetIntersectionTKHR = 6018,
@@ -2040,11 +2121,6 @@ pub const Opcode = enum(u16) {
OpControlBarrierArriveINTEL = 6142,
OpControlBarrierWaitINTEL = 6143,
OpArithmeticFenceEXT = 6145,
- OpTaskSequenceCreateINTEL = 6163,
- OpTaskSequenceAsyncINTEL = 6164,
- OpTaskSequenceGetINTEL = 6165,
- OpTaskSequenceReleaseINTEL = 6166,
- OpTypeTaskSequenceINTEL = 6199,
OpSubgroupBlockPrefetchINTEL = 6221,
OpSubgroup2DBlockLoadINTEL = 6231,
OpSubgroup2DBlockLoadTransformINTEL = 6232,
@@ -2053,6 +2129,14 @@ pub const Opcode = enum(u16) {
OpSubgroup2DBlockStoreINTEL = 6235,
OpSubgroupMatrixMultiplyAccumulateINTEL = 6237,
OpBitwiseFunctionINTEL = 6242,
+ OpUntypedVariableLengthArrayINTEL = 6244,
+ OpConditionalExtensionINTEL = 6248,
+ OpConditionalEntryPointINTEL = 6249,
+ OpConditionalCapabilityINTEL = 6250,
+ OpSpecConstantTargetINTEL = 6251,
+ OpSpecConstantArchitectureINTEL = 6252,
+ OpSpecConstantCapabilitiesINTEL = 6253,
+ OpConditionalCopyObjectINTEL = 6254,
OpGroupIMulKHR = 6401,
OpGroupFMulKHR = 6402,
OpGroupBitwiseAndKHR = 6403,
@@ -2067,6 +2151,9 @@ pub const Opcode = enum(u16) {
OpConvertHandleToImageINTEL = 6529,
OpConvertHandleToSamplerINTEL = 6530,
OpConvertHandleToSampledImageINTEL = 6531,
+ OpFDot2MixAcc32VALVE = 6916,
+ OpFDot2MixAcc16VALVE = 6917,
+ OpFDot4MixAcc32VALVE = 6918,
pub fn Operands(comptime self: Opcode) type {
return switch (self) {
@@ -2380,7 +2467,7 @@ pub const Opcode = enum(u16) {
.OpGroupNonUniformAll => struct { id_result_type: Id, id_result: Id, execution: Id, predicate: Id },
.OpGroupNonUniformAny => struct { id_result_type: Id, id_result: Id, execution: Id, predicate: Id },
.OpGroupNonUniformAllEqual => struct { id_result_type: Id, id_result: Id, execution: Id, value: Id },
- .OpGroupNonUniformBroadcast => struct { id_result_type: Id, id_result: Id, execution: Id, value: Id, id: Id },
+ .OpGroupNonUniformBroadcast => struct { id_result_type: Id, id_result: Id, execution: Id, value: Id, invocation_id: Id },
.OpGroupNonUniformBroadcastFirst => struct { id_result_type: Id, id_result: Id, execution: Id, value: Id },
.OpGroupNonUniformBallot => struct { id_result_type: Id, id_result: Id, execution: Id, predicate: Id },
.OpGroupNonUniformInverseBallot => struct { id_result_type: Id, id_result: Id, execution: Id, value: Id },
@@ -2388,7 +2475,7 @@ pub const Opcode = enum(u16) {
.OpGroupNonUniformBallotBitCount => struct { id_result_type: Id, id_result: Id, execution: Id, operation: GroupOperation, value: Id },
.OpGroupNonUniformBallotFindLSB => struct { id_result_type: Id, id_result: Id, execution: Id, value: Id },
.OpGroupNonUniformBallotFindMSB => struct { id_result_type: Id, id_result: Id, execution: Id, value: Id },
- .OpGroupNonUniformShuffle => struct { id_result_type: Id, id_result: Id, execution: Id, value: Id, id: Id },
+ .OpGroupNonUniformShuffle => struct { id_result_type: Id, id_result: Id, execution: Id, value: Id, invocation_id: Id },
.OpGroupNonUniformShuffleXor => struct { id_result_type: Id, id_result: Id, execution: Id, value: Id, mask: Id },
.OpGroupNonUniformShuffleUp => struct { id_result_type: Id, id_result: Id, execution: Id, value: Id, delta: Id },
.OpGroupNonUniformShuffleDown => struct { id_result_type: Id, id_result: Id, execution: Id, value: Id, delta: Id },
@@ -2439,12 +2526,14 @@ pub const Opcode = enum(u16) {
.OpUntypedInBoundsPtrAccessChainKHR => struct { id_result_type: Id, id_result: Id, base_type: Id, base: Id, element: Id, indexes: []const Id = &.{} },
.OpUntypedArrayLengthKHR => struct { id_result_type: Id, id_result: Id, structure: Id, pointer: Id, array_member: LiteralInteger },
.OpUntypedPrefetchKHR => struct { pointer_type: Id, num_bytes: Id, rw: ?Id = null, locality: ?Id = null, cache_type: ?Id = null },
+ .OpFmaKHR => struct { id_result_type: Id, id_result: Id, operand_1: Id, operand_2: Id, operand_3: Id },
.OpSubgroupAllKHR => struct { id_result_type: Id, id_result: Id, predicate: Id },
.OpSubgroupAnyKHR => struct { id_result_type: Id, id_result: Id, predicate: Id },
.OpSubgroupAllEqualKHR => struct { id_result_type: Id, id_result: Id, predicate: Id },
.OpGroupNonUniformRotateKHR => struct { id_result_type: Id, id_result: Id, execution: Id, value: Id, delta: Id, cluster_size: ?Id = null },
.OpSubgroupReadInvocationKHR => struct { id_result_type: Id, id_result: Id, value: Id, index: Id },
.OpExtInstWithForwardRefsKHR => struct { id_result_type: Id, id_result: Id, set: Id, instruction: LiteralExtInstInteger, id_ref_4: []const Id = &.{} },
+ .OpUntypedGroupAsyncCopyKHR => struct { id_result_type: Id, id_result: Id, execution: Id, destination: Id, source: Id, element_num_bytes: Id, num_elements: Id, stride: Id, event: Id, destination_memory_operands: ?MemoryAccess.Extended = null, source_memory_operands: ?MemoryAccess.Extended = null },
.OpTraceRayKHR => struct { accel: Id, ray_flags: Id, cull_mask: Id, sbt_offset: Id, sbt_stride: Id, miss_index: Id, ray_origin: Id, ray_tmin: Id, ray_direction: Id, ray_tmax: Id, payload: Id },
.OpExecuteCallableKHR => struct { sbt_index: Id, callable_data: Id },
.OpConvertUToAccelerationStructureKHR => struct { id_result_type: Id, id_result: Id, accel: Id },
@@ -2475,10 +2564,14 @@ pub const Opcode = enum(u16) {
.OpImageBoxFilterQCOM => struct { id_result_type: Id, id_result: Id, texture: Id, coordinates: Id, box_size: Id },
.OpImageBlockMatchSSDQCOM => struct { id_result_type: Id, id_result: Id, target: Id, target_coordinates: Id, reference: Id, reference_coordinates: Id, block_size: Id },
.OpImageBlockMatchSADQCOM => struct { id_result_type: Id, id_result: Id, target: Id, target_coordinates: Id, reference: Id, reference_coordinates: Id, block_size: Id },
+ .OpBitCastArrayQCOM => struct { id_result_type: Id, id_result: Id, source_array: Id },
.OpImageBlockMatchWindowSSDQCOM => struct { id_result_type: Id, id_result: Id, target_sampled_image: Id, target_coordinates: Id, reference_sampled_image: Id, reference_coordinates: Id, block_size: Id },
.OpImageBlockMatchWindowSADQCOM => struct { id_result_type: Id, id_result: Id, target_sampled_image: Id, target_coordinates: Id, reference_sampled_image: Id, reference_coordinates: Id, block_size: Id },
.OpImageBlockMatchGatherSSDQCOM => struct { id_result_type: Id, id_result: Id, target_sampled_image: Id, target_coordinates: Id, reference_sampled_image: Id, reference_coordinates: Id, block_size: Id },
.OpImageBlockMatchGatherSADQCOM => struct { id_result_type: Id, id_result: Id, target_sampled_image: Id, target_coordinates: Id, reference_sampled_image: Id, reference_coordinates: Id, block_size: Id },
+ .OpCompositeConstructCoopMatQCOM => struct { id_result_type: Id, id_result: Id, source_array: Id },
+ .OpCompositeExtractCoopMatQCOM => struct { id_result_type: Id, id_result: Id, source_cooperative_matrix: Id },
+ .OpExtractSubArrayQCOM => struct { id_result_type: Id, id_result: Id, source_array: Id, index: Id },
.OpGroupIAddNonUniformAMD => struct { id_result_type: Id, id_result: Id, execution: Id, operation: GroupOperation, x: Id },
.OpGroupFAddNonUniformAMD => struct { id_result_type: Id, id_result: Id, execution: Id, operation: GroupOperation, x: Id },
.OpGroupFMinNonUniformAMD => struct { id_result_type: Id, id_result: Id, execution: Id, operation: GroupOperation, x: Id },
@@ -2500,6 +2593,16 @@ pub const Opcode = enum(u16) {
.OpSpecConstantStringAMDX => struct { id_result: Id, literal_string: LiteralString },
.OpGroupNonUniformQuadAllKHR => struct { id_result_type: Id, id_result: Id, predicate: Id },
.OpGroupNonUniformQuadAnyKHR => struct { id_result_type: Id, id_result: Id, predicate: Id },
+ .OpTypeBufferEXT => struct { id_result: Id, storage_class: StorageClass },
+ .OpBufferPointerEXT => struct { id_result_type: Id, id_result: Id, buffer: Id },
+ .OpAbortKHR => struct { message_type: Id, message: Id },
+ .OpUntypedImageTexelPointerEXT => struct { id_result_type: Id, id_result: Id, image_type: Id, image: Id, coordinate: Id, sample: Id },
+ .OpMemberDecorateIdEXT => struct { structure_type: Id, member: LiteralInteger, decoration: Decoration.Extended },
+ .OpConstantSizeOfEXT => struct { id_result_type: Id, id_result: Id, type: Id },
+ .OpConstantDataKHR => struct { id_result_type: Id, id_result: Id, data: []const LiteralInteger = &.{} },
+ .OpSpecConstantDataKHR => struct { id_result_type: Id, id_result: Id, data: []const LiteralInteger = &.{} },
+ .OpPoisonKHR => struct { id_result_type: Id, id_result: Id },
+ .OpFreezeKHR => struct { id_result_type: Id, id_result: Id, value: Id },
.OpHitObjectRecordHitMotionNV => struct { hit_object: Id, acceleration_structure: Id, instance_id: Id, primitive_id: Id, geometry_index: Id, hit_kind: Id, sbt_record_offset: Id, sbt_record_stride: Id, origin: Id, t_min: Id, direction: Id, t_max: Id, current_time: Id, hit_object_attributes: Id },
.OpHitObjectRecordHitWithIndexMotionNV => struct { hit_object: Id, acceleration_structure: Id, instance_id: Id, primitive_id: Id, geometry_index: Id, hit_kind: Id, sbt_record_index: Id, origin: Id, t_min: Id, direction: Id, t_max: Id, current_time: Id, hit_object_attributes: Id },
.OpHitObjectRecordMissMotionNV => struct { hit_object: Id, sbt_index: Id, origin: Id, t_min: Id, direction: Id, t_max: Id, current_time: Id },
@@ -2534,7 +2637,7 @@ pub const Opcode = enum(u16) {
.OpReorderThreadWithHintNV => struct { hint: Id, bits: Id },
.OpTypeHitObjectNV => struct { id_result: Id },
.OpImageSampleFootprintNV => struct { id_result_type: Id, id_result: Id, sampled_image: Id, coordinate: Id, granularity: Id, coarse: Id, image_operands: ?ImageOperands.Extended = null },
- .OpTypeCooperativeVectorNV => struct { id_result: Id, component_type: Id, component_count: Id },
+ .OpTypeVectorIdEXT => struct { id_result: Id, component_type: Id, component_count: Id },
.OpCooperativeVectorMatrixMulNV => struct { id_result_type: Id, id_result: Id, input: Id, input_interpretation: Id, matrix: Id, matrix_offset: Id, matrix_interpretation: Id, m: Id, k: Id, memory_layout: Id, transpose: Id, matrix_stride: ?Id = null, cooperative_matrix_operands: ?CooperativeMatrixOperands = null },
.OpCooperativeVectorOuterProductAccumulateNV => struct { pointer: Id, offset: Id, a: Id, b: Id, memory_layout: Id, matrix_interpretation: Id, matrix_stride: ?Id = null },
.OpCooperativeVectorReduceSumAccumulateNV => struct { pointer: Id, offset: Id, v: Id },
@@ -2542,12 +2645,42 @@ pub const Opcode = enum(u16) {
.OpCooperativeMatrixConvertNV => struct { id_result_type: Id, id_result: Id, matrix: Id },
.OpEmitMeshTasksEXT => struct { group_count_x: Id, group_count_y: Id, group_count_z: Id, payload: ?Id = null },
.OpSetMeshOutputsEXT => struct { vertex_count: Id, primitive_count: Id },
- .OpGroupNonUniformPartitionNV => struct { id_result_type: Id, id_result: Id, value: Id },
+ .OpGroupNonUniformPartitionEXT => struct { id_result_type: Id, id_result: Id, value: Id },
.OpWritePackedPrimitiveIndices4x8NV => struct { index_offset: Id, packed_indices: Id },
.OpFetchMicroTriangleVertexPositionNV => struct { id_result_type: Id, id_result: Id, accel: Id, instance_id: Id, geometry_index: Id, primitive_index: Id, barycentric: Id },
.OpFetchMicroTriangleVertexBarycentricNV => struct { id_result_type: Id, id_result: Id, accel: Id, instance_id: Id, geometry_index: Id, primitive_index: Id, barycentric: Id },
.OpCooperativeVectorLoadNV => struct { id_result_type: Id, id_result: Id, pointer: Id, offset: Id, memory_access: ?MemoryAccess.Extended = null },
.OpCooperativeVectorStoreNV => struct { pointer: Id, offset: Id, object: Id, memory_access: ?MemoryAccess.Extended = null },
+ .OpHitObjectRecordFromQueryEXT => struct { hit_object: Id, ray_query: Id, sbt_record_index: Id, hit_object_attributes: Id },
+ .OpHitObjectRecordMissEXT => struct { hit_object: Id, ray_flags: Id, miss_index: Id, ray_origin: Id, ray_tmin: Id, ray_direction: Id, ray_tmax: Id },
+ .OpHitObjectRecordMissMotionEXT => struct { hit_object: Id, ray_flags: Id, miss_index: Id, ray_origin: Id, ray_tmin: Id, ray_direction: Id, ray_tmax: Id, current_time: Id },
+ .OpHitObjectGetIntersectionTriangleVertexPositionsEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectGetRayFlagsEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectSetShaderBindingTableRecordIndexEXT => struct { hit_object: Id, sbt_record_index: Id },
+ .OpHitObjectReorderExecuteShaderEXT => struct { hit_object: Id, payload: Id, hint: ?Id = null, bits: ?Id = null },
+ .OpHitObjectTraceReorderExecuteEXT => struct { hit_object: Id, acceleration_structure: Id, ray_flags: Id, cull_mask: Id, sbt_offset: Id, sbt_stride: Id, miss_index: Id, ray_origin: Id, ray_tmin: Id, ray_direction: Id, ray_tmax: Id, payload: Id, hint: ?Id = null, bits: ?Id = null },
+ .OpHitObjectTraceMotionReorderExecuteEXT => struct { hit_object: Id, acceleration_structure: Id, ray_flags: Id, cull_mask: Id, sbt_offset: Id, sbt_stride: Id, miss_index: Id, ray_origin: Id, ray_tmin: Id, ray_direction: Id, ray_tmax: Id, current_time: Id, payload: Id, hint: ?Id = null, bits: ?Id = null },
+ .OpTypeHitObjectEXT => struct { id_result: Id },
+ .OpReorderThreadWithHintEXT => struct { hint: Id, bits: Id },
+ .OpReorderThreadWithHitObjectEXT => struct { hit_object: Id, hint: ?Id = null, bits: ?Id = null },
+ .OpHitObjectTraceRayEXT => struct { hit_object: Id, acceleration_structure: Id, ray_flags: Id, cull_mask: Id, sbt_offset: Id, sbt_stride: Id, miss_index: Id, ray_origin: Id, ray_tmin: Id, ray_direction: Id, ray_tmax: Id, payload: Id },
+ .OpHitObjectTraceRayMotionEXT => struct { hit_object: Id, acceleration_structure: Id, ray_flags: Id, cull_mask: Id, sbt_offset: Id, sbt_stride: Id, miss_index: Id, ray_origin: Id, ray_tmin: Id, ray_direction: Id, ray_tmax: Id, current_time: Id, payload: Id },
+ .OpHitObjectRecordEmptyEXT => struct { hit_object: Id },
+ .OpHitObjectExecuteShaderEXT => struct { hit_object: Id, payload: Id },
+ .OpHitObjectGetCurrentTimeEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectGetAttributesEXT => struct { hit_object: Id, hit_object_attribute: Id },
+ .OpHitObjectGetHitKindEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectGetPrimitiveIndexEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectGetGeometryIndexEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectGetInstanceIdEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectGetInstanceCustomIndexEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectGetObjectRayOriginEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectGetObjectRayDirectionEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectGetWorldRayDirectionEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectGetWorldRayOriginEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectGetObjectToWorldEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectGetWorldToObjectEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectGetRayTMaxEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
.OpReportIntersectionKHR => struct { id_result_type: Id, id_result: Id, hit: Id, hit_kind: Id },
.OpIgnoreIntersectionNV => void,
.OpTerminateRayNV => void,
@@ -2557,8 +2690,14 @@ pub const Opcode = enum(u16) {
.OpRayQueryGetIntersectionTriangleVertexPositionsKHR => struct { id_result_type: Id, id_result: Id, ray_query: Id, intersection: Id },
.OpTypeAccelerationStructureKHR => struct { id_result: Id },
.OpExecuteCallableNV => struct { sbt_index: Id, callable_data_id: Id },
- .OpRayQueryGetClusterIdNV => struct { id_result_type: Id, id_result: Id, ray_query: Id, intersection: Id },
+ .OpRayQueryGetIntersectionClusterIdNV => struct { id_result_type: Id, id_result: Id, ray_query: Id, intersection: Id },
.OpHitObjectGetClusterIdNV => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectGetRayTMinEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectGetShaderBindingTableRecordIndexEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectGetShaderRecordBufferHandleEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectIsEmptyEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectIsHitEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
+ .OpHitObjectIsMissEXT => struct { id_result_type: Id, id_result: Id, hit_object: Id },
.OpTypeCooperativeMatrixNV => struct { id_result: Id, component_type: Id, execution: Id, rows: Id, columns: Id },
.OpCooperativeMatrixLoadNV => struct { id_result_type: Id, id_result: Id, pointer: Id, stride: Id, column_major: Id, memory_access: ?MemoryAccess.Extended = null },
.OpCooperativeMatrixStoreNV => struct { pointer: Id, object: Id, stride: Id, column_major: Id, memory_access: ?MemoryAccess.Extended = null },
@@ -2636,10 +2775,10 @@ pub const Opcode = enum(u16) {
.OpExpectKHR => struct { id_result_type: Id, id_result: Id, value: Id, expected_value: Id },
.OpDecorateString => struct { target: Id, decoration: Decoration.Extended },
.OpMemberDecorateString => struct { struct_type: Id, member: LiteralInteger, decoration: Decoration.Extended },
+ .OpVariableLengthArrayINTEL => struct { id_result_type: Id, id_result: Id, length: Id },
+ .OpSaveMemoryINTEL => struct { id_result_type: Id, id_result: Id },
+ .OpRestoreMemoryINTEL => struct { ptr: Id },
.OpLoopControlINTEL => struct { loop_control_parameters: []const LiteralInteger = &.{} },
- .OpReadPipeBlockingINTEL => struct { id_result_type: Id, id_result: Id, packet_size: Id, packet_alignment: Id },
- .OpWritePipeBlockingINTEL => struct { id_result_type: Id, id_result: Id, packet_size: Id, packet_alignment: Id },
- .OpFPGARegINTEL => struct { id_result_type: Id, id_result: Id, input: Id },
.OpRayQueryGetRayTMinKHR => struct { id_result_type: Id, id_result: Id, ray_query: Id },
.OpRayQueryGetRayFlagsKHR => struct { id_result_type: Id, id_result: Id, ray_query: Id },
.OpRayQueryGetIntersectionTKHR => struct { id_result_type: Id, id_result: Id, ray_query: Id, intersection: Id },
@@ -2668,11 +2807,6 @@ pub const Opcode = enum(u16) {
.OpControlBarrierArriveINTEL => struct { execution: Id, memory: Id, semantics: Id },
.OpControlBarrierWaitINTEL => struct { execution: Id, memory: Id, semantics: Id },
.OpArithmeticFenceEXT => struct { id_result_type: Id, id_result: Id, target: Id },
- .OpTaskSequenceCreateINTEL => struct { id_result_type: Id, id_result: Id, function: Id, pipelined: LiteralInteger, use_stall_enable_clusters: LiteralInteger, get_capacity: LiteralInteger, async_capacity: LiteralInteger },
- .OpTaskSequenceAsyncINTEL => struct { sequence: Id, arguments: []const Id = &.{} },
- .OpTaskSequenceGetINTEL => struct { id_result_type: Id, id_result: Id, sequence: Id },
- .OpTaskSequenceReleaseINTEL => struct { sequence: Id },
- .OpTypeTaskSequenceINTEL => struct { id_result: Id },
.OpSubgroupBlockPrefetchINTEL => struct { ptr: Id, num_bytes: Id, memory_access: ?MemoryAccess.Extended = null },
.OpSubgroup2DBlockLoadINTEL => struct { element_size: Id, block_width: Id, block_height: Id, block_count: Id, src_base_pointer: Id, memory_width: Id, memory_height: Id, memory_pitch: Id, coordinate: Id, dst_pointer: Id },
.OpSubgroup2DBlockLoadTransformINTEL => struct { element_size: Id, block_width: Id, block_height: Id, block_count: Id, src_base_pointer: Id, memory_width: Id, memory_height: Id, memory_pitch: Id, coordinate: Id, dst_pointer: Id },
@@ -2681,6 +2815,14 @@ pub const Opcode = enum(u16) {
.OpSubgroup2DBlockStoreINTEL => struct { element_size: Id, block_width: Id, block_height: Id, block_count: Id, src_pointer: Id, dst_base_pointer: Id, memory_width: Id, memory_height: Id, memory_pitch: Id, coordinate: Id },
.OpSubgroupMatrixMultiplyAccumulateINTEL => struct { id_result_type: Id, id_result: Id, k_dim: Id, matrix_a: Id, matrix_b: Id, matrix_c: Id, matrix_multiply_accumulate_operands: ?MatrixMultiplyAccumulateOperands = null },
.OpBitwiseFunctionINTEL => struct { id_result_type: Id, id_result: Id, a: Id, b: Id, c: Id, lut_index: Id },
+ .OpUntypedVariableLengthArrayINTEL => struct { id_result_type: Id, id_result: Id, element_type: Id, length: Id },
+ .OpConditionalExtensionINTEL => struct { condition: Id, name: LiteralString },
+ .OpConditionalEntryPointINTEL => struct { condition: Id, execution_model: ExecutionModel, entry_point: Id, name: LiteralString, interface: []const Id = &.{} },
+ .OpConditionalCapabilityINTEL => struct { condition: Id, capability: Capability },
+ .OpSpecConstantTargetINTEL => struct { id_result_type: Id, id_result: Id, target: LiteralInteger, features: []const LiteralInteger = &.{} },
+ .OpSpecConstantArchitectureINTEL => struct { id_result_type: Id, id_result: Id, category: LiteralInteger, family: LiteralInteger, opcode: LiteralInteger, architecture: LiteralInteger },
+ .OpSpecConstantCapabilitiesINTEL => struct { id_result_type: Id, id_result: Id, capabilities: []const Capability = &.{} },
+ .OpConditionalCopyObjectINTEL => struct { id_result_type: Id, id_result: Id, id_ref: []const Id = &.{} },
.OpGroupIMulKHR => struct { id_result_type: Id, id_result: Id, execution: Id, operation: GroupOperation, x: Id },
.OpGroupFMulKHR => struct { id_result_type: Id, id_result: Id, execution: Id, operation: GroupOperation, x: Id },
.OpGroupBitwiseAndKHR => struct { id_result_type: Id, id_result: Id, execution: Id, operation: GroupOperation, x: Id },
@@ -2695,6 +2837,9 @@ pub const Opcode = enum(u16) {
.OpConvertHandleToImageINTEL => struct { id_result_type: Id, id_result: Id, operand: Id },
.OpConvertHandleToSamplerINTEL => struct { id_result_type: Id, id_result: Id, operand: Id },
.OpConvertHandleToSampledImageINTEL => struct { id_result_type: Id, id_result: Id, operand: Id },
+ .OpFDot2MixAcc32VALVE => struct { id_result_type: Id, id_result: Id, vector_1: Id, vector_2: Id, accumulator: Id },
+ .OpFDot2MixAcc16VALVE => struct { id_result_type: Id, id_result: Id, vector_1: Id, vector_2: Id, accumulator: Id },
+ .OpFDot4MixAcc32VALVE => struct { id_result_type: Id, id_result: Id, vector_1: Id, vector_2: Id, accumulator: Id },
};
}
pub fn class(self: Opcode) Class {
@@ -3068,12 +3213,14 @@ pub const Opcode = enum(u16) {
.OpUntypedInBoundsPtrAccessChainKHR => .memory,
.OpUntypedArrayLengthKHR => .memory,
.OpUntypedPrefetchKHR => .memory,
+ .OpFmaKHR => .arithmetic,
.OpSubgroupAllKHR => .group,
.OpSubgroupAnyKHR => .group,
.OpSubgroupAllEqualKHR => .group,
.OpGroupNonUniformRotateKHR => .group,
.OpSubgroupReadInvocationKHR => .group,
.OpExtInstWithForwardRefsKHR => .extension,
+ .OpUntypedGroupAsyncCopyKHR => .group,
.OpTraceRayKHR => .reserved,
.OpExecuteCallableKHR => .reserved,
.OpConvertUToAccelerationStructureKHR => .reserved,
@@ -3104,10 +3251,14 @@ pub const Opcode = enum(u16) {
.OpImageBoxFilterQCOM => .image,
.OpImageBlockMatchSSDQCOM => .image,
.OpImageBlockMatchSADQCOM => .image,
+ .OpBitCastArrayQCOM => .conversion,
.OpImageBlockMatchWindowSSDQCOM => .image,
.OpImageBlockMatchWindowSADQCOM => .image,
.OpImageBlockMatchGatherSSDQCOM => .image,
.OpImageBlockMatchGatherSADQCOM => .image,
+ .OpCompositeConstructCoopMatQCOM => .composite,
+ .OpCompositeExtractCoopMatQCOM => .composite,
+ .OpExtractSubArrayQCOM => .composite,
.OpGroupIAddNonUniformAMD => .group,
.OpGroupFAddNonUniformAMD => .group,
.OpGroupFMinNonUniformAMD => .group,
@@ -3129,6 +3280,16 @@ pub const Opcode = enum(u16) {
.OpSpecConstantStringAMDX => .reserved,
.OpGroupNonUniformQuadAllKHR => .non_uniform,
.OpGroupNonUniformQuadAnyKHR => .non_uniform,
+ .OpTypeBufferEXT => .type_declaration,
+ .OpBufferPointerEXT => .memory,
+ .OpAbortKHR => .control_flow,
+ .OpUntypedImageTexelPointerEXT => .memory,
+ .OpMemberDecorateIdEXT => .annotation,
+ .OpConstantSizeOfEXT => .constant_creation,
+ .OpConstantDataKHR => .constant_creation,
+ .OpSpecConstantDataKHR => .constant_creation,
+ .OpPoisonKHR => .miscellaneous,
+ .OpFreezeKHR => .miscellaneous,
.OpHitObjectRecordHitMotionNV => .reserved,
.OpHitObjectRecordHitWithIndexMotionNV => .reserved,
.OpHitObjectRecordMissMotionNV => .reserved,
@@ -3163,7 +3324,7 @@ pub const Opcode = enum(u16) {
.OpReorderThreadWithHintNV => .reserved,
.OpTypeHitObjectNV => .type_declaration,
.OpImageSampleFootprintNV => .image,
- .OpTypeCooperativeVectorNV => .type_declaration,
+ .OpTypeVectorIdEXT => .type_declaration,
.OpCooperativeVectorMatrixMulNV => .reserved,
.OpCooperativeVectorOuterProductAccumulateNV => .reserved,
.OpCooperativeVectorReduceSumAccumulateNV => .reserved,
@@ -3171,12 +3332,42 @@ pub const Opcode = enum(u16) {
.OpCooperativeMatrixConvertNV => .conversion,
.OpEmitMeshTasksEXT => .reserved,
.OpSetMeshOutputsEXT => .reserved,
- .OpGroupNonUniformPartitionNV => .non_uniform,
+ .OpGroupNonUniformPartitionEXT => .non_uniform,
.OpWritePackedPrimitiveIndices4x8NV => .reserved,
.OpFetchMicroTriangleVertexPositionNV => .reserved,
.OpFetchMicroTriangleVertexBarycentricNV => .reserved,
.OpCooperativeVectorLoadNV => .memory,
.OpCooperativeVectorStoreNV => .memory,
+ .OpHitObjectRecordFromQueryEXT => .reserved,
+ .OpHitObjectRecordMissEXT => .reserved,
+ .OpHitObjectRecordMissMotionEXT => .reserved,
+ .OpHitObjectGetIntersectionTriangleVertexPositionsEXT => .reserved,
+ .OpHitObjectGetRayFlagsEXT => .reserved,
+ .OpHitObjectSetShaderBindingTableRecordIndexEXT => .reserved,
+ .OpHitObjectReorderExecuteShaderEXT => .reserved,
+ .OpHitObjectTraceReorderExecuteEXT => .reserved,
+ .OpHitObjectTraceMotionReorderExecuteEXT => .reserved,
+ .OpTypeHitObjectEXT => .type_declaration,
+ .OpReorderThreadWithHintEXT => .reserved,
+ .OpReorderThreadWithHitObjectEXT => .reserved,
+ .OpHitObjectTraceRayEXT => .reserved,
+ .OpHitObjectTraceRayMotionEXT => .reserved,
+ .OpHitObjectRecordEmptyEXT => .reserved,
+ .OpHitObjectExecuteShaderEXT => .reserved,
+ .OpHitObjectGetCurrentTimeEXT => .reserved,
+ .OpHitObjectGetAttributesEXT => .reserved,
+ .OpHitObjectGetHitKindEXT => .reserved,
+ .OpHitObjectGetPrimitiveIndexEXT => .reserved,
+ .OpHitObjectGetGeometryIndexEXT => .reserved,
+ .OpHitObjectGetInstanceIdEXT => .reserved,
+ .OpHitObjectGetInstanceCustomIndexEXT => .reserved,
+ .OpHitObjectGetObjectRayOriginEXT => .reserved,
+ .OpHitObjectGetObjectRayDirectionEXT => .reserved,
+ .OpHitObjectGetWorldRayDirectionEXT => .reserved,
+ .OpHitObjectGetWorldRayOriginEXT => .reserved,
+ .OpHitObjectGetObjectToWorldEXT => .reserved,
+ .OpHitObjectGetWorldToObjectEXT => .reserved,
+ .OpHitObjectGetRayTMaxEXT => .reserved,
.OpReportIntersectionKHR => .reserved,
.OpIgnoreIntersectionNV => .reserved,
.OpTerminateRayNV => .reserved,
@@ -3186,8 +3377,14 @@ pub const Opcode = enum(u16) {
.OpRayQueryGetIntersectionTriangleVertexPositionsKHR => .reserved,
.OpTypeAccelerationStructureKHR => .type_declaration,
.OpExecuteCallableNV => .reserved,
- .OpRayQueryGetClusterIdNV => .reserved,
+ .OpRayQueryGetIntersectionClusterIdNV => .reserved,
.OpHitObjectGetClusterIdNV => .reserved,
+ .OpHitObjectGetRayTMinEXT => .reserved,
+ .OpHitObjectGetShaderBindingTableRecordIndexEXT => .reserved,
+ .OpHitObjectGetShaderRecordBufferHandleEXT => .reserved,
+ .OpHitObjectIsEmptyEXT => .reserved,
+ .OpHitObjectIsHitEXT => .reserved,
+ .OpHitObjectIsMissEXT => .reserved,
.OpTypeCooperativeMatrixNV => .type_declaration,
.OpCooperativeMatrixLoadNV => .reserved,
.OpCooperativeMatrixStoreNV => .reserved,
@@ -3265,10 +3462,10 @@ pub const Opcode = enum(u16) {
.OpExpectKHR => .miscellaneous,
.OpDecorateString => .annotation,
.OpMemberDecorateString => .annotation,
+ .OpVariableLengthArrayINTEL => .memory,
+ .OpSaveMemoryINTEL => .memory,
+ .OpRestoreMemoryINTEL => .memory,
.OpLoopControlINTEL => .reserved,
- .OpReadPipeBlockingINTEL => .pipe,
- .OpWritePipeBlockingINTEL => .pipe,
- .OpFPGARegINTEL => .reserved,
.OpRayQueryGetRayTMinKHR => .reserved,
.OpRayQueryGetRayFlagsKHR => .reserved,
.OpRayQueryGetIntersectionTKHR => .reserved,
@@ -3297,11 +3494,6 @@ pub const Opcode = enum(u16) {
.OpControlBarrierArriveINTEL => .barrier,
.OpControlBarrierWaitINTEL => .barrier,
.OpArithmeticFenceEXT => .miscellaneous,
- .OpTaskSequenceCreateINTEL => .reserved,
- .OpTaskSequenceAsyncINTEL => .reserved,
- .OpTaskSequenceGetINTEL => .reserved,
- .OpTaskSequenceReleaseINTEL => .reserved,
- .OpTypeTaskSequenceINTEL => .type_declaration,
.OpSubgroupBlockPrefetchINTEL => .group,
.OpSubgroup2DBlockLoadINTEL => .group,
.OpSubgroup2DBlockLoadTransformINTEL => .group,
@@ -3310,6 +3502,14 @@ pub const Opcode = enum(u16) {
.OpSubgroup2DBlockStoreINTEL => .group,
.OpSubgroupMatrixMultiplyAccumulateINTEL => .group,
.OpBitwiseFunctionINTEL => .bit,
+ .OpUntypedVariableLengthArrayINTEL => .memory,
+ .OpConditionalExtensionINTEL => .extension,
+ .OpConditionalEntryPointINTEL => .mode_setting,
+ .OpConditionalCapabilityINTEL => .mode_setting,
+ .OpSpecConstantTargetINTEL => .constant_creation,
+ .OpSpecConstantArchitectureINTEL => .constant_creation,
+ .OpSpecConstantCapabilitiesINTEL => .constant_creation,
+ .OpConditionalCopyObjectINTEL => .composite,
.OpGroupIMulKHR => .group,
.OpGroupFMulKHR => .group,
.OpGroupBitwiseAndKHR => .group,
@@ -3324,94 +3524,13 @@ pub const Opcode = enum(u16) {
.OpConvertHandleToImageINTEL => .image,
.OpConvertHandleToSamplerINTEL => .image,
.OpConvertHandleToSampledImageINTEL => .image,
+ .OpFDot2MixAcc32VALVE => .reserved,
+ .OpFDot2MixAcc16VALVE => .reserved,
+ .OpFDot4MixAcc32VALVE => .reserved,
};
}
};
-pub const GlslOpcode = enum(u16) {
- Round = 1,
- RoundEven = 2,
- Trunc = 3,
- FAbs = 4,
- SAbs = 5,
- FSign = 6,
- SSign = 7,
- Floor = 8,
- Ceil = 9,
- Fract = 10,
- Radians = 11,
- Degrees = 12,
- Sin = 13,
- Cos = 14,
- Tan = 15,
- Asin = 16,
- Acos = 17,
- Atan = 18,
- Sinh = 19,
- Cosh = 20,
- Tanh = 21,
- Asinh = 22,
- Acosh = 23,
- Atanh = 24,
- Atan2 = 25,
- Pow = 26,
- Exp = 27,
- Log = 28,
- Exp2 = 29,
- Log2 = 30,
- Sqrt = 31,
- InverseSqrt = 32,
- Determinant = 33,
- MatrixInverse = 34,
- Modf = 35,
- ModfStruct = 36,
- FMin = 37,
- UMin = 38,
- SMin = 39,
- FMax = 40,
- UMax = 41,
- SMax = 42,
- FClamp = 43,
- UClamp = 44,
- SClamp = 45,
- FMix = 46,
- IMix = 47,
- Step = 48,
- SmoothStep = 49,
- Fma = 50,
- Frexp = 51,
- FrexpStruct = 52,
- Ldexp = 53,
- PackSnorm4x8 = 54,
- PackUnorm4x8 = 55,
- PackSnorm2x16 = 56,
- PackUnorm2x16 = 57,
- PackHalf2x16 = 58,
- PackDouble2x32 = 59,
- UnpackSnorm2x16 = 60,
- UnpackUnorm2x16 = 61,
- UnpackHalf2x16 = 62,
- UnpackSnorm4x8 = 63,
- UnpackUnorm4x8 = 64,
- UnpackDouble2x32 = 65,
- Length = 66,
- Distance = 67,
- Cross = 68,
- Normalize = 69,
- FaceForward = 70,
- Reflect = 71,
- Refract = 72,
- FindILsb = 73,
- FindSMsb = 74,
- FindUMsb = 75,
- InterpolateAtCentroid = 76,
- InterpolateAtSample = 77,
- InterpolateAtOffset = 78,
- NMin = 79,
- NMax = 80,
- NClamp = 81,
-};
-
pub const OpenClOpcode = enum(u16) {
acos = 0,
acosh = 1,
@@ -3577,6 +3696,90 @@ pub const OpenClOpcode = enum(u16) {
u_mad_hi = 204,
};
+pub const GlslOpcode = enum(u16) {
+ Round = 1,
+ RoundEven = 2,
+ Trunc = 3,
+ FAbs = 4,
+ SAbs = 5,
+ FSign = 6,
+ SSign = 7,
+ Floor = 8,
+ Ceil = 9,
+ Fract = 10,
+ Radians = 11,
+ Degrees = 12,
+ Sin = 13,
+ Cos = 14,
+ Tan = 15,
+ Asin = 16,
+ Acos = 17,
+ Atan = 18,
+ Sinh = 19,
+ Cosh = 20,
+ Tanh = 21,
+ Asinh = 22,
+ Acosh = 23,
+ Atanh = 24,
+ Atan2 = 25,
+ Pow = 26,
+ Exp = 27,
+ Log = 28,
+ Exp2 = 29,
+ Log2 = 30,
+ Sqrt = 31,
+ InverseSqrt = 32,
+ Determinant = 33,
+ MatrixInverse = 34,
+ Modf = 35,
+ ModfStruct = 36,
+ FMin = 37,
+ UMin = 38,
+ SMin = 39,
+ FMax = 40,
+ UMax = 41,
+ SMax = 42,
+ FClamp = 43,
+ UClamp = 44,
+ SClamp = 45,
+ FMix = 46,
+ IMix = 47,
+ Step = 48,
+ SmoothStep = 49,
+ Fma = 50,
+ Frexp = 51,
+ FrexpStruct = 52,
+ Ldexp = 53,
+ PackSnorm4x8 = 54,
+ PackUnorm4x8 = 55,
+ PackSnorm2x16 = 56,
+ PackUnorm2x16 = 57,
+ PackHalf2x16 = 58,
+ PackDouble2x32 = 59,
+ UnpackSnorm2x16 = 60,
+ UnpackUnorm2x16 = 61,
+ UnpackHalf2x16 = 62,
+ UnpackSnorm4x8 = 63,
+ UnpackUnorm4x8 = 64,
+ UnpackDouble2x32 = 65,
+ Length = 66,
+ Distance = 67,
+ Cross = 68,
+ Normalize = 69,
+ FaceForward = 70,
+ Reflect = 71,
+ Refract = 72,
+ FindILsb = 73,
+ FindSMsb = 74,
+ FindUMsb = 75,
+ InterpolateAtCentroid = 76,
+ InterpolateAtSample = 77,
+ InterpolateAtOffset = 78,
+ NMin = 79,
+ NMax = 80,
+ NClamp = 81,
+};
+
pub const Zig = enum(u16) {
InvocationGlobal = 0,
};
@@ -3734,16 +3937,16 @@ pub const LoopControl = packed struct {
_reserved_bit_13: bool = false,
_reserved_bit_14: bool = false,
_reserved_bit_15: bool = false,
- initiation_interval_intel: bool = false,
- max_concurrency_intel: bool = false,
- dependency_array_intel: bool = false,
- pipeline_enable_intel: bool = false,
- loop_coalesce_intel: bool = false,
- max_interleaving_intel: bool = false,
- speculated_iterations_intel: bool = false,
- no_fusion_intel: bool = false,
- loop_count_intel: bool = false,
- max_reinvocation_delay_intel: bool = false,
+ initiation_interval_altera: bool = false,
+ max_concurrency_altera: bool = false,
+ dependency_array_altera: bool = false,
+ pipeline_enable_altera: bool = false,
+ loop_coalesce_altera: bool = false,
+ max_interleaving_altera: bool = false,
+ speculated_iterations_altera: bool = false,
+ no_fusion_altera: bool = false,
+ loop_count_altera: bool = false,
+ max_reinvocation_delay_altera: bool = false,
_reserved_bit_26: bool = false,
_reserved_bit_27: bool = false,
_reserved_bit_28: bool = false,
@@ -3768,16 +3971,16 @@ pub const LoopControl = packed struct {
_reserved_bit_13: bool = false,
_reserved_bit_14: bool = false,
_reserved_bit_15: bool = false,
- initiation_interval_intel: ?struct { literal_integer: LiteralInteger } = null,
- max_concurrency_intel: ?struct { literal_integer: LiteralInteger } = null,
- dependency_array_intel: ?struct { literal_integer: LiteralInteger } = null,
- pipeline_enable_intel: ?struct { literal_integer: LiteralInteger } = null,
- loop_coalesce_intel: ?struct { literal_integer: LiteralInteger } = null,
- max_interleaving_intel: ?struct { literal_integer: LiteralInteger } = null,
- speculated_iterations_intel: ?struct { literal_integer: LiteralInteger } = null,
- no_fusion_intel: bool = false,
- loop_count_intel: ?struct { literal_integer: LiteralInteger } = null,
- max_reinvocation_delay_intel: ?struct { literal_integer: LiteralInteger } = null,
+ initiation_interval_altera: ?struct { literal_integer: LiteralInteger } = null,
+ max_concurrency_altera: ?struct { literal_integer: LiteralInteger } = null,
+ dependency_array_altera: ?struct { literal_integer: LiteralInteger } = null,
+ pipeline_enable_altera: ?struct { literal_integer: LiteralInteger } = null,
+ loop_coalesce_altera: ?struct { literal_integer: LiteralInteger } = null,
+ max_interleaving_altera: ?struct { literal_integer: LiteralInteger } = null,
+ speculated_iterations_altera: ?struct { literal_integer: LiteralInteger } = null,
+ no_fusion_altera: bool = false,
+ loop_count_altera: ?struct { literal_integer: LiteralInteger } = null,
+ max_reinvocation_delay_altera: ?struct { literal_integer: LiteralInteger } = null,
_reserved_bit_26: bool = false,
_reserved_bit_27: bool = false,
_reserved_bit_28: bool = false,
@@ -4174,6 +4377,7 @@ pub const ExecutionMode = enum(u32) {
quad_derivatives_khr = 5088,
require_full_quads_khr = 5089,
shares_input_with_amdx = 5102,
+ arithmetic_poison_khr = 5157,
output_lines_ext = 5269,
output_primitives_ext = 5270,
derivative_group_quads_khr = 5289,
@@ -4185,6 +4389,7 @@ pub const ExecutionMode = enum(u32) {
sample_interlock_unordered_ext = 5369,
shading_rate_interlock_ordered_ext = 5370,
shading_rate_interlock_unordered_ext = 5371,
+ shader64bit_indexing_ext = 5427,
shared_local_memory_size_intel = 5618,
rounding_mode_rtpintel = 5620,
rounding_mode_rtnintel = 5621,
@@ -4272,6 +4477,7 @@ pub const ExecutionMode = enum(u32) {
quad_derivatives_khr,
require_full_quads_khr,
shares_input_with_amdx: struct { node_name: Id, shader_index: Id },
+ arithmetic_poison_khr,
output_lines_ext,
output_primitives_ext: struct { primitive_count: LiteralInteger },
derivative_group_quads_khr,
@@ -4283,6 +4489,7 @@ pub const ExecutionMode = enum(u32) {
sample_interlock_unordered_ext,
shading_rate_interlock_ordered_ext,
shading_rate_interlock_unordered_ext,
+ shader64bit_indexing_ext,
shared_local_memory_size_intel: struct { size: LiteralInteger },
rounding_mode_rtpintel: struct { target_width: LiteralInteger },
rounding_mode_rtnintel: struct { target_width: LiteralInteger },
@@ -4329,9 +4536,10 @@ pub const StorageClass = enum(u32) {
physical_storage_buffer = 5349,
hit_object_attribute_nv = 5385,
task_payload_workgroup_ext = 5402,
+ hit_object_attribute_ext = 5411,
code_section_intel = 5605,
- device_only_intel = 5936,
- host_only_intel = 5937,
+ device_only_altera = 5936,
+ host_only_altera = 5937,
};
pub const Dim = enum(u32) {
@"1d" = 0,
@@ -4503,7 +4711,7 @@ pub const FunctionParameterAttribute = enum(u32) {
no_capture = 5,
no_write = 6,
no_read_write = 7,
- runtime_aligned_intel = 5940,
+ runtime_aligned_altera = 5940,
};
pub const Decoration = enum(u32) {
relaxed_precision = 0,
@@ -4568,6 +4776,9 @@ pub const Decoration = enum(u32) {
payload_node_sparse_array_amdx = 5099,
payload_node_array_size_amdx = 5100,
payload_dispatch_indirect_amdx = 5105,
+ array_stride_id_ext = 5124,
+ offset_id_ext = 5125,
+ utf_encoded_khr = 5145,
override_coverage_nv = 5248,
passthrough_nv = 5250,
viewport_relative_nv = 5252,
@@ -4579,7 +4790,10 @@ pub const Decoration = enum(u32) {
non_uniform = 5300,
restrict_pointer = 5355,
aliased_pointer = 5356,
+ member_offset_nv = 5358,
hit_object_shader_record_buffer_nv = 5386,
+ hit_object_shader_record_buffer_ext = 5389,
+ bank_nv = 5397,
bindless_sampler_nv = 5398,
bindless_image_nv = 5399,
bound_sampler_nv = 5400,
@@ -4598,55 +4812,56 @@ pub const Decoration = enum(u32) {
user_type_google = 5636,
function_rounding_mode_intel = 5822,
function_denorm_mode_intel = 5823,
- register_intel = 5825,
- memory_intel = 5826,
- numbanks_intel = 5827,
- bankwidth_intel = 5828,
- max_private_copies_intel = 5829,
- singlepump_intel = 5830,
- doublepump_intel = 5831,
- max_replicates_intel = 5832,
- simple_dual_port_intel = 5833,
- merge_intel = 5834,
- bank_bits_intel = 5835,
- force_pow2depth_intel = 5836,
- stridesize_intel = 5883,
- wordsize_intel = 5884,
- true_dual_port_intel = 5885,
- burst_coalesce_intel = 5899,
- cache_size_intel = 5900,
- dont_statically_coalesce_intel = 5901,
- prefetch_intel = 5902,
- stall_enable_intel = 5905,
- fuse_loops_in_function_intel = 5907,
- math_op_dsp_mode_intel = 5909,
+ register_altera = 5825,
+ memory_altera = 5826,
+ numbanks_altera = 5827,
+ bankwidth_altera = 5828,
+ max_private_copies_altera = 5829,
+ singlepump_altera = 5830,
+ doublepump_altera = 5831,
+ max_replicates_altera = 5832,
+ simple_dual_port_altera = 5833,
+ merge_altera = 5834,
+ bank_bits_altera = 5835,
+ force_pow2depth_altera = 5836,
+ stridesize_altera = 5883,
+ wordsize_altera = 5884,
+ true_dual_port_altera = 5885,
+ burst_coalesce_altera = 5899,
+ cache_size_altera = 5900,
+ dont_statically_coalesce_altera = 5901,
+ prefetch_altera = 5902,
+ stall_enable_altera = 5905,
+ fuse_loops_in_function_altera = 5907,
+ math_op_dsp_mode_altera = 5909,
alias_scope_intel = 5914,
no_alias_intel = 5915,
- initiation_interval_intel = 5917,
- max_concurrency_intel = 5918,
- pipeline_enable_intel = 5919,
- buffer_location_intel = 5921,
- io_pipe_storage_intel = 5944,
+ initiation_interval_altera = 5917,
+ max_concurrency_altera = 5918,
+ pipeline_enable_altera = 5919,
+ buffer_location_altera = 5921,
+ io_pipe_storage_altera = 5944,
function_floating_point_mode_intel = 6080,
single_element_vector_intel = 6085,
vector_compute_callable_function_intel = 6087,
media_block_iointel = 6140,
- stall_free_intel = 6151,
+ stall_free_altera = 6151,
fp_max_error_decoration_intel = 6170,
- latency_control_label_intel = 6172,
- latency_control_constraint_intel = 6173,
- conduit_kernel_argument_intel = 6175,
- register_map_kernel_argument_intel = 6176,
- mm_host_interface_address_width_intel = 6177,
- mm_host_interface_data_width_intel = 6178,
- mm_host_interface_latency_intel = 6179,
- mm_host_interface_read_write_mode_intel = 6180,
- mm_host_interface_max_burst_intel = 6181,
- mm_host_interface_wait_request_intel = 6182,
- stable_kernel_argument_intel = 6183,
+ latency_control_label_altera = 6172,
+ latency_control_constraint_altera = 6173,
+ conduit_kernel_argument_altera = 6175,
+ register_map_kernel_argument_altera = 6176,
+ mm_host_interface_address_width_altera = 6177,
+ mm_host_interface_data_width_altera = 6178,
+ mm_host_interface_latency_altera = 6179,
+ mm_host_interface_read_write_mode_altera = 6180,
+ mm_host_interface_max_burst_altera = 6181,
+ mm_host_interface_wait_request_altera = 6182,
+ stable_kernel_argument_altera = 6183,
host_access_intel = 6188,
- init_mode_intel = 6190,
- implement_in_register_map_intel = 6191,
+ init_mode_altera = 6190,
+ implement_in_register_map_altera = 6191,
+ conditional_intel = 6247,
cache_control_load_intel = 6442,
cache_control_store_intel = 6443,
@@ -4713,6 +4928,9 @@ pub const Decoration = enum(u32) {
payload_node_sparse_array_amdx,
payload_node_array_size_amdx: struct { array_size: Id },
payload_dispatch_indirect_amdx,
+ array_stride_id_ext: struct { array_stride: Id },
+ offset_id_ext: struct { byte_offset: Id },
+ utf_encoded_khr,
override_coverage_nv,
passthrough_nv,
viewport_relative_nv,
@@ -4724,7 +4942,10 @@ pub const Decoration = enum(u32) {
non_uniform,
restrict_pointer,
aliased_pointer,
+ member_offset_nv: struct { member_offset: LiteralInteger },
hit_object_shader_record_buffer_nv,
+ hit_object_shader_record_buffer_ext,
+ bank_nv: struct { bank: LiteralInteger },
bindless_sampler_nv,
bindless_image_nv,
bound_sampler_nv,
@@ -4743,55 +4964,56 @@ pub const Decoration = enum(u32) {
user_type_google: struct { user_type: LiteralString },
function_rounding_mode_intel: struct { target_width: LiteralInteger, fp_rounding_mode: FPRoundingMode },
function_denorm_mode_intel: struct { target_width: LiteralInteger, fp_denorm_mode: FPDenormMode },
- register_intel,
- memory_intel: struct { memory_type: LiteralString },
- numbanks_intel: struct { banks: LiteralInteger },
- bankwidth_intel: struct { bank_width: LiteralInteger },
- max_private_copies_intel: struct { maximum_copies: LiteralInteger },
- singlepump_intel,
- doublepump_intel,
- max_replicates_intel: struct { maximum_replicates: LiteralInteger },
- simple_dual_port_intel,
- merge_intel: struct { merge_key: LiteralString, merge_type: LiteralString },
- bank_bits_intel: struct { bank_bits: []const LiteralInteger = &.{} },
- force_pow2depth_intel: struct { force_key: LiteralInteger },
- stridesize_intel: struct { stride_size: LiteralInteger },
- wordsize_intel: struct { word_size: LiteralInteger },
- true_dual_port_intel,
- burst_coalesce_intel,
- cache_size_intel: struct { cache_size_in_bytes: LiteralInteger },
- dont_statically_coalesce_intel,
- prefetch_intel: struct { prefetcher_size_in_bytes: LiteralInteger },
- stall_enable_intel,
- fuse_loops_in_function_intel,
- math_op_dsp_mode_intel: struct { mode: LiteralInteger, propagate: LiteralInteger },
+ register_altera,
+ memory_altera: struct { memory_type: LiteralString },
+ numbanks_altera: struct { banks: LiteralInteger },
+ bankwidth_altera: struct { bank_width: LiteralInteger },
+ max_private_copies_altera: struct { maximum_copies: LiteralInteger },
+ singlepump_altera,
+ doublepump_altera,
+ max_replicates_altera: struct { maximum_replicates: LiteralInteger },
+ simple_dual_port_altera,
+ merge_altera: struct { merge_key: LiteralString, merge_type: LiteralString },
+ bank_bits_altera: struct { bank_bits: []const LiteralInteger = &.{} },
+ force_pow2depth_altera: struct { force_key: LiteralInteger },
+ stridesize_altera: struct { stride_size: LiteralInteger },
+ wordsize_altera: struct { word_size: LiteralInteger },
+ true_dual_port_altera,
+ burst_coalesce_altera,
+ cache_size_altera: struct { cache_size_in_bytes: LiteralInteger },
+ dont_statically_coalesce_altera,
+ prefetch_altera: struct { prefetcher_size_in_bytes: LiteralInteger },
+ stall_enable_altera,
+ fuse_loops_in_function_altera,
+ math_op_dsp_mode_altera: struct { mode: LiteralInteger, propagate: LiteralInteger },
alias_scope_intel: struct { aliasing_scopes_list: Id },
no_alias_intel: struct { aliasing_scopes_list: Id },
- initiation_interval_intel: struct { cycles: LiteralInteger },
- max_concurrency_intel: struct { invocations: LiteralInteger },
- pipeline_enable_intel: struct { enable: LiteralInteger },
- buffer_location_intel: struct { buffer_location_id: LiteralInteger },
- io_pipe_storage_intel: struct { io_pipe_id: LiteralInteger },
+ initiation_interval_altera: struct { cycles: LiteralInteger },
+ max_concurrency_altera: struct { invocations: LiteralInteger },
+ pipeline_enable_altera: struct { enable: LiteralInteger },
+ buffer_location_altera: struct { buffer_location_id: LiteralInteger },
+ io_pipe_storage_altera: struct { io_pipe_id: LiteralInteger },
function_floating_point_mode_intel: struct { target_width: LiteralInteger, fp_operation_mode: FPOperationMode },
single_element_vector_intel,
vector_compute_callable_function_intel,
media_block_iointel,
- stall_free_intel,
+ stall_free_altera,
fp_max_error_decoration_intel: struct { max_error: LiteralFloat },
- latency_control_label_intel: struct { latency_label: LiteralInteger },
- latency_control_constraint_intel: struct { relative_to: LiteralInteger, control_type: LiteralInteger, relative_cycle: LiteralInteger },
- conduit_kernel_argument_intel,
- register_map_kernel_argument_intel,
- mm_host_interface_address_width_intel: struct { address_width: LiteralInteger },
- mm_host_interface_data_width_intel: struct { data_width: LiteralInteger },
- mm_host_interface_latency_intel: struct { latency: LiteralInteger },
- mm_host_interface_read_write_mode_intel: struct { read_write_mode: AccessQualifier },
- mm_host_interface_max_burst_intel: struct { max_burst_count: LiteralInteger },
- mm_host_interface_wait_request_intel: struct { waitrequest: LiteralInteger },
- stable_kernel_argument_intel,
+ latency_control_label_altera: struct { latency_label: LiteralInteger },
+ latency_control_constraint_altera: struct { relative_to: LiteralInteger, control_type: LiteralInteger, relative_cycle: LiteralInteger },
+ conduit_kernel_argument_altera,
+ register_map_kernel_argument_altera,
+ mm_host_interface_address_width_altera: struct { address_width: LiteralInteger },
+ mm_host_interface_data_width_altera: struct { data_width: LiteralInteger },
+ mm_host_interface_latency_altera: struct { latency: LiteralInteger },
+ mm_host_interface_read_write_mode_altera: struct { read_write_mode: AccessQualifier },
+ mm_host_interface_max_burst_altera: struct { max_burst_count: LiteralInteger },
+ mm_host_interface_wait_request_altera: struct { waitrequest: LiteralInteger },
+ stable_kernel_argument_altera,
host_access_intel: struct { access: HostAccessQualifier, name: LiteralString },
- init_mode_intel: struct { trigger: InitializationModeQualifier },
- implement_in_register_map_intel: struct { value: LiteralInteger },
+ init_mode_altera: struct { trigger: InitializationModeQualifier },
+ implement_in_register_map_altera: struct { value: LiteralInteger },
+ conditional_intel: struct { condition: Id },
cache_control_load_intel: struct { cache_level: LiteralInteger, cache_control: LoadCacheControl },
cache_control_store_intel: struct { cache_level: LiteralInteger, cache_control: StoreCacheControl },
};
@@ -4868,6 +5090,8 @@ pub const BuiltIn = enum(u32) {
frag_stencil_ref_ext = 5014,
remaining_recursion_levels_amdx = 5021,
shader_index_amdx = 5073,
+ sampler_heap_ext = 5122,
+ resource_heap_ext = 5123,
viewport_mask_nv = 5253,
secondary_position_nv = 5257,
secondary_viewport_mask_nv = 5258,
@@ -4938,9 +5162,9 @@ pub const GroupOperation = enum(u32) {
inclusive_scan = 1,
exclusive_scan = 2,
clustered_reduce = 3,
- partitioned_reduce_nv = 6,
- partitioned_inclusive_scan_nv = 7,
- partitioned_exclusive_scan_nv = 8,
+ partitioned_reduce_ext = 6,
+ partitioned_inclusive_scan_ext = 7,
+ partitioned_exclusive_scan_ext = 8,
};
pub const KernelEnqueueFlags = enum(u32) {
no_wait = 0,
@@ -4989,8 +5213,6 @@ pub const Capability = enum(u32) {
input_attachment = 40,
sparse_residency = 41,
min_lod = 42,
- sampled1d = 43,
- image1d = 44,
sampled_cube_array = 45,
sampled_buffer = 46,
image_buffer = 47,
@@ -5018,15 +5240,9 @@ pub const Capability = enum(u32) {
shader_layer = 69,
shader_viewport_index = 70,
uniform_decoration = 71,
- core_builtins_arm = 4165,
tile_image_color_read_access_ext = 4166,
tile_image_depth_read_access_ext = 4167,
tile_image_stencil_read_access_ext = 4168,
- tensors_arm = 4174,
- storage_tensor_array_dynamic_indexing_arm = 4175,
- storage_tensor_array_non_uniform_indexing_arm = 4176,
- graph_arm = 4191,
- cooperative_matrix_layouts_arm = 4201,
float8ext = 4212,
float8cooperative_matrix_ext = 4213,
fragment_shading_rate_khr = 4422,
@@ -5052,46 +5268,29 @@ pub const Capability = enum(u32) {
denorm_preserve = 4464,
denorm_flush_to_zero = 4465,
signed_zero_inf_nan_preserve = 4466,
- rounding_mode_rte = 4467,
- rounding_mode_rtz = 4468,
ray_query_provisional_khr = 4471,
ray_query_khr = 4472,
untyped_pointers_khr = 4473,
ray_traversal_primitive_culling_khr = 4478,
ray_tracing_khr = 4479,
- texture_sample_weighted_qcom = 4484,
- texture_box_filter_qcom = 4485,
- texture_block_match_qcom = 4486,
- tile_shading_qcom = 4495,
- texture_block_match2qcom = 4498,
- float16image_amd = 5008,
- image_gather_bias_lod_amd = 5009,
- fragment_mask_amd = 5010,
stencil_export_ext = 5013,
- image_read_write_lod_amd = 5015,
int64image_ext = 5016,
shader_clock_khr = 5055,
- shader_enqueue_amdx = 5067,
quad_control_khr = 5087,
- int4type_intel = 5112,
- int4cooperative_matrix_intel = 5114,
b_float16type_khr = 5116,
b_float16dot_product_khr = 5117,
b_float16cooperative_matrix_khr = 5118,
- sample_mask_override_coverage_nv = 5249,
- geometry_shader_passthrough_nv = 5251,
+ abort_khr = 5120,
+ descriptor_heap_ext = 5128,
+ constant_data_khr = 5146,
+ poison_freeze_khr = 5156,
shader_viewport_index_layer_ext = 5254,
- shader_viewport_mask_nv = 5255,
- shader_stereo_view_nv = 5259,
- per_view_attributes_nv = 5260,
fragment_fully_covered_ext = 5265,
- mesh_shading_nv = 5266,
- image_footprint_nv = 5282,
mesh_shading_ext = 5283,
fragment_barycentric_khr = 5284,
compute_derivative_group_quads_khr = 5288,
fragment_density_ext = 5291,
- group_non_uniform_partitioned_nv = 5297,
+ group_non_uniform_partitioned_ext = 5297,
shader_non_uniform = 5301,
runtime_descriptor_array = 5302,
input_attachment_array_dynamic_indexing = 5303,
@@ -5105,80 +5304,24 @@ pub const Capability = enum(u32) {
uniform_texel_buffer_array_non_uniform_indexing = 5311,
storage_texel_buffer_array_non_uniform_indexing = 5312,
ray_tracing_position_fetch_khr = 5336,
- ray_tracing_nv = 5340,
- ray_tracing_motion_blur_nv = 5341,
vulkan_memory_model = 5345,
vulkan_memory_model_device_scope = 5346,
physical_storage_buffer_addresses = 5347,
compute_derivative_group_linear_khr = 5350,
ray_tracing_provisional_khr = 5353,
- cooperative_matrix_nv = 5357,
fragment_shader_sample_interlock_ext = 5363,
fragment_shader_shading_rate_interlock_ext = 5372,
- shader_sm_builtins_nv = 5373,
fragment_shader_pixel_interlock_ext = 5378,
demote_to_helper_invocation = 5379,
- displacement_micromap_nv = 5380,
ray_tracing_opacity_micromap_ext = 5381,
- shader_invocation_reorder_nv = 5383,
- bindless_texture_nv = 5390,
+ shader_invocation_reorder_ext = 5388,
ray_query_position_fetch_khr = 5391,
- cooperative_vector_nv = 5394,
- atomic_float16vector_nv = 5404,
- ray_tracing_displacement_micromap_nv = 5409,
- raw_access_chains_nv = 5414,
- ray_tracing_spheres_geometry_nv = 5418,
- ray_tracing_linear_swept_spheres_geometry_nv = 5419,
- cooperative_matrix_reductions_nv = 5430,
- cooperative_matrix_conversions_nv = 5431,
- cooperative_matrix_per_element_operations_nv = 5432,
- cooperative_matrix_tensor_addressing_nv = 5433,
- cooperative_matrix_block_loads_nv = 5434,
- cooperative_vector_training_nv = 5435,
- ray_tracing_cluster_acceleration_structure_nv = 5437,
- tensor_addressing_nv = 5439,
- subgroup_shuffle_intel = 5568,
- subgroup_buffer_block_iointel = 5569,
- subgroup_image_block_iointel = 5570,
- subgroup_image_media_block_iointel = 5579,
- round_to_infinity_intel = 5582,
- floating_point_mode_intel = 5583,
- integer_functions2intel = 5584,
- function_pointers_intel = 5603,
- indirect_references_intel = 5604,
- asm_intel = 5606,
+ long_vector_ext = 5425,
+ shader64bit_indexing_ext = 5426,
atomic_float32min_max_ext = 5612,
atomic_float64min_max_ext = 5613,
atomic_float16min_max_ext = 5616,
- vector_compute_intel = 5617,
- vector_any_intel = 5619,
expect_assume_khr = 5629,
- subgroup_avc_motion_estimation_intel = 5696,
- subgroup_avc_motion_estimation_intra_intel = 5697,
- subgroup_avc_motion_estimation_chroma_intel = 5698,
- variable_length_array_intel = 5817,
- function_float_control_intel = 5821,
- fpga_memory_attributes_intel = 5824,
- fp_fast_math_mode_intel = 5837,
- arbitrary_precision_integers_intel = 5844,
- arbitrary_precision_floating_point_intel = 5845,
- unstructured_loop_controls_intel = 5886,
- fpga_loop_controls_intel = 5888,
- kernel_attributes_intel = 5892,
- fpga_kernel_attributes_intel = 5897,
- fpga_memory_accesses_intel = 5898,
- fpga_cluster_attributes_intel = 5904,
- loop_fuse_intel = 5906,
- fpgadsp_control_intel = 5908,
- memory_access_aliasing_intel = 5910,
- fpga_invocation_pipelining_attributes_intel = 5916,
- fpga_buffer_location_intel = 5920,
- arbitrary_precision_fixed_point_intel = 5922,
- usm_storage_classes_intel = 5935,
- runtime_aligned_attribute_intel = 5939,
- io_pipes_intel = 5943,
- blocking_pipes_intel = 5945,
- fpga_reg_intel = 5948,
dot_product_input_all = 6016,
dot_product_input4x8bit = 6017,
dot_product_input4x8bit_packed = 6018,
@@ -5189,35 +5332,620 @@ pub const Capability = enum(u32) {
bit_instructions = 6025,
group_non_uniform_rotate_khr = 6026,
float_controls2 = 6029,
+ fmakhr = 6030,
atomic_float32add_ext = 6033,
atomic_float64add_ext = 6034,
- long_composites_intel = 6089,
opt_none_ext = 6094,
atomic_float16add_ext = 6095,
- debug_info_module_intel = 6114,
- b_float16conversion_intel = 6115,
- split_barrier_intel = 6141,
arithmetic_fence_ext = 6144,
- fpga_cluster_attributes_v2intel = 6150,
- fpga_kernel_attributesv2intel = 6161,
- task_sequence_intel = 6162,
- fp_max_error_intel = 6169,
- fpga_latency_control_intel = 6171,
- fpga_argument_interfaces_intel = 6174,
- global_variable_host_access_intel = 6187,
- global_variable_fpga_decorations_intel = 6189,
- subgroup_buffer_prefetch_intel = 6220,
- subgroup2d_block_iointel = 6228,
- subgroup2d_block_transform_intel = 6229,
- subgroup2d_block_transpose_intel = 6230,
- subgroup_matrix_multiply_accumulate_intel = 6236,
- ternary_bitwise_function_intel = 6241,
group_uniform_arithmetic_khr = 6400,
- tensor_float32rounding_intel = 6425,
- masked_gather_scatter_intel = 6427,
- cache_controls_intel = 6441,
- register_limits_intel = 6460,
- bindless_images_intel = 6528,
+
+ pub fn dependencies(self: Capability) []const Extension {
+ return switch (self) {
+ .matrix => &.{
+ .v1_0,
+ },
+ .shader => &.{
+ .v1_0,
+ },
+ .geometry => &.{
+ .v1_0,
+ },
+ .tessellation => &.{
+ .v1_0,
+ },
+ .addresses => &.{
+ .v1_0,
+ },
+ .linkage => &.{
+ .v1_0,
+ },
+ .kernel => &.{
+ .v1_0,
+ },
+ .vector16 => &.{
+ .v1_0,
+ },
+ .float16buffer => &.{
+ .v1_0,
+ },
+ .float16 => &.{
+ .v1_0,
+ },
+ .float64 => &.{
+ .v1_0,
+ },
+ .int64 => &.{
+ .v1_0,
+ },
+ .int64atomics => &.{
+ .v1_0,
+ },
+ .image_basic => &.{
+ .v1_0,
+ },
+ .image_read_write => &.{
+ .v1_0,
+ },
+ .image_mipmap => &.{
+ .v1_0,
+ },
+ .pipes => &.{
+ .v1_0,
+ },
+ .groups => &.{
+ .v1_0,
+ },
+ .device_enqueue => &.{
+ .v1_0,
+ },
+ .literal_sampler => &.{
+ .v1_0,
+ },
+ .atomic_storage => &.{
+ .v1_0,
+ },
+ .int16 => &.{
+ .v1_0,
+ },
+ .tessellation_point_size => &.{
+ .v1_0,
+ },
+ .geometry_point_size => &.{
+ .v1_0,
+ },
+ .image_gather_extended => &.{
+ .v1_0,
+ },
+ .storage_image_multisample => &.{
+ .v1_0,
+ },
+ .uniform_buffer_array_dynamic_indexing => &.{
+ .v1_0,
+ },
+ .sampled_image_array_dynamic_indexing => &.{
+ .v1_0,
+ },
+ .storage_buffer_array_dynamic_indexing => &.{
+ .v1_0,
+ },
+ .storage_image_array_dynamic_indexing => &.{
+ .v1_0,
+ },
+ .clip_distance => &.{
+ .v1_0,
+ },
+ .cull_distance => &.{
+ .v1_0,
+ },
+ .image_cube_array => &.{
+ .v1_0,
+ },
+ .sample_rate_shading => &.{
+ .v1_0,
+ },
+ .image_rect => &.{
+ .v1_0,
+ },
+ .sampled_rect => &.{
+ .v1_0,
+ },
+ .generic_pointer => &.{
+ .v1_0,
+ },
+ .int8 => &.{
+ .v1_0,
+ },
+ .input_attachment => &.{
+ .v1_0,
+ },
+ .sparse_residency => &.{
+ .v1_0,
+ },
+ .min_lod => &.{
+ .v1_0,
+ },
+ .sampled_cube_array => &.{
+ .v1_0,
+ },
+ .sampled_buffer => &.{
+ .v1_0,
+ },
+ .image_buffer => &.{
+ .v1_0,
+ },
+ .image_ms_array => &.{
+ .v1_0,
+ },
+ .storage_image_extended_formats => &.{
+ .v1_0,
+ },
+ .image_query => &.{
+ .v1_0,
+ },
+ .derivative_control => &.{
+ .v1_0,
+ },
+ .interpolation_function => &.{
+ .v1_0,
+ },
+ .transform_feedback => &.{
+ .v1_0,
+ },
+ .geometry_streams => &.{
+ .v1_0,
+ },
+ .storage_image_read_without_format => &.{
+ .v1_0,
+ },
+ .storage_image_write_without_format => &.{
+ .v1_0,
+ },
+ .multi_viewport => &.{
+ .v1_0,
+ },
+ .subgroup_dispatch => &.{
+ .v1_1,
+ },
+ .named_barrier => &.{
+ .v1_1,
+ },
+ .pipe_storage => &.{
+ .v1_1,
+ },
+ .group_non_uniform => &.{
+ .v1_3,
+ },
+ .group_non_uniform_vote => &.{
+ .v1_3,
+ },
+ .group_non_uniform_arithmetic => &.{
+ .v1_3,
+ },
+ .group_non_uniform_ballot => &.{
+ .v1_3,
+ },
+ .group_non_uniform_shuffle => &.{
+ .v1_3,
+ },
+ .group_non_uniform_shuffle_relative => &.{
+ .v1_3,
+ },
+ .group_non_uniform_clustered => &.{
+ .v1_3,
+ },
+ .group_non_uniform_quad => &.{
+ .v1_3,
+ },
+ .shader_layer => &.{
+ .v1_5,
+ },
+ .shader_viewport_index => &.{
+ .v1_5,
+ },
+ .uniform_decoration => &.{
+ .v1_6,
+ },
+ .tile_image_color_read_access_ext => &.{
+ .v1_0,
+ .SPV_EXT_shader_tile_image,
+ },
+ .tile_image_depth_read_access_ext => &.{
+ .v1_0,
+ .SPV_EXT_shader_tile_image,
+ },
+ .tile_image_stencil_read_access_ext => &.{
+ .v1_0,
+ .SPV_EXT_shader_tile_image,
+ },
+ .float8ext => &.{
+ .v1_0,
+ .SPV_EXT_float8,
+ },
+ .float8cooperative_matrix_ext => &.{
+ .v1_0,
+ .SPV_EXT_float8,
+ },
+ .fragment_shading_rate_khr => &.{
+ .v1_0,
+ .SPV_KHR_fragment_shading_rate,
+ },
+ .subgroup_ballot_khr => &.{
+ .v1_0,
+ .SPV_KHR_shader_ballot,
+ },
+ .draw_parameters => &.{
+ .v1_3,
+ .SPV_KHR_shader_draw_parameters,
+ },
+ .workgroup_memory_explicit_layout_khr => &.{
+ .v1_0,
+ .SPV_KHR_workgroup_memory_explicit_layout,
+ },
+ .workgroup_memory_explicit_layout8bit_access_khr => &.{
+ .v1_0,
+ .SPV_KHR_workgroup_memory_explicit_layout,
+ },
+ .workgroup_memory_explicit_layout16bit_access_khr => &.{
+ .v1_0,
+ .SPV_KHR_workgroup_memory_explicit_layout,
+ },
+ .subgroup_vote_khr => &.{
+ .v1_0,
+ .SPV_KHR_subgroup_vote,
+ },
+ .storage_buffer16bit_access => &.{
+ .v1_3,
+ .SPV_KHR_16bit_storage,
+ },
+ .uniform_and_storage_buffer16bit_access => &.{
+ .v1_3,
+ .SPV_KHR_16bit_storage,
+ },
+ .storage_push_constant16 => &.{
+ .v1_3,
+ .SPV_KHR_16bit_storage,
+ },
+ .storage_input_output16 => &.{
+ .v1_3,
+ .SPV_KHR_16bit_storage,
+ },
+ .device_group => &.{
+ .v1_3,
+ .SPV_KHR_device_group,
+ },
+ .multi_view => &.{
+ .v1_3,
+ .SPV_KHR_multiview,
+ },
+ .variable_pointers_storage_buffer => &.{
+ .v1_3,
+ .SPV_KHR_variable_pointers,
+ },
+ .variable_pointers => &.{
+ .v1_3,
+ .SPV_KHR_variable_pointers,
+ },
+ .atomic_storage_ops => &.{
+ .v1_0,
+ .SPV_KHR_shader_atomic_counter_ops,
+ },
+ .sample_mask_post_depth_coverage => &.{
+ .v1_0,
+ .SPV_KHR_post_depth_coverage,
+ },
+ .storage_buffer8bit_access => &.{
+ .v1_5,
+ .SPV_KHR_8bit_storage,
+ },
+ .uniform_and_storage_buffer8bit_access => &.{
+ .v1_5,
+ .SPV_KHR_8bit_storage,
+ },
+ .storage_push_constant8 => &.{
+ .v1_5,
+ .SPV_KHR_8bit_storage,
+ },
+ .denorm_preserve => &.{
+ .v1_4,
+ .SPV_KHR_float_controls,
+ },
+ .denorm_flush_to_zero => &.{
+ .v1_4,
+ .SPV_KHR_float_controls,
+ },
+ .signed_zero_inf_nan_preserve => &.{
+ .v1_4,
+ .SPV_KHR_float_controls,
+ },
+ .ray_query_provisional_khr => &.{
+ .v1_0,
+ .SPV_KHR_ray_query,
+ },
+ .ray_query_khr => &.{
+ .v1_0,
+ .SPV_KHR_ray_query,
+ },
+ .untyped_pointers_khr => &.{
+ .v1_0,
+ .SPV_KHR_untyped_pointers,
+ },
+ .ray_traversal_primitive_culling_khr => &.{
+ .v1_0,
+ .SPV_KHR_ray_query,
+ .SPV_KHR_ray_tracing,
+ },
+ .ray_tracing_khr => &.{
+ .v1_0,
+ .SPV_KHR_ray_tracing,
+ },
+ .stencil_export_ext => &.{
+ .v1_0,
+ .SPV_EXT_shader_stencil_export,
+ },
+ .int64image_ext => &.{
+ .v1_0,
+ .SPV_EXT_shader_image_int64,
+ },
+ .shader_clock_khr => &.{
+ .v1_0,
+ .SPV_KHR_shader_clock,
+ },
+ .quad_control_khr => &.{
+ .v1_0,
+ .SPV_KHR_quad_control,
+ },
+ .b_float16type_khr => &.{
+ .v1_0,
+ .SPV_KHR_bfloat16,
+ },
+ .b_float16dot_product_khr => &.{
+ .v1_0,
+ .SPV_KHR_bfloat16,
+ },
+ .b_float16cooperative_matrix_khr => &.{
+ .v1_0,
+ .SPV_KHR_bfloat16,
+ },
+ .abort_khr => &.{
+ .v1_0,
+ .SPV_KHR_abort,
+ },
+ .descriptor_heap_ext => &.{
+ .v1_0,
+ .SPV_EXT_descriptor_heap,
+ },
+ .constant_data_khr => &.{
+ .v1_0,
+ .SPV_KHR_constant_data,
+ },
+ .poison_freeze_khr => &.{
+ .v1_0,
+ .SPV_KHR_poison_freeze,
+ },
+ .shader_viewport_index_layer_ext => &.{
+ .v1_0,
+ .SPV_EXT_shader_viewport_index_layer,
+ },
+ .fragment_fully_covered_ext => &.{
+ .v1_0,
+ .SPV_EXT_fragment_fully_covered,
+ },
+ .mesh_shading_ext => &.{
+ .v1_0,
+ .SPV_EXT_mesh_shader,
+ },
+ .fragment_barycentric_khr => &.{
+ .v1_0,
+ .SPV_KHR_fragment_shader_barycentric,
+ },
+ .compute_derivative_group_quads_khr => &.{
+ .v1_0,
+ .SPV_KHR_compute_shader_derivatives,
+ },
+ .fragment_density_ext => &.{
+ .v1_0,
+ .SPV_EXT_fragment_invocation_density,
+ },
+ .group_non_uniform_partitioned_ext => &.{
+ .v1_0,
+ .SPV_EXT_shader_subgroup_partitioned,
+ },
+ .shader_non_uniform => &.{
+ .v1_5,
+ .SPV_EXT_descriptor_indexing,
+ },
+ .runtime_descriptor_array => &.{
+ .v1_5,
+ .SPV_EXT_descriptor_indexing,
+ },
+ .input_attachment_array_dynamic_indexing => &.{
+ .v1_5,
+ .SPV_EXT_descriptor_indexing,
+ },
+ .uniform_texel_buffer_array_dynamic_indexing => &.{
+ .v1_5,
+ .SPV_EXT_descriptor_indexing,
+ },
+ .storage_texel_buffer_array_dynamic_indexing => &.{
+ .v1_5,
+ .SPV_EXT_descriptor_indexing,
+ },
+ .uniform_buffer_array_non_uniform_indexing => &.{
+ .v1_5,
+ .SPV_EXT_descriptor_indexing,
+ },
+ .sampled_image_array_non_uniform_indexing => &.{
+ .v1_5,
+ .SPV_EXT_descriptor_indexing,
+ },
+ .storage_buffer_array_non_uniform_indexing => &.{
+ .v1_5,
+ .SPV_EXT_descriptor_indexing,
+ },
+ .storage_image_array_non_uniform_indexing => &.{
+ .v1_5,
+ .SPV_EXT_descriptor_indexing,
+ },
+ .input_attachment_array_non_uniform_indexing => &.{
+ .v1_5,
+ .SPV_EXT_descriptor_indexing,
+ },
+ .uniform_texel_buffer_array_non_uniform_indexing => &.{
+ .v1_5,
+ .SPV_EXT_descriptor_indexing,
+ },
+ .storage_texel_buffer_array_non_uniform_indexing => &.{
+ .v1_5,
+ .SPV_EXT_descriptor_indexing,
+ },
+ .ray_tracing_position_fetch_khr => &.{
+ .v1_0,
+ .SPV_KHR_ray_tracing_position_fetch,
+ },
+ .vulkan_memory_model => &.{
+ .v1_5,
+ .SPV_KHR_vulkan_memory_model,
+ },
+ .vulkan_memory_model_device_scope => &.{
+ .v1_5,
+ .SPV_KHR_vulkan_memory_model,
+ },
+ .physical_storage_buffer_addresses => &.{
+ .v1_5,
+ .SPV_EXT_physical_storage_buffer,
+ .SPV_KHR_physical_storage_buffer,
+ },
+ .compute_derivative_group_linear_khr => &.{
+ .v1_0,
+ .SPV_KHR_compute_shader_derivatives,
+ },
+ .ray_tracing_provisional_khr => &.{
+ .v1_0,
+ .SPV_KHR_ray_tracing,
+ },
+ .fragment_shader_sample_interlock_ext => &.{
+ .v1_0,
+ .SPV_EXT_fragment_shader_interlock,
+ },
+ .fragment_shader_shading_rate_interlock_ext => &.{
+ .v1_0,
+ .SPV_EXT_fragment_shader_interlock,
+ },
+ .fragment_shader_pixel_interlock_ext => &.{
+ .v1_0,
+ .SPV_EXT_fragment_shader_interlock,
+ },
+ .demote_to_helper_invocation => &.{
+ .v1_6,
+ .SPV_EXT_demote_to_helper_invocation,
+ },
+ .ray_tracing_opacity_micromap_ext => &.{
+ .v1_0,
+ .SPV_EXT_opacity_micromap,
+ },
+ .shader_invocation_reorder_ext => &.{
+ .v1_0,
+ .SPV_EXT_shader_invocation_reorder,
+ },
+ .ray_query_position_fetch_khr => &.{
+ .v1_0,
+ .SPV_KHR_ray_tracing_position_fetch,
+ },
+ .long_vector_ext => &.{
+ .v1_0,
+ .SPV_EXT_long_vector,
+ },
+ .shader64bit_indexing_ext => &.{
+ .v1_0,
+ .SPV_EXT_shader_64bit_indexing,
+ },
+ .atomic_float32min_max_ext => &.{
+ .v1_0,
+ .SPV_EXT_shader_atomic_float_min_max,
+ },
+ .atomic_float64min_max_ext => &.{
+ .v1_0,
+ .SPV_EXT_shader_atomic_float_min_max,
+ },
+ .atomic_float16min_max_ext => &.{
+ .v1_0,
+ .SPV_EXT_shader_atomic_float_min_max,
+ },
+ .expect_assume_khr => &.{
+ .v1_0,
+ .SPV_KHR_expect_assume,
+ },
+ .dot_product_input_all => &.{
+ .v1_6,
+ .SPV_KHR_integer_dot_product,
+ },
+ .dot_product_input4x8bit => &.{
+ .v1_6,
+ .SPV_KHR_integer_dot_product,
+ },
+ .dot_product_input4x8bit_packed => &.{
+ .v1_6,
+ .SPV_KHR_integer_dot_product,
+ },
+ .dot_product => &.{
+ .v1_6,
+ .SPV_KHR_integer_dot_product,
+ },
+ .ray_cull_mask_khr => &.{
+ .v1_0,
+ .SPV_KHR_ray_cull_mask,
+ },
+ .cooperative_matrix_khr => &.{
+ .v1_0,
+ .SPV_KHR_cooperative_matrix,
+ },
+ .replicated_composites_ext => &.{
+ .v1_0,
+ .SPV_EXT_replicated_composites,
+ },
+ .bit_instructions => &.{
+ .v1_0,
+ .SPV_KHR_bit_instructions,
+ },
+ .group_non_uniform_rotate_khr => &.{
+ .v1_0,
+ .SPV_KHR_subgroup_rotate,
+ },
+ .float_controls2 => &.{
+ .v1_0,
+ .SPV_KHR_float_controls2,
+ },
+ .fmakhr => &.{
+ .v1_0,
+ .SPV_KHR_fma,
+ },
+ .atomic_float32add_ext => &.{
+ .v1_0,
+ .SPV_EXT_shader_atomic_float_add,
+ },
+ .atomic_float64add_ext => &.{
+ .v1_0,
+ .SPV_EXT_shader_atomic_float_add,
+ },
+ .opt_none_ext => &.{
+ .v1_0,
+ .SPV_EXT_optnone,
+ },
+ .atomic_float16add_ext => &.{
+ .v1_0,
+ .SPV_EXT_shader_atomic_float16_add,
+ },
+ .arithmetic_fence_ext => &.{
+ .v1_0,
+ .SPV_EXT_arithmetic_fence,
+ },
+ .group_uniform_arithmetic_khr => &.{
+ .v1_0,
+ .SPV_KHR_uniform_group_instructions,
+ },
+ };
+ }
};
pub const RayQueryIntersection = enum(u32) {
ray_query_candidate_intersection_khr = 0,
@@ -5391,8 +6119,8 @@ pub const TensorAddressingOperands = packed struct {
};
};
pub const InitializationModeQualifier = enum(u32) {
- init_on_device_reprogram_intel = 0,
- init_on_device_reset_intel = 1,
+ init_on_device_reprogram_altera = 0,
+ init_on_device_reset_altera = 1,
};
pub const LoadCacheControl = enum(u32) {
uncached_intel = 0,
@@ -5543,8 +6271,8 @@ pub const TensorOperands = packed struct {
};
pub const InstructionSet = enum {
core,
- @"GLSL.std.450",
@"OpenCL.std",
+ @"GLSL.std.450",
zig,
pub fn instructions(self: InstructionSet) []const Instruction {
@@ -9178,6 +9906,17 @@ pub const InstructionSet = enum {
.{ .kind = .id_ref, .quantifier = .optional },
},
},
+ .{
+ .name = "OpFmaKHR",
+ .opcode = 4427,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
.{
.name = "OpSubgroupAllKHR",
.opcode = 4428,
@@ -9238,6 +9977,23 @@ pub const InstructionSet = enum {
.{ .kind = .id_ref, .quantifier = .variadic },
},
},
+ .{
+ .name = "OpUntypedGroupAsyncCopyKHR",
+ .opcode = 4434,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .memory_access, .quantifier = .optional },
+ .{ .kind = .memory_access, .quantifier = .optional },
+ },
+ },
.{
.name = "OpTraceRayKHR",
.opcode = 4445,
@@ -9544,6 +10300,15 @@ pub const InstructionSet = enum {
.{ .kind = .id_ref, .quantifier = .required },
},
},
+ .{
+ .name = "OpBitCastArrayQCOM",
+ .opcode = 4497,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
.{
.name = "OpImageBlockMatchWindowSSDQCOM",
.opcode = 4500,
@@ -9596,6 +10361,34 @@ pub const InstructionSet = enum {
.{ .kind = .id_ref, .quantifier = .required },
},
},
+ .{
+ .name = "OpCompositeConstructCoopMatQCOM",
+ .opcode = 4540,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpCompositeExtractCoopMatQCOM",
+ .opcode = 4541,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpExtractSubArrayQCOM",
+ .opcode = 4542,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
.{
.name = "OpGroupIAddNonUniformAMD",
.opcode = 5000,
@@ -9802,6 +10595,96 @@ pub const InstructionSet = enum {
.{ .kind = .id_ref, .quantifier = .required },
},
},
+ .{
+ .name = "OpTypeBufferEXT",
+ .opcode = 5115,
+ .operands = &.{
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .storage_class, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpBufferPointerEXT",
+ .opcode = 5119,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpAbortKHR",
+ .opcode = 5121,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpUntypedImageTexelPointerEXT",
+ .opcode = 5126,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpMemberDecorateIdEXT",
+ .opcode = 5127,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .literal_integer, .quantifier = .required },
+ .{ .kind = .decoration, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpConstantSizeOfEXT",
+ .opcode = 5129,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpConstantDataKHR",
+ .opcode = 5147,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .literal_integer, .quantifier = .variadic },
+ },
+ },
+ .{
+ .name = "OpSpecConstantDataKHR",
+ .opcode = 5148,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .literal_integer, .quantifier = .variadic },
+ },
+ },
+ .{
+ .name = "OpPoisonKHR",
+ .opcode = 5158,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpFreezeKHR",
+ .opcode = 5159,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
.{
.name = "OpHitObjectRecordHitMotionNV",
.opcode = 5249,
@@ -10172,7 +11055,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpTypeCooperativeVectorNV",
+ .name = "OpTypeVectorIdEXT",
.opcode = 5288,
.operands = &.{
.{ .kind = .id_result, .quantifier = .required },
@@ -10271,7 +11154,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpGroupNonUniformPartitionNV",
+ .name = "OpGroupNonUniformPartitionEXT",
.opcode = 5296,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -10334,6 +11217,321 @@ pub const InstructionSet = enum {
.{ .kind = .memory_access, .quantifier = .optional },
},
},
+ .{
+ .name = "OpHitObjectRecordFromQueryEXT",
+ .opcode = 5304,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectRecordMissEXT",
+ .opcode = 5305,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectRecordMissMotionEXT",
+ .opcode = 5306,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetIntersectionTriangleVertexPositionsEXT",
+ .opcode = 5307,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetRayFlagsEXT",
+ .opcode = 5308,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectSetShaderBindingTableRecordIndexEXT",
+ .opcode = 5309,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectReorderExecuteShaderEXT",
+ .opcode = 5310,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .optional },
+ .{ .kind = .id_ref, .quantifier = .optional },
+ },
+ },
+ .{
+ .name = "OpHitObjectTraceReorderExecuteEXT",
+ .opcode = 5311,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .optional },
+ .{ .kind = .id_ref, .quantifier = .optional },
+ },
+ },
+ .{
+ .name = "OpHitObjectTraceMotionReorderExecuteEXT",
+ .opcode = 5312,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .optional },
+ .{ .kind = .id_ref, .quantifier = .optional },
+ },
+ },
+ .{
+ .name = "OpTypeHitObjectEXT",
+ .opcode = 5313,
+ .operands = &.{
+ .{ .kind = .id_result, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpReorderThreadWithHintEXT",
+ .opcode = 5314,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpReorderThreadWithHitObjectEXT",
+ .opcode = 5315,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .optional },
+ .{ .kind = .id_ref, .quantifier = .optional },
+ },
+ },
+ .{
+ .name = "OpHitObjectTraceRayEXT",
+ .opcode = 5316,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectTraceRayMotionEXT",
+ .opcode = 5317,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectRecordEmptyEXT",
+ .opcode = 5318,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectExecuteShaderEXT",
+ .opcode = 5319,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetCurrentTimeEXT",
+ .opcode = 5320,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetAttributesEXT",
+ .opcode = 5321,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetHitKindEXT",
+ .opcode = 5322,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetPrimitiveIndexEXT",
+ .opcode = 5323,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetGeometryIndexEXT",
+ .opcode = 5324,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetInstanceIdEXT",
+ .opcode = 5325,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetInstanceCustomIndexEXT",
+ .opcode = 5326,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetObjectRayOriginEXT",
+ .opcode = 5327,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetObjectRayDirectionEXT",
+ .opcode = 5328,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetWorldRayDirectionEXT",
+ .opcode = 5329,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetWorldRayOriginEXT",
+ .opcode = 5330,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetObjectToWorldEXT",
+ .opcode = 5331,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetWorldToObjectEXT",
+ .opcode = 5332,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetRayTMaxEXT",
+ .opcode = 5333,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
.{
.name = "OpReportIntersectionKHR",
.opcode = 5334,
@@ -10433,7 +11631,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpRayQueryGetClusterIdNV",
+ .name = "OpRayQueryGetIntersectionClusterIdNV",
.opcode = 5345,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -10451,6 +11649,60 @@ pub const InstructionSet = enum {
.{ .kind = .id_ref, .quantifier = .required },
},
},
+ .{
+ .name = "OpHitObjectGetRayTMinEXT",
+ .opcode = 5347,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetShaderBindingTableRecordIndexEXT",
+ .opcode = 5348,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectGetShaderRecordBufferHandleEXT",
+ .opcode = 5349,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectIsEmptyEXT",
+ .opcode = 5350,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectIsHitEXT",
+ .opcode = 5351,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpHitObjectIsMissEXT",
+ .opcode = 5352,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
.{
.name = "OpTypeCooperativeMatrixNV",
.opcode = 5358,
@@ -12432,7 +13684,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatSinCosPiINTEL",
+ .name = "OpArbitraryFloatSinCosPiALTERA",
.opcode = 5840,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12446,7 +13698,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatCastINTEL",
+ .name = "OpArbitraryFloatCastALTERA",
.opcode = 5841,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12460,7 +13712,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatCastFromIntINTEL",
+ .name = "OpArbitraryFloatCastFromIntALTERA",
.opcode = 5842,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12474,7 +13726,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatCastToIntINTEL",
+ .name = "OpArbitraryFloatCastToIntALTERA",
.opcode = 5843,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12488,7 +13740,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatAddINTEL",
+ .name = "OpArbitraryFloatAddALTERA",
.opcode = 5846,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12504,7 +13756,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatSubINTEL",
+ .name = "OpArbitraryFloatSubALTERA",
.opcode = 5847,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12520,7 +13772,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatMulINTEL",
+ .name = "OpArbitraryFloatMulALTERA",
.opcode = 5848,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12536,7 +13788,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatDivINTEL",
+ .name = "OpArbitraryFloatDivALTERA",
.opcode = 5849,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12552,7 +13804,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatGTINTEL",
+ .name = "OpArbitraryFloatGTALTERA",
.opcode = 5850,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12564,7 +13816,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatGEINTEL",
+ .name = "OpArbitraryFloatGEALTERA",
.opcode = 5851,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12576,7 +13828,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatLTINTEL",
+ .name = "OpArbitraryFloatLTALTERA",
.opcode = 5852,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12588,7 +13840,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatLEINTEL",
+ .name = "OpArbitraryFloatLEALTERA",
.opcode = 5853,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12600,7 +13852,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatEQINTEL",
+ .name = "OpArbitraryFloatEQALTERA",
.opcode = 5854,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12612,7 +13864,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatRecipINTEL",
+ .name = "OpArbitraryFloatRecipALTERA",
.opcode = 5855,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12626,7 +13878,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatRSqrtINTEL",
+ .name = "OpArbitraryFloatRSqrtALTERA",
.opcode = 5856,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12640,7 +13892,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatCbrtINTEL",
+ .name = "OpArbitraryFloatCbrtALTERA",
.opcode = 5857,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12654,7 +13906,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatHypotINTEL",
+ .name = "OpArbitraryFloatHypotALTERA",
.opcode = 5858,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -12670,7 +13922,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpArbitraryFloatSqrtINTEL",
+ .name = "OpArbitraryFloatSqrtALTERA",
.opcode = 5859,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13046,7 +14298,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpFixedSqrtINTEL",
+ .name = "OpFixedSqrtALTERA",
.opcode = 5923,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13060,7 +14312,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpFixedRecipINTEL",
+ .name = "OpFixedRecipALTERA",
.opcode = 5924,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13074,7 +14326,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpFixedRsqrtINTEL",
+ .name = "OpFixedRsqrtALTERA",
.opcode = 5925,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13088,7 +14340,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpFixedSinINTEL",
+ .name = "OpFixedSinALTERA",
.opcode = 5926,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13102,7 +14354,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpFixedCosINTEL",
+ .name = "OpFixedCosALTERA",
.opcode = 5927,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13116,7 +14368,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpFixedSinCosINTEL",
+ .name = "OpFixedSinCosALTERA",
.opcode = 5928,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13130,7 +14382,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpFixedSinPiINTEL",
+ .name = "OpFixedSinPiALTERA",
.opcode = 5929,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13144,7 +14396,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpFixedCosPiINTEL",
+ .name = "OpFixedCosPiALTERA",
.opcode = 5930,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13158,7 +14410,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpFixedSinCosPiINTEL",
+ .name = "OpFixedSinCosPiALTERA",
.opcode = 5931,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13172,7 +14424,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpFixedLogINTEL",
+ .name = "OpFixedLogALTERA",
.opcode = 5932,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13186,7 +14438,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpFixedExpINTEL",
+ .name = "OpFixedExpALTERA",
.opcode = 5933,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13200,7 +14452,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpPtrCastToCrossWorkgroupINTEL",
+ .name = "OpPtrCastToCrossWorkgroupALTERA",
.opcode = 5934,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13209,7 +14461,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpCrossWorkgroupCastToPtrINTEL",
+ .name = "OpCrossWorkgroupCastToPtrALTERA",
.opcode = 5938,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13218,7 +14470,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpReadPipeBlockingINTEL",
+ .name = "OpReadPipeBlockingALTERA",
.opcode = 5946,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13228,7 +14480,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpWritePipeBlockingINTEL",
+ .name = "OpWritePipeBlockingALTERA",
.opcode = 5947,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13238,7 +14490,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpFPGARegINTEL",
+ .name = "OpFPGARegALTERA",
.opcode = 5949,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13507,7 +14759,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpTaskSequenceCreateINTEL",
+ .name = "OpTaskSequenceCreateALTERA",
.opcode = 6163,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13520,7 +14772,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpTaskSequenceAsyncINTEL",
+ .name = "OpTaskSequenceAsyncALTERA",
.opcode = 6164,
.operands = &.{
.{ .kind = .id_ref, .quantifier = .required },
@@ -13528,7 +14780,7 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpTaskSequenceGetINTEL",
+ .name = "OpTaskSequenceGetALTERA",
.opcode = 6165,
.operands = &.{
.{ .kind = .id_result_type, .quantifier = .required },
@@ -13537,14 +14789,14 @@ pub const InstructionSet = enum {
},
},
.{
- .name = "OpTaskSequenceReleaseINTEL",
+ .name = "OpTaskSequenceReleaseALTERA",
.opcode = 6166,
.operands = &.{
.{ .kind = .id_ref, .quantifier = .required },
},
},
.{
- .name = "OpTypeTaskSequenceINTEL",
+ .name = "OpTypeTaskSequenceALTERA",
.opcode = 6199,
.operands = &.{
.{ .kind = .id_result, .quantifier = .required },
@@ -13663,6 +14915,83 @@ pub const InstructionSet = enum {
.{ .kind = .id_ref, .quantifier = .required },
},
},
+ .{
+ .name = "OpUntypedVariableLengthArrayINTEL",
+ .opcode = 6244,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpConditionalExtensionINTEL",
+ .opcode = 6248,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .literal_string, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpConditionalEntryPointINTEL",
+ .opcode = 6249,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .execution_model, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .literal_string, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .variadic },
+ },
+ },
+ .{
+ .name = "OpConditionalCapabilityINTEL",
+ .opcode = 6250,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .capability, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpSpecConstantTargetINTEL",
+ .opcode = 6251,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .literal_integer, .quantifier = .required },
+ .{ .kind = .literal_integer, .quantifier = .variadic },
+ },
+ },
+ .{
+ .name = "OpSpecConstantArchitectureINTEL",
+ .opcode = 6252,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .literal_integer, .quantifier = .required },
+ .{ .kind = .literal_integer, .quantifier = .required },
+ .{ .kind = .literal_integer, .quantifier = .required },
+ .{ .kind = .literal_integer, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "OpSpecConstantCapabilitiesINTEL",
+ .opcode = 6253,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .capability, .quantifier = .variadic },
+ },
+ },
+ .{
+ .name = "OpConditionalCopyObjectINTEL",
+ .opcode = 6254,
+ .operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .variadic },
+ },
+ },
.{
.name = "OpGroupIMulKHR",
.opcode = 6401,
@@ -13809,609 +15138,34 @@ pub const InstructionSet = enum {
.{ .kind = .id_ref, .quantifier = .required },
},
},
- },
- .@"GLSL.std.450" => &.{
.{
- .name = "Round",
- .opcode = 1,
+ .name = "OpFDot2MixAcc32VALVE",
+ .opcode = 6916,
.operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
.{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "RoundEven",
- .opcode = 2,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Trunc",
- .opcode = 3,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "FAbs",
- .opcode = 4,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "SAbs",
- .opcode = 5,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "FSign",
- .opcode = 6,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "SSign",
- .opcode = 7,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Floor",
- .opcode = 8,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Ceil",
- .opcode = 9,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Fract",
- .opcode = 10,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Radians",
- .opcode = 11,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Degrees",
- .opcode = 12,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Sin",
- .opcode = 13,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Cos",
- .opcode = 14,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Tan",
- .opcode = 15,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Asin",
- .opcode = 16,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Acos",
- .opcode = 17,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Atan",
- .opcode = 18,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Sinh",
- .opcode = 19,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Cosh",
- .opcode = 20,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Tanh",
- .opcode = 21,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Asinh",
- .opcode = 22,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Acosh",
- .opcode = 23,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Atanh",
- .opcode = 24,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Atan2",
- .opcode = 25,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Pow",
- .opcode = 26,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Exp",
- .opcode = 27,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Log",
- .opcode = 28,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Exp2",
- .opcode = 29,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Log2",
- .opcode = 30,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Sqrt",
- .opcode = 31,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "InverseSqrt",
- .opcode = 32,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Determinant",
- .opcode = 33,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "MatrixInverse",
- .opcode = 34,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Modf",
- .opcode = 35,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "ModfStruct",
- .opcode = 36,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "FMin",
- .opcode = 37,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "UMin",
- .opcode = 38,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "SMin",
- .opcode = 39,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "FMax",
- .opcode = 40,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "UMax",
- .opcode = 41,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "SMax",
- .opcode = 42,
- .operands = &.{
.{ .kind = .id_ref, .quantifier = .required },
.{ .kind = .id_ref, .quantifier = .required },
},
},
.{
- .name = "FClamp",
- .opcode = 43,
+ .name = "OpFDot2MixAcc16VALVE",
+ .opcode = 6917,
.operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
.{ .kind = .id_ref, .quantifier = .required },
.{ .kind = .id_ref, .quantifier = .required },
.{ .kind = .id_ref, .quantifier = .required },
},
},
.{
- .name = "UClamp",
- .opcode = 44,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "SClamp",
- .opcode = 45,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "FMix",
- .opcode = 46,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "IMix",
- .opcode = 47,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Step",
- .opcode = 48,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "SmoothStep",
- .opcode = 49,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Fma",
- .opcode = 50,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Frexp",
- .opcode = 51,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "FrexpStruct",
- .opcode = 52,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Ldexp",
- .opcode = 53,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "PackSnorm4x8",
- .opcode = 54,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "PackUnorm4x8",
- .opcode = 55,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "PackSnorm2x16",
- .opcode = 56,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "PackUnorm2x16",
- .opcode = 57,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "PackHalf2x16",
- .opcode = 58,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "PackDouble2x32",
- .opcode = 59,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "UnpackSnorm2x16",
- .opcode = 60,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "UnpackUnorm2x16",
- .opcode = 61,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "UnpackHalf2x16",
- .opcode = 62,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "UnpackSnorm4x8",
- .opcode = 63,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "UnpackUnorm4x8",
- .opcode = 64,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "UnpackDouble2x32",
- .opcode = 65,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Length",
- .opcode = 66,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Distance",
- .opcode = 67,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Cross",
- .opcode = 68,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Normalize",
- .opcode = 69,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "FaceForward",
- .opcode = 70,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Reflect",
- .opcode = 71,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "Refract",
- .opcode = 72,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "FindILsb",
- .opcode = 73,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "FindSMsb",
- .opcode = 74,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "FindUMsb",
- .opcode = 75,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "InterpolateAtCentroid",
- .opcode = 76,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "InterpolateAtSample",
- .opcode = 77,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "InterpolateAtOffset",
- .opcode = 78,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "NMin",
- .opcode = 79,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "NMax",
- .opcode = 80,
- .operands = &.{
- .{ .kind = .id_ref, .quantifier = .required },
- .{ .kind = .id_ref, .quantifier = .required },
- },
- },
- .{
- .name = "NClamp",
- .opcode = 81,
+ .name = "OpFDot4MixAcc32VALVE",
+ .opcode = 6918,
.operands = &.{
+ .{ .kind = .id_result_type, .quantifier = .required },
+ .{ .kind = .id_result, .quantifier = .required },
.{ .kind = .id_ref, .quantifier = .required },
.{ .kind = .id_ref, .quantifier = .required },
.{ .kind = .id_ref, .quantifier = .required },
@@ -15668,6 +16422,614 @@ pub const InstructionSet = enum {
},
},
},
+ .@"GLSL.std.450" => &.{
+ .{
+ .name = "Round",
+ .opcode = 1,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "RoundEven",
+ .opcode = 2,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Trunc",
+ .opcode = 3,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "FAbs",
+ .opcode = 4,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "SAbs",
+ .opcode = 5,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "FSign",
+ .opcode = 6,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "SSign",
+ .opcode = 7,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Floor",
+ .opcode = 8,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Ceil",
+ .opcode = 9,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Fract",
+ .opcode = 10,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Radians",
+ .opcode = 11,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Degrees",
+ .opcode = 12,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Sin",
+ .opcode = 13,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Cos",
+ .opcode = 14,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Tan",
+ .opcode = 15,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Asin",
+ .opcode = 16,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Acos",
+ .opcode = 17,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Atan",
+ .opcode = 18,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Sinh",
+ .opcode = 19,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Cosh",
+ .opcode = 20,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Tanh",
+ .opcode = 21,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Asinh",
+ .opcode = 22,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Acosh",
+ .opcode = 23,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Atanh",
+ .opcode = 24,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Atan2",
+ .opcode = 25,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Pow",
+ .opcode = 26,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Exp",
+ .opcode = 27,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Log",
+ .opcode = 28,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Exp2",
+ .opcode = 29,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Log2",
+ .opcode = 30,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Sqrt",
+ .opcode = 31,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "InverseSqrt",
+ .opcode = 32,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Determinant",
+ .opcode = 33,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "MatrixInverse",
+ .opcode = 34,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Modf",
+ .opcode = 35,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "ModfStruct",
+ .opcode = 36,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "FMin",
+ .opcode = 37,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "UMin",
+ .opcode = 38,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "SMin",
+ .opcode = 39,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "FMax",
+ .opcode = 40,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "UMax",
+ .opcode = 41,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "SMax",
+ .opcode = 42,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "FClamp",
+ .opcode = 43,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "UClamp",
+ .opcode = 44,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "SClamp",
+ .opcode = 45,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "FMix",
+ .opcode = 46,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "IMix",
+ .opcode = 47,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Step",
+ .opcode = 48,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "SmoothStep",
+ .opcode = 49,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Fma",
+ .opcode = 50,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Frexp",
+ .opcode = 51,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "FrexpStruct",
+ .opcode = 52,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Ldexp",
+ .opcode = 53,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "PackSnorm4x8",
+ .opcode = 54,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "PackUnorm4x8",
+ .opcode = 55,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "PackSnorm2x16",
+ .opcode = 56,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "PackUnorm2x16",
+ .opcode = 57,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "PackHalf2x16",
+ .opcode = 58,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "PackDouble2x32",
+ .opcode = 59,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "UnpackSnorm2x16",
+ .opcode = 60,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "UnpackUnorm2x16",
+ .opcode = 61,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "UnpackHalf2x16",
+ .opcode = 62,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "UnpackSnorm4x8",
+ .opcode = 63,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "UnpackUnorm4x8",
+ .opcode = 64,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "UnpackDouble2x32",
+ .opcode = 65,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Length",
+ .opcode = 66,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Distance",
+ .opcode = 67,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Cross",
+ .opcode = 68,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Normalize",
+ .opcode = 69,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "FaceForward",
+ .opcode = 70,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Reflect",
+ .opcode = 71,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "Refract",
+ .opcode = 72,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "FindILsb",
+ .opcode = 73,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "FindSMsb",
+ .opcode = 74,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "FindUMsb",
+ .opcode = 75,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "InterpolateAtCentroid",
+ .opcode = 76,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "InterpolateAtSample",
+ .opcode = 77,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "InterpolateAtOffset",
+ .opcode = 78,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "NMin",
+ .opcode = 79,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "NMax",
+ .opcode = 80,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ .{
+ .name = "NClamp",
+ .opcode = 81,
+ .operands = &.{
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ .{ .kind = .id_ref, .quantifier = .required },
+ },
+ },
+ },
.zig => &.{
.{
.name = "InvocationGlobal",
@@ -15680,3 +17042,72 @@ pub const InstructionSet = enum {
};
}
};
+pub const Extension = enum {
+ v1_0,
+ v1_1,
+ v1_2,
+ v1_3,
+ v1_4,
+ v1_5,
+ v1_6,
+ SPV_EXT_shader_tile_image,
+ SPV_EXT_float8,
+ SPV_KHR_fragment_shading_rate,
+ SPV_KHR_shader_ballot,
+ SPV_KHR_shader_draw_parameters,
+ SPV_KHR_workgroup_memory_explicit_layout,
+ SPV_KHR_subgroup_vote,
+ SPV_KHR_16bit_storage,
+ SPV_KHR_device_group,
+ SPV_KHR_multiview,
+ SPV_KHR_variable_pointers,
+ SPV_KHR_shader_atomic_counter_ops,
+ SPV_KHR_post_depth_coverage,
+ SPV_KHR_8bit_storage,
+ SPV_KHR_float_controls,
+ SPV_KHR_ray_query,
+ SPV_KHR_untyped_pointers,
+ SPV_KHR_ray_tracing,
+ SPV_EXT_shader_stencil_export,
+ SPV_EXT_shader_image_int64,
+ SPV_KHR_shader_clock,
+ SPV_KHR_quad_control,
+ SPV_KHR_bfloat16,
+ SPV_KHR_abort,
+ SPV_EXT_descriptor_heap,
+ SPV_KHR_constant_data,
+ SPV_KHR_poison_freeze,
+ SPV_EXT_shader_viewport_index_layer,
+ SPV_EXT_fragment_fully_covered,
+ SPV_EXT_mesh_shader,
+ SPV_KHR_fragment_shader_barycentric,
+ SPV_KHR_compute_shader_derivatives,
+ SPV_EXT_fragment_invocation_density,
+ SPV_EXT_shader_subgroup_partitioned,
+ SPV_EXT_descriptor_indexing,
+ SPV_KHR_ray_tracing_position_fetch,
+ SPV_KHR_vulkan_memory_model,
+ SPV_EXT_physical_storage_buffer,
+ SPV_KHR_physical_storage_buffer,
+ SPV_EXT_fragment_shader_interlock,
+ SPV_EXT_demote_to_helper_invocation,
+ SPV_EXT_opacity_micromap,
+ SPV_EXT_shader_invocation_reorder,
+ SPV_EXT_long_vector,
+ SPV_EXT_shader_64bit_indexing,
+ SPV_EXT_shader_atomic_float_min_max,
+ SPV_KHR_expect_assume,
+ SPV_KHR_integer_dot_product,
+ SPV_KHR_ray_cull_mask,
+ SPV_KHR_cooperative_matrix,
+ SPV_EXT_replicated_composites,
+ SPV_KHR_bit_instructions,
+ SPV_KHR_subgroup_rotate,
+ SPV_KHR_float_controls2,
+ SPV_KHR_fma,
+ SPV_EXT_shader_atomic_float_add,
+ SPV_EXT_optnone,
+ SPV_EXT_shader_atomic_float16_add,
+ SPV_EXT_arithmetic_fence,
+ SPV_KHR_uniform_group_instructions,
+};
diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig
index 11eed60c75e3d375f7008d5e6f3c81f4cb60b949..08e1f4ab30210f52fc5de80d0042ab0ae1887859 100644
--- a/src/codegen/wasm/CodeGen.zig
+++ b/src/codegen/wasm/CodeGen.zig
@@ -32,7 +32,7 @@ const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev;
pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
return comptime &.initMany(&.{
- .expand_intcast_safe,
+ .expand_int_cast_safe,
.expand_int_from_float_safe,
.expand_int_from_float_optimized_safe,
.expand_add_safe,
@@ -83,7 +83,6 @@ pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
.scalarize_shl_sat,
.scalarize_xor,
.scalarize_not,
- .scalarize_bitcast,
.scalarize_clz,
.scalarize_ctz,
.scalarize_popcount,
@@ -109,7 +108,10 @@ pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
.scalarize_cmp_vector_optimized,
.scalarize_fptrunc,
.scalarize_fpext,
- .scalarize_intcast,
+ .scalarize_int_cast,
+ .scalarize_ptr_cast,
+ .scalarize_ptr_from_int,
+ .scalarize_int_from_ptr,
.scalarize_trunc,
.scalarize_int_from_float,
.scalarize_int_from_float_optimized,
@@ -120,6 +122,8 @@ pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
.scalarize_shuffle_two,
.scalarize_select,
.scalarize_mul_add,
+
+ .scalarize_bit_cast_padded_elems,
});
}
@@ -141,7 +145,7 @@ branches: std.ArrayList(Branch) = .empty,
/// Table to save `WValue`'s generated by an `Air.Inst`
// values: ValueTable,
/// Mapping from Air.Inst.Index to block ids
-blocks: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, struct {
+blocks: std.array_hash_map.Auto(Air.Inst.Index, struct {
label: u32,
value: WValue,
}) = .{},
@@ -171,12 +175,12 @@ mir_extra: std.ArrayList(u32),
mir_locals: std.ArrayList(std.wasm.Valtype),
/// Set of all UAVs referenced by this function. Key is the UAV value, value is the alignment.
/// `.none` means naturally aligned. An explicit alignment is never less than the natural alignment.
-mir_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
+mir_uavs: std.array_hash_map.Auto(InternPool.Index, Alignment),
/// Set of all functions whose address this function has taken and which therefore might be called
/// via a `call_indirect` function.
-mir_indirect_function_set: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void),
+mir_indirect_function_set: std.array_hash_map.Auto(InternPool.Nav.Index, void),
/// Set of all function types used by this function. These must be interned by the linker.
-mir_func_tys: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
+mir_func_tys: std.array_hash_map.Auto(InternPool.Index, void),
/// The number of `error_name_table_ref` instructions emitted.
error_name_table_ref_count: u32,
/// When a function is executing, we store the the current stack pointer's value within this local.
@@ -322,7 +326,7 @@ const WValue = union(enum) {
};
/// Hashmap to store generated `WValue` for each `Air.Inst.Ref`
-const ValueTable = std.AutoArrayHashMapUnmanaged(Air.Inst.Ref, WValue);
+const ValueTable = std.array_hash_map.Auto(Air.Inst.Ref, WValue);
const bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {};
@@ -1195,6 +1199,7 @@ fn isByRef(ty: Type, zcu: *const Zcu, target: *const std.Target) bool {
.undefined,
.null,
.@"opaque",
+ .spirv,
=> unreachable,
.noreturn,
@@ -1549,9 +1554,17 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
try cg.finishAir(inst, result, &.{ty_op.operand});
},
- .bitcast => cg.airBitcast(inst),
+ .ptr_cast => cg.airNopCast(inst),
+ .error_cast => cg.airNopCast(inst),
+ .error_from_int => cg.airNopCast(inst),
+ .int_from_error => cg.airNopCast(inst),
+ .ptr_from_int => cg.airNopCast(inst),
+ .int_from_ptr => cg.airIntFromPtr(inst),
- .intcast => {
+ .bit_cast => cg.airBitcast(inst),
+ .union_from_enum => cg.airBitcast(inst),
+
+ .int_cast => {
const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const dest_ty = ty_op.ty.toType();
@@ -1559,7 +1572,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
const src_ty = cg.typeOf(ty_op.operand);
if (dest_ty.zigTypeTag(zcu) == .vector) {
- return cg.fail("TODO: implement AIR op: intcast for vectors", .{});
+ return cg.fail("TODO: implement AIR op: int_cast for vectors", .{});
}
const src_int_ty: IntType = .fromType(cg, src_ty);
@@ -1874,7 +1887,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
.add_safe,
.sub_safe,
.mul_safe,
- .intcast_safe,
+ .int_cast_safe,
.int_from_float_safe,
.int_from_float_optimized_safe,
=> return cg.fail("TODO implement safety_checked_instructions", .{}),
@@ -1882,6 +1895,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
.work_item_id,
.work_group_size,
.work_group_id,
+ .spirv_runtime_array_len,
=> unreachable,
};
}
@@ -2097,16 +2111,20 @@ fn airStore(cg: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void {
const rhs = try cg.resolveInst(bin_op.rhs);
const ptr_ty = cg.typeOf(bin_op.lhs);
const ptr_info = ptr_ty.ptrInfo(zcu);
- const ty = ptr_ty.childType(zcu);
+ const elem_ty = ptr_ty.childType(zcu);
if (!safety and bin_op.rhs == .undef) {
return cg.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
}
- assert(!(ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none)); // legalize .expand_packed_store
-
- try cg.store(lhs, rhs, ty, 0);
-
+ const offset: u32 = switch (ptr_info.flags.vector_index) {
+ .none => offset: {
+ assert(ptr_info.packed_offset.host_size == 0); // legalize .expand_packed_store
+ break :offset 0;
+ },
+ else => |index| @intCast(@intFromEnum(index) * elem_ty.abiSize(zcu)),
+ };
+ try cg.store(lhs, rhs, elem_ty, offset);
return cg.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
}
@@ -2119,7 +2137,16 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr
if (!ty.hasRuntimeBits(zcu)) return;
if (isByRef(ty, zcu, cg.target)) {
- return cg.memcpy(lhs, rhs, .{ .imm32 = @intCast(abi_size) });
+ const offset_ptr: WValue = switch (offset + lhs.offset()) {
+ 0 => lhs,
+ else => |total_offset| ptr: {
+ try cg.emitWValue(lhs);
+ try cg.addImm32(total_offset);
+ try cg.addTag(.i32_add);
+ break :ptr .stack;
+ },
+ };
+ return cg.memcpy(offset_ptr, rhs, .{ .imm32 = @intCast(abi_size) });
}
if (ty.zigTypeTag(zcu) == .vector) {
@@ -2131,7 +2158,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr
try cg.mir_extra.appendSlice(cg.gpa, &[_]u32{
@intFromEnum(std.wasm.SimdOpcode.v128_store),
offset + lhs.offset(),
- @intCast(ty.abiAlignment(zcu).toByteUnits() orelse 0),
+ @intCast(ty.abiAlignment(zcu).toByteUnits().?),
});
return cg.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
}
@@ -2172,15 +2199,20 @@ fn airLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
const zcu = pt.zcu;
const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const operand = try cg.resolveInst(ty_op.operand);
- const ty = ty_op.ty.toType();
+ const elem_ty = ty_op.ty.toType();
const ptr_ty = cg.typeOf(ty_op.operand);
const ptr_info = ptr_ty.ptrInfo(zcu);
- if (!ty.hasRuntimeBits(zcu)) return cg.finishAir(inst, .none, &.{ty_op.operand});
+ assert(elem_ty.hasRuntimeBits(zcu));
- assert(!(ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none)); // legalize .expand_packed_load
-
- const result = try cg.load(operand, ty, 0);
+ const offset: u32 = switch (ptr_info.flags.vector_index) {
+ .none => offset: {
+ assert(ptr_info.packed_offset.host_size == 0); // legalize .expand_packed_load
+ break :offset 0;
+ },
+ else => |index| @intCast(@intFromEnum(index) * elem_ty.abiSize(zcu)),
+ };
+ const result = try cg.load(operand, elem_ty, offset);
return cg.finishAir(inst, result, &.{ty_op.operand});
}
@@ -2189,9 +2221,19 @@ fn airLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
fn load(cg: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValue {
const zcu = cg.pt.zcu;
if (isByRef(ty, zcu, cg.target)) {
- const val = try cg.allocStack(ty);
- try cg.store(val, try operand.toLocal(cg, .usize), ty, 0);
- return val;
+ const src_ptr_maybe_stack: WValue = switch (offset + operand.offset()) {
+ 0 => operand,
+ else => |total_offset| ptr: {
+ try cg.emitWValue(operand);
+ try cg.addImm32(total_offset);
+ try cg.addTag(.i32_add);
+ break :ptr .stack;
+ },
+ };
+ const src_ptr = try src_ptr_maybe_stack.toLocal(cg, .usize);
+ const new_ptr = try cg.allocStack(ty);
+ try cg.store(new_ptr, src_ptr, ty, 0);
+ return new_ptr;
}
// load local's value from memory by its stack position
@@ -4698,6 +4740,7 @@ fn lowerConstant(cg: *CodeGen, val: Value) InnerError!WValue {
.tuple_type,
.union_type,
.opaque_type,
+ .spirv_type,
.enum_type,
.func_type,
.error_set_type,
@@ -5232,6 +5275,39 @@ fn airUnreachable(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
return cg.finishAir(inst, .none, &.{});
}
+fn airNopCast(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
+ const zcu = cg.pt.zcu;
+ const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
+
+ const operand_ty = cg.typeOf(ty_op.operand);
+ const dest_ty = cg.typeOfIndex(inst);
+ assert(isByRef(operand_ty, zcu, cg.target) == isByRef(dest_ty, zcu, cg.target));
+ assert(operand_ty.abiSize(zcu) == dest_ty.abiSize(zcu));
+ assert(operand_ty.abiAlignment(zcu) == dest_ty.abiAlignment(zcu));
+
+ const operand = try cg.resolveInst(ty_op.operand);
+ const result = cg.reuseOperand(ty_op.operand, operand);
+ return cg.finishAir(inst, result, &.{ty_op.operand});
+}
+
+fn airIntFromPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
+ const zcu = cg.pt.zcu;
+ const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
+
+ const operand_ty = cg.typeOf(ty_op.operand);
+ const dest_ty = cg.typeOfIndex(inst);
+ assert(isByRef(operand_ty, zcu, cg.target) == isByRef(dest_ty, zcu, cg.target));
+ assert(operand_ty.abiSize(zcu) == dest_ty.abiSize(zcu));
+ assert(operand_ty.abiAlignment(zcu) == dest_ty.abiAlignment(zcu));
+
+ const operand = try cg.resolveInst(ty_op.operand);
+ const result = switch (operand) {
+ .stack_offset => try cg.buildPointerOffset(operand, 0, .new),
+ else => cg.reuseOperand(ty_op.operand, operand),
+ };
+ return cg.finishAir(inst, result, &.{ty_op.operand});
+}
+
fn airBitcast(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const operand = try cg.resolveInst(ty_op.operand);
@@ -6337,12 +6413,11 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
}
}
- const elem_result = if (isByRef(elem_ty, zcu, cg.target))
+ const result = if (isByRef(elem_ty, zcu, cg.target))
.stack
else
try cg.load(.stack, elem_ty, 0);
-
- return cg.finishAir(inst, elem_result, &.{ bin_op.lhs, bin_op.rhs });
+ return cg.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
}
fn airSplat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
diff --git a/src/codegen/wasm/Mir.zig b/src/codegen/wasm/Mir.zig
index 662e177447cdb966b961731253c0334c53e519aa..f3b96f1c7939b4566630b8c3261cb432206d49ac 100644
--- a/src/codegen/wasm/Mir.zig
+++ b/src/codegen/wasm/Mir.zig
@@ -26,11 +26,11 @@ prologue: Prologue,
/// Not directly used by `Emit`, but the linker needs this to merge it with a global set.
/// Value is the explicit alignment if greater than natural alignment, `.none` otherwise.
-uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
+uavs: std.array_hash_map.Auto(InternPool.Index, Alignment),
/// Not directly used by `Emit`, but the linker needs this to merge it with a global set.
-indirect_function_set: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void),
+indirect_function_set: std.array_hash_map.Auto(InternPool.Nav.Index, void),
/// Not directly used by `Emit`, but the linker needs this to ensure these types are interned.
-func_tys: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
+func_tys: std.array_hash_map.Auto(InternPool.Index, void),
/// Not directly used by `Emit`, but the linker needs this to add it to its own refcount.
error_name_table_ref_count: u32,
diff --git a/src/codegen/wasm/abi.zig b/src/codegen/wasm/abi.zig
index d59047044b302fc86485237e03300efb89d7c151..7a643e8dc7a755937f096f9826e5d770c2394b42 100644
--- a/src/codegen/wasm/abi.zig
+++ b/src/codegen/wasm/abi.zig
@@ -77,6 +77,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
.null,
.@"fn",
.@"opaque",
+ .spirv,
.enum_literal,
=> unreachable,
}
diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig
index 821aaf50270149896b83619c82e1989678d98be9..71b7a5bc21fcc3c68d1ef31673306560d8f364ce 100644
--- a/src/codegen/x86_64/CodeGen.zig
+++ b/src/codegen/x86_64/CodeGen.zig
@@ -47,7 +47,6 @@ pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
.scalarize_shl,
.scalarize_shl_exact,
.scalarize_shl_sat,
- .scalarize_bitcast,
.scalarize_ctz,
.scalarize_popcount,
.scalarize_byte_swap,
@@ -58,11 +57,13 @@ pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
.scalarize_shuffle_two,
.scalarize_select,
+ .scalarize_bit_cast_padded_elems,
+
//.unsplat_shift_rhs,
- .reduce_one_elem_to_bitcast,
- .splat_one_elem_to_bitcast,
+ .reduce_one_elem_to_bit_cast,
+ .splat_one_elem_to_bit_cast,
- .expand_intcast_safe,
+ .expand_int_cast_safe,
.expand_int_from_float_safe,
.expand_int_from_float_optimized_safe,
.expand_add_safe,
@@ -140,7 +141,7 @@ register_manager: RegisterManager = .{},
scope_generation: u32 = 0,
frame_allocs: std.MultiArrayList(FrameAlloc) = .empty,
-free_frame_indices: std.AutoArrayHashMapUnmanaged(FrameIndex, void) = .empty,
+free_frame_indices: std.array_hash_map.Auto(FrameIndex, void) = .empty,
frame_locs: std.MultiArrayList(Mir.FrameLoc) = .empty,
loops: std.AutoHashMapUnmanaged(Air.Inst.Index, struct {
@@ -164,11 +165,16 @@ next_temp_index: Temp.Index = @enumFromInt(0),
temp_type: [Temp.Index.max]Type = undefined,
const MaskInfo = packed struct {
- kind: enum(u1) { sign, all },
+ kind: enum(u2) { lsb, msb, zero_extend, sign_extend },
inverted: bool = false,
scalar: Memory.Size,
};
+const ArgsInfo = struct {
+ info: packed struct { reg_index: u3, frame_off: i29 },
+ frame_index: FrameIndex,
+};
+
pub const MCValue = union(enum) {
/// No runtime bits. `void` types, empty structs, u0, enums with 1 tag, etc.
/// TODO Look into deleting this tag and using `dead` instead, since every use
@@ -199,17 +205,19 @@ pub const MCValue = union(enum) {
/// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.
register_overflow: struct { reg: Register, eflags: Condition },
/// The value is a bool vector stored in a vector register with a different scalar type.
- register_mask: struct { reg: Register, info: MaskInfo },
+ register_mask: Mask,
/// The value is in memory at a hard-coded address.
/// If the type is a pointer, it means the pointer address is stored at this memory location.
memory: u64,
/// The value is in memory at a constant offset from the address in a register.
indirect: bits.RegisterOffset,
indirect_load_frame: bits.FrameAddr,
- /// The value stored at an offset from a frame index
+ /// The value is a bool vector stored in memory with a different scalar type at the address in a register.
+ indirect_mask: Mask,
+ /// The value stored at an offset from a frame index.
/// Payload is a frame address.
load_frame: bits.FrameAddr,
- /// The address of an offset from a frame index
+ /// The address of an offset from a frame index.
/// Payload is a frame address.
lea_frame: bits.FrameAddr,
load_nav: InternPool.Nav.Index,
@@ -220,14 +228,26 @@ pub const MCValue = union(enum) {
lea_lazy_sym: link.File.LazySymbol,
load_extern_func: Mir.NullTerminatedString,
lea_extern_func: Mir.NullTerminatedString,
- /// Supports integer_per_element abi
- elementwise_args: packed struct { regs: u3, frame_off: i29, frame_index: FrameIndex },
+ /// The value is duplicated in two different registers.
+ register_tee: [4]Register,
+ /// Supports `integer_per_element` abi.
+ elementwise_gpr: ArgsInfo,
+ /// Supports `sse_per_element` abi.
+ elementwise_sse: ArgsInfo,
+ /// Supports `sse_per_xword` abi.
+ xwordwise_sse: ArgsInfo,
+ /// Supports `sse_per_yword` abi.
+ ywordwise_sse: ArgsInfo,
+ /// Supports `sse_per_zword` abi.
+ zwordwise_sse: ArgsInfo,
/// This indicates that we have already allocated a frame index for this instruction,
/// but it has not been spilled there yet in the current control flow.
/// Payload is a frame index.
reserved_frame: FrameIndex,
air_ref: Air.Inst.Ref,
+ const Mask = struct { reg: Register, info: MaskInfo };
+
fn isModifiable(mcv: MCValue) bool {
return switch (mcv) {
.none,
@@ -248,7 +268,12 @@ pub const MCValue = union(enum) {
.lea_lazy_sym,
.lea_extern_func,
.load_extern_func,
- .elementwise_args,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
.air_ref,
=> false,
@@ -258,6 +283,7 @@ pub const MCValue = union(enum) {
.register_quadruple,
.memory,
.indirect,
+ .indirect_mask,
.load_nav,
=> true,
.load_frame => |frame_addr| !frame_addr.index.isNamed(),
@@ -326,9 +352,10 @@ pub const MCValue = union(enum) {
.register_quadruple,
=> |*regs| regs,
inline .register_offset,
- .indirect,
.register_overflow,
.register_mask,
+ .indirect,
+ .indirect_mask,
=> |*pl| (&pl.reg)[0..1],
else => &.{},
};
@@ -364,12 +391,18 @@ pub const MCValue = union(enum) {
.register_offset,
.register_overflow,
.register_mask,
+ .indirect_mask,
.lea_frame,
.lea_nav,
.lea_uav,
.lea_lazy_sym,
.lea_extern_func,
- .elementwise_args,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
.air_ref,
=> unreachable, // not in memory
@@ -402,11 +435,17 @@ pub const MCValue = union(enum) {
.memory,
.indirect,
.indirect_load_frame,
+ .indirect_mask,
.load_nav,
.load_uav,
.load_lazy_sym,
.load_extern_func,
- .elementwise_args,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
.air_ref,
=> unreachable, // not dereferenceable
@@ -428,7 +467,12 @@ pub const MCValue = union(enum) {
.unreach,
.dead,
.undef,
- .elementwise_args,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
.air_ref,
=> unreachable, // not valid
@@ -441,6 +485,7 @@ pub const MCValue = union(enum) {
.memory,
.indirect,
.indirect_load_frame,
+ .indirect_mask,
.load_frame,
.load_nav,
.lea_nav,
@@ -482,7 +527,12 @@ pub const MCValue = union(enum) {
.register_mask,
.indirect_load_frame,
.lea_frame,
- .elementwise_args,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
.lea_nav,
.lea_uav,
@@ -507,6 +557,10 @@ pub const MCValue = union(enum) {
.disp = reg_off.off + mod_rm.disp,
} },
},
+ .indirect_mask => |reg_mask| .{
+ .base = .{ .reg = reg_mask.reg.toSize(.ptr, function.target) },
+ .mod = .{ .rm = mod_rm },
+ },
.load_frame => |frame_addr| .{
.base = .{ .frame = frame_addr.index },
.mod = .{ .rm = .{
@@ -528,7 +582,6 @@ pub const MCValue = union(enum) {
switch (mcv) {
.none, .unreach, .dead, .undef => try w.print("({s})", .{@tagName(mcv)}),
.immediate => |pl| try w.print("0x{x}", .{pl}),
- .memory => |pl| try w.print("[ds:0x{x}]", .{pl}),
inline .eflags, .register => |pl| try w.print("{s}", .{@tagName(pl)}),
.register_pair => |pl| try w.print("{s}:{s}", .{ @tagName(pl[1]), @tagName(pl[0]) }),
.register_triple => |pl| try w.print("{s}:{s}:{s}", .{
@@ -542,14 +595,21 @@ pub const MCValue = union(enum) {
@tagName(pl.eflags),
@tagName(pl.reg),
}),
- .register_mask => |pl| try w.print("mask({s},{f}):{c}{s}", .{
+ .register_mask => |pl| try w.print("mask({s},{f}):{s}{s}", .{
@tagName(pl.info.kind),
pl.info.scalar,
- @as(u8, if (pl.info.inverted) '!' else ' '),
+ if (pl.info.inverted) "!" else "",
@tagName(pl.reg),
}),
+ .memory => |pl| try w.print("[ds:0x{x}]", .{pl}),
.indirect => |pl| try w.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
.indirect_load_frame => |pl| try w.print("[[{f} + 0x{x}]]", .{ pl.index, pl.off }),
+ .indirect_mask => |pl| try w.print("[mask({s},{f}):{s}{s}]", .{
+ @tagName(pl.info.kind),
+ pl.info.scalar,
+ if (pl.info.inverted) "!" else "",
+ @tagName(pl.reg),
+ }),
.load_frame => |pl| try w.print("[{f} + 0x{x}]", .{ pl.index, pl.off }),
.lea_frame => |pl| try w.print("{f} + 0x{x}", .{ pl.index, pl.off }),
.load_nav => |pl| try w.print("[nav:{d}]", .{@intFromEnum(pl)}),
@@ -560,8 +620,21 @@ pub const MCValue = union(enum) {
.lea_lazy_sym => |pl| try w.print("lazy:{s}:{d}", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),
.load_extern_func => |pl| try w.print("[extern:{d}]", .{@intFromEnum(pl)}),
.lea_extern_func => |pl| try w.print("extern:{d}", .{@intFromEnum(pl)}),
- .elementwise_args => |pl| try w.print("elementwise:{d}:[{f} + 0x{x}]", .{
- pl.regs, pl.frame_index, pl.frame_off,
+ .register_tee => |pl| try w.print("tee:{s}:{s}", .{ @tagName(pl[1]), @tagName(pl[0]) }),
+ .elementwise_gpr => |pl| try w.print("elementwise:gpr{d}:[{f} + 0x{x}]", .{
+ pl.info.reg_index, pl.frame_index, pl.info.frame_off,
+ }),
+ .elementwise_sse => |pl| try w.print("elementwise:sse{d}:[{f} + 0x{x}]", .{
+ pl.info.reg_index, pl.frame_index, pl.info.frame_off,
+ }),
+ .xwordwise_sse => |pl| try w.print("xwordwise:sse{d}:[{f} + 0x{x}]", .{
+ pl.info.reg_index, pl.frame_index, pl.info.frame_off,
+ }),
+ .ywordwise_sse => |pl| try w.print("ywordwise:sse{d}:[{f} + 0x{x}]", .{
+ pl.info.reg_index, pl.frame_index, pl.info.frame_off,
+ }),
+ .zwordwise_sse => |pl| try w.print("zwordwise:sse{d}:[{f} + 0x{x}]", .{
+ pl.info.reg_index, pl.frame_index, pl.info.frame_off,
}),
.reserved_frame => |pl| try w.print("(dead:{f})", .{pl}),
.air_ref => |pl| try w.print("(air:0x{x})", .{@intFromEnum(pl)}),
@@ -569,8 +642,8 @@ pub const MCValue = union(enum) {
}
};
-const InstTrackingMap = std.AutoArrayHashMapUnmanaged(Air.Inst.Index, InstTracking);
-const ConstTrackingMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, InstTracking);
+const InstTrackingMap = std.array_hash_map.Auto(Air.Inst.Index, InstTracking);
+const ConstTrackingMap = std.array_hash_map.Auto(InternPool.Index, InstTracking);
const InstTracking = struct {
long: MCValue,
short: MCValue,
@@ -595,7 +668,12 @@ const InstTracking = struct {
.lea_extern_func,
=> result,
.dead,
- .elementwise_args,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
.air_ref,
=> unreachable,
@@ -608,6 +686,7 @@ const InstTracking = struct {
.register_overflow,
.register_mask,
.indirect,
+ .indirect_mask,
=> .none,
}, .short = result };
}
@@ -707,7 +786,13 @@ const InstTracking = struct {
.register_overflow,
.register_mask,
.indirect,
- .elementwise_args,
+ .indirect_mask,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.air_ref,
=> unreachable,
}
@@ -789,19 +874,24 @@ const InstTracking = struct {
// Disable death.
var found_reg = false;
- var remaining_reg: Register = .none;
+ var remaining_regs: [4]Register = undefined;
+ var remaining_regs_len: usize = 0;
for (tracking.getRegs()) |tracked_reg| if (tracked_reg.id() == reg.id()) {
assert(!found_reg);
found_reg = true;
} else {
- assert(remaining_reg == .none);
- remaining_reg = tracked_reg;
+ remaining_regs[remaining_regs_len] = tracked_reg;
+ remaining_regs_len += 1;
};
assert(found_reg);
if (tracking.long == .none) tracking.long = tracking.short;
- tracking.short = switch (remaining_reg) {
- .none => .{ .dead = function.scope_generation },
- else => .{ .register = remaining_reg },
+ tracking.short = switch (remaining_regs_len) {
+ 0 => .{ .dead = function.scope_generation },
+ 1 => .{ .register = remaining_regs[0] },
+ 2 => .{ .register_pair = remaining_regs[0..2].* },
+ 3 => .{ .register_triple = remaining_regs[0..3].* },
+ 4 => .{ .register_quadruple = remaining_regs[0..4].* },
+ else => unreachable,
};
// Perform side-effects of freeValue manually.
@@ -67344,7 +67434,15 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
};
try res[0].finish(inst, &.{ty_op.operand}, &ops, cg);
},
- .bitcast => try cg.airBitCast(inst),
+ .bit_cast,
+ .ptr_cast,
+ .ptr_from_int,
+ .int_from_ptr,
+ .error_cast,
+ .error_from_int,
+ .int_from_error,
+ .union_from_enum,
+ => try cg.airBitCast(inst),
.block => {
const block = cg.air.unwrapBlock(inst);
if (!cg.mod.strip) try cg.asmPseudo(.pseudo_dbg_enter_block_none);
@@ -72449,7 +72547,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -72473,7 +72571,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -72497,7 +72595,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .sse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
@@ -72525,7 +72623,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .sse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
@@ -72554,7 +72652,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
.unused,
@@ -72583,7 +72681,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
.unused,
@@ -72650,7 +72748,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -72676,7 +72774,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -72702,7 +72800,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .sse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
@@ -72732,7 +72830,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .sse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
@@ -72763,7 +72861,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
.unused,
@@ -72794,7 +72892,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
.unused,
@@ -72864,7 +72962,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -72890,7 +72988,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -72916,7 +73014,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .sse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
@@ -72946,7 +73044,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .sse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
@@ -72977,7 +73075,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
.unused,
@@ -73008,7 +73106,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
.unused,
@@ -73078,8 +73176,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .word } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .word } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -73104,8 +73202,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .word } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .word } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -73130,7 +73228,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -73156,8 +73254,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .word, .smear = 8 } } },
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .word, .smear = 8 } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .sse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
@@ -73185,8 +73283,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .word, .smear = 8 } } },
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .word, .smear = 8 } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
.unused,
@@ -73255,8 +73353,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .word } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .word } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -73282,8 +73380,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .word } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .word } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -73309,7 +73407,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -73336,8 +73434,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .word, .smear = 8 } } },
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .word, .smear = 8 } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .sse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
@@ -73367,8 +73465,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .word, .smear = 8 } } },
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .word, .smear = 8 } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
.unused,
@@ -73440,8 +73538,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .word } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .word } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -73467,8 +73565,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .word } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .word } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -73494,7 +73592,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
@@ -73522,8 +73620,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .word, .smear = 8 } } },
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .word, .smear = 8 } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .sse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
@@ -73553,8 +73651,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .word, .smear = 8 } } },
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .word, .smear = 8 } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.unused,
.unused,
@@ -73626,8 +73724,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .dword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .dword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -73652,8 +73750,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .dword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .dword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -73678,7 +73776,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -73705,8 +73803,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_32_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .dword, .smear = 8 } } },
- .{ .type = .vector_32_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_32_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .dword, .smear = 8 } } },
+ .{ .type = .vector_32_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_32_u8, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .sse } } },
.{ .type = .vector_32_u8, .kind = .{ .rc = .sse } },
.unused,
@@ -73776,8 +73874,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .dword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .dword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -73803,8 +73901,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .dword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .dword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -73830,7 +73928,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -73858,8 +73956,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_32_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .dword, .smear = 8 } } },
- .{ .type = .vector_32_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_32_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .dword, .smear = 8 } } },
+ .{ .type = .vector_32_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_32_u8, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .sse } } },
.{ .type = .vector_32_u8, .kind = .{ .rc = .sse } },
.unused,
@@ -73932,8 +74030,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .dword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .dword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -73959,8 +74057,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .dword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .dword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -73986,7 +74084,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -74014,8 +74112,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_32_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .dword, .smear = 8 } } },
- .{ .type = .vector_32_u8, .kind = .{ .bits_mem = .reverse } },
+ .{ .type = .vector_32_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .dword, .smear = 8 } } },
+ .{ .type = .vector_32_u8, .kind = .{ .bits_mem = .{ .direction = .reverse } } },
.{ .type = .vector_32_u8, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .sse } } },
.{ .type = .vector_32_u8, .kind = .{ .rc = .sse } },
.unused,
@@ -74088,8 +74186,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .qword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .qword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -74114,8 +74212,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .qword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .qword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -74140,7 +74238,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
.unused,
.unused,
.unused,
@@ -74211,7 +74309,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
.{ .type = .vector_16_u8, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .sse } } },
.unused,
.unused,
@@ -74239,7 +74337,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
.unused,
.unused,
.unused,
@@ -74313,8 +74411,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .qword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .qword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -74340,8 +74438,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .qword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .qword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -74367,7 +74465,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
.unused,
.unused,
.unused,
@@ -74441,8 +74539,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .xword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .xword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -74467,8 +74565,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .xword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .xword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -74493,8 +74591,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .xword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .xword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .vector_16_u8, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .sse } } },
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
@@ -74526,8 +74624,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .xword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .xword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.unused,
@@ -74559,8 +74657,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .xword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .xword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .vector_16_u8, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .sse } } },
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
@@ -74592,8 +74690,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .xword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .xword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .u64, .kind = .{ .rc = .general_purpose } },
.unused,
@@ -74625,8 +74723,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_32_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_32_u8, .kind = .{ .pshufb_bswap_mem = .{ .repeat = 2, .size = .xword } } },
+ .{ .type = .vector_32_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_32_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .repeat = 2, .size = .xword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -74652,8 +74750,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .none, .none } },
},
.extra_temps = .{
- .{ .type = .vector_32_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .xword } } },
+ .{ .type = .vector_32_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .xword } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
@@ -74684,8 +74782,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
- .{ .type = .vector_32_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_32_u8, .kind = .{ .pshufb_bswap_mem = .{ .repeat = 2, .size = .xword } } },
+ .{ .type = .vector_32_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_32_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .repeat = 2, .size = .xword } } },
.{ .type = .vector_32_u8, .kind = .{ .rc = .sse } },
.{ .type = .vector_32_u8, .kind = .{ .rc = .sse } },
.{ .type = .vector_32_u8, .kind = .{ .rc = .sse } },
@@ -74720,8 +74818,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.extra_temps = .{
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .isize, .kind = .{ .rc = .general_purpose } },
- .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .forward } },
- .{ .type = .vector_16_u8, .kind = .{ .pshufb_bswap_mem = .{ .size = .xword } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .reverse, .size = .xword } } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
@@ -81999,7 +82097,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_ps, .cvtph2, .dst0x, .src0q, ._, ._ },
@@ -82039,7 +82137,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_ps, .cvtph2, .dst0x, .src0q, ._, ._ },
@@ -82079,7 +82177,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_ps, .cvtph2, .dst0y, .src0x, ._, ._ },
@@ -82103,7 +82201,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_ss, .cmp, .dst0x, .src0x, .src1d, .vp(switch (cc) {
@@ -82126,7 +82224,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_ss, .cmp, .dst0x, .src0x, .src1d, .vp(switch (cc) {
@@ -82148,7 +82246,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.dst_temps = .{ .{ .ref_mask = .{
.ref = .src0,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, ._ss, .cmp, .dst0x, .src1d, .sp(switch (cc) {
@@ -82170,7 +82268,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_ps, .cmp, .dst0x, .src0x, .src1x, .vp(switch (cc) {
@@ -82193,7 +82291,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_ps, .cmp, .dst0x, .src0x, .src1x, .vp(switch (cc) {
@@ -82215,7 +82313,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.dst_temps = .{ .{ .ref_mask = .{
.ref = .src0,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, ._ps, .cmp, .dst0x, .src1x, .sp(switch (cc) {
@@ -82237,7 +82335,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_ps, .cmp, .dst0y, .src0y, .src1y, .vp(switch (cc) {
@@ -82260,7 +82358,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_ps, .cmp, .dst0y, .src0y, .src1y, .vp(switch (cc) {
@@ -82282,7 +82380,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .qword },
+ .info = .{ .kind = .sign_extend, .scalar = .qword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_sd, .cmp, .dst0x, .src0x, .src1q, .vp(switch (cc) {
@@ -82305,7 +82403,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .qword },
+ .info = .{ .kind = .sign_extend, .scalar = .qword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_sd, .cmp, .dst0x, .src0x, .src1q, .vp(switch (cc) {
@@ -82327,7 +82425,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.dst_temps = .{ .{ .ref_mask = .{
.ref = .src0,
- .info = .{ .kind = .all, .scalar = .qword },
+ .info = .{ .kind = .sign_extend, .scalar = .qword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, ._sd, .cmp, .dst0x, .src1q, .sp(switch (cc) {
@@ -82349,7 +82447,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .qword },
+ .info = .{ .kind = .sign_extend, .scalar = .qword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_pd, .cmp, .dst0x, .src0x, .src1x, .vp(switch (cc) {
@@ -82372,7 +82470,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .qword },
+ .info = .{ .kind = .sign_extend, .scalar = .qword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_pd, .cmp, .dst0x, .src0x, .src1x, .vp(switch (cc) {
@@ -82394,7 +82492,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.dst_temps = .{ .{ .ref_mask = .{
.ref = .src0,
- .info = .{ .kind = .all, .scalar = .qword },
+ .info = .{ .kind = .sign_extend, .scalar = .qword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, ._pd, .cmp, .dst0x, .src1x, .sp(switch (cc) {
@@ -82416,7 +82514,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .qword },
+ .info = .{ .kind = .sign_extend, .scalar = .qword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_pd, .cmp, .dst0y, .src0y, .src1y, .vp(switch (cc) {
@@ -82439,7 +82537,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .qword },
+ .info = .{ .kind = .sign_extend, .scalar = .qword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_pd, .cmp, .dst0y, .src0y, .src1y, .vp(switch (cc) {
@@ -84643,7 +84741,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .to_sse, .none } },
},
.dst_temps = .{ .{ .mut_rc_mask = .{ .ref = .src0, .rc = .sse, .info = .{
- .kind = .all,
+ .kind = .sign_extend,
.inverted = switch (cc) {
else => unreachable,
.e => false,
@@ -84667,7 +84765,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .to_sse, .none } },
},
.dst_temps = .{ .{ .mut_rc_mask = .{ .ref = .src0, .rc = .sse, .info = .{
- .kind = .all,
+ .kind = .sign_extend,
.inverted = switch (cc) {
else => unreachable,
.e => false,
@@ -84691,7 +84789,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .to_sse, .none } },
},
.dst_temps = .{ .{ .mut_rc_mask = .{ .ref = .src0, .rc = .sse, .info = .{
- .kind = .all,
+ .kind = .sign_extend,
.inverted = switch (cc) {
else => unreachable,
.e => false,
@@ -84715,7 +84813,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .to_sse, .none } },
},
.dst_temps = .{ .{ .mut_rc_mask = .{ .ref = .src0, .rc = .sse, .info = .{
- .kind = .all,
+ .kind = .sign_extend,
.inverted = switch (cc) {
else => unreachable,
.e => false,
@@ -84739,7 +84837,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .to_sse, .none } },
},
.dst_temps = .{ .{ .ref_mask = .{ .ref = .src0, .info = .{
- .kind = .all,
+ .kind = .sign_extend,
.inverted = switch (cc) {
else => unreachable,
.e => false,
@@ -84763,7 +84861,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .to_sse, .none } },
},
.dst_temps = .{ .{ .ref_mask = .{ .ref = .src0, .info = .{
- .kind = .all,
+ .kind = .sign_extend,
.inverted = switch (cc) {
else => unreachable,
.e => false,
@@ -84787,7 +84885,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .to_sse, .none } },
},
.dst_temps = .{ .{ .ref_mask = .{ .ref = .src0, .info = .{
- .kind = .all,
+ .kind = .sign_extend,
.inverted = switch (cc) {
else => unreachable,
.e => false,
@@ -84811,7 +84909,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_sse, .to_sse, .none } },
},
.dst_temps = .{ .{ .ref_mask = .{ .ref = .src0, .info = .{
- .kind = .all,
+ .kind = .sign_extend,
.inverted = switch (cc) {
else => unreachable,
.e => false,
@@ -84835,7 +84933,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_mmx, .to_mmx, .none } },
},
.dst_temps = .{ .{ .ref_mask = .{ .ref = .src0, .info = .{
- .kind = .all,
+ .kind = .sign_extend,
.inverted = switch (cc) {
else => unreachable,
.e => false,
@@ -84859,7 +84957,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_mmx, .to_mmx, .none } },
},
.dst_temps = .{ .{ .ref_mask = .{ .ref = .src0, .info = .{
- .kind = .all,
+ .kind = .sign_extend,
.inverted = switch (cc) {
else => unreachable,
.e => false,
@@ -84883,7 +84981,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_mut_mmx, .to_mmx, .none } },
},
.dst_temps = .{ .{ .ref_mask = .{ .ref = .src0, .info = .{
- .kind = .all,
+ .kind = .sign_extend,
.inverted = switch (cc) {
else => unreachable,
.e => false,
@@ -84907,7 +85005,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .to_sse, .none } },
},
.dst_temps = .{ .{ .mut_rc_mask = .{ .ref = .src0, .rc = .sse, .info = .{
- .kind = .all,
+ .kind = .sign_extend,
.inverted = switch (cc) {
else => unreachable,
.e => false,
@@ -84931,7 +85029,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .to_sse, .none } },
},
.dst_temps = .{ .{ .mut_rc_mask = .{ .ref = .src0, .rc = .sse, .info = .{
- .kind = .all,
+ .kind = .sign_extend,
.inverted = switch (cc) {
else => unreachable,
.e => false,
@@ -84955,7 +85053,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .to_sse, .none } },
},
.dst_temps = .{ .{ .mut_rc_mask = .{ .ref = .src0, .rc = .sse, .info = .{
- .kind = .all,
+ .kind = .sign_extend,
.inverted = switch (cc) {
else => unreachable,
.e => false,
@@ -84979,7 +85077,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_sse, .to_sse, .none } },
},
.dst_temps = .{ .{ .mut_rc_mask = .{ .ref = .src0, .rc = .sse, .info = .{
- .kind = .all,
+ .kind = .sign_extend,
.inverted = switch (cc) {
else => unreachable,
.e => false,
@@ -86631,7 +86729,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_ps, .cvtph2, .dst0x, .src0q, ._, ._ },
@@ -86671,7 +86769,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_ps, .cvtph2, .dst0x, .src0q, ._, ._ },
@@ -86711,7 +86809,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_ps, .cvtph2, .dst0y, .src0x, ._, ._ },
@@ -86737,7 +86835,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_ss, .cmp, .dst0x, .src0x, .src1d, .vp(switch (cc) {
@@ -86760,7 +86858,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.dst_temps = .{ .{ .ref_mask = .{
.ref = .src0,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, ._ss, .cmp, .dst0x, .src1d, .sp(switch (cc) {
@@ -86784,7 +86882,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_ps, .cmp, .dst0x, .src0x, .src1x, .vp(switch (cc) {
@@ -86807,7 +86905,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.dst_temps = .{ .{ .ref_mask = .{
.ref = .src0,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, ._ps, .cmp, .dst0x, .src1x, .sp(switch (cc) {
@@ -86831,7 +86929,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .dword },
+ .info = .{ .kind = .sign_extend, .scalar = .dword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_ps, .cmp, .dst0y, .src0y, .src1y, .vp(switch (cc) {
@@ -86855,7 +86953,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .qword },
+ .info = .{ .kind = .sign_extend, .scalar = .qword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_sd, .cmp, .dst0x, .src0x, .src1q, .vp(switch (cc) {
@@ -86878,7 +86976,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.dst_temps = .{ .{ .ref_mask = .{
.ref = .src0,
- .info = .{ .kind = .all, .scalar = .qword },
+ .info = .{ .kind = .sign_extend, .scalar = .qword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, ._sd, .cmp, .dst0x, .src1q, .sp(switch (cc) {
@@ -86902,7 +87000,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .qword },
+ .info = .{ .kind = .sign_extend, .scalar = .qword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_pd, .cmp, .dst0x, .src0x, .src1x, .vp(switch (cc) {
@@ -86925,7 +87023,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.dst_temps = .{ .{ .ref_mask = .{
.ref = .src0,
- .info = .{ .kind = .all, .scalar = .qword },
+ .info = .{ .kind = .sign_extend, .scalar = .qword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, ._pd, .cmp, .dst0x, .src1x, .sp(switch (cc) {
@@ -86949,7 +87047,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_temps = .{ .{ .mut_rc_mask = .{
.ref = .src0,
.rc = .sse,
- .info = .{ .kind = .all, .scalar = .qword },
+ .info = .{ .kind = .sign_extend, .scalar = .qword },
} }, .unused },
.each = .{ .once = &.{
.{ ._, .v_pd, .cmp, .dst0y, .src0y, .src1y, .vp(switch (cc) {
@@ -89204,7 +89302,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
var ops = try cg.tempsFromOperands(inst, .{un_op});
while (try ops[0].toBase(false, cg)) {}
try cg.asmMemoryImmediate(.{ ._, .cmp }, try ops[0].tracking(cg).short.mem(cg, .{
- .size = cg.memSize(eu_err_ty),
+ .size = cg.memSize(eu_err_ty, .general_purpose),
.disp = eu_err_off,
}), .u(0));
const is_err = try cg.tempInit(.bool, .{ .eflags = .ne });
@@ -89220,7 +89318,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
var ops = try cg.tempsFromOperands(inst, .{un_op});
while (try ops[0].toBase(false, cg)) {}
try cg.asmMemoryImmediate(.{ ._, .cmp }, try ops[0].tracking(cg).short.mem(cg, .{
- .size = cg.memSize(eu_err_ty),
+ .size = cg.memSize(eu_err_ty, .general_purpose),
.disp = eu_err_off,
}), .u(0));
const is_non_err = try cg.tempInit(.bool, .{ .eflags = .e });
@@ -89236,11 +89334,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
var ops = try cg.tempsFromOperands(inst, .{un_op});
try ops[0].toOffset(eu_err_off, cg);
while (try ops[0].toLea(cg)) {}
- try cg.asmMemoryImmediate(
- .{ ._, .cmp },
- try ops[0].tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(eu_err_ty) }),
- .u(0),
- );
+ try cg.asmMemoryImmediate(.{ ._, .cmp }, try ops[0].tracking(cg).short.deref().mem(cg, .{
+ .size = cg.memSize(eu_err_ty, .general_purpose),
+ }), .u(0));
const is_err = try cg.tempInit(.bool, .{ .eflags = .ne });
try is_err.finish(inst, &.{un_op}, &ops, cg);
},
@@ -89254,11 +89350,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
var ops = try cg.tempsFromOperands(inst, .{un_op});
try ops[0].toOffset(eu_err_off, cg);
while (try ops[0].toLea(cg)) {}
- try cg.asmMemoryImmediate(
- .{ ._, .cmp },
- try ops[0].tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(eu_err_ty) }),
- .u(0),
- );
+ try cg.asmMemoryImmediate(.{ ._, .cmp }, try ops[0].tracking(cg).short.deref().mem(cg, .{
+ .size = cg.memSize(eu_err_ty, .general_purpose),
+ }), .u(0));
const is_non_err = try cg.tempInit(.bool, .{ .eflags = .e });
try is_non_err.finish(inst, &.{un_op}, &ops, cg);
},
@@ -89328,6 +89422,25 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.store, .store_safe => |air_tag| {
const bin_op = air_datas[@intFromEnum(inst)].bin_op;
var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
+ switch (ops[1].tracking(cg).short) {
+ else => {},
+ .register_mask => |src_reg_mask| {
+ const ty = ops[1].typeOf(cg);
+ const new_op1 = try cg.tempAllocReg(ty, abi.RegisterClass.gp);
+ try cg.genSetReg(
+ new_op1.tracking(cg).short.register,
+ ty,
+ .{ .register_mask = src_reg_mask },
+ .{ .safety = switch (air_tag) {
+ else => unreachable,
+ .store => false,
+ .store_safe => true,
+ } },
+ );
+ try ops[1].die(cg);
+ ops[1] = new_op1;
+ },
+ }
cg.select(&.{}, &.{}, &ops, comptime &.{ .{
.src_constraints = .{ .{ .ptr_bool_vec_elem = .byte }, .bool, .any },
.patterns = &.{
@@ -93270,7 +93383,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
};
try res[0].finish(inst, &.{ty_op.operand}, &ops, cg);
},
- .intcast => |air_tag| {
+ .int_cast => |air_tag| {
const ty_op = air_datas[@intFromEnum(inst)].ty_op;
const dst_ty = ty_op.ty.toType();
const src_ty = cg.typeOf(ty_op.operand);
@@ -98028,7 +98141,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
};
try res[0].finish(inst, &.{ty_op.operand}, &ops, cg);
},
- .intcast_safe => unreachable,
+ .int_cast_safe => unreachable,
.trunc => |air_tag| {
const ty_op = air_datas[@intFromEnum(inst)].ty_op;
var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
@@ -104246,7 +104359,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
try ops[0].toSlicePtr(cg);
const dst_ty = ty_pl.ty.toType();
- if (dst_ty.ptrInfo(zcu).flags.vector_index == .none) zero_offset: {
+ zero_offset: {
const elem_size = dst_ty.childType(zcu).abiSize(zcu);
if (hack_around_sema_opv_bugs and elem_size == 0) break :zero_offset;
while (true) for (&ops) |*op| {
@@ -127103,7 +127216,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .all_reg_mask = .{ .size = .xword, .is = .inverted } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .sign_extend, .is = .inverted } }, .none, .none } },
},
.dst_temps = .{ .{ .cc = .z }, .unused },
.clobbers = .{ .eflags = true },
@@ -127115,7 +127228,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .all_reg_mask = .{ .size = .xword, .is = .inverted } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .sign_extend, .is = .inverted } }, .none, .none } },
},
.dst_temps = .{ .{ .cc = .z }, .unused },
.clobbers = .{ .eflags = true },
@@ -127127,7 +127240,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .all_reg_mask = .{ .size = .xword } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .sign_extend } }, .none, .none } },
},
.extra_temps = .{
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
@@ -127153,7 +127266,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .all_reg_mask = .{ .size = .xword } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .sign_extend } }, .none, .none } },
},
.extra_temps = .{
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
@@ -127179,7 +127292,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .reg_mask = .{ .size = .xword } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .msb } }, .none, .none } },
},
.extra_temps = .{
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
@@ -127205,7 +127318,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .reg_mask = .{ .size = .xword } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .msb } }, .none, .none } },
},
.extra_temps = .{
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
@@ -127231,7 +127344,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .all_reg_mask = .{ .size = .yword, .is = .inverted } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .yword, .kind = .sign_extend, .is = .inverted } }, .none, .none } },
},
.dst_temps = .{ .{ .cc = .z }, .unused },
.clobbers = .{ .eflags = true },
@@ -127243,7 +127356,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .all_reg_mask = .{ .size = .yword, .is = .inverted } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .yword, .kind = .sign_extend, .is = .inverted } }, .none, .none } },
},
.dst_temps = .{ .{ .cc = .z }, .unused },
.clobbers = .{ .eflags = true },
@@ -127255,7 +127368,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .all_reg_mask = .{ .size = .yword } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .yword, .kind = .sign_extend } }, .none, .none } },
},
.extra_temps = .{
.{ .type = .vector_32_u8, .kind = .{ .rc = .sse } },
@@ -127281,7 +127394,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .all_reg_mask = .{ .size = .yword } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .yword, .kind = .sign_extend } }, .none, .none } },
},
.extra_temps = .{
.{ .type = .vector_8_f32, .kind = .{ .rc = .sse } },
@@ -127307,7 +127420,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .reg_mask = .{ .size = .yword } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .yword, .kind = .msb } }, .none, .none } },
},
.extra_temps = .{
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
@@ -127508,7 +127621,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .all_reg_mask = .{ .size = .xword, .is = .uninverted } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .sign_extend, .is = .uninverted } }, .none, .none } },
},
.dst_temps = .{ .{ .cc = .nz }, .unused },
.clobbers = .{ .eflags = true },
@@ -127520,7 +127633,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .all_reg_mask = .{ .size = .xword, .is = .uninverted } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .sign_extend, .is = .uninverted } }, .none, .none } },
},
.dst_temps = .{ .{ .cc = .nz }, .unused },
.clobbers = .{ .eflags = true },
@@ -127532,7 +127645,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .all_reg_mask = .{ .size = .xword } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .sign_extend } }, .none, .none } },
},
.extra_temps = .{
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
@@ -127558,7 +127671,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .all_reg_mask = .{ .size = .xword } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .sign_extend } }, .none, .none } },
},
.extra_temps = .{
.{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
@@ -127584,7 +127697,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .reg_mask = .{ .size = .xword } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .msb } }, .none, .none } },
},
.extra_temps = .{
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
@@ -127610,7 +127723,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .reg_mask = .{ .size = .xword } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .msb } }, .none, .none } },
},
.extra_temps = .{
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
@@ -127636,7 +127749,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .all_reg_mask = .{ .size = .yword, .is = .uninverted } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .yword, .kind = .sign_extend, .is = .uninverted } }, .none, .none } },
},
.dst_temps = .{ .{ .cc = .nz }, .unused },
.clobbers = .{ .eflags = true },
@@ -127648,7 +127761,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .all_reg_mask = .{ .size = .yword, .is = .uninverted } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .yword, .kind = .sign_extend, .is = .uninverted } }, .none, .none } },
},
.dst_temps = .{ .{ .cc = .nz }, .unused },
.clobbers = .{ .eflags = true },
@@ -127660,7 +127773,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .all_reg_mask = .{ .size = .yword } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .yword, .kind = .sign_extend } }, .none, .none } },
},
.extra_temps = .{
.{ .type = .vector_32_u8, .kind = .{ .rc = .sse } },
@@ -127686,7 +127799,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .all_reg_mask = .{ .size = .yword } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .yword, .kind = .sign_extend } }, .none, .none } },
},
.extra_temps = .{
.{ .type = .vector_8_f32, .kind = .{ .rc = .sse } },
@@ -127712,7 +127825,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.dst_constraints = .{ .bool, .any },
.src_constraints = .{ .any_bool_vec, .any, .any },
.patterns = &.{
- .{ .src = .{ .{ .reg_mask = .{ .size = .yword } }, .none, .none } },
+ .{ .src = .{ .{ .reg_mask = .{ .size = .yword, .kind = .msb } }, .none, .none } },
},
.extra_temps = .{
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
@@ -168986,12 +169099,56 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
};
try res[0].finish(inst, &.{reduce.operand}, &ops, cg);
},
- .splat => |air_tag| fallback: {
+ .splat => |air_tag| {
const ty_op = air_datas[@intFromEnum(inst)].ty_op;
- if (cg.typeOf(ty_op.operand).toIntern() == .bool_type) break :fallback try cg.airSplat(inst);
var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
var res: [1]Temp = undefined;
cg.select(&res, &.{ty_op.ty.toType()}, &ops, comptime &.{ .{
+ .dst_constraints = .{ .{ .bool_vec = .qword }, .any },
+ .src_constraints = .{ .bool, .any, .any },
+ .patterns = &.{
+ .{ .src = .{ .to_gpr, .none, .none } },
+ },
+ .dst_temps = .{ .{ .rc = .general_purpose }, .unused },
+ .clobbers = .{ .eflags = true },
+ .each = .{ .once = &.{
+ .{ ._, ._, .bt, .src0d, .si(0), ._, ._ },
+ .{ ._, ._, .sbb, .dst0q, .dst0q, ._, ._ },
+ .{ ._, ._r, .sh, .dst0q, .uia(64, .dst0, .sub_bit_size), ._, ._ },
+ } },
+ }, .{
+ .dst_constraints = .{ .any_bool_vec, .any },
+ .src_constraints = .{ .bool, .any, .any },
+ .patterns = &.{
+ .{ .src = .{ .to_gpr, .none, .none } },
+ },
+ .dst_temps = .{ .mem, .unused },
+ .extra_temps = .{
+ .{ .type = .isize, .kind = .{ .reg = .rdi } },
+ .{ .type = .u8, .kind = .{ .reg = .rax } },
+ .{ .type = .u32, .kind = .{ .reg = .rcx } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .clobbers = .{ .eflags = true },
+ .each = .{ .once = &.{
+ .{ ._, ._, .bt, .src0d, .si(0), ._, ._ },
+ .{ ._, ._, .sbb, .tmp1b, .tmp1b, ._, ._ },
+ .{ ._, ._, .lea, .tmp0q, .dst0b, ._, ._ },
+ .{ ._, ._, .mov, .tmp2d, .sia(1, .dst0, .add_bit_size_sub_1_div_8_down_1), ._, ._ },
+ .{ ._, .@"rep _sb", .sto, ._, ._, ._, ._ },
+ .{ ._, ._, .@"and", .memad(.dst0b, .add_bit_size_sub_1_div_8_down_1, 0), .ua(.dst0, .bit_size_last_byte_mask), ._, ._ },
+ .{ ._, ._, .mov, .tmp2d, .sa(.dst0, .add_size_sub_bit_size_div_8_down_1_sub_1), ._, ._ },
+ .{ ._, ._, .xor, .tmp1b, .tmp1b, ._, ._ },
+ .{ ._, .@"rep _sb", .sto, ._, ._, ._, ._ },
+ } },
+ }, .{
.required_features = .{ .avx2, null, null, null },
.dst_constraints = .{ .{ .scalar_int = .{ .of = .xword, .is = .byte } }, .any },
.src_constraints = .{ .{ .int = .byte }, .any, .any },
@@ -173719,7 +173876,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
// No soft-float `Legalize` features are enabled, so this instruction never appears.
.legalize_compiler_rt_call => unreachable,
- .work_item_id, .work_group_size, .work_group_id => unreachable,
+ .work_item_id, .work_group_size, .work_group_id, .spirv_runtime_array_len => unreachable,
}
try cg.resetTemps(@enumFromInt(0));
cg.checkInvariantsAfterAirInst();
@@ -174212,15 +174369,16 @@ fn restoreState(self: *CodeGen, state: State, deaths: []const Air.Inst.Index, co
const ExpectedContents = [@typeInfo(RegisterManager.TrackedRegisters).array.len]RegisterLock;
const bfa_buf_len = if (opts.update_tracking) 0 else 1;
var bfa_buf: [bfa_buf_len]ExpectedContents = undefined;
- var stack = if (opts.update_tracking) {} else std.heap.BufferFirstAllocator.init(@ptrCast(&bfa_buf), self.gpa);
+ var stack = if (!opts.update_tracking) std.heap.BufferFirstAllocator.init(@ptrCast(&bfa_buf), self.gpa);
+ const allocator = if (!opts.update_tracking) stack.allocator();
- var reg_locks = if (opts.update_tracking) {} else try std.array_list.Managed(RegisterLock).initCapacity(
- stack.allocator(),
+ var reg_locks = if (!opts.update_tracking) try std.ArrayList(RegisterLock).initCapacity(
+ allocator,
@typeInfo(ExpectedContents).array.len,
);
defer if (!opts.update_tracking) {
for (reg_locks.items) |lock| self.register_manager.unlockReg(lock);
- reg_locks.deinit();
+ reg_locks.deinit(allocator);
};
for (
@@ -174250,7 +174408,7 @@ fn restoreState(self: *CodeGen, state: State, deaths: []const Air.Inst.Index, co
self.inst_tracking.getPtr(target_inst).?.trackMaterialize(target_inst, reg_tracking);
}
} else if (target_maybe_inst) |_|
- try reg_locks.append(self.register_manager.lockRegIndexAssumeUnused(reg_index));
+ try reg_locks.append(allocator, self.register_manager.lockRegIndexAssumeUnused(reg_index));
}
if (opts.emit_instructions) if (self.eflags_inst) |inst|
try self.inst_tracking.getPtr(inst).?.spill(self, inst);
@@ -174463,7 +174621,13 @@ fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerE
.register_overflow,
.register_mask,
.indirect_load_frame,
- .elementwise_args,
+ .indirect_mask,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
=> unreachable, // not a valid pointer
.immediate,
@@ -174516,7 +174680,13 @@ fn store(
.register_overflow,
.register_mask,
.indirect_load_frame,
- .elementwise_args,
+ .indirect_mask,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
=> unreachable, // not a valid pointer
.immediate,
@@ -174561,12 +174731,18 @@ fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv:
.register_overflow,
.register_mask,
.indirect_load_frame,
+ .indirect_mask,
.lea_frame,
.lea_nav,
.lea_uav,
.lea_lazy_sym,
.lea_extern_func,
- .elementwise_args,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
.air_ref,
=> unreachable, // unmodifiable destination
@@ -175256,7 +175432,13 @@ fn genBinOpMir(
.lea_lazy_sym,
.lea_extern_func,
.indirect_load_frame,
- .elementwise_args,
+ .indirect_mask,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
.air_ref,
=> unreachable, // unmodifiable destination
@@ -175293,7 +175475,13 @@ fn genBinOpMir(
.register_overflow,
.register_mask,
.indirect_load_frame,
- .elementwise_args,
+ .indirect_mask,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
=> unreachable,
.register,
@@ -175465,7 +175653,13 @@ fn genBinOpMir(
.register_overflow,
.register_mask,
.indirect_load_frame,
- .elementwise_args,
+ .indirect_mask,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
.air_ref,
=> unreachable,
@@ -175569,7 +175763,13 @@ fn genBinOpMir(
.register_overflow,
.register_mask,
.indirect_load_frame,
- .elementwise_args,
+ .indirect_mask,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
.air_ref,
=> unreachable,
@@ -175683,120 +175883,255 @@ fn genBinOpMir(
}
}
-fn airArg(self: *CodeGen, inst: Air.Inst.Index) !void {
- const zcu = self.pt.zcu;
- const arg_index = for (self.args, 0..) |arg, arg_index| {
+fn airArg(cg: *CodeGen, inst: Air.Inst.Index) !void {
+ const zcu = cg.pt.zcu;
+ const arg_index = for (cg.args, 0..) |arg, arg_index| {
if (arg != .none) break arg_index;
} else unreachable;
- const src_mcv = self.args[arg_index];
- self.args = self.args[arg_index + 1 ..];
- const result: MCValue = if (self.mod.strip and self.liveness.isUnused(inst)) .unreach else result: {
- const arg_ty = self.typeOfIndex(inst);
+ const src_mcv = cg.args[arg_index];
+ cg.args = cg.args[arg_index + 1 ..];
+ const result: MCValue = if (cg.mod.strip and cg.liveness.isUnused(inst)) .unreach else result: {
+ const arg_ty = cg.typeOfIndex(inst);
switch (src_mcv) {
- .register, .register_pair, .load_frame => {
- for (src_mcv.getRegs()) |reg| self.register_manager.getRegAssumeFree(reg, inst);
+ .register,
+ .register_pair,
+ .register_triple,
+ .register_quadruple,
+ .register_mask,
+ .load_frame,
+ => {
+ for (src_mcv.getRegs()) |reg| cg.register_manager.getRegAssumeFree(reg, inst);
break :result src_mcv;
},
.indirect => |reg_off| {
- self.register_manager.getRegAssumeFree(reg_off.reg, null);
- const dst_mcv = try self.allocRegOrMem(inst, false);
- try self.genCopy(arg_ty, dst_mcv, src_mcv, .{});
+ cg.register_manager.getRegAssumeFree(reg_off.reg, null);
+ const dst_mcv = try cg.allocRegOrMem(inst, false);
+ try cg.genCopy(arg_ty, dst_mcv, src_mcv, .{});
break :result dst_mcv;
},
+ .indirect_mask => |reg_mask| {
+ cg.register_manager.getRegAssumeFree(reg_mask.reg, null);
+ const dst_reg = try cg.register_manager.allocReg(inst, abi.RegisterClass.sse);
+ const mask_size: u32 = @intCast(
+ @divExact(reg_mask.info.scalar.bitSize(cg.target), 8) * arg_ty.vectorLen(zcu),
+ );
+ try cg.asmRegisterMemory(
+ .{ if (cg.hasFeature(.avx)) .v_dqa else ._dqa, .mov },
+ registerAlias(dst_reg, mask_size),
+ .{
+ .base = .{ .reg = reg_mask.reg },
+ .mod = .{ .rm = .{ .size = .fromSize(mask_size) } },
+ },
+ );
+ break :result .{ .register_mask = .{ .reg = dst_reg, .info = reg_mask.info } };
+ },
.indirect_load_frame => |frame_addr| {
- const dst_mcv = try self.allocRegOrMem(inst, false);
- const ptr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
- const ptr_lock = self.register_manager.lockRegAssumeUnused(ptr_reg);
- defer self.register_manager.unlockReg(ptr_lock);
- try self.genSetReg(ptr_reg, .usize, .{ .load_frame = frame_addr }, .{});
- try self.genCopy(arg_ty, dst_mcv, .{ .indirect = .{ .reg = ptr_reg } }, .{});
+ const dst_mcv = try cg.allocRegOrMem(inst, false);
+ const ptr_reg = try cg.register_manager.allocReg(null, abi.RegisterClass.gp);
+ const ptr_lock = cg.register_manager.lockRegAssumeUnused(ptr_reg);
+ defer cg.register_manager.unlockReg(ptr_lock);
+ try cg.genSetReg(ptr_reg, .usize, .{ .load_frame = frame_addr }, .{});
+ try cg.genCopy(arg_ty, dst_mcv, .{ .indirect = .{ .reg = ptr_reg } }, .{});
break :result dst_mcv;
},
- .elementwise_args => |regs_frame_addr| {
- try self.spillEflagsIfOccupied();
+ .elementwise_gpr, .elementwise_sse => |regs_frame_addr| {
+ const fn_info = zcu.typeToFunc(cg.fn_type).?;
+ const elem_ty = arg_ty.childType(zcu);
+ const elem_rc: Register.Class, const param_regs = switch (src_mcv) {
+ else => unreachable,
+ .elementwise_gpr => .{ .general_purpose, abi.getCAbiIntParamRegs(fn_info.cc) },
+ .elementwise_sse => .{ .sse, abi.getCAbiSseParamRegs(fn_info.cc, cg.target) },
+ };
+ const len = arg_ty.vectorLen(zcu);
+ const param_reg_len: u31 =
+ @intCast(@min(param_regs.len - regs_frame_addr.info.reg_index, len));
- const fn_info = zcu.typeToFunc(self.fn_type).?;
- const param_int_regs = abi.getCAbiIntParamRegs(fn_info.cc);
- var prev_reg: Register = undefined;
- for (
- param_int_regs[param_int_regs.len - regs_frame_addr.regs ..],
- 0..,
- ) |dst_reg, elem_index| {
- assert(self.register_manager.isRegFree(dst_reg));
- if (elem_index > 0) {
- try self.asmRegisterImmediate(.{ ._l, .sh }, dst_reg.to8(), .u(elem_index));
- try self.asmRegisterRegister(
- .{ ._, .@"or" },
- dst_reg.to8(),
- prev_reg.to8(),
+ const elem_size = cg.memSize(elem_ty, .general_purpose);
+ const elem_abi_size = @divExact(elem_size.bitSize(cg.target), 8);
+ const strat = if (elem_ty.toIntern() == .bool_type) strat: {
+ try cg.spillEflagsIfOccupied();
+ break :strat undefined;
+ } else try cg.moveStrategy(elem_ty, elem_rc, true);
+
+ const dst_mcv = try cg.allocRegOrMem(inst, false);
+ {
+ var prev_reg: Register = undefined;
+ for (
+ param_regs[regs_frame_addr.info.reg_index..][0..param_reg_len],
+ 0..,
+ ) |src_reg, elem_index| {
+ assert(cg.register_manager.isRegFree(src_reg));
+ if (elem_ty.toIntern() == .bool_type) {
+ if (elem_index > 0) {
+ try cg.asmRegisterImmediate(
+ .{ ._l, .sh },
+ src_reg.to8(),
+ .u(elem_index),
+ );
+ try cg.asmRegisterRegister(
+ .{ ._, .@"or" },
+ src_reg.to8(),
+ prev_reg.to8(),
+ );
+ }
+ prev_reg = src_reg;
+ } else try strat.write(cg, try dst_mcv.mem(cg, .{
+ .size = elem_size,
+ .disp = @intCast(elem_abi_size * elem_index),
+ }), src_reg.toSize(elem_size, cg.target));
+ }
+ if (elem_ty.toIntern() == .bool_type) {
+ if (param_reg_len > 0) {
+ const prev_lock = cg.register_manager.lockRegAssumeUnused(prev_reg);
+ defer cg.register_manager.unlockReg(prev_lock);
+ try cg.asmMemoryRegister(
+ .{ ._, .mov },
+ try dst_mcv.mem(cg, .{ .size = .byte }),
+ prev_reg.to8(),
+ );
+ }
+ const clear_len = arg_ty.abiSize(zcu) - @intFromBool(param_reg_len > 0);
+ if (clear_len > 0) try cg.genInlineMemset(
+ dst_mcv.address().offset(@intFromBool(param_reg_len > 0)),
+ .{ .immediate = 0 },
+ .{ .immediate = clear_len },
+ .{},
+ );
+ }
+ }
+ if (len - param_reg_len > 0) {
+ const index_reg = try cg.register_manager.allocReg(null, abi.RegisterClass.gp);
+ const index_lock = cg.register_manager.lockRegAssumeUnused(index_reg);
+ defer cg.register_manager.unlockReg(index_lock);
+ try cg.asmRegisterImmediate(.{ ._, .mov }, index_reg.to32(), .u(param_reg_len));
+
+ const loop: Mir.Inst.Index = @intCast(cg.mir_instructions.len);
+ if (elem_ty.toIntern() == .bool_type) {
+ try cg.asmMemoryImmediate(.{ ._, .cmp }, .{
+ .base = .{ .frame = regs_frame_addr.frame_index },
+ .mod = .{ .rm = .{
+ .size = .byte,
+ .index = index_reg.to64(),
+ .scale = .@"8",
+ .disp = @as(i32, regs_frame_addr.info.frame_off) - 8 * param_reg_len,
+ } },
+ }, Immediate.u(0));
+ const unset = try cg.asmJccReloc(.e, undefined);
+ try cg.asmMemoryRegister(
+ .{ ._s, .bt },
+ try dst_mcv.mem(cg, .{ .size = .dword }),
+ index_reg.to32(),
);
+ cg.performReloc(unset);
+ } else {
+ const elem_reg =
+ try cg.register_manager.allocReg(null, regSetForRegClass(elem_rc));
+ const elem_lock = cg.register_manager.lockRegAssumeUnused(elem_reg);
+ defer cg.register_manager.unlockReg(elem_lock);
+
+ try strat.read(cg, elem_reg.toSize(elem_size, cg.target), .{
+ .base = .{ .frame = regs_frame_addr.frame_index },
+ .mod = .{ .rm = .{
+ .size = elem_size,
+ .index = index_reg.to64(),
+ .scale = .@"8",
+ .disp = @as(i32, regs_frame_addr.info.frame_off) - 8 * param_reg_len,
+ } },
+ });
+ try strat.write(cg, try dst_mcv.mem(cg, .{
+ .size = elem_size,
+ .index = index_reg.to64(),
+ .scale = .fromFactor(@intCast(elem_abi_size)),
+ }), elem_reg.toSize(elem_size, cg.target));
+ }
+ if (cg.hasFeature(.slow_incdec)) {
+ try cg.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), .u(1));
+ } else {
+ try cg.asmRegister(.{ ._c, .in }, index_reg.to32());
}
- prev_reg = dst_reg;
+ try cg.asmRegisterImmediate(.{ ._, .cmp }, index_reg.to32(), .u(len));
+ _ = try cg.asmJccReloc(.b, loop);
}
- const prev_lock = if (regs_frame_addr.regs > 0)
- self.register_manager.lockRegAssumeUnused(prev_reg)
- else
- null;
- defer if (prev_lock) |lock| self.register_manager.unlockReg(lock);
+ break :result dst_mcv;
+ },
+ .xwordwise_sse, .ywordwise_sse, .zwordwise_sse => |regs_frame_addr| {
+ const fn_info = zcu.typeToFunc(cg.fn_type).?;
+ const elem_size: Memory.Size, const elem_ty: Type = switch (src_mcv) {
+ else => unreachable,
+ .xwordwise_sse => .{ .xword, .vector_16_u8 },
+ .ywordwise_sse => .{ .yword, .vector_32_u8 },
+ .zwordwise_sse => .{ .zword, .vector_64_u8 },
+ };
+ const elem_abi_size: u31 = @intCast(@divExact(elem_size.bitSize(cg.target), 8));
+ const strat = try cg.moveStrategy(elem_ty, .sse, true);
+
+ const param_gpr_regs = abi.getCAbiIntParamRegs(fn_info.cc);
+ const len = @divExact(arg_ty.abiSize(zcu), elem_abi_size);
+ const param_gpr_len: u31 =
+ @intCast(@min(param_gpr_regs.len - regs_frame_addr.info.reg_index, len));
+
+ const part_reg = try cg.register_manager.allocReg(null, abi.RegisterClass.sse);
+ const part_lock = cg.register_manager.lockRegAssumeUnused(part_reg);
+ defer cg.register_manager.unlockReg(part_lock);
+ const part_alias = part_reg.toSize(elem_size, cg.target);
- const dst_mcv = try self.allocRegOrMem(inst, false);
- if (regs_frame_addr.regs > 0) try self.asmMemoryRegister(
- .{ ._, .mov },
- try dst_mcv.mem(self, .{ .size = .byte }),
- prev_reg.to8(),
- );
- try self.genInlineMemset(
- dst_mcv.address().offset(@intFromBool(regs_frame_addr.regs > 0)),
- .{ .immediate = 0 },
- .{ .immediate = arg_ty.abiSize(zcu) - @intFromBool(regs_frame_addr.regs > 0) },
- .{},
- );
+ const dst_mcv = try cg.allocRegOrMem(inst, false);
- const index_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
- const index_lock = self.register_manager.lockRegAssumeUnused(index_reg);
- defer self.register_manager.unlockReg(index_lock);
+ var arg_offset: u31 = 0;
+ for (param_gpr_regs[regs_frame_addr.info.reg_index..][0..param_gpr_len]) |src_reg| {
+ try strat.read(cg, part_alias, .{
+ .base = .{ .reg = src_reg },
+ .mod = .{ .rm = .{ .size = elem_size } },
+ });
+ try strat.write(cg, try dst_mcv.mem(cg, .{
+ .size = elem_size,
+ .disp = arg_offset,
+ }), part_alias);
+ arg_offset += elem_abi_size;
+ }
+
+ if (len - param_gpr_len > 0) {
+ const index_reg = try cg.register_manager.allocReg(null, abi.RegisterClass.gp);
+ const index_lock = cg.register_manager.lockRegAssumeUnused(index_reg);
+ defer cg.register_manager.unlockReg(index_lock);
+ try cg.asmRegisterImmediate(.{ ._, .mov }, index_reg.to32(), .u(8 * param_gpr_len));
- try self.asmRegisterImmediate(
- .{ ._, .mov },
- index_reg.to32(),
- .u(regs_frame_addr.regs),
- );
- const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
- try self.asmMemoryImmediate(.{ ._, .cmp }, .{
- .base = .{ .frame = regs_frame_addr.frame_index },
- .mod = .{ .rm = .{
- .size = .byte,
- .index = index_reg.to64(),
- .scale = .@"8",
- .disp = regs_frame_addr.frame_off - @as(u6, regs_frame_addr.regs) * 8,
- } },
- }, Immediate.u(0));
- const unset = try self.asmJccReloc(.e, undefined);
- try self.asmMemoryRegister(
- .{ ._s, .bt },
- try dst_mcv.mem(self, .{ .size = .dword }),
- index_reg.to32(),
- );
- self.performReloc(unset);
- if (self.hasFeature(.slow_incdec)) {
- try self.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), .u(1));
- } else {
- try self.asmRegister(.{ ._c, .in }, index_reg.to32());
+ const loop: Mir.Inst.Index = @intCast(cg.mir_instructions.len);
+ {
+ const ptr_reg = try cg.register_manager.allocReg(null, abi.RegisterClass.gp);
+ const ptr_lock = cg.register_manager.lockRegAssumeUnused(ptr_reg);
+ defer cg.register_manager.unlockReg(ptr_lock);
+
+ try cg.asmRegisterMemory(.{ ._, .mov }, ptr_reg.to64(), .{
+ .base = .{ .frame = regs_frame_addr.frame_index },
+ .mod = .{ .rm = .{
+ .size = .ptr,
+ .index = index_reg.to64(),
+ .disp = @as(i32, regs_frame_addr.info.frame_off) - 8 * param_gpr_len,
+ } },
+ });
+ try strat.read(cg, part_alias, .{
+ .base = .{ .reg = ptr_reg },
+ .mod = .{ .rm = .{ .size = elem_size } },
+ });
+ try strat.write(cg, try dst_mcv.mem(cg, .{
+ .size = elem_size,
+ .index = index_reg.to64(),
+ .scale = .fromFactor(@intCast(@divExact(elem_abi_size, 8))),
+ }), part_alias);
+ }
+ try cg.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), .u(8));
+ try cg.asmRegisterImmediate(.{ ._, .cmp }, index_reg.to32(), .u(8 * len));
+ _ = try cg.asmJccReloc(.b, loop);
}
- try self.asmRegisterImmediate(
- .{ ._, .cmp },
- index_reg.to32(),
- .u(arg_ty.vectorLen(zcu)),
- );
- _ = try self.asmJccReloc(.b, loop);
break :result dst_mcv;
},
- else => return self.fail("TODO implement arg for {f}", .{src_mcv}),
+ else => return cg.fail("TODO implement arg for {f}", .{src_mcv}),
}
};
- return self.finishAir(inst, result, .{ .none, .none, .none });
+ return cg.finishAir(inst, result, .{ .none, .none, .none });
}
fn genLocalDebugInfo(cg: *CodeGen, air_tag: Air.Inst.Tag, ty: Type, mcv: MCValue) !void {
@@ -175804,7 +176139,18 @@ fn genLocalDebugInfo(cg: *CodeGen, air_tag: Air.Inst.Tag, ty: Type, mcv: MCValue
_ = switch (air_tag) {
else => unreachable,
.arg, .dbg_var_val, .dbg_arg_inline => switch (mcv) {
- .none, .unreach, .dead, .elementwise_args, .reserved_frame, .air_ref => unreachable,
+ .none,
+ .unreach,
+ .dead,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
+ .reserved_frame,
+ .air_ref,
+ => unreachable,
.immediate => |imm| if (std.math.cast(u32, imm)) |small| try cg.addInst(.{
.tag = .pseudo,
.ops = switch (air_tag) {
@@ -175852,7 +176198,18 @@ fn genLocalDebugInfo(cg: *CodeGen, air_tag: Air.Inst.Tag, ty: Type, mcv: MCValue
},
.dbg_var_ptr => switch (mcv) {
else => unreachable,
- .none, .unreach, .dead, .elementwise_args, .reserved_frame, .air_ref => unreachable,
+ .none,
+ .unreach,
+ .dead,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
+ .reserved_frame,
+ .air_ref,
+ => unreachable,
.lea_frame => |frame_addr| try cg.addInst(.{
.tag = .pseudo,
.ops = .pseudo_dbg_var_m,
@@ -175910,10 +176267,10 @@ fn genLocalDebugInfo(cg: *CodeGen, air_tag: Air.Inst.Tag, ty: Type, mcv: MCValue
};
}
-fn airCall(self: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier, opts: CopyOptions) !void {
- if (modifier == .always_tail) return self.fail("TODO implement tail calls for x86_64", .{});
+fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier, opts: CopyOptions) !void {
+ if (modifier == .always_tail) return cg.fail("TODO implement tail calls for x86_64", .{});
- const call = self.air.unwrapCall(inst);
+ const call = cg.air.unwrapCall(inst);
const arg_refs = call.args;
const ExpectedContents = extern struct {
@@ -175921,28 +176278,28 @@ fn airCall(self: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier
vals: [32][@sizeOf(MCValue)]u8 align(@alignOf(MCValue)),
};
var bfa_buf: [1]ExpectedContents = undefined;
- var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), self.gpa);
+ var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), cg.gpa);
const allocator = bfa.allocator();
const arg_tys = try allocator.alloc(Type, arg_refs.len);
defer allocator.free(arg_tys);
- for (arg_tys, arg_refs) |*arg_ty, arg_ref| arg_ty.* = self.typeOf(arg_ref);
+ for (arg_tys, arg_refs) |*arg_ty, arg_ref| arg_ty.* = cg.typeOf(arg_ref);
const arg_vals = try allocator.alloc(MCValue, arg_refs.len);
defer allocator.free(arg_vals);
for (arg_vals, arg_refs) |*arg_val, arg_ref| arg_val.* = .{ .air_ref = arg_ref };
- const ret = try self.genCall(.{ .air = call.callee }, arg_tys, arg_vals, opts);
+ const ret = try cg.genCall(.{ .air = call.callee }, arg_tys, arg_vals, opts);
- var bt = self.liveness.iterateBigTomb(inst);
- try self.feed(&bt, call.callee);
- for (arg_refs) |arg_ref| try self.feed(&bt, arg_ref);
+ var bt = cg.liveness.iterateBigTomb(inst);
+ try cg.feed(&bt, call.callee);
+ for (arg_refs) |arg_ref| try cg.feed(&bt, arg_ref);
- const result = if (self.liveness.isUnused(inst)) .unreach else ret;
- return self.finishAirResult(inst, result);
+ const result = if (cg.liveness.isUnused(inst)) .unreach else ret;
+ return cg.finishAirResult(inst, result);
}
-fn genCall(self: *CodeGen, info: union(enum) {
+fn genCall(cg: *CodeGen, info: union(enum) {
air: Air.Inst.Ref,
extern_func: struct {
return_type: InternPool.Index,
@@ -175950,13 +176307,13 @@ fn genCall(self: *CodeGen, info: union(enum) {
sym: []const u8,
},
}, arg_types: []const Type, args: []const MCValue, opts: CopyOptions) !MCValue {
- const pt = self.pt;
+ const pt = cg.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const fn_ty = switch (info) {
.air => |callee| fn_info: {
- const callee_ty = self.typeOf(callee);
+ const callee_ty = cg.typeOf(callee);
break :fn_info switch (callee_ty.zigTypeTag(zcu)) {
.@"fn" => callee_ty,
.pointer => callee_ty.childType(zcu),
@@ -175966,7 +176323,7 @@ fn genCall(self: *CodeGen, info: union(enum) {
.extern_func => |extern_func| try pt.funcType(.{
.param_types = extern_func.param_types,
.return_type = extern_func.return_type,
- .cc = self.target.cCallingConvention().?,
+ .cc = cg.target.cCallingConvention().?,
}),
};
const fn_info = zcu.typeToFunc(fn_ty).?;
@@ -175977,23 +176334,23 @@ fn genCall(self: *CodeGen, info: union(enum) {
reg_locks: [32][@sizeOf(?RegisterLock)]u8 align(@alignOf(?RegisterLock)),
};
var bfa_buf: ExpectedContents = undefined;
- var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), self.gpa);
+ var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), cg.gpa);
const allocator = bfa.allocator();
const var_args = try allocator.alloc(Type, args.len - fn_info.param_types.len);
defer allocator.free(var_args);
- for (var_args, arg_types[fn_info.param_types.len..]) |*var_arg, arg_ty| var_arg.* = arg_ty;
+ @memcpy(var_args, arg_types[fn_info.param_types.len..]);
const frame_indices = try allocator.alloc(FrameIndex, args.len);
defer allocator.free(frame_indices);
- var reg_locks: std.array_list.Managed(?RegisterLock) = .init(allocator);
- defer reg_locks.deinit();
- try reg_locks.ensureTotalCapacity(16);
- defer for (reg_locks.items) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock);
+ var reg_locks: std.ArrayList(?RegisterLock) = .empty;
+ defer reg_locks.deinit(allocator);
+ try reg_locks.ensureTotalCapacity(allocator, 16);
+ defer for (reg_locks.items) |reg_lock| if (reg_lock) |lock| cg.register_manager.unlockReg(lock);
- var call_info = try self.resolveCallingConventionValues(fn_info, var_args, .call_frame);
- defer call_info.deinit(self);
+ var call_info = try cg.resolveCallingConventionValues(fn_info, var_args, .call_frame);
+ defer call_info.deinit(cg);
// We need a properly aligned and sized call frame to be able to call this function.
{
@@ -176001,7 +176358,7 @@ fn genCall(self: *CodeGen, info: union(enum) {
.size = call_info.stack_byte_count,
.alignment = call_info.stack_align,
});
- const frame_allocs_slice = self.frame_allocs.slice();
+ const frame_allocs_slice = cg.frame_allocs.slice();
const stack_frame_size =
&frame_allocs_slice.items(.abi_size)[@intFromEnum(FrameIndex.call_frame)];
stack_frame_size.* = @max(stack_frame_size.*, needed_call_frame.abi_size);
@@ -176010,112 +176367,228 @@ fn genCall(self: *CodeGen, info: union(enum) {
stack_frame_align.* = stack_frame_align.max(needed_call_frame.abi_align);
}
- try self.spillEflagsIfOccupied();
- try self.spillCallerPreservedRegs(fn_info.cc, call_info.err_ret_trace_reg);
+ try cg.spillEflagsIfOccupied();
+ try cg.spillCallerPreservedRegs(fn_info.cc, call_info.err_ret_trace_reg);
// set stack arguments first because this can clobber registers
// also clobber spill arguments as we go
switch (call_info.return_value.long) {
.none, .unreach => {},
- .indirect => |reg_off| try self.register_manager.getReg(reg_off.reg, null),
+ .indirect => |reg_off| try cg.register_manager.getReg(reg_off.reg, null),
else => unreachable,
}
- for (call_info.args, arg_types, args, frame_indices, 0..) |dst_arg, arg_ty, src_arg, *frame_index, arg_i|
- switch (dst_arg) {
- .none => {},
- .register => |reg| {
- try self.register_manager.getReg(reg, null);
- try reg_locks.append(self.register_manager.lockReg(reg));
+ for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, *frame_index| switch (dst_arg) {
+ .none => {},
+ .register => |reg| {
+ try cg.register_manager.getReg(reg, null);
+ try reg_locks.append(allocator, cg.register_manager.lockReg(reg));
+ },
+ inline .register_pair, .register_triple, .register_quadruple => |regs| {
+ for (regs) |reg| try cg.register_manager.getReg(reg, null);
+ try reg_locks.appendSlice(allocator, &cg.register_manager.lockRegs(regs.len, regs));
+ },
+ .register_mask => |reg_mask| {
+ try cg.register_manager.getReg(reg_mask.reg, null);
+ try reg_locks.append(allocator, cg.register_manager.lockReg(reg_mask.reg));
+ },
+ .indirect => |reg_off| {
+ frame_index.* = try cg.allocFrameIndex(.initType(arg_ty, zcu));
+ try cg.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg, opts);
+ try cg.register_manager.getReg(reg_off.reg, null);
+ try reg_locks.append(allocator, cg.register_manager.lockReg(reg_off.reg));
+ },
+ .indirect_load_frame => |frame_addr| {
+ frame_index.* = try cg.allocFrameIndex(.initType(arg_ty, zcu));
+ try cg.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg, opts);
+ try cg.genSetMem(
+ .{ .frame = frame_addr.index },
+ frame_addr.off,
+ .usize,
+ .{ .lea_frame = .{ .index = frame_index.* } },
+ opts,
+ );
+ },
+ .indirect_mask => |reg_mask| {
+ var src = switch (src_arg) {
+ else => try cg.tempInit(arg_ty, src_arg),
+ .air_ref => |src_ref| try cg.tempFromOperand(src_ref, false),
+ };
+ var dst = try cg.tempInit(arg_ty, .{ .register_mask = .{
+ .reg = try cg.register_manager.allocReg(null, abi.RegisterClass.sse),
+ .info = reg_mask.info,
+ } });
+ dst.copyToMask(&src, cg) catch |err| switch (err) {
+ error.SelectFailed => return cg.fail("failed to select arg {f} {f} {f}", .{
+ arg_ty.fmt(pt),
+ dst.tracking(cg),
+ src.tracking(cg),
+ }),
+ else => |e| return e,
+ };
+ try src.die(cg);
+ const mask_size: u32 = @intCast(
+ @divExact(reg_mask.info.scalar.bitSize(cg.target), 8) * arg_ty.vectorLen(zcu),
+ );
+ frame_index.* = try cg.allocFrameIndex(.init(.{
+ .size = mask_size,
+ .alignment = .fromByteUnits(std.math.ceilPowerOfTwoAssert(u32, mask_size)),
+ }));
+ try cg.asmMemoryRegister(
+ .{ if (cg.hasFeature(.avx)) .v_dqa else ._dqa, .mov },
+ .{
+ .base = .{ .frame = frame_index.* },
+ .mod = .{ .rm = .{ .size = .fromSize(mask_size) } },
+ },
+ registerAlias(dst.tracking(cg).short.register_mask.reg, mask_size),
+ );
+ try dst.die(cg);
- if (fn_info.is_var_args and
- fn_info.cc == .x86_64_win and
- reg.class() == .sse and
- arg_i < abi.Win64.c_abi_int_param_regs.len)
- {
- // Floating point arguments must be duplicated into the equivalent integer registers on this ABI
- const int_reg = abi.Win64.c_abi_int_param_regs[arg_i];
- try reg_locks.append(self.register_manager.lockReg(int_reg));
- }
- },
- .register_pair => |regs| {
- for (regs) |reg| try self.register_manager.getReg(reg, null);
- try reg_locks.appendSlice(&self.register_manager.lockRegs(2, regs));
- },
- .indirect => |reg_off| {
- frame_index.* = try self.allocFrameIndex(.initType(arg_ty, zcu));
- try self.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg, opts);
- try self.register_manager.getReg(reg_off.reg, null);
- try reg_locks.append(self.register_manager.lockReg(reg_off.reg));
- },
- .load_frame => {
- try self.genCopy(arg_ty, dst_arg, src_arg, opts);
- try self.freeValue(src_arg, .{});
- },
- .elementwise_args => |regs_frame_addr| {
- const index_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
- const index_lock = self.register_manager.lockRegAssumeUnused(index_reg);
- defer self.register_manager.unlockReg(index_lock);
+ try cg.register_manager.getReg(reg_mask.reg, null);
+ try reg_locks.append(allocator, cg.register_manager.lockReg(reg_mask.reg));
+ },
+ .load_frame => {
+ try cg.genCopy(arg_ty, dst_arg, src_arg, opts);
+ try cg.freeValue(src_arg, .{});
+ },
+ .register_tee => |regs| {
+ try reg_locks.ensureUnusedCapacity(allocator, regs.len);
+ for (regs) |reg| if (reg != .none) {
+ try cg.register_manager.getReg(reg, null);
+ reg_locks.appendAssumeCapacity(cg.register_manager.lockReg(reg));
+ };
+ },
+ .elementwise_gpr, .elementwise_sse => |regs_frame_addr| {
+ const src_mem: Memory = if (src_arg.isBase()) try src_arg.mem(cg, .{ .size = .dword }) else .{
+ .base = .{ .reg = try cg.copyToTmpRegister(.usize, switch (src_arg) {
+ else => src_arg,
+ .air_ref => |src_ref| try cg.resolveInst(src_ref),
+ }.address()) },
+ .mod = .{ .rm = .{ .size = .dword } },
+ };
+ const src_lock = switch (src_mem.base) {
+ .reg => |src_reg| cg.register_manager.lockReg(src_reg),
+ else => null,
+ };
+ defer if (src_lock) |lock| cg.register_manager.unlockReg(lock);
+
+ const elem_rc: Register.Class, const param_regs = switch (dst_arg) {
+ else => unreachable,
+ .elementwise_gpr => .{ .general_purpose, abi.getCAbiIntParamRegs(fn_info.cc) },
+ .elementwise_sse => .{ .sse, abi.getCAbiSseParamRegs(fn_info.cc, cg.target) },
+ };
+ const len = arg_ty.vectorLen(zcu);
+ const param_reg_len: u31 =
+ @intCast(@min(param_regs.len - regs_frame_addr.info.reg_index, len));
- const src_mem: Memory = if (src_arg.isBase()) try src_arg.mem(self, .{ .size = .dword }) else .{
- .base = .{ .reg = try self.copyToTmpRegister(.usize, switch (src_arg) {
- else => src_arg,
- .air_ref => |src_ref| try self.resolveInst(src_ref),
- }.address()) },
- .mod = .{ .rm = .{ .size = .dword } },
- };
- const src_lock = switch (src_mem.base) {
- .reg => |src_reg| self.register_manager.lockReg(src_reg),
- else => null,
- };
- defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
+ if (len - param_reg_len > 0) {
+ const index_reg = try cg.register_manager.allocReg(null, abi.RegisterClass.gp);
+ const index_lock = cg.register_manager.lockRegAssumeUnused(index_reg);
+ defer cg.register_manager.unlockReg(index_lock);
+ try cg.asmRegisterImmediate(.{ ._, .mov }, index_reg.to32(), .u(param_reg_len));
- try self.asmRegisterImmediate(
- .{ ._, .mov },
- index_reg.to32(),
- .u(regs_frame_addr.regs),
- );
- const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
- try self.asmMemoryRegister(.{ ._, .bt }, src_mem, index_reg.to32());
- try self.asmSetccMemory(.c, .{
- .base = .{ .frame = regs_frame_addr.frame_index },
- .mod = .{ .rm = .{
- .size = .byte,
- .index = index_reg.to64(),
- .scale = .@"8",
- .disp = regs_frame_addr.frame_off - @as(u6, regs_frame_addr.regs) * 8,
- } },
- });
- if (self.hasFeature(.slow_incdec)) {
- try self.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), .u(1));
+ const loop: Mir.Inst.Index = @intCast(cg.mir_instructions.len);
+ const elem_ty = arg_ty.childType(zcu);
+ if (elem_ty.toIntern() == .bool_type) {
+ try cg.asmMemoryRegister(.{ ._, .bt }, src_mem, index_reg.to32());
+ try cg.asmSetccMemory(.c, .{
+ .base = .{ .frame = regs_frame_addr.frame_index },
+ .mod = .{ .rm = .{
+ .size = .byte,
+ .index = index_reg.to64(),
+ .scale = .@"8",
+ .disp = @as(i32, regs_frame_addr.info.frame_off) - 8 * param_reg_len,
+ } },
+ });
} else {
- try self.asmRegister(.{ ._c, .in }, index_reg.to32());
- }
- try self.asmRegisterImmediate(
- .{ ._, .cmp },
- index_reg.to32(),
- .u(arg_ty.vectorLen(zcu)),
- );
- _ = try self.asmJccReloc(.b, loop);
+ const elem_reg =
+ try cg.register_manager.allocReg(null, regSetForRegClass(elem_rc));
+ const elem_lock = cg.register_manager.lockRegAssumeUnused(elem_reg);
+ defer cg.register_manager.unlockReg(elem_lock);
+ const elem_size = cg.memSize(elem_ty, .general_purpose);
+ const elem_alias = elem_reg.toSize(elem_size, cg.target);
- const param_int_regs = abi.getCAbiIntParamRegs(fn_info.cc);
- for (param_int_regs[param_int_regs.len - regs_frame_addr.regs ..]) |dst_reg| {
- try self.register_manager.getReg(dst_reg, null);
- try reg_locks.append(self.register_manager.lockReg(dst_reg));
+ const strat = try cg.moveStrategy(elem_ty, elem_rc, true);
+ assert(src_mem.mod.rm.index == .none and src_mem.mod.rm.scale == .@"1");
+ try strat.read(cg, elem_alias, .{
+ .base = src_mem.base,
+ .mod = .{ .rm = .{
+ .size = elem_size,
+ .index = index_reg.to64(),
+ .scale = .fromFactor(@intCast(@divExact(elem_size.bitSize(cg.target), 8))),
+ .disp = src_mem.mod.rm.disp,
+ } },
+ });
+ try strat.write(cg, .{
+ .base = .{ .frame = regs_frame_addr.frame_index },
+ .mod = .{ .rm = .{
+ .size = elem_size,
+ .index = index_reg.to64(),
+ .scale = .@"8",
+ .disp = @as(i32, regs_frame_addr.info.frame_off) - 8 * param_reg_len,
+ } },
+ }, elem_alias);
+ }
+ if (cg.hasFeature(.slow_incdec)) {
+ try cg.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), .u(1));
+ } else {
+ try cg.asmRegister(.{ ._c, .in }, index_reg.to32());
}
- },
- else => unreachable,
- };
+ try cg.asmRegisterImmediate(.{ ._, .cmp }, index_reg.to32(), .u(len));
+ _ = try cg.asmJccReloc(.b, loop);
+ }
+
+ for (param_regs[regs_frame_addr.info.reg_index..][0..param_reg_len]) |dst_reg| {
+ try cg.register_manager.getReg(dst_reg, null);
+ try reg_locks.append(allocator, cg.register_manager.lockReg(dst_reg));
+ }
+ },
+ .xwordwise_sse, .ywordwise_sse, .zwordwise_sse => |regs_frame_addr| {
+ const elem_size: u31 = switch (dst_arg) {
+ else => unreachable,
+ .xwordwise_sse => 16,
+ .ywordwise_sse => 32,
+ .zwordwise_sse => 64,
+ };
+ const param_gpr_regs = abi.getCAbiIntParamRegs(fn_info.cc);
+ const arg_size: u31 = @intCast(arg_ty.abiSize(zcu));
+ const len = @divExact(arg_size, elem_size);
+ const param_gpr_len: u31 =
+ @intCast(@min(param_gpr_regs.len - regs_frame_addr.info.reg_index, len));
+
+ frame_index.* = try cg.allocFrameIndex(.initType(arg_ty, zcu));
+ try cg.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg, opts);
+
+ var frame_offset: i32 = regs_frame_addr.info.frame_off;
+ var arg_offset = elem_size * param_gpr_len;
+ while (arg_size - arg_offset > 0) : ({
+ frame_offset += 8;
+ arg_offset += elem_size;
+ }) try cg.genSetMem(
+ .{ .frame = regs_frame_addr.frame_index },
+ frame_offset,
+ .usize,
+ .{ .lea_frame = .{ .index = frame_index.*, .off = arg_offset } },
+ opts,
+ );
+
+ for (param_gpr_regs[regs_frame_addr.info.reg_index..][0..param_gpr_len]) |dst_reg| {
+ try cg.register_manager.getReg(dst_reg, null);
+ try reg_locks.append(allocator, cg.register_manager.lockReg(dst_reg));
+ }
+ },
+ else => unreachable,
+ };
if (call_info.err_ret_trace_reg != .none) {
- if (self.inst_tracking.getPtr(err_ret_trace_index)) |err_ret_trace| {
+ if (cg.inst_tracking.getPtr(err_ret_trace_index)) |err_ret_trace| {
if (switch (err_ret_trace.short) {
.register => |reg| call_info.err_ret_trace_reg != reg,
else => true,
}) {
- try self.register_manager.getReg(call_info.err_ret_trace_reg, err_ret_trace_index);
- try reg_locks.append(self.register_manager.lockReg(call_info.err_ret_trace_reg));
+ try cg.register_manager.getReg(call_info.err_ret_trace_reg, err_ret_trace_index);
+ try reg_locks.append(allocator, cg.register_manager.lockReg(call_info.err_ret_trace_reg));
- try self.genSetReg(call_info.err_ret_trace_reg, .usize, err_ret_trace.short, .{});
+ try cg.genSetReg(call_info.err_ret_trace_reg, .usize, err_ret_trace.short, opts);
err_ret_trace.trackMaterialize(err_ret_trace_index, .{
.long = err_ret_trace.long,
.short = .{ .register = call_info.err_ret_trace_reg },
@@ -176129,79 +176602,130 @@ fn genCall(self: *CodeGen, info: union(enum) {
.none, .unreach => {},
.indirect => |reg_off| {
const ret_ty: Type = .fromInterned(fn_info.return_type);
- const frame_index = try self.allocFrameIndex(.initSpill(ret_ty, zcu));
- try self.genSetReg(reg_off.reg, .usize, .{
+ const frame_index = try cg.allocFrameIndex(.initSpill(ret_ty, zcu));
+ try cg.genSetReg(reg_off.reg, .usize, .{
.lea_frame = .{ .index = frame_index, .off = -reg_off.off },
- }, .{});
+ }, opts);
call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };
- try reg_locks.append(self.register_manager.lockReg(reg_off.reg));
+ try reg_locks.append(allocator, cg.register_manager.lockReg(reg_off.reg));
},
else => unreachable,
}
- for (call_info.args, arg_types, args, frame_indices, 0..) |dst_arg, arg_ty, src_arg, frame_index, arg_i|
- switch (dst_arg) {
- .none, .load_frame => {},
- .register => |dst_reg| switch (fn_info.cc) {
- else => try self.genSetReg(registerAlias(
+ for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, frame_index| switch (dst_arg) {
+ .none, .load_frame, .indirect_load_frame => {},
+ .register => |dst_reg| try cg.genSetReg(registerAlias(
+ dst_reg,
+ @intCast(cg.unalignedSize(arg_ty)),
+ ), arg_ty, src_arg, opts),
+ .register_pair,
+ .register_triple,
+ .register_quadruple,
+ => try cg.genCopy(arg_ty, dst_arg, src_arg, opts),
+ .register_mask => {
+ var src = switch (src_arg) {
+ else => try cg.tempInit(arg_ty, src_arg),
+ .air_ref => |src_ref| try cg.tempFromOperand(src_ref, false),
+ };
+ var dst = try cg.tempInit(arg_ty, dst_arg);
+ dst.copyToMask(&src, cg) catch |err| switch (err) {
+ error.SelectFailed => return cg.fail("failed to select arg {f} {f} {f}", .{
+ arg_ty.fmt(pt),
+ dst.tracking(cg),
+ src.tracking(cg),
+ }),
+ else => |e| return e,
+ };
+ try src.die(cg);
+ try dst.die(cg);
+ },
+ .indirect => |dst_reg_off| try cg.genSetReg(dst_reg_off.reg, .usize, .{
+ .lea_frame = .{ .index = frame_index, .off = -dst_reg_off.off },
+ }, opts),
+ .indirect_mask => |dst_reg_mask| try cg.genSetReg(dst_reg_mask.reg, .usize, .{
+ .lea_frame = .{ .index = frame_index },
+ }, opts),
+ .register_tee => |dst_regs| {
+ try cg.genSetReg(dst_regs[0], arg_ty, src_arg, opts);
+ for (dst_regs[1..]) |dst_reg| if (dst_reg != .none) try cg.genSetReg(dst_reg, arg_ty, .{
+ .register = dst_regs[0],
+ }, opts);
+ },
+ .elementwise_gpr, .elementwise_sse => |regs_frame_addr| {
+ const src_mem: Memory = if (src_arg.isBase()) try src_arg.mem(cg, .{ .size = .dword }) else .{
+ .base = .{ .reg = try cg.copyToTmpRegister(
+ .usize,
+ switch (src_arg) {
+ else => src_arg,
+ .air_ref => |src_ref| try cg.resolveInst(src_ref),
+ }.address(),
+ ) },
+ .mod = .{ .rm = .{ .size = .dword } },
+ };
+ const src_lock = switch (src_mem.base) {
+ .reg => |src_reg| cg.register_manager.lockReg(src_reg),
+ else => null,
+ };
+ defer if (src_lock) |lock| cg.register_manager.unlockReg(lock);
+
+ const elem_rc: Register.Class, const param_regs = switch (dst_arg) {
+ else => unreachable,
+ .elementwise_gpr => .{ .general_purpose, abi.getCAbiIntParamRegs(fn_info.cc) },
+ .elementwise_sse => .{ .sse, abi.getCAbiSseParamRegs(fn_info.cc, cg.target) },
+ };
+ const len = arg_ty.vectorLen(zcu);
+ const elem_ty = arg_ty.childType(zcu);
+ const elem_size = cg.memSize(elem_ty, .general_purpose);
+ const elem_abi_size = @divExact(elem_size.bitSize(cg.target), 8);
+ const param_reg_len: u31 =
+ @intCast(@min(param_regs.len - regs_frame_addr.info.reg_index, len));
+ const strat = if (elem_ty.toIntern() == .bool_type) strat: {
+ try cg.spillEflagsIfOccupied();
+ break :strat undefined;
+ } else try cg.moveStrategy(elem_ty, elem_rc, true);
+ for (
+ param_regs[regs_frame_addr.info.reg_index..][0..param_reg_len],
+ 0..,
+ ) |dst_reg, elem_index| if (elem_ty.toIntern() == .bool_type) {
+ try cg.asmRegisterRegister(.{ ._, .xor }, dst_reg.to32(), dst_reg.to32());
+ try cg.asmMemoryImmediate(.{ ._, .bt }, src_mem, .u(elem_index));
+ try cg.asmSetccRegister(.c, dst_reg.to8());
+ } else try strat.read(cg, dst_reg.toSize(elem_size, cg.target), .{
+ .base = src_mem.base,
+ .mod = .{ .rm = .{
+ .size = elem_size,
+ .disp = src_mem.mod.rm.disp + @as(u31, @intCast(elem_abi_size * elem_index)),
+ } },
+ });
+ },
+ .xwordwise_sse, .ywordwise_sse, .zwordwise_sse => |regs_frame_addr| {
+ const elem_size: u31 = switch (dst_arg) {
+ else => unreachable,
+ .xwordwise_sse => 16,
+ .ywordwise_sse => 32,
+ .zwordwise_sse => 64,
+ };
+ const param_gpr_regs = abi.getCAbiIntParamRegs(fn_info.cc);
+ const len = @divExact(arg_ty.abiSize(zcu), elem_size);
+ const param_gpr_len: u31 =
+ @intCast(@min(param_gpr_regs.len - regs_frame_addr.info.reg_index, len));
+
+ var arg_offset: u31 = 0;
+ for (param_gpr_regs[regs_frame_addr.info.reg_index..][0..param_gpr_len]) |dst_reg| {
+ try cg.genSetReg(
dst_reg,
- @intCast(arg_ty.abiSize(zcu)),
- ), arg_ty, src_arg, opts),
- .x86_64_sysv, .x86_64_win => {
- const promoted_ty = self.promoteInt(arg_ty);
- const promoted_abi_size: u32 = @intCast(promoted_ty.abiSize(zcu));
- const dst_alias = registerAlias(dst_reg, promoted_abi_size);
- try self.genSetReg(dst_alias, promoted_ty, src_arg, opts);
- if (promoted_ty.toIntern() != arg_ty.toIntern())
- try self.truncateRegister(arg_ty, dst_alias);
-
- if (fn_info.is_var_args and
- fn_info.cc == .x86_64_win and
- dst_reg.class() == .sse and
- arg_i < abi.Win64.c_abi_int_param_regs.len)
- {
- const int_dst_reg = abi.Win64.c_abi_int_param_regs[arg_i];
- const int_dst_alias = registerAlias(int_dst_reg, promoted_abi_size);
- try self.genSetReg(int_dst_alias, promoted_ty, .{ .register = dst_alias }, opts);
- }
- },
- },
- .register_pair => try self.genCopy(arg_ty, dst_arg, src_arg, opts),
- .indirect => |reg_off| try self.genSetReg(reg_off.reg, .usize, .{
- .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
- }, .{}),
- .elementwise_args => |regs_frame_addr| {
- const src_mem: Memory = if (src_arg.isBase()) try src_arg.mem(self, .{ .size = .dword }) else .{
- .base = .{ .reg = try self.copyToTmpRegister(
- .usize,
- switch (src_arg) {
- else => src_arg,
- .air_ref => |src_ref| try self.resolveInst(src_ref),
- }.address(),
- ) },
- .mod = .{ .rm = .{ .size = .dword } },
- };
- const src_lock = switch (src_mem.base) {
- .reg => |src_reg| self.register_manager.lockReg(src_reg),
- else => null,
- };
- defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
-
- const param_int_regs = abi.getCAbiIntParamRegs(fn_info.cc);
- for (
- param_int_regs[param_int_regs.len - regs_frame_addr.regs ..],
- 0..,
- ) |dst_reg, elem_index| {
- try self.asmRegisterRegister(.{ ._, .xor }, dst_reg.to32(), dst_reg.to32());
- try self.asmMemoryImmediate(.{ ._, .bt }, src_mem, .u(elem_index));
- try self.asmSetccRegister(.c, dst_reg.to8());
- }
- },
- else => unreachable,
- };
+ .usize,
+ .{ .lea_frame = .{ .index = frame_index, .off = arg_offset } },
+ opts,
+ );
+ arg_offset += elem_size;
+ }
+ },
+ else => unreachable,
+ };
if (fn_info.is_var_args and fn_info.cc == .x86_64_sysv)
- try self.asmRegisterImmediate(.{ ._, .mov }, .al, .u(call_info.fp_count));
+ try cg.asmRegisterImmediate(.{ ._, .mov }, .al, .u(call_info.fp_count));
// Due to incremental compilation, how function calls are generated depends
// on linking.
@@ -176216,45 +176740,57 @@ fn genCall(self: *CodeGen, info: union(enum) {
} else func_key,
}) {
else => unreachable,
- .func => |func| try self.asmImmediate(.{ ._, .call }, .{ .nav = .{ .index = func.owner_nav } }),
- .@"extern" => |@"extern"| try self.asmImmediate(.{ ._, .call }, .{ .nav = .{ .index = @"extern".owner_nav } }),
+ .func => |func| try cg.asmImmediate(.{ ._, .call }, .{ .nav = .{ .index = func.owner_nav } }),
+ .@"extern" => |@"extern"| try cg.asmImmediate(.{ ._, .call }, .{ .nav = .{ .index = @"extern".owner_nav } }),
}
} else {
- assert(self.typeOf(callee).zigTypeTag(zcu) == .pointer);
+ assert(cg.typeOf(callee).zigTypeTag(zcu) == .pointer);
const scratch_reg = abi.getCAbiLinkerScratchReg(fn_info.cc);
- try self.genSetReg(scratch_reg, .usize, .{ .air_ref = callee }, .{});
- try self.asmRegister(.{ ._, .call }, scratch_reg);
+ try cg.genSetReg(scratch_reg, .usize, .{ .air_ref = callee }, opts);
+ try cg.asmRegister(.{ ._, .call }, scratch_reg);
},
- .extern_func => |extern_func| try self.asmImmediate(.{ ._, .call }, .{ .extern_func = try self.addString(extern_func.sym) }),
+ .extern_func => |extern_func| try cg.asmImmediate(.{ ._, .call }, .{ .extern_func = try cg.addString(extern_func.sym) }),
}
return call_info.return_value.short;
}
-fn airRet(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
- const pt = self.pt;
- const zcu = pt.zcu;
- const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
+fn airRet(cg: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
+ const un_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
- const ret_ty = self.fn_type.fnReturnType(zcu);
- switch (self.ret_mcv.short) {
+ const ret_ty = cg.fn_type.fnReturnType(cg.pt.zcu);
+ switch (cg.ret_mcv.short) {
.none => {},
.register => |reg| {
- const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
- defer self.register_manager.unlockReg(reg_lock);
- try self.genCopy(ret_ty, self.ret_mcv.short, .{ .air_ref = un_op }, .{ .safety = safety });
+ const reg_lock = cg.register_manager.lockRegAssumeUnused(reg);
+ defer cg.register_manager.unlockReg(reg_lock);
+ try cg.genCopy(ret_ty, cg.ret_mcv.short, .{ .air_ref = un_op }, .{ .safety = safety });
},
inline .register_pair, .register_triple, .register_quadruple => |regs| {
- const reg_locks = self.register_manager.lockRegsAssumeUnused(regs.len, regs);
- defer for (reg_locks) |reg_lock| self.register_manager.unlockReg(reg_lock);
- try self.genCopy(ret_ty, self.ret_mcv.short, .{ .air_ref = un_op }, .{ .safety = safety });
+ const reg_locks = cg.register_manager.lockRegsAssumeUnused(regs.len, regs);
+ defer for (reg_locks) |reg_lock| cg.register_manager.unlockReg(reg_lock);
+ try cg.genCopy(ret_ty, cg.ret_mcv.short, .{ .air_ref = un_op }, .{ .safety = safety });
+ },
+ .register_mask => {
+ var src = try cg.tempFromOperand(un_op, true);
+ var dst = try cg.tempInit(ret_ty, cg.ret_mcv.short);
+ dst.copyToMask(&src, cg) catch |err| switch (err) {
+ error.SelectFailed => return cg.fail("failed to select ret {f} {f} {f}", .{
+ ret_ty.fmt(cg.pt),
+ dst.tracking(cg),
+ src.tracking(cg),
+ }),
+ else => |e| return e,
+ };
+ try src.die(cg);
+ try dst.die(cg);
},
.indirect => |reg_off| {
- try self.register_manager.getReg(reg_off.reg, null);
- const lock = self.register_manager.lockRegAssumeUnused(reg_off.reg);
- defer self.register_manager.unlockReg(lock);
+ try cg.register_manager.getReg(reg_off.reg, null);
+ const lock = cg.register_manager.lockRegAssumeUnused(reg_off.reg);
+ defer cg.register_manager.unlockReg(lock);
- try self.genSetReg(reg_off.reg, .usize, self.ret_mcv.long, .{});
- try self.genSetMem(
+ try cg.genSetReg(reg_off.reg, .usize, cg.ret_mcv.long, .{});
+ try cg.genSetMem(
.{ .reg = reg_off.reg },
reg_off.off,
ret_ty,
@@ -176264,55 +176800,78 @@ fn airRet(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
},
else => unreachable,
}
- self.ret_mcv.liveOut(self, inst);
+ cg.ret_mcv.liveOut(cg, inst);
- if (self.err_ret_trace_reg != .none) {
- if (self.inst_tracking.getPtr(err_ret_trace_index)) |err_ret_trace| {
+ if (cg.err_ret_trace_reg != .none) {
+ if (cg.inst_tracking.getPtr(err_ret_trace_index)) |err_ret_trace| {
if (switch (err_ret_trace.short) {
- .register => |reg| self.err_ret_trace_reg != reg,
+ .register => |reg| cg.err_ret_trace_reg != reg,
else => true,
- }) try self.genSetReg(self.err_ret_trace_reg, .usize, err_ret_trace.short, .{});
- err_ret_trace.liveOut(self, err_ret_trace_index);
+ }) try cg.genSetReg(cg.err_ret_trace_reg, .usize, err_ret_trace.short, .{});
+ err_ret_trace.liveOut(cg, err_ret_trace_index);
}
}
- try self.finishAir(inst, .unreach, .{ un_op, .none, .none });
+ try cg.finishAir(inst, .unreach, .{ un_op, .none, .none });
// TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction
// which is available if the jump is 127 bytes or less forward.
- const jmp_reloc = try self.asmJmpReloc(undefined);
- try self.epilogue_relocs.append(self.gpa, jmp_reloc);
+ const jmp_reloc = try cg.asmJmpReloc(undefined);
+ try cg.epilogue_relocs.append(cg.gpa, jmp_reloc);
}
-fn airRetLoad(self: *CodeGen, inst: Air.Inst.Index) !void {
- const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
- const ptr = try self.resolveInst(un_op);
-
- const ptr_ty = self.typeOf(un_op);
- switch (self.ret_mcv.short) {
+fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) !void {
+ const un_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
+ switch (cg.ret_mcv.short) {
.none => {},
- .register, .register_pair => try self.load(self.ret_mcv.short, ptr_ty, ptr),
- .indirect => |reg_off| try self.genSetReg(reg_off.reg, ptr_ty, ptr, .{}),
+ .register,
+ .register_pair,
+ .register_triple,
+ .register_quadruple,
+ => try cg.load(cg.ret_mcv.short, cg.typeOf(un_op), try cg.resolveInst(un_op)),
+ .register_mask => {
+ var ptr = try cg.tempFromOperand(un_op, true);
+ const ret_ty = ptr.typeOf(cg).childType(cg.pt.zcu);
+ var src = try ptr.load(ret_ty, .{}, cg);
+ try ptr.die(cg);
+ var dst = try cg.tempInit(ret_ty, cg.ret_mcv.short);
+ dst.copyToMask(&src, cg) catch |err| switch (err) {
+ error.SelectFailed => return cg.fail("failed to select ret_load {f} {f} {f}", .{
+ ret_ty.fmt(cg.pt),
+ dst.tracking(cg),
+ src.tracking(cg),
+ }),
+ else => |e| return e,
+ };
+ try src.die(cg);
+ try dst.die(cg);
+ },
+ .indirect => |dst_reg_off| try cg.genSetReg(
+ dst_reg_off.reg,
+ cg.typeOf(un_op),
+ try cg.resolveInst(un_op),
+ .{},
+ ),
else => unreachable,
}
- self.ret_mcv.liveOut(self, inst);
+ cg.ret_mcv.liveOut(cg, inst);
- if (self.err_ret_trace_reg != .none) {
- if (self.inst_tracking.getPtr(err_ret_trace_index)) |err_ret_trace| {
+ if (cg.err_ret_trace_reg != .none) {
+ if (cg.inst_tracking.getPtr(err_ret_trace_index)) |err_ret_trace| {
if (switch (err_ret_trace.short) {
- .register => |reg| self.err_ret_trace_reg != reg,
+ .register => |reg| cg.err_ret_trace_reg != reg,
else => true,
- }) try self.genSetReg(self.err_ret_trace_reg, .usize, err_ret_trace.short, .{});
- err_ret_trace.liveOut(self, err_ret_trace_index);
+ }) try cg.genSetReg(cg.err_ret_trace_reg, .usize, err_ret_trace.short, .{});
+ err_ret_trace.liveOut(cg, err_ret_trace_index);
}
}
- try self.finishAir(inst, .unreach, .{ un_op, .none, .none });
+ try cg.finishAir(inst, .unreach, .{ un_op, .none, .none });
// TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction
// which is available if the jump is 127 bytes or less forward.
- const jmp_reloc = try self.asmJmpReloc(undefined);
- try self.epilogue_relocs.append(self.gpa, jmp_reloc);
+ const jmp_reloc = try cg.asmJmpReloc(undefined);
+ try cg.epilogue_relocs.append(cg.gpa, jmp_reloc);
}
fn airTry(self: *CodeGen, inst: Air.Inst.Index) !void {
@@ -176504,17 +177063,13 @@ fn isErrPtr(self: *CodeGen, maybe_inst: ?Air.Inst.Index, ptr_ty: Type, ptr_mcv:
defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
const err_off: u31 = @intCast(codegen.errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu));
- try self.asmMemoryImmediate(
- .{ ._, .cmp },
- .{
- .base = .{ .reg = ptr_reg },
- .mod = .{ .rm = .{
- .size = self.memSize(.anyerror),
- .disp = err_off,
- } },
- },
- .u(0),
- );
+ try self.asmMemoryImmediate(.{ ._, .cmp }, .{
+ .base = .{ .reg = ptr_reg },
+ .mod = .{ .rm = .{
+ .size = self.memSize(.anyerror, .general_purpose),
+ .disp = err_off,
+ } },
+ }, .u(0));
if (maybe_inst) |inst| self.eflags_inst = inst;
return MCValue{ .eflags = .a };
@@ -176662,7 +177217,7 @@ fn lowerSwitchBr(
};
const condition_index_lock = cg.register_manager.lockReg(condition_index_reg);
defer if (condition_index_lock) |lock| cg.register_manager.unlockReg(lock);
- try cg.truncateRegister(condition_ty, condition_index_reg);
+ try cg.truncateRegister(unsigned_condition_ty, condition_index_reg);
const ptr_size = @divExact(cg.target.ptrBitWidth(), 8);
try cg.asmMemory(.{ ._mp, .j }, .{
.base = .table,
@@ -177138,13 +177693,13 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
const inputs = unwrapped_asm.inputs;
var result: MCValue = .none;
- var args: std.array_list.Managed(MCValue) = .init(self.gpa);
- try args.ensureTotalCapacity(outputs.len + inputs.len);
+ var args = try self.gpa.alloc(MCValue, outputs.len + inputs.len);
+ var args_len: usize = 0;
defer {
- for (args.items) |arg| if (arg.getReg()) |reg| self.register_manager.unlockReg(.{
+ for (args[0..args_len]) |arg| if (arg.getReg()) |reg| self.register_manager.unlockReg(.{
.tracked_index = RegisterManager.indexOfRegIntoTracked(reg) orelse continue,
});
- args.deinit();
+ self.gpa.free(args);
}
var arg_map: std.StringHashMap(u8) = .init(self.gpa);
try arg_map.ensureTotalCapacity(@intCast(outputs.len + inputs.len));
@@ -177203,10 +177758,10 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
return self.fail("invalid register constraint: '{s}'", .{out.constraint})
else if (rest.len == 1 and std.ascii.isDigit(rest[0])) {
const index = std.fmt.charToDigit(rest[0], 10) catch unreachable;
- if (index >= args.items.len) return self.fail("constraint out of bounds: '{s}'", .{
+ if (index >= args_len) return self.fail("constraint out of bounds: '{s}'", .{
out.constraint,
});
- break :arg_mcv args.items[index];
+ break :arg_mcv args[index];
} else return self.fail("invalid constraint: '{s}'", .{out.constraint});
break :arg_mcv if (arg_maybe_reg) |reg| .{ .register = reg } else arg: {
const ptr_mcv = try self.resolveInst(out.operand);
@@ -177224,8 +177779,9 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
_ = self.register_manager.lockRegIndexAssumeUnused(tracked_index);
};
if (!std.mem.eql(u8, out.name, "_"))
- arg_map.putAssumeCapacityNoClobber(out.name, @intCast(args.items.len));
- args.appendAssumeCapacity(arg_mcv);
+ arg_map.putAssumeCapacityNoClobber(out.name, @intCast(args_len));
+ args[args_len] = arg_mcv;
+ args_len += 1;
if (out.operand == .none) result = arg_mcv;
if (is_read) try self.load(arg_mcv, self.typeOf(out.operand), .{ .air_ref = out.operand });
}
@@ -177308,17 +177864,19 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
break :arg .{ .register = reg };
} else if (in.constraint.len == 1 and std.ascii.isDigit(in.constraint[0])) arg: {
const index = std.fmt.charToDigit(in.constraint[0], 10) catch unreachable;
- if (index >= args.items.len) return self.fail("constraint out of bounds: '{s}'", .{in.constraint});
- try self.genCopy(ty, args.items[index], input_mcv, .{});
- break :arg args.items[index];
+ if (index >= args_len) return self.fail("constraint out of bounds: '{s}'", .{in.constraint});
+ try self.genCopy(ty, args[index], input_mcv, .{});
+ break :arg args[index];
} else return self.fail("invalid constraint: '{s}'", .{in.constraint});
if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |_| {
_ = self.register_manager.lockReg(reg);
};
if (!std.mem.eql(u8, in.name, "_"))
- arg_map.putAssumeCapacityNoClobber(in.name, @intCast(args.items.len));
- args.appendAssumeCapacity(arg_mcv);
+ arg_map.putAssumeCapacityNoClobber(in.name, @intCast(args_len));
+ args[args_len] = arg_mcv;
+ args_len += 1;
}
+ assert(args_len == args.len);
const ip = &zcu.intern_pool;
const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers);
@@ -177469,6 +178027,10 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
fixed_mnem_size: {
const fixed_mnem_size: Memory.Size = switch (mnem_tag) {
.clflush => .byte,
+ .crc32 => {
+ mnem_size.op_has_size.unset(1);
+ break :fixed_mnem_size;
+ },
.fldcw, .fnstcw, .fstcw, .fnstsw, .fstsw => .word,
.fldenv, .fnstenv, .fstenv => .none,
.frstor, .fsave, .fnsave, .fxrstor, .fxrstor64, .fxsave, .fxsave64 => .none,
@@ -177551,7 +178113,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
op_str[colon_pos + ":".len .. op_str.len - "]".len]
else
"";
- op.* = switch (args.items[
+ op.* = switch (args[
arg_map.get(op_str["%[".len .. colon orelse op_str.len - "]".len]) orelse
return self.fail("no matching constraint: '{s}'", .{op_str})
]) {
@@ -177695,7 +178257,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
op_str[colon_pos + ":".len .. open - "]".len]
else
"";
- break :disp switch (args.items[
+ break :disp switch (args[
arg_map.get(op_str["%[".len .. colon orelse open - "]".len]) orelse
return self.fail("no matching constraint: '{s}'", .{op_str})
]) {
@@ -177855,7 +178417,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
it = unwrapped_asm.iterateOutputs();
while (it.next()) |out| {
- const arg_mcv = args.items[it.current - 1];
+ const arg_mcv = args[it.current - 1];
if (out.operand == .none) continue;
if (arg_mcv != .register) continue;
if (out.constraint.len == 2 and std.ascii.isDigit(out.constraint[1])) continue;
@@ -178297,12 +178859,18 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
.register_overflow,
.register_mask,
.indirect_load_frame,
+ .indirect_mask,
.lea_frame,
.lea_nav,
.lea_uav,
.lea_lazy_sym,
.lea_extern_func,
- .elementwise_args,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
.air_ref,
=> unreachable, // unmodifiable destination
@@ -178313,7 +178881,12 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
.dead,
.undef,
.register_overflow,
- .elementwise_args,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
=> unreachable,
.immediate,
@@ -178414,9 +178987,9 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
for ([_]bool{ false, true }) |emit_hazard| {
var hazard_count: u3 = 0;
- var part_disp: i32 = 0;
+ var part_disp: u31 = 0;
for (dst_regs, try self.splitType(dst_regs.len, ty), 0..) |dst_reg, dst_ty, part_i| {
- defer part_disp += @intCast(dst_ty.abiSize(pt.zcu));
+ defer part_disp += @intCast(self.unalignedSize(dst_ty));
const is_hazard = if (src_mcv.getReg()) |src_reg|
dst_reg.id() == src_reg.id()
else if (src_info) |info|
@@ -178483,36 +179056,45 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
}
fn genSetReg(
- self: *CodeGen,
+ cg: *CodeGen,
dst_reg: Register,
ty: Type,
src_mcv: MCValue,
opts: CopyOptions,
) InnerError!void {
- const pt = self.pt;
+ const pt = cg.pt;
const zcu = pt.zcu;
const abi_size: u32 = @intCast(ty.abiSize(zcu));
- const dst_alias = registerAlias(dst_reg, abi_size);
- if (ty.bitSize(zcu) > dst_alias.size().bitSize(self.target))
- return self.fail("genSetReg called with a value larger than dst_reg", .{});
+ const dst_alias = registerAlias(dst_reg, @intCast(cg.unalignedSize(ty)));
+ {
+ const ty_bit_size = if (ty.hasBitRepresentation(zcu)) ty.bitSize(zcu) else 8 * abi_size;
+ if (ty_bit_size > dst_alias.size().bitSize(cg.target))
+ return cg.fail("genSetReg called with a value larger than dst_reg", .{});
+ }
switch (src_mcv) {
.none,
.unreach,
.dead,
.indirect_load_frame,
- .elementwise_args,
+ .indirect_mask,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
=> unreachable,
.undef => if (opts.safety) switch (dst_reg.class()) {
.general_purpose, .gphi => switch (abi_size) {
- 1 => try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to8(), .u(0xaa)),
- 2 => try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to16(), .u(0xaaaa)),
- 3...4 => try self.asmRegisterImmediate(
+ 1 => try cg.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to8(), .u(0xaa)),
+ 2 => try cg.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to16(), .u(0xaaaa)),
+ 3...4 => try cg.asmRegisterImmediate(
.{ ._, .mov },
dst_reg.to32(),
.s(@as(i32, @bitCast(@as(u32, 0xaaaaaaaa)))),
),
- 5...8 => try self.asmRegisterImmediate(
+ 5...8 => try cg.asmRegisterImmediate(
.{ ._, .mov },
dst_reg.to64(),
.u(0xaaaaaaaaaaaaaaaa),
@@ -178521,36 +179103,36 @@ fn genSetReg(
},
.segment, .mmx, .sse => {
const full_ty = try pt.vectorType(.{
- .len = self.vectorSize(.float),
+ .len = cg.vectorSize(.float),
.child = .u8_type,
});
- try self.genSetReg(dst_reg, full_ty, try self.lowerValue(
+ try cg.genSetReg(dst_reg, full_ty, try cg.lowerValue(
try pt.aggregateSplatValue(full_ty, try pt.intValue(.u8, 0xaa)),
), opts);
},
- .x87 => try self.genSetReg(dst_reg, .f80, try self.lowerValue(
+ .x87 => try cg.genSetReg(dst_reg, .f80, try cg.lowerValue(
try pt.floatValue(.f80, @as(f80, @bitCast(@as(u80, 0xaaaaaaaaaaaaaaaaaaaa)))),
), opts),
.ip, .cr, .dr => unreachable,
},
- .eflags => |cc| try self.asmSetccRegister(cc, dst_reg.to8()),
+ .eflags => |cc| try cg.asmSetccRegister(cc, dst_reg.to8()),
.immediate => |imm| {
if (imm == 0) {
// 32-bit moves zero-extend to 64-bit, so xoring the 32-bit
// register is the fastest way to zero a register.
- try self.spillEflagsIfOccupied();
- try self.asmRegisterRegister(.{ ._, .xor }, dst_reg.to32(), dst_reg.to32());
+ try cg.spillEflagsIfOccupied();
+ try cg.asmRegisterRegister(.{ ._, .xor }, dst_reg.to32(), dst_reg.to32());
} else if (abi_size > 4 and std.math.cast(u32, imm) != null) {
// 32-bit moves zero-extend to 64-bit.
- try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to32(), .u(imm));
+ try cg.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to32(), .u(imm));
} else if (abi_size <= 4 and @as(i64, @bitCast(imm)) < 0) {
- try self.asmRegisterImmediate(
+ try cg.asmRegisterImmediate(
.{ ._, .mov },
dst_alias,
.s(@intCast(@as(i64, @bitCast(imm)))),
);
} else {
- try self.asmRegisterImmediate(
+ try cg.asmRegisterImmediate(
.{ ._, .mov },
dst_alias,
.u(imm),
@@ -178559,44 +179141,44 @@ fn genSetReg(
},
.register => |src_reg| if (dst_reg.id() != src_reg.id()) switch (dst_reg.class()) {
.general_purpose => switch (src_reg.class()) {
- .general_purpose => try self.asmRegisterRegister(
+ .general_purpose => try cg.asmRegisterRegister(
.{ ._, .mov },
dst_alias,
- registerAlias(src_reg, abi_size),
+ registerAlias(src_reg, @intCast(cg.unalignedSize(ty))),
),
- .gphi => if (dst_reg.isClass(.gphi)) try self.asmRegisterRegister(
+ .gphi => if (dst_reg.isClass(.gphi)) try cg.asmRegisterRegister(
.{ ._, .mov },
dst_alias,
- registerAlias(src_reg, abi_size),
+ registerAlias(src_reg, @intCast(cg.unalignedSize(ty))),
) else {
- const src_lock = self.register_manager.lockReg(src_reg);
- defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
- const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gphi);
+ const src_lock = cg.register_manager.lockReg(src_reg);
+ defer if (src_lock) |lock| cg.register_manager.unlockReg(lock);
+ const tmp_reg = try cg.register_manager.allocReg(null, abi.RegisterClass.gphi);
- try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg.to8(), src_reg);
- try self.asmRegisterRegister(.{ ._, .mov }, dst_alias, tmp_reg.to8());
+ try cg.asmRegisterRegister(.{ ._, .mov }, tmp_reg.to8(), src_reg);
+ try cg.asmRegisterRegister(.{ ._, .mov }, dst_alias, tmp_reg.to8());
},
- .segment => try self.asmRegisterRegister(
+ .segment => try cg.asmRegisterRegister(
.{ ._, .mov },
dst_alias,
src_reg,
),
.x87, .mmx, .ip, .cr, .dr => unreachable,
- .sse => if (self.hasFeature(.sse2)) try self.asmRegisterRegister(
+ .sse => if (cg.hasFeature(.sse2)) try cg.asmRegisterRegister(
switch (abi_size) {
- 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },
- 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov },
+ 1...4 => if (cg.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },
+ 5...8 => if (cg.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov },
else => unreachable,
},
- registerAlias(dst_reg, @max(abi_size, 4)),
+ registerAlias(dst_reg, @intCast(@max(cg.unalignedSize(ty), 4))),
src_reg.to128(),
) else {
const frame_size = std.math.ceilPowerOfTwoAssert(u32, @max(abi_size, 4));
- const frame_index = try self.allocFrameIndex(.init(.{
+ const frame_index = try cg.allocFrameIndex(.init(.{
.size = frame_size,
.alignment = .fromNonzeroByteUnits(frame_size),
}));
- try self.asmMemoryRegister(switch (frame_size) {
+ try cg.asmMemoryRegister(switch (frame_size) {
4 => .{ ._ss, .mov },
8 => .{ ._ps, .movl },
16 => .{ ._ps, .mov },
@@ -178605,82 +179187,85 @@ fn genSetReg(
.base = .{ .frame = frame_index },
.mod = .{ .rm = .{ .size = .fromSize(frame_size) } },
}, src_reg.to128());
- try self.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
+ try cg.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
.base = .{ .frame = frame_index },
.mod = .{ .rm = .{ .size = .fromSize(abi_size) } },
});
},
},
.gphi => switch (src_reg.class()) {
- .general_purpose => if (src_reg.isClass(.gphi)) try self.asmRegisterRegister(
+ .general_purpose => if (src_reg.isClass(.gphi)) try cg.asmRegisterRegister(
.{ ._, .mov },
dst_alias,
- registerAlias(src_reg, abi_size),
+ registerAlias(src_reg, @intCast(cg.unalignedSize(ty))),
) else {
- const dst_lock = self.register_manager.lockReg(dst_reg);
- defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
- const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gphi);
+ const dst_lock = cg.register_manager.lockReg(dst_reg);
+ defer if (dst_lock) |lock| cg.register_manager.unlockReg(lock);
+ const tmp_reg = try cg.register_manager.allocReg(null, abi.RegisterClass.gphi);
- try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg.to8(), src_reg.to8());
- try self.asmRegisterRegister(.{ ._, .mov }, dst_reg, tmp_reg.to8());
+ try cg.asmRegisterRegister(.{ ._, .mov }, tmp_reg.to8(), src_reg.to8());
+ try cg.asmRegisterRegister(.{ ._, .mov }, dst_reg, tmp_reg.to8());
},
- .gphi => try self.asmRegisterRegister(
+ .gphi => try cg.asmRegisterRegister(
.{ ._, .mov },
dst_alias,
- registerAlias(src_reg, abi_size),
+ registerAlias(src_reg, @intCast(cg.unalignedSize(ty))),
),
.segment, .x87, .mmx, .ip, .cr, .dr, .sse => unreachable,
},
- .segment => try self.asmRegisterRegister(
+ .segment => try cg.asmRegisterRegister(
.{ ._, .mov },
dst_reg,
switch (src_reg.class()) {
- .general_purpose, .gphi, .segment => registerAlias(src_reg, abi_size),
+ .general_purpose,
+ .gphi,
+ .segment,
+ => registerAlias(src_reg, @intCast(cg.unalignedSize(ty))),
.x87, .mmx, .ip, .cr, .dr => unreachable,
- .sse => try self.copyToTmpRegister(ty, src_mcv),
+ .sse => try cg.copyToTmpRegister(ty, src_mcv),
},
),
.x87 => switch (src_reg.class()) {
.general_purpose, .gphi, .segment, .mmx, .ip, .cr, .dr => unreachable,
.x87 => switch (src_reg) {
- .st0 => try self.asmRegister(.{ .f_, .st }, dst_reg),
+ .st0 => try cg.asmRegister(.{ .f_, .st }, dst_reg),
.st1, .st2, .st3, .st4, .st5, .st6 => switch (dst_reg) {
.st0 => {
- try self.asmRegister(.{ .f_p, .st }, .st0);
- try self.asmRegister(.{ .f_, .ld }, @enumFromInt(@intFromEnum(src_reg) - 1));
+ try cg.asmRegister(.{ .f_p, .st }, .st0);
+ try cg.asmRegister(.{ .f_, .ld }, @enumFromInt(@intFromEnum(src_reg) - 1));
},
- .st2, .st3, .st4, .st5, .st6 => if (self.register_manager.isKnownRegFree(.st7)) {
- try self.asmRegister(.{ .f_, .ld }, src_reg);
- try self.asmRegister(.{ .f_p, .st }, @enumFromInt(@intFromEnum(dst_reg) + 1));
+ .st2, .st3, .st4, .st5, .st6 => if (cg.register_manager.isKnownRegFree(.st7)) {
+ try cg.asmRegister(.{ .f_, .ld }, src_reg);
+ try cg.asmRegister(.{ .f_p, .st }, @enumFromInt(@intFromEnum(dst_reg) + 1));
} else {
- try self.asmRegister(.{ .f_, .xch }, src_reg);
- try self.asmRegister(.{ .f_, .xch }, dst_reg);
- try self.asmRegister(.{ .f_, .xch }, src_reg);
+ try cg.asmRegister(.{ .f_, .xch }, src_reg);
+ try cg.asmRegister(.{ .f_, .xch }, dst_reg);
+ try cg.asmRegister(.{ .f_, .xch }, src_reg);
},
.st7 => {
- if (!self.register_manager.isKnownRegFree(.st7)) try self.asmRegister(.{ .f_, .free }, dst_reg);
- try self.asmRegister(.{ .f_, .ld }, src_reg);
- try self.asmOpOnly(.{ .f_cstp, .in });
+ if (!cg.register_manager.isKnownRegFree(.st7)) try cg.asmRegister(.{ .f_, .free }, dst_reg);
+ try cg.asmRegister(.{ .f_, .ld }, src_reg);
+ try cg.asmOpOnly(.{ .f_cstp, .in });
},
else => unreachable,
},
else => unreachable,
},
.sse => if (abi_size <= 16) {
- const frame_index = try self.allocFrameIndex(.init(.{
+ const frame_index = try cg.allocFrameIndex(.init(.{
.size = 16,
.alignment = .@"16",
}));
- try self.asmMemoryRegister(if (self.hasFeature(.avx))
+ try cg.asmMemoryRegister(if (cg.hasFeature(.avx))
.{ .v_dqa, .mov }
- else if (self.hasFeature(.sse2))
+ else if (cg.hasFeature(.sse2))
.{ ._dqa, .mov }
else
.{ ._ps, .mova }, .{
.base = .{ .frame = frame_index },
.mod = .{ .rm = .{ .size = .xword } },
}, src_reg.to128());
- try MoveStrategy.read(.load_store_x87, self, dst_reg, .{
+ try MoveStrategy.read(.load_store_x87, cg, dst_reg, .{
.base = .{ .frame = frame_index },
.mod = .{ .rm = .{ .size = .tbyte } },
});
@@ -178688,29 +179273,29 @@ fn genSetReg(
},
.mmx => unreachable,
.sse => switch (src_reg.class()) {
- .general_purpose, .gphi => if (self.hasFeature(.sse2)) try self.asmRegisterRegister(
+ .general_purpose, .gphi => if (cg.hasFeature(.sse2)) try cg.asmRegisterRegister(
switch (abi_size) {
- 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },
- 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov },
+ 1...4 => if (cg.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },
+ 5...8 => if (cg.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov },
else => unreachable,
},
dst_reg.to128(),
- registerAlias(src_reg, @max(abi_size, 4)),
+ registerAlias(src_reg, @intCast(@max(cg.unalignedSize(ty), 4))),
) else {
const frame_size = std.math.ceilPowerOfTwoAssert(u32, @max(abi_size, 4));
- const frame_index = try self.allocFrameIndex(.init(.{
+ const frame_index = try cg.allocFrameIndex(.init(.{
.size = frame_size,
.alignment = .fromNonzeroByteUnits(frame_size),
}));
- try self.asmMemoryRegister(.{ ._, .mov }, .{
+ try cg.asmMemoryRegister(.{ ._, .mov }, .{
.base = .{ .frame = frame_index },
.mod = .{ .rm = .{ .size = .fromSize(abi_size) } },
- }, registerAlias(src_reg, abi_size));
+ }, registerAlias(src_reg, @intCast(cg.unalignedSize(ty))));
switch (frame_size) {
else => {},
- 8 => try self.asmRegisterRegister(.{ ._ps, .xor }, dst_reg.to128(), dst_reg.to128()),
+ 8 => try cg.asmRegisterRegister(.{ ._ps, .xor }, dst_reg.to128(), dst_reg.to128()),
}
- try self.asmRegisterMemory(switch (frame_size) {
+ try cg.asmRegisterMemory(switch (frame_size) {
4 => .{ ._ss, .mov },
8 => .{ ._ps, .movl },
16 => .{ ._ps, .mova },
@@ -178720,24 +179305,24 @@ fn genSetReg(
.mod = .{ .rm = .{ .size = .fromSize(frame_size) } },
});
},
- .segment => try self.genSetReg(
+ .segment => try cg.genSetReg(
dst_reg,
ty,
- .{ .register = try self.copyToTmpRegister(ty, src_mcv) },
+ .{ .register = try cg.copyToTmpRegister(ty, src_mcv) },
opts,
),
.x87 => if (abi_size <= 16) {
- const frame_index = try self.allocFrameIndex(.init(.{
+ const frame_index = try cg.allocFrameIndex(.init(.{
.size = 16,
.alignment = .@"16",
}));
- try MoveStrategy.write(.load_store_x87, self, .{
+ try MoveStrategy.write(.load_store_x87, cg, .{
.base = .{ .frame = frame_index },
.mod = .{ .rm = .{ .size = .tbyte } },
}, src_reg);
- try self.asmRegisterMemory(if (self.hasFeature(.avx))
+ try cg.asmRegisterMemory(if (cg.hasFeature(.avx))
.{ .v_dqa, .mov }
- else if (self.hasFeature(.sse2))
+ else if (cg.hasFeature(.sse2))
.{ ._dqa, .mov }
else
.{ ._ps, .mova }, dst_reg.to128(), .{
@@ -178746,46 +179331,46 @@ fn genSetReg(
});
} else unreachable,
.mmx, .ip, .cr, .dr => unreachable,
- .sse => try self.asmRegisterRegister(
+ .sse => try cg.asmRegisterRegister(
@as(?Mir.Inst.FixedTag, switch (ty.scalarType(zcu).zigTypeTag(zcu)) {
else => switch (abi_size) {
- 1...16 => if (self.hasFeature(.avx))
+ 1...16 => if (cg.hasFeature(.avx))
.{ .v_dqa, .mov }
- else if (self.hasFeature(.sse2))
+ else if (cg.hasFeature(.sse2))
.{ ._dqa, .mov }
else
.{ ._ps, .mova },
- 17...32 => if (self.hasFeature(.avx)) .{ .v_dqa, .mov } else null,
+ 17...32 => if (cg.hasFeature(.avx)) .{ .v_dqa, .mov } else null,
else => null,
},
- .float => switch (ty.scalarType(zcu).floatBits(self.target)) {
+ .float => switch (ty.scalarType(zcu).floatBits(cg.target)) {
16, 128 => switch (abi_size) {
- 2...16 => if (self.hasFeature(.avx))
+ 2...16 => if (cg.hasFeature(.avx))
.{ .v_dqa, .mov }
- else if (self.hasFeature(.sse2))
+ else if (cg.hasFeature(.sse2))
.{ ._dqa, .mov }
else
.{ ._ps, .mova },
- 17...32 => if (self.hasFeature(.avx)) .{ .v_dqa, .mov } else null,
+ 17...32 => if (cg.hasFeature(.avx)) .{ .v_dqa, .mov } else null,
else => null,
},
- 32 => if (self.hasFeature(.avx)) .{ .v_ps, .mova } else .{ ._ps, .mova },
- 64 => if (self.hasFeature(.avx))
+ 32 => if (cg.hasFeature(.avx)) .{ .v_ps, .mova } else .{ ._ps, .mova },
+ 64 => if (cg.hasFeature(.avx))
.{ .v_pd, .mova }
- else if (self.hasFeature(.sse2))
+ else if (cg.hasFeature(.sse2))
.{ ._pd, .mova }
else
.{ ._ps, .mova },
80 => null,
else => unreachable,
},
- }) orelse return self.fail("TODO implement genSetReg for {f}", .{ty.fmt(pt)}),
+ }) orelse return cg.fail("TODO implement genSetReg for {f}", .{ty.fmt(pt)}),
dst_alias,
- registerAlias(src_reg, abi_size),
+ registerAlias(src_reg, @intCast(cg.unalignedSize(ty))),
),
},
.ip, .cr, .dr => unreachable,
- } else if ((dst_reg.class() == .gphi) != (src_reg.class() == .gphi)) try self.asmRegisterRegister(
+ } else if ((dst_reg.class() == .gphi) != (src_reg.class() == .gphi)) try cg.asmRegisterRegister(
.{ ._, .mov },
dst_reg.to8(),
src_reg.to8(),
@@ -178795,41 +179380,41 @@ fn genSetReg(
.register_quadruple,
=> |src_regs| switch (dst_reg.class()) {
.general_purpose => switch (src_regs[0].class()) {
- .general_purpose => try self.genSetReg(dst_reg, ty, .{ .register = src_regs[0] }, opts),
+ .general_purpose => try cg.genSetReg(dst_reg, ty, .{ .register = src_regs[0] }, opts),
else => unreachable,
},
.sse => switch (src_regs[0].class()) {
.general_purpose => if (abi_size <= 16) {
- if (self.hasFeature(.avx)) {
- try self.asmRegisterRegister(.{ .v_q, .mov }, dst_reg.to128(), src_regs[0].to64());
- try self.asmRegisterRegisterRegisterImmediate(
+ if (cg.hasFeature(.avx)) {
+ try cg.asmRegisterRegister(.{ .v_q, .mov }, dst_reg.to128(), src_regs[0].to64());
+ try cg.asmRegisterRegisterRegisterImmediate(
.{ .vp_q, .insr },
dst_reg.to128(),
dst_reg.to128(),
src_regs[1].to64(),
.u(1),
);
- } else if (self.hasFeature(.sse4_1)) {
- try self.asmRegisterRegister(.{ ._q, .mov }, dst_reg.to128(), src_regs[0].to64());
- try self.asmRegisterRegisterImmediate(.{ .p_q, .insr }, dst_reg.to128(), src_regs[1].to64(), .u(1));
- } else if (self.hasFeature(.sse2)) {
- const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.sse);
- const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
- defer self.register_manager.unlockReg(tmp_lock);
+ } else if (cg.hasFeature(.sse4_1)) {
+ try cg.asmRegisterRegister(.{ ._q, .mov }, dst_reg.to128(), src_regs[0].to64());
+ try cg.asmRegisterRegisterImmediate(.{ .p_q, .insr }, dst_reg.to128(), src_regs[1].to64(), .u(1));
+ } else if (cg.hasFeature(.sse2)) {
+ const tmp_reg = try cg.register_manager.allocReg(null, abi.RegisterClass.sse);
+ const tmp_lock = cg.register_manager.lockRegAssumeUnused(tmp_reg);
+ defer cg.register_manager.unlockReg(tmp_lock);
- try self.asmRegisterRegister(.{ ._q, .mov }, dst_reg.to128(), src_regs[0].to64());
- try self.asmRegisterRegister(.{ ._q, .mov }, tmp_reg.to128(), src_regs[1].to64());
- try self.asmRegisterRegister(.{ ._ps, .movlh }, dst_reg.to128(), tmp_reg.to128());
+ try cg.asmRegisterRegister(.{ ._q, .mov }, dst_reg.to128(), src_regs[0].to64());
+ try cg.asmRegisterRegister(.{ ._q, .mov }, tmp_reg.to128(), src_regs[1].to64());
+ try cg.asmRegisterRegister(.{ ._ps, .movlh }, dst_reg.to128(), tmp_reg.to128());
} else {
- const frame_index = try self.allocFrameIndex(.init(.{
+ const frame_index = try cg.allocFrameIndex(.init(.{
.size = 16,
.alignment = .@"16",
}));
- for (src_regs, 0..) |src_reg, src_index| try self.asmMemoryRegister(.{ ._, .mov }, .{
+ for (src_regs, 0..) |src_reg, src_index| try cg.asmMemoryRegister(.{ ._, .mov }, .{
.base = .{ .frame = frame_index },
.mod = .{ .rm = .{ .size = .qword, .disp = @intCast(8 * src_index) } },
}, src_reg.to64());
- try self.asmRegisterMemory(.{ ._ps, .mova }, dst_reg.to128(), .{
+ try cg.asmRegisterMemory(.{ ._ps, .mova }, dst_reg.to128(), .{
.base = .{ .frame = frame_index },
.mod = .{ .rm = .{ .size = .xword } },
});
@@ -178843,38 +179428,41 @@ fn genSetReg(
.indirect,
.load_frame,
.lea_frame,
- => try @as(MoveStrategy, switch (src_mcv) {
- .register_offset => |reg_off| switch (reg_off.off) {
- 0 => return self.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }, opts),
- else => .{ .load_store = .{ ._, .lea } },
- },
- .indirect => try self.moveStrategy(ty, dst_reg.class(), false),
- .load_frame => |frame_addr| try self.moveStrategy(
- ty,
- dst_reg.class(),
- self.getFrameAddrAlignment(frame_addr).compare(.gte, .fromLog2Units(
- std.math.log2_int_ceil(u64, @divExact(dst_reg.size().bitSize(self.target), 8)),
- )),
- ),
- .lea_frame => .{ .load_store = .{ ._, .lea } },
- else => unreachable,
- }).read(self, dst_alias, switch (src_mcv) {
- .register_offset, .indirect => |reg_off| .{
- .base = .{ .reg = reg_off.reg.to64() },
- .mod = .{ .rm = .{
- .size = self.memSize(ty),
- .disp = reg_off.off,
- } },
- },
- .load_frame, .lea_frame => |frame_addr| .{
- .base = .{ .frame = frame_addr.index },
- .mod = .{ .rm = .{
- .size = self.memSize(ty),
- .disp = frame_addr.off,
- } },
- },
- else => unreachable,
- }),
+ => {
+ const dst_rc = dst_reg.class();
+ try @as(MoveStrategy, switch (src_mcv) {
+ .register_offset => |reg_off| switch (reg_off.off) {
+ 0 => return cg.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }, opts),
+ else => .{ .load_store = .{ ._, .lea } },
+ },
+ .indirect => try cg.moveStrategy(ty, dst_rc, false),
+ .load_frame => |frame_addr| try cg.moveStrategy(
+ ty,
+ dst_rc,
+ cg.getFrameAddrAlignment(frame_addr).compare(.gte, .fromLog2Units(
+ std.math.log2_int_ceil(u64, @divExact(dst_reg.size().bitSize(cg.target), 8)),
+ )),
+ ),
+ .lea_frame => .{ .load_store = .{ ._, .lea } },
+ else => unreachable,
+ }).read(cg, dst_alias, switch (src_mcv) {
+ .register_offset, .indirect => |reg_off| .{
+ .base = .{ .reg = reg_off.reg.to64() },
+ .mod = .{ .rm = .{
+ .size = cg.memSize(ty, dst_rc),
+ .disp = reg_off.off,
+ } },
+ },
+ .load_frame, .lea_frame => |frame_addr| .{
+ .base = .{ .frame = frame_addr.index },
+ .mod = .{ .rm = .{
+ .size = cg.memSize(ty, dst_rc),
+ .disp = frame_addr.off,
+ } },
+ },
+ else => unreachable,
+ });
+ },
.register_overflow => |src_reg_ov| {
const ip = &zcu.intern_pool;
const first_ty: Type = .fromInterned(first_ty: switch (ip.indexToKey(ty.toIntern())) {
@@ -178891,116 +179479,189 @@ fn genSetReg(
});
const first_size: u31 = @intCast(first_ty.abiSize(zcu));
const frame_size = std.math.ceilPowerOfTwoAssert(u32, abi_size);
- const frame_index = try self.allocFrameIndex(.init(.{
+ const frame_index = try cg.allocFrameIndex(.init(.{
.size = frame_size,
.alignment = .fromNonzeroByteUnits(frame_size),
}));
- try self.asmMemoryRegister(.{ ._, .mov }, .{
+ try cg.asmMemoryRegister(.{ ._, .mov }, .{
.base = .{ .frame = frame_index },
.mod = .{ .rm = .{ .size = .fromSize(first_size) } },
}, registerAlias(src_reg_ov.reg, first_size));
- try self.asmSetccMemory(src_reg_ov.eflags, .{
+ try cg.asmSetccMemory(src_reg_ov.eflags, .{
.base = .{ .frame = frame_index },
.mod = .{ .rm = .{ .size = .byte, .disp = first_size } },
});
- try self.asmRegisterMemory(.{ ._, .mov }, registerAlias(dst_reg, abi_size), .{
+ try cg.asmRegisterMemory(.{ ._, .mov }, registerAlias(dst_reg, abi_size), .{
.base = .{ .frame = frame_index },
.mod = .{ .rm = .{ .size = .fromSize(frame_size) } },
});
},
.register_mask => |src_reg_mask| {
assert(src_reg_mask.reg.isClass(.sse));
- const has_avx = self.hasFeature(.avx);
+ const has_avx = cg.hasFeature(.avx);
const bits_reg = switch (dst_reg.class()) {
.general_purpose => dst_reg,
- else => try self.register_manager.allocReg(null, abi.RegisterClass.gp),
+ else => try cg.register_manager.allocReg(null, abi.RegisterClass.gp),
};
- const bits_lock = self.register_manager.lockReg(bits_reg);
- defer if (bits_lock) |lock| self.register_manager.unlockReg(lock);
+ const bits_lock = cg.register_manager.lockReg(bits_reg);
+ defer if (bits_lock) |lock| cg.register_manager.unlockReg(lock);
+
+ var mask_size: u32 = @intCast(
+ @divExact(src_reg_mask.info.scalar.bitSize(cg.target), 8) * ty.vectorLen(zcu),
+ );
+ const sign_reg = switch (src_reg_mask.info.kind) {
+ .lsb => sign_reg: {
+ const sign_reg = try cg.register_manager.allocReg(null, abi.RegisterClass.sse);
+ const src_alias = registerAlias(src_reg_mask.reg, mask_size);
+ const sign_alias = registerAlias(sign_reg, mask_size);
+ if (cg.hasFeature(.avx2)) try cg.asmRegisterRegisterImmediate(
+ .{ switch (src_reg_mask.info.scalar) {
+ else => unreachable,
+ .byte, .word => .vp_w,
+ .dword => .vp_d,
+ .qword => .vp_q,
+ }, .sll },
+ sign_alias,
+ src_alias,
+ .u(src_reg_mask.info.scalar.bitSize(cg.target) - 1),
+ ) else {
+ if (sign_alias != src_alias) try cg.asmRegisterRegister(
+ .{ ._dqa, .mov },
+ sign_alias,
+ src_alias,
+ );
+ try cg.asmRegisterImmediate(
+ .{ switch (src_reg_mask.info.scalar) {
+ else => unreachable,
+ .byte, .word => .p_w,
+ .dword => .p_d,
+ .qword => .p_q,
+ }, .sll },
+ sign_alias,
+ .u(src_reg_mask.info.scalar.bitSize(cg.target) - 1),
+ );
+ }
+ break :sign_reg sign_reg;
+ },
+ .zero_extend => sign_reg: {
+ const sign_reg = try cg.register_manager.allocReg(null, abi.RegisterClass.sse);
+ const src_alias = registerAlias(src_reg_mask.reg, mask_size);
+ const sign_alias = registerAlias(sign_reg, mask_size);
+ if (has_avx) {
+ try cg.asmRegisterRegisterRegister(
+ .{ .vp_, .xor },
+ sign_alias,
+ sign_alias,
+ sign_alias,
+ );
+ try cg.asmRegisterRegisterRegister(.{ switch (src_reg_mask.info.scalar) {
+ else => unreachable,
+ .byte => .vp_b,
+ .word => .vp_w,
+ .dword => .vp_d,
+ .qword => .vp_q,
+ }, .sub }, sign_alias, sign_alias, src_alias);
+ } else {
+ try cg.asmRegisterRegister(.{ .p_, .xor }, sign_alias, sign_alias);
+ try cg.asmRegisterRegister(.{ switch (src_reg_mask.info.scalar) {
+ else => unreachable,
+ .byte => .p_b,
+ .word => .p_w,
+ .dword => .p_d,
+ .qword => .p_q,
+ }, .sub }, sign_alias, src_alias);
+ }
+ break :sign_reg sign_reg;
+ },
+ .msb, .sign_extend => src_reg_mask.reg,
+ };
+ const sign_lock = cg.register_manager.lockReg(sign_reg);
+ defer if (sign_lock) |lock| cg.register_manager.unlockReg(lock);
const pack_reg = switch (src_reg_mask.info.scalar) {
- else => src_reg_mask.reg,
- .word => try self.register_manager.allocReg(null, abi.RegisterClass.sse),
- };
- const pack_lock = self.register_manager.lockReg(pack_reg);
- defer if (pack_lock) |lock| self.register_manager.unlockReg(lock);
-
- var mask_size: u32 = @intCast(ty.vectorLen(zcu) * @divExact(src_reg_mask.info.scalar.bitSize(self.target), 8));
- switch (src_reg_mask.info.scalar) {
- else => {},
- .word => {
- const src_alias = registerAlias(src_reg_mask.reg, mask_size);
+ else => sign_reg,
+ .word => pack_reg: {
+ const pack_reg = if (sign_reg == src_reg_mask.reg)
+ try cg.register_manager.allocReg(null, abi.RegisterClass.sse)
+ else
+ sign_reg;
+ const sign_alias = registerAlias(sign_reg, mask_size);
const pack_alias = registerAlias(pack_reg, mask_size);
if (has_avx) {
- try self.asmRegisterRegisterRegister(.{ .vp_b, .ackssw }, pack_alias, src_alias, src_alias);
+ try cg.asmRegisterRegisterRegister(.{ .vp_b, .ackssw }, pack_alias, sign_alias, sign_alias);
} else {
- try self.asmRegisterRegister(.{ ._dqa, .mov }, pack_alias, src_alias);
- try self.asmRegisterRegister(.{ .p_b, .ackssw }, pack_alias, pack_alias);
+ if (pack_alias != sign_alias) try cg.asmRegisterRegister(.{ ._dqa, .mov }, pack_alias, sign_alias);
+ try cg.asmRegisterRegister(.{ .p_b, .ackssw }, pack_alias, pack_alias);
}
mask_size = std.math.divCeil(u32, mask_size, 2) catch unreachable;
+ break :pack_reg pack_reg;
},
- }
- try self.asmRegisterRegister(.{ switch (src_reg_mask.info.scalar) {
+ };
+ const pack_lock = cg.register_manager.lockReg(pack_reg);
+ defer if (pack_lock) |lock| cg.register_manager.unlockReg(lock);
+
+ try cg.asmRegisterRegister(.{ switch (src_reg_mask.info.scalar) {
+ else => unreachable,
.byte, .word => if (has_avx) .vp_b else .p_b,
.dword => if (has_avx) .v_ps else ._ps,
.qword => if (has_avx) .v_pd else ._pd,
- else => unreachable,
}, .movmsk }, bits_reg.to32(), registerAlias(pack_reg, mask_size));
- if (src_reg_mask.info.inverted) try self.asmRegister(.{ ._, .not }, registerAlias(bits_reg, abi_size));
- try self.genSetReg(dst_reg, ty, .{ .register = bits_reg }, .{});
+ if (src_reg_mask.info.inverted) try cg.asmRegister(.{ ._, .not }, registerAlias(bits_reg, abi_size));
+ try cg.genSetReg(dst_reg, ty, .{ .register = bits_reg }, .{});
},
.memory, .load_nav, .load_uav, .load_lazy_sym, .load_extern_func => {
+ const dst_rc = dst_reg.class();
switch (src_mcv) {
.memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
- return (try self.moveStrategy(
+ return (try cg.moveStrategy(
ty,
- dst_reg.class(),
+ dst_rc,
ty.abiAlignment(zcu).check(@as(u32, @bitCast(small_addr))),
- )).read(self, dst_alias, .{
+ )).read(cg, dst_alias, .{
.base = .{ .reg = .ds },
.mod = .{ .rm = .{
- .size = self.memSize(ty),
+ .size = cg.memSize(ty, dst_rc),
.disp = small_addr,
} },
}),
- .load_nav => |nav| switch (dst_reg.class()) {
+ .load_nav => |nav| switch (dst_rc) {
.general_purpose, .gphi => {
- try self.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
+ try cg.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
.base = .{ .nav = nav },
- .mod = .{ .rm = .{ .size = self.memSize(ty) } },
+ .mod = .{ .rm = .{ .size = cg.memSize(ty, dst_rc) } },
});
return;
},
.segment, .mmx, .ip, .cr, .dr => unreachable,
.x87, .sse => {},
},
- .load_uav => |uav| switch (dst_reg.class()) {
+ .load_uav => |uav| switch (dst_rc) {
.general_purpose, .gphi => {
- try self.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
+ try cg.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
.base = .{ .uav = uav },
- .mod = .{ .rm = .{ .size = self.memSize(ty) } },
+ .mod = .{ .rm = .{ .size = cg.memSize(ty, dst_rc) } },
});
return;
},
.segment, .mmx, .ip, .cr, .dr => unreachable,
.x87, .sse => {},
},
- .load_lazy_sym => |lazy_sym| switch (dst_reg.class()) {
+ .load_lazy_sym => |lazy_sym| switch (dst_rc) {
.general_purpose, .gphi => {
- try self.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
+ try cg.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
.base = .{ .lazy_sym = lazy_sym },
- .mod = .{ .rm = .{ .size = self.memSize(ty) } },
+ .mod = .{ .rm = .{ .size = cg.memSize(ty, dst_rc) } },
});
return;
},
.segment, .mmx, .ip, .cr, .dr => unreachable,
.x87, .sse => {},
},
- .load_extern_func => |extern_func| switch (dst_reg.class()) {
+ .load_extern_func => |extern_func| switch (dst_rc) {
.general_purpose, .gphi => {
- try self.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
+ try cg.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
.base = .{ .extern_func = extern_func },
- .mod = .{ .rm = .{ .size = self.memSize(ty) } },
+ .mod = .{ .rm = .{ .size = cg.memSize(ty, dst_rc) } },
});
return;
},
@@ -179010,40 +179671,40 @@ fn genSetReg(
else => unreachable,
}
- const addr_reg = try self.copyToTmpRegister(.usize, src_mcv.address());
- const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
- defer self.register_manager.unlockReg(addr_lock);
+ const addr_reg = try cg.copyToTmpRegister(.usize, src_mcv.address());
+ const addr_lock = cg.register_manager.lockRegAssumeUnused(addr_reg);
+ defer cg.register_manager.unlockReg(addr_lock);
- try (try self.moveStrategy(ty, dst_reg.class(), false)).read(self, dst_alias, .{
+ try (try cg.moveStrategy(ty, dst_rc, false)).read(cg, dst_alias, .{
.base = .{ .reg = addr_reg.to64() },
- .mod = .{ .rm = .{ .size = self.memSize(ty) } },
+ .mod = .{ .rm = .{ .size = cg.memSize(ty, dst_rc) } },
});
},
- .lea_nav => |nav| try self.asmRegisterMemory(.{ ._, .lea }, dst_reg.to64(), .{
+ .lea_nav => |nav| try cg.asmRegisterMemory(.{ ._, .lea }, dst_reg.to64(), .{
.base = .{ .nav = nav },
}),
- .lea_uav => |uav| try self.asmRegisterMemory(.{ ._, .lea }, dst_reg.to64(), .{
+ .lea_uav => |uav| try cg.asmRegisterMemory(.{ ._, .lea }, dst_reg.to64(), .{
.base = .{ .uav = uav },
}),
- .lea_lazy_sym => |lazy_sym| try self.asmRegisterMemory(.{ ._, .lea }, dst_reg.to64(), .{
+ .lea_lazy_sym => |lazy_sym| try cg.asmRegisterMemory(.{ ._, .lea }, dst_reg.to64(), .{
.base = .{ .lazy_sym = lazy_sym },
}),
- .lea_extern_func => |lazy_sym| try self.asmRegisterMemory(.{ ._, .lea }, dst_reg.to64(), .{
+ .lea_extern_func => |lazy_sym| try cg.asmRegisterMemory(.{ ._, .lea }, dst_reg.to64(), .{
.base = .{ .extern_func = lazy_sym },
}),
- .air_ref => |src_ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(src_ref), opts),
+ .air_ref => |src_ref| try cg.genSetReg(dst_reg, ty, try cg.resolveInst(src_ref), opts),
}
}
fn genSetMem(
- self: *CodeGen,
+ cg: *CodeGen,
base: Memory.Base,
disp: i32,
ty: Type,
src_mcv: MCValue,
opts: CopyOptions,
) InnerError!void {
- const pt = self.pt;
+ const pt = cg.pt;
const zcu = pt.zcu;
const abi_size: u32 = @intCast(ty.abiSize(zcu));
const dst_ptr_mcv: MCValue = switch (base) {
@@ -179053,11 +179714,11 @@ fn genSetMem(
.table, .rip_inst, .lazy_sym => unreachable,
.nav => |nav| {
// hack around linker relocation bugs
- const addr_reg = try self.copyToTmpRegister(.usize, .{ .lea_nav = nav });
- const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
- defer self.register_manager.unlockReg(addr_lock);
+ const addr_reg = try cg.copyToTmpRegister(.usize, .{ .lea_nav = nav });
+ const addr_lock = cg.register_manager.lockRegAssumeUnused(addr_reg);
+ defer cg.register_manager.unlockReg(addr_lock);
- return self.genSetMem(.{ .reg = addr_reg }, disp, ty, src_mcv, opts);
+ return cg.genSetMem(.{ .reg = addr_reg }, disp, ty, src_mcv, opts);
},
.uav => |uav| .{ .lea_uav = uav },
.extern_func => |extern_func| .{ .lea_extern_func = extern_func },
@@ -179067,10 +179728,16 @@ fn genSetMem(
.unreach,
.dead,
.indirect_load_frame,
- .elementwise_args,
+ .indirect_mask,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
=> unreachable,
- .undef => if (opts.safety) try self.genInlineMemset(
+ .undef => if (opts.safety) try cg.genInlineMemset(
dst_ptr_mcv,
src_mcv,
.{ .immediate = abi_size },
@@ -179085,7 +179752,7 @@ fn genSetMem(
.signed => .s(@truncate(@as(i64, @bitCast(imm)))),
.unsigned => .u(@as(u32, @intCast(imm))),
};
- try self.asmMemoryImmediate(
+ try cg.asmMemoryImmediate(
.{ ._, .mov },
.{ .base = base, .mod = .{ .rm = .{
.size = .fromSize(abi_size),
@@ -179096,7 +179763,7 @@ fn genSetMem(
},
3, 5...7 => unreachable,
else => if (std.math.cast(i32, @as(i64, @bitCast(imm)))) |small| {
- try self.asmMemoryImmediate(
+ try cg.asmMemoryImmediate(
.{ ._, .mov },
.{ .base = base, .mod = .{ .rm = .{
.size = .fromSize(abi_size),
@@ -179106,7 +179773,7 @@ fn genSetMem(
);
} else {
var offset: i32 = 0;
- while (offset < abi_size) : (offset += 4) try self.asmMemoryImmediate(
+ while (offset < abi_size) : (offset += 4) try cg.asmMemoryImmediate(
.{ ._, .mov },
.{ .base = base, .mod = .{ .rm = .{
.size = .dword,
@@ -179120,7 +179787,7 @@ fn genSetMem(
);
},
},
- .eflags => |cc| try self.asmSetccMemory(cc, .{ .base = base, .mod = .{
+ .eflags => |cc| try cg.asmSetccMemory(cc, .{ .base = base, .mod = .{
.rm = .{ .size = .byte, .disp = disp },
} }),
.register => |src_reg| {
@@ -179128,75 +179795,75 @@ fn genSetMem(
const mem_size = switch (base) {
.frame => |base_fi| mem_size: {
assert(disp >= 0);
- const frame_abi_size = self.frame_allocs.items(.abi_size)[@intFromEnum(base_fi)];
- const frame_spill_pad = self.frame_allocs.items(.spill_pad)[@intFromEnum(base_fi)];
+ const frame_abi_size = cg.frame_allocs.items(.abi_size)[@intFromEnum(base_fi)];
+ const frame_spill_pad = cg.frame_allocs.items(.spill_pad)[@intFromEnum(base_fi)];
assert(frame_abi_size - frame_spill_pad - disp >= abi_size);
break :mem_size if (frame_abi_size - frame_spill_pad - disp == abi_size) frame_abi_size else abi_size;
},
else => abi_size,
};
- const src_alias = registerAlias(src_reg, @intCast(self.unalignedSize(ty)));
- const src_class = src_alias.class();
- const src_size: Memory.Size = switch (src_class) {
+ const src_alias = registerAlias(src_reg, @intCast(cg.unalignedSize(ty)));
+ const src_rc = src_alias.class();
+ const src_size: Memory.Size = switch (src_rc) {
.general_purpose, .gphi, .segment, .ip, .cr, .dr => src_alias.size(),
.mmx, .sse => .fromSize(abi_size),
- .x87 => switch (abi.classifySystemV(ty, zcu, self.target, .other)[0]) {
+ .x87 => switch (abi.classifySystemV(ty, zcu, cg.target, .other)[0]) {
else => unreachable,
.float => .dword,
.float_combine, .sse => .qword,
.x87 => .tbyte,
},
};
- const src_bit_size = src_size.bitSize(self.target);
+ const src_bit_size = src_size.bitSize(cg.target);
const src_align: InternPool.Alignment = .fromNonzeroByteUnits(std.math.ceilPowerOfTwoAssert(u64, src_bit_size));
const src_byte_size = @divExact(src_bit_size, 8);
if (src_byte_size > mem_size) {
- const frame_index = try self.allocFrameIndex(.init(.{
+ const frame_index = try cg.allocFrameIndex(.init(.{
.size = src_byte_size,
.alignment = src_align,
}));
const frame_mcv: MCValue = .{ .load_frame = .{ .index = frame_index } };
- try (try self.moveStrategy(ty, src_class, true)).write(self, .{
+ try (try cg.moveStrategy(ty, src_rc, true)).write(cg, .{
.base = .{ .frame = frame_index },
.mod = .{ .rm = .{ .size = src_size } },
}, src_alias);
- try self.genSetMem(base, disp, ty, frame_mcv, opts);
- try self.freeValue(frame_mcv, .{});
- } else try (try self.moveStrategy(ty, src_class, switch (base) {
+ try cg.genSetMem(base, disp, ty, frame_mcv, opts);
+ try cg.freeValue(frame_mcv, .{});
+ } else try (try cg.moveStrategy(ty, src_rc, switch (base) {
.none => src_align.check(@as(u32, @bitCast(disp))),
.reg => |reg| switch (reg) {
.es, .cs, .ss, .ds => src_align.check(@as(u32, @bitCast(disp))),
else => false,
},
- .frame => |frame_index| self.getFrameAddrAlignment(.{
+ .frame => |frame_index| cg.getFrameAddrAlignment(.{
.index = frame_index,
.off = disp,
}).compare(.gte, src_align),
.table, .rip_inst, .lazy_sym, .extern_func => unreachable,
.nav => |nav| ip.getNav(nav).resolved.?.@"align".compare(.gte, src_align),
.uav => |uav| Type.fromInterned(uav.orig_ty).ptrAlignment(zcu).compare(.gte, src_align),
- })).write(self, .{
+ })).write(cg, .{
.base = base,
.mod = .{ .rm = .{ .size = src_size, .disp = disp } },
}, src_alias);
},
inline .register_pair, .register_triple, .register_quadruple => |src_regs| {
var part_disp: i32 = disp;
- for (try self.splitType(src_regs.len, ty), src_regs) |src_ty, src_reg| {
- try self.genSetMem(base, part_disp, src_ty, .{ .register = src_reg }, opts);
- part_disp += @intCast(src_ty.abiSize(zcu));
+ for (try cg.splitType(src_regs.len, ty), src_regs) |src_ty, src_reg| {
+ try cg.genSetMem(base, part_disp, src_ty, .{ .register = src_reg }, opts);
+ part_disp += @intCast(cg.unalignedSize(src_ty));
}
},
.register_overflow => |ro| switch (ty.zigTypeTag(zcu)) {
.@"struct" => {
- try self.genSetMem(
+ try cg.genSetMem(
base,
disp + @as(i32, @intCast(ty.structFieldOffset(0, zcu))),
ty.fieldType(0, zcu),
.{ .register = ro.reg },
opts,
);
- try self.genSetMem(
+ try cg.genSetMem(
base,
disp + @as(i32, @intCast(ty.structFieldOffset(1, zcu))),
ty.fieldType(1, zcu),
@@ -179207,8 +179874,8 @@ fn genSetMem(
.optional => {
assert(!ty.optionalReprIsPayload(zcu));
const child_ty = ty.optionalChild(zcu);
- try self.genSetMem(base, disp, child_ty, .{ .register = ro.reg }, opts);
- try self.genSetMem(
+ try cg.genSetMem(base, disp, child_ty, .{ .register = ro.reg }, opts);
+ try cg.genSetMem(
base,
disp + @as(i32, @intCast(child_ty.abiSize(zcu))),
.bool,
@@ -179216,37 +179883,37 @@ fn genSetMem(
opts,
);
},
- else => return self.fail("TODO implement genSetMem for {s} of {f}", .{
+ else => return cg.fail("TODO implement genSetMem for {s} of {f}", .{
@tagName(src_mcv), ty.fmt(pt),
}),
},
.register_offset => |reg_off| {
- const src_reg = self.copyToTmpRegister(ty, src_mcv) catch |err| switch (err) {
+ const src_reg = cg.copyToTmpRegister(ty, src_mcv) catch |err| switch (err) {
error.OutOfRegisters => {
- const src_reg = registerAlias(reg_off.reg, abi_size);
- try self.asmRegisterMemory(.{ ._, .lea }, src_reg, .{
- .base = .{ .reg = src_reg },
+ const src_alias = registerAlias(reg_off.reg, @intCast(cg.unalignedSize(ty)));
+ try cg.asmRegisterMemory(.{ ._, .lea }, src_alias, .{
+ .base = .{ .reg = src_alias },
.mod = .{ .rm = .{ .disp = reg_off.off } },
});
- try self.genSetMem(base, disp, ty, .{ .register = reg_off.reg }, opts);
- return self.asmRegisterMemory(.{ ._, .lea }, src_reg, .{
- .base = .{ .reg = src_reg },
+ try cg.genSetMem(base, disp, ty, .{ .register = reg_off.reg }, opts);
+ return cg.asmRegisterMemory(.{ ._, .lea }, src_alias, .{
+ .base = .{ .reg = src_alias },
.mod = .{ .rm = .{ .disp = -reg_off.off } },
});
},
else => |e| return e,
};
- const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
- defer self.register_manager.unlockReg(src_lock);
+ const src_lock = cg.register_manager.lockRegAssumeUnused(src_reg);
+ defer cg.register_manager.unlockReg(src_lock);
- try self.genSetMem(base, disp, ty, .{ .register = src_reg }, opts);
+ try cg.genSetMem(base, disp, ty, .{ .register = src_reg }, opts);
},
.register_mask => {
- const src_reg = try self.copyToTmpRegister(ty, src_mcv);
- const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
- defer self.register_manager.unlockReg(src_lock);
+ const src_reg = try cg.copyToTmpRegister(ty, src_mcv);
+ const src_lock = cg.register_manager.lockRegAssumeUnused(src_reg);
+ defer cg.register_manager.unlockReg(src_lock);
- try self.genSetMem(base, disp, ty, .{ .register = src_reg }, opts);
+ try cg.genSetMem(base, disp, ty, .{ .register = src_reg }, opts);
},
.memory,
.indirect,
@@ -179263,15 +179930,15 @@ fn genSetMem(
=> switch (abi_size) {
0 => {},
1, 2, 4, 8 => {
- const src_reg = try self.copyToTmpRegister(ty, src_mcv);
- const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
- defer self.register_manager.unlockReg(src_lock);
+ const src_reg = try cg.copyToTmpRegister(ty, src_mcv);
+ const src_lock = cg.register_manager.lockRegAssumeUnused(src_reg);
+ defer cg.register_manager.unlockReg(src_lock);
- try self.genSetMem(base, disp, ty, .{ .register = src_reg }, opts);
+ try cg.genSetMem(base, disp, ty, .{ .register = src_reg }, opts);
},
- else => try self.genInlineMemcpy(dst_ptr_mcv, src_mcv.address(), .{ .immediate = abi_size }, .{ .no_alias = true }),
+ else => try cg.genInlineMemcpy(dst_ptr_mcv, src_mcv.address(), .{ .immediate = abi_size }, .{ .no_alias = true }),
},
- .air_ref => |src_ref| try self.genSetMem(base, disp, ty, try self.resolveInst(src_ref), opts),
+ .air_ref => |src_ref| try cg.genSetMem(base, disp, ty, try cg.resolveInst(src_ref), opts),
}
}
@@ -179476,14 +180143,19 @@ fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void {
break :dst dst_mcv;
};
- if (dst_ty.isRuntimeFloat()) break :result dst_mcv;
+ switch (dst_ty.zigTypeTag(zcu)) {
+ .float, .error_union, .error_set, .vector => break :result dst_mcv,
+ .@"struct", .@"union" => if (dst_ty.containerLayout(zcu) != .@"packed") break :result dst_mcv,
+ .optional, .pointer => if (!dst_ty.isPtrAtRuntime(zcu)) break :result dst_mcv,
+ else => {},
+ }
if (dst_ty.isAbiInt(zcu) and src_ty.isAbiInt(zcu) and src_ty.zigTypeTag(zcu) != .@"struct" and
dst_ty.intInfo(zcu).signedness == src_ty.intInfo(zcu).signedness) break :result dst_mcv;
const abi_size = dst_ty.abiSize(zcu);
const bit_size = dst_ty.bitSize(zcu);
- if (abi_size * 8 <= bit_size or dst_ty.isVector(zcu)) break :result dst_mcv;
+ if (abi_size * 8 <= bit_size) break :result dst_mcv;
const dst_limbs_len = std.math.divCeil(u31, @intCast(bit_size), 64) catch unreachable;
const high_mcv: MCValue = switch (dst_mcv) {
@@ -179780,7 +180452,7 @@ fn atomicOp(
mir_tag,
sse_reg.to128(),
sse_reg.to128(),
- try val_mcv.mem(self, .{ .size = self.memSize(val_ty) }),
+ try val_mcv.mem(self, .{ .size = self.memSize(val_ty, sse_reg.class()) }),
) else try self.asmRegisterRegisterRegister(
mir_tag,
sse_reg.to128(),
@@ -179793,7 +180465,7 @@ fn atomicOp(
._ss, ._sd => if (val_mcv.isBase()) try self.asmRegisterMemory(
mir_tag,
sse_reg.to128(),
- try val_mcv.mem(self, .{ .size = self.memSize(val_ty) }),
+ try val_mcv.mem(self, .{ .size = self.memSize(val_ty, sse_reg.class()) }),
) else try self.asmRegisterRegister(
mir_tag,
sse_reg.to128(),
@@ -180196,56 +180868,6 @@ fn airMemset(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
return self.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
}
-fn airSplat(self: *CodeGen, inst: Air.Inst.Index) !void {
- const pt = self.pt;
- const zcu = pt.zcu;
- const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
- const vector_ty = self.typeOfIndex(inst);
- const vector_len = vector_ty.vectorLen(zcu);
- const scalar_ty = self.typeOf(ty_op.operand);
-
- const result: MCValue = result: {
- if (scalar_ty.toIntern() != .bool_type) return self.fail("TODO implement airSplat for {f}", .{
- vector_ty.fmt(pt),
- });
- const regs =
- try self.register_manager.allocRegs(2, .{ inst, null }, abi.RegisterClass.gp);
- const reg_locks = self.register_manager.lockRegsAssumeUnused(2, regs);
- defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
-
- try self.genSetReg(regs[1], vector_ty, .{ .immediate = 0 }, .{});
- try self.genSetReg(
- regs[1],
- vector_ty,
- .{ .immediate = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - vector_len) },
- .{},
- );
- const src_mcv = try self.resolveInst(ty_op.operand);
- const abi_size = @max(std.math.divCeil(u32, vector_len, 8) catch unreachable, 4);
- try self.asmCmovccRegisterRegister(
- switch (src_mcv) {
- .eflags => |cc| cc,
- .register => |src_reg| cc: {
- try self.asmRegisterImmediate(.{ ._, .@"test" }, src_reg.to8(), .u(1));
- break :cc .nz;
- },
- else => cc: {
- try self.asmMemoryImmediate(
- .{ ._, .@"test" },
- try src_mcv.mem(self, .{ .size = .byte }),
- .u(1),
- );
- break :cc .nz;
- },
- },
- registerAlias(regs[0], abi_size),
- registerAlias(regs[1], abi_size),
- );
- break :result .{ .register = regs[0] };
- };
- return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
-}
-
fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
const pt = self.pt;
const zcu = pt.zcu;
@@ -180327,32 +180949,32 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
const dst_lock = self.register_manager.lockReg(dst_reg);
defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
- const mir_tag = @as(?Mir.Inst.FixedTag, if ((pred_reg_mask.info.kind == .all and
+ const mir_tag = @as(?Mir.Inst.FixedTag, if ((pred_reg_mask.info.kind == .sign_extend and
elem_ty.toIntern() != .f32_type and elem_ty.toIntern() != .f64_type) or pred_reg_mask.info.scalar == .byte)
if (has_avx)
.{ .vp_b, .blendv }
else if (has_blend)
.{ .p_b, .blendv }
- else if (pred_reg_mask.info.kind == .all)
+ else if (pred_reg_mask.info.kind == .sign_extend)
.{ .p_, undefined }
else
null
- else if ((pred_reg_mask.info.kind == .all and (elem_ty.toIntern() != .f64_type or !self.hasFeature(.sse2))) or
+ else if ((pred_reg_mask.info.kind == .sign_extend and (elem_ty.toIntern() != .f64_type or !self.hasFeature(.sse2))) or
pred_reg_mask.info.scalar == .dword)
if (has_avx)
.{ .v_ps, .blendv }
else if (has_blend)
.{ ._ps, .blendv }
- else if (pred_reg_mask.info.kind == .all)
+ else if (pred_reg_mask.info.kind == .sign_extend)
.{ ._ps, undefined }
else
null
- else if (pred_reg_mask.info.kind == .all or pred_reg_mask.info.scalar == .qword)
+ else if (pred_reg_mask.info.kind == .sign_extend or pred_reg_mask.info.scalar == .qword)
if (has_avx)
.{ .v_pd, .blendv }
else if (has_blend)
.{ ._pd, .blendv }
- else if (pred_reg_mask.info.kind == .all)
+ else if (pred_reg_mask.info.kind == .sign_extend)
.{ ._pd, undefined }
else
null
@@ -180369,7 +180991,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
mir_tag,
dst_alias,
rhs_alias,
- try other_mcv.mem(self, .{ .size = self.memSize(ty) }),
+ try other_mcv.mem(self, .{ .size = self.memSize(ty, dst_reg.class()) }),
mask_alias,
) else try self.asmRegisterRegisterRegisterRegister(
mir_tag,
@@ -180384,7 +181006,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
} else if (has_blend) if (other_mcv.isBase()) try self.asmRegisterMemoryRegister(
mir_tag,
dst_alias,
- try other_mcv.mem(self, .{ .size = self.memSize(ty) }),
+ try other_mcv.mem(self, .{ .size = self.memSize(ty, dst_reg.class()) }),
mask_alias,
) else try self.asmRegisterRegisterRegister(
mir_tag,
@@ -180527,7 +181149,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
} })));
const mask_mem: Memory = .{
.base = .{ .reg = try self.copyToTmpRegister(.usize, mask_mcv.address()) },
- .mod = .{ .rm = .{ .size = self.memSize(ty) } },
+ .mod = .{ .rm = .{ .size = self.memSize(ty, mask_reg.class()) } },
};
if (has_avx) try self.asmRegisterRegisterMemory(
.{ .vp_b, .shuf },
@@ -180552,7 +181174,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
const mask_mcv = try self.lowerValue(try pt.aggregateValue(mask_ty, mask_elems));
const mask_mem: Memory = .{
.base = .{ .reg = try self.copyToTmpRegister(.usize, mask_mcv.address()) },
- .mod = .{ .rm = .{ .size = self.memSize(ty) } },
+ .mod = .{ .rm = .{ .size = self.memSize(ty, mask_reg.class()) } },
};
if (has_avx) {
try self.asmRegisterRegisterMemory(
@@ -180671,7 +181293,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
mir_tag,
dst_alias,
rhs_alias,
- try lhs_mcv.mem(self, .{ .size = self.memSize(ty) }),
+ try lhs_mcv.mem(self, .{ .size = self.memSize(ty, dst_reg.class()) }),
mask_alias,
) else try self.asmRegisterRegisterRegisterRegister(
mir_tag,
@@ -180686,7 +181308,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
} else if (has_blend) if (lhs_mcv.isBase()) try self.asmRegisterMemoryRegister(
mir_tag,
dst_alias,
- try lhs_mcv.mem(self, .{ .size = self.memSize(ty) }),
+ try lhs_mcv.mem(self, .{ .size = self.memSize(ty, dst_reg.class()) }),
mask_alias,
) else try self.asmRegisterRegisterRegister(
mir_tag,
@@ -181205,100 +181827,163 @@ fn resolveCallingConventionValues(
result.stack_align = .fromByteUnits(cc_opts.incoming_stack_alignment orelse 16);
switch (cc) {
+ else => unreachable,
.x86_64_sysv => {},
.x86_64_win => result.stack_byte_count += @intCast(win64_shadow_space),
- else => unreachable,
}
- // Return values
- if (ret_ty.isNoReturn(zcu)) {
- result.return_value = .init(.unreach);
- } else if (!ret_ty.hasRuntimeBits(zcu)) {
- // TODO: is this even possible for C calling convention?
- result.return_value = .init(.none);
- } else {
- var ret_tracking: [4]InstTracking = undefined;
- var ret_tracking_len: u32 = 0;
- var ret_gpr = abi.getCAbiIntReturnRegs(cc);
- var ret_sse = abi.getCAbiSseReturnRegs(cc);
- var ret_x87 = abi.getCAbiX87ReturnRegs(cc);
+ result.return_value = switch (ret_ty.classify(zcu)) {
+ .no_possible_value => .init(.unreach),
+ .one_possible_value => .init(.none),
+ .runtime, .partially_comptime => return_value: {
+ var ret_tracking: [4]InstTracking = undefined;
+ var ret_tracking_len: u32 = 0;
+ var ret_gpr = abi.getCAbiIntReturnRegs(cc);
+ var ret_sse = abi.getCAbiSseReturnRegs(cc);
+ var ret_x87 = abi.getCAbiX87ReturnRegs(cc);
- const classes: []const abi.Class = switch (cc) {
- .x86_64_sysv => std.mem.sliceTo(&abi.classifySystemV(ret_ty, zcu, cg.target, .ret), .none),
- .x86_64_win => &.{abi.classifyWindows(ret_ty, zcu, cg.target, .ret)},
- else => unreachable,
- };
- for (classes) |class| switch (class) {
- .integer => {
- ret_tracking[ret_tracking_len] = .init(.{ .register = registerAlias(
- ret_gpr[0],
- @intCast(@min(ret_ty.abiSize(zcu), 8)),
- ) });
- ret_tracking_len += 1;
- ret_gpr = ret_gpr[1..];
- },
- .sse, .float, .float_combine, .win_i128 => {
- const abi_size: u32 = @intCast(ret_ty.abiSize(zcu));
- const reg_size = @min(abi_size, cg.vectorSize(.float));
- var byte_offset: u32 = 0;
- while (byte_offset < abi_size) : (byte_offset += reg_size) {
- const ret_sse_reg = registerAlias(ret_sse[0], reg_size);
+ var classes_buf: [8]abi.Class = undefined;
+ const classes = classes: switch (cc) {
+ else => unreachable,
+ .x86_64_sysv => {
+ classes_buf = abi.classifySystemV(ret_ty, zcu, cg.target, .ret);
+ break :classes &classes_buf;
+ },
+ .x86_64_win => {
+ classes_buf[0] = abi.classifyWindows(ret_ty, zcu, cg.target, .ret);
+ break :classes classes_buf[0..1];
+ },
+ };
+ for (classes) |class| switch (class) {
+ .integer => {
+ ret_tracking[ret_tracking_len] = .init(.{ .register = registerAlias(
+ ret_gpr[0],
+ @intCast(@min(ret_ty.abiSize(zcu), 8)),
+ ) });
+ ret_tracking_len += 1;
+ ret_gpr = ret_gpr[1..];
+ },
+ .sse, .float, .float_combine, .win_i128 => {
+ ret_tracking[ret_tracking_len] = .init(.{
+ .register = registerAlias(ret_sse[0], @intCast(ret_ty.abiSize(zcu))),
+ });
+ ret_tracking_len += 1;
ret_sse = ret_sse[1..];
-
- ret_tracking[ret_tracking_len] = .init(.{ .register = ret_sse_reg });
+ },
+ .sseup => assert(ret_tracking[ret_tracking_len - 1].short.register.isClass(.sse)),
+ .x87 => {
+ ret_tracking[ret_tracking_len] = .init(.{ .register = ret_x87[0] });
ret_tracking_len += 1;
- }
- },
- .sseup => assert(ret_tracking[ret_tracking_len - 1].short.register.isClass(.sse)),
- .x87 => {
- ret_tracking[ret_tracking_len] = .init(.{ .register = ret_x87[0] });
- ret_tracking_len += 1;
- ret_x87 = ret_x87[1..];
- },
- .x87up => assert(ret_tracking[ret_tracking_len - 1].short.register.isClass(.x87)),
- .memory, .integer_per_element => {
- ret_tracking[ret_tracking_len] = .{
- .short = .{ .indirect = .{ .reg = ret_gpr[0].to64() } },
- .long = .{ .indirect = .{ .reg = param_gpr[param_gpr_index].to64() } },
- };
- ret_tracking_len += 1;
- ret_gpr = ret_gpr[1..];
- param_gpr_index += 1;
- },
- .none => unreachable,
- };
- result.return_value = switch (ret_tracking_len) {
- else => unreachable,
- 1 => ret_tracking[0],
- 2 => .init(.{ .register_pair = .{
- ret_tracking[0].short.register,
- ret_tracking[1].short.register,
- } }),
- 3 => .init(.{ .register_triple = .{
- ret_tracking[0].short.register,
- ret_tracking[1].short.register,
- ret_tracking[2].short.register,
- } }),
- 4 => .init(.{ .register_quadruple = .{
- ret_tracking[0].short.register,
- ret_tracking[1].short.register,
- ret_tracking[2].short.register,
- ret_tracking[3].short.register,
- } }),
- };
- }
+ ret_x87 = ret_x87[1..];
+ },
+ .x87up => assert(ret_tracking[ret_tracking_len - 1].short.register.isClass(.x87)),
+ .none => {},
+ .memory => {
+ ret_tracking[ret_tracking_len] = .{
+ .short = .{ .indirect = .{ .reg = ret_gpr[0].to64() } },
+ .long = .{ .indirect = .{ .reg = param_gpr[param_gpr_index].to64() } },
+ };
+ ret_tracking_len += 1;
+ ret_gpr = ret_gpr[1..];
+ param_gpr_index += 1;
+ },
+ .bool_vector_mask => {
+ const len = ret_ty.vectorLen(zcu);
+ const elem_size =
+ @divExact(16, std.math.ceilPowerOfTwoAssert(u32, @min(len, 16)));
+ ret_tracking[ret_tracking_len] = .init(.{ .register_mask = .{
+ .reg = registerAlias(ret_sse[0], elem_size * len),
+ .info = .{ .kind = .lsb, .scalar = .fromSize(elem_size) },
+ } });
+ ret_tracking_len += 1;
+ ret_sse = ret_sse[1..];
+ },
+ .integer_per_element => {
+ const len: u32 = @intCast(ret_ty.vectorLen(zcu));
+ const alias_size: u32 = @intCast(@min(ret_ty.childType(zcu).abiSize(zcu), 8));
+ for (ret_tracking[ret_tracking_len..][0..len], ret_gpr[0..len]) |*tracking, gpr|
+ tracking.* = .init(.{ .register = registerAlias(gpr, alias_size) });
+ ret_tracking_len += len;
+ ret_gpr = ret_gpr[len..];
+ },
+ .sse_per_element => {
+ const len: u32 = @intCast(ret_ty.vectorLen(zcu));
+ const alias_size: u32 = @intCast(@min(ret_ty.childType(zcu).abiSize(zcu), 8));
+ for (ret_tracking[ret_tracking_len..][0..len], ret_sse[0..len]) |*tracking, sse|
+ tracking.* = .init(.{ .register = registerAlias(sse, alias_size) });
+ ret_tracking_len += len;
+ ret_sse = ret_sse[len..];
+ },
+ .sse_sse_x87_per_qword, .sse_per_xword, .sse_per_yword, .sse_per_zword => {
+ const reg_size: u32 = switch (class) {
+ else => unreachable,
+ .sse_sse_x87_per_qword => 8,
+ .sse_per_xword => 16,
+ .sse_per_yword => 32,
+ .sse_per_zword => 64,
+ };
+ var byte_offset: u32 = 0;
+ const unaligned_size = cg.unalignedSize(ret_ty);
+ while (byte_offset < unaligned_size) : (byte_offset += reg_size) {
+ switch (@as(enum { sse, x87 }, switch (class) {
+ else => unreachable,
+ .sse_sse_x87_per_qword => switch (byte_offset) {
+ 0 => .sse, // duck
+ 8 => .sse, // duck
+ else => .x87, // goose!
+ },
+ .sse_per_xword, .sse_per_yword, .sse_per_zword => .sse,
+ })) {
+ .sse => {
+ ret_tracking[ret_tracking_len] = .init(.{
+ .register = registerAlias(ret_sse[0], reg_size),
+ });
+ ret_tracking_len += 1;
+ ret_sse = ret_sse[1..];
+ },
+ .x87 => {
+ ret_tracking[ret_tracking_len] = .init(.{
+ .register = registerAlias(ret_x87[0], reg_size),
+ });
+ ret_tracking_len += 1;
+ ret_x87 = ret_x87[1..];
+ },
+ }
+ }
+ },
+ };
+ break :return_value switch (ret_tracking_len) {
+ else => unreachable,
+ 1 => ret_tracking[0],
+ 2 => .init(.{ .register_pair = .{
+ ret_tracking[0].short.register,
+ ret_tracking[1].short.register,
+ } }),
+ 3 => .init(.{ .register_triple = .{
+ ret_tracking[0].short.register,
+ ret_tracking[1].short.register,
+ ret_tracking[2].short.register,
+ } }),
+ 4 => .init(.{ .register_quadruple = .{
+ ret_tracking[0].short.register,
+ ret_tracking[1].short.register,
+ ret_tracking[2].short.register,
+ ret_tracking[3].short.register,
+ } }),
+ };
+ },
+ .fully_comptime => unreachable,
+ };
- // Input params
- params: for (param_types, result.args) |ty, *arg| {
- assert(ty.hasRuntimeBits(zcu));
+ params: for (0.., param_types, result.args) |param_index, ty, *arg| {
result.air_arg_count += 1;
switch (cc) {
+ else => unreachable,
.x86_64_sysv => {},
.x86_64_win => {
param_gpr_index = @max(param_gpr_index, param_sse_index);
param_sse_index = param_gpr_index;
},
- else => unreachable,
}
const save_param_gpr_index = param_gpr_index;
@@ -181307,17 +181992,25 @@ fn resolveCallingConventionValues(
var arg_mcv: [4]MCValue = undefined;
var arg_mcv_len: u32 = 0;
- const classes = switch (cc) {
- .x86_64_sysv => std.mem.sliceTo(&abi.classifySystemV(ty, zcu, cg.target, .arg), .none),
- .x86_64_win => &.{abi.classifyWindows(ty, zcu, cg.target, .arg)},
+ var classes_buf: [8]abi.Class = undefined;
+ const classes = classes: switch (cc) {
else => unreachable,
+ .x86_64_sysv => {
+ classes_buf = abi.classifySystemV(ty, zcu, cg.target, .arg);
+ break :classes &classes_buf;
+ },
+ .x86_64_win => {
+ classes_buf[0] = abi.classifyWindows(ty, zcu, cg.target, .arg);
+ break :classes classes_buf[0..1];
+ },
};
classes: for (classes) |class| switch (class) {
.integer => {
if (param_gpr_index >= param_gpr.len) break;
- arg_mcv[arg_mcv_len] = .{
- .register = registerAlias(param_gpr[param_gpr_index], @intCast(@min(ty.abiSize(zcu), 8))),
- };
+ arg_mcv[arg_mcv_len] = .{ .register = registerAlias(
+ param_gpr[param_gpr_index],
+ @intCast(@min(ty.abiSize(zcu), 8)),
+ ) };
arg_mcv_len += 1;
param_gpr_index += 1;
},
@@ -181327,62 +182020,138 @@ fn resolveCallingConventionValues(
var byte_offset: u32 = 0;
while (byte_offset < abi_size) : (byte_offset += reg_size) {
if (param_sse_index >= param_sse.len) break :classes;
-
- const param_sse_reg = registerAlias(param_sse[param_sse_index], reg_size);
+ arg_mcv[arg_mcv_len] = arg_mcv: {
+ const param_sse_reg =
+ registerAlias(param_sse[param_sse_index], reg_size);
+ switch (cc) {
+ else => unreachable,
+ .x86_64_sysv => {},
+ .x86_64_win => if (param_index >= fn_info.param_types.len) {
+ const param_gpr_reg =
+ registerAlias(param_gpr[param_gpr_index], reg_size);
+ param_gpr_index += 1;
+ break :arg_mcv .{ .register_tee = .{
+ param_sse_reg,
+ param_gpr_reg,
+ .none,
+ .none,
+ } };
+ },
+ }
+ break :arg_mcv .{ .register = param_sse_reg };
+ };
+ arg_mcv_len += 1;
param_sse_index += 1;
-
- arg_mcv[arg_mcv_len] = .{ .register = param_sse_reg };
- arg_mcv_len += 1;
}
},
.sseup => assert(arg_mcv[arg_mcv_len - 1].register.isClass(.sse)),
.x87, .x87up, .memory, .win_i128 => switch (cc) {
.x86_64_sysv => switch (class) {
+ else => unreachable,
.x87, .x87up, .memory => break,
- else => unreachable,
},
- .x86_64_win => if (ty.abiSize(zcu) > 8) {
- if (param_gpr_index < param_gpr.len) {
- arg_mcv[arg_mcv_len] = .{ .indirect = .{ .reg = param_gpr[param_gpr_index].to64() } };
- arg_mcv_len += 1;
- param_gpr_index += 1;
- } else {
- assert(arg_mcv_len == 0);
- const param_align = Type.usize.abiAlignment(zcu);
- result.stack_byte_count = @intCast(param_align.forward(result.stack_byte_count));
- result.stack_align = result.stack_align.max(param_align);
- arg.* = .{ .indirect_load_frame = .{
- .index = stack_frame_base,
- .off = result.stack_byte_count,
- } };
- result.stack_byte_count += @intCast(Type.usize.abiSize(zcu));
- continue :params;
- }
- } else break,
+ .x86_64_win => if (param_gpr_index < param_gpr.len) {
+ arg_mcv[arg_mcv_len] = .{ .indirect = .{
+ .reg = param_gpr[param_gpr_index].to64(),
+ } };
+ arg_mcv_len += 1;
+ param_gpr_index += 1;
+ } else {
+ assert(arg_mcv_len == 0);
+ const param_align = Type.usize.abiAlignment(zcu);
+ result.stack_byte_count =
+ @intCast(param_align.forward(result.stack_byte_count));
+ result.stack_align = result.stack_align.max(param_align);
+ arg.* = .{ .indirect_load_frame = .{
+ .index = stack_frame_base,
+ .off = result.stack_byte_count,
+ } };
+ result.stack_byte_count += @intCast(Type.usize.abiSize(zcu));
+ continue :params;
+ },
else => unreachable,
},
- .none => unreachable,
- .integer_per_element => {
- const remaining_param_gpr_len: u3 = @intCast(param_gpr.len - param_gpr_index);
- param_gpr_index = @intCast(param_gpr.len);
-
+ .none => {},
+ .bool_vector_mask => {
+ arg_mcv[arg_mcv_len] = .{ .indirect_mask = .{
+ .reg = param_gpr[param_gpr_index].to64(),
+ .info = .{ .kind = .lsb, .scalar = .fromSize(@divExact(
+ 16,
+ std.math.ceilPowerOfTwoAssert(u32, @min(ty.vectorLen(zcu), 16)),
+ )) },
+ } };
+ arg_mcv_len += 1;
+ param_gpr_index += 1;
+ },
+ .integer_per_element,
+ .sse_per_element,
+ .sse_per_xword,
+ .sse_per_yword,
+ .sse_per_zword,
+ => {
+ const len = switch (class) {
+ else => unreachable,
+ .integer_per_element, .sse_per_element => ty.vectorLen(zcu),
+ .sse_per_xword => @divExact(ty.abiSize(zcu), 16),
+ .sse_per_yword => @divExact(ty.abiSize(zcu), 32),
+ .sse_per_zword => @divExact(ty.abiSize(zcu), 64),
+ };
+ const param_reg_len: u32 = @intCast(@min(len, switch (class) {
+ else => unreachable,
+ .integer_per_element => param_gpr.len - param_gpr_index,
+ .sse_per_element,
+ .sse_per_xword,
+ .sse_per_yword,
+ .sse_per_zword,
+ => param_sse.len - param_sse_index,
+ }));
+ const frame_elem_len = len - param_reg_len;
const frame_elem_align = 8;
- const frame_elems_len = ty.vectorLen(zcu) - remaining_param_gpr_len;
- const frame_elem_size = std.mem.alignForward(u64, ty.childType(zcu).abiSize(zcu), frame_elem_align);
- const frame_size: u31 = @intCast(frame_elems_len * frame_elem_size);
+ const frame_elem_size = switch (class) {
+ else => unreachable,
+ .integer_per_element, .sse_per_element => std.mem.alignForward(
+ u64,
+ ty.childType(zcu).abiSize(zcu),
+ frame_elem_align,
+ ),
+ .sse_per_xword, .sse_per_yword, .sse_per_zword => 8,
+ };
+ const frame_size: u31 = @intCast(frame_elem_size * frame_elem_len);
- result.stack_byte_count = std.mem.alignForward(u31, result.stack_byte_count, frame_elem_align);
- arg_mcv[arg_mcv_len] = .{ .elementwise_args = .{
- .regs = remaining_param_gpr_len,
- .frame_off = @intCast(result.stack_byte_count),
+ if (frame_size > 0) result.stack_byte_count =
+ std.mem.alignForward(u31, result.stack_byte_count, frame_elem_align);
+ const info: ArgsInfo = .{
+ .info = .{
+ .reg_index = @intCast(param_gpr_index),
+ .frame_off = @intCast(result.stack_byte_count),
+ },
.frame_index = stack_frame_base,
- } };
+ };
+ arg_mcv[arg_mcv_len] = switch (class) {
+ else => unreachable,
+ .integer_per_element => .{ .elementwise_gpr = info },
+ .sse_per_element => .{ .elementwise_sse = info },
+ .sse_per_xword => .{ .xwordwise_sse = info },
+ .sse_per_yword => .{ .ywordwise_sse = info },
+ .sse_per_zword => .{ .zwordwise_sse = info },
+ };
arg_mcv_len += 1;
+ switch (class) {
+ else => unreachable,
+ .integer_per_element => param_gpr_index += param_reg_len,
+ .sse_per_element,
+ .sse_per_xword,
+ .sse_per_yword,
+ .sse_per_zword,
+ => param_sse_index += param_reg_len,
+ }
result.stack_byte_count += frame_size;
},
+ .sse_sse_x87_per_qword => unreachable, // thank goodness
} else {
arg.* = switch (arg_mcv_len) {
else => unreachable,
+ 0 => .none,
1 => arg_mcv[0],
2 => .{ .register_pair = .{
arg_mcv[0].register,
@@ -181432,82 +182201,82 @@ fn resolveCallingConventionValues(
param_gpr = param_gpr[0 .. param_gpr.len - 1];
}
- // Return values
- result.return_value = if (ret_ty.isNoReturn(zcu))
- .init(.unreach)
- else if (!ret_ty.hasRuntimeBits(zcu))
- .init(.none)
- else return_value: {
- const ret_gpr = abi.getCAbiIntReturnRegs(cc);
- const ret_size: u31 = @intCast(ret_ty.abiSize(zcu));
- if (abi.zigcc.return_in_regs) switch (cg.regClassForType(ret_ty)) {
- .general_purpose, .gphi => if (ret_size <= @as(u4, switch (cg.target.cpu.arch) {
- else => unreachable,
- .x86 => 4,
- .x86_64 => 8,
- }))
- break :return_value .init(.{ .register = registerAlias(ret_gpr[0], ret_size) })
- else if (ret_gpr.len >= 2 and ret_ty.isSliceAtRuntime(zcu))
- break :return_value .init(.{ .register_pair = ret_gpr[0..2].* }),
- .segment, .mmx, .ip, .cr, .dr => unreachable,
- .x87 => if (ret_size <= 16) break :return_value .init(.{ .register = .st0 }),
- .sse => if (ret_size <= cg.vectorSize(.float)) break :return_value .init(.{
- .register = registerAlias(abi.getCAbiSseReturnRegs(cc)[0], @max(ret_size, 16)),
- }),
- };
- const ret_indirect_reg = param_gpr[0];
- param_gpr = param_gpr[1..];
- break :return_value .{
- .short = .{ .indirect = .{ .reg = ret_gpr[0] } },
- .long = .{ .indirect = .{ .reg = ret_indirect_reg } },
- };
+ result.return_value = switch (ret_ty.classify(zcu)) {
+ .no_possible_value => .init(.unreach),
+ .one_possible_value => .init(.none),
+ .runtime, .partially_comptime => return_value: {
+ const ret_gpr = abi.getCAbiIntReturnRegs(cc);
+ const ret_size: u31 = @intCast(ret_ty.abiSize(zcu));
+ if (abi.zigcc.return_in_regs) switch (cg.regClassForType(ret_ty)) {
+ .general_purpose, .gphi => if (ret_size <= @as(u4, switch (cg.target.cpu.arch) {
+ else => unreachable,
+ .x86 => 4,
+ .x86_64 => 8,
+ }))
+ break :return_value .init(.{ .register = registerAlias(ret_gpr[0], ret_size) })
+ else if (ret_gpr.len >= 2 and ret_ty.isSliceAtRuntime(zcu))
+ break :return_value .init(.{ .register_pair = ret_gpr[0..2].* }),
+ .segment, .mmx, .ip, .cr, .dr => unreachable,
+ .x87 => if (ret_size <= 16) break :return_value .init(.{ .register = .st0 }),
+ .sse => if (ret_size <= cg.vectorSize(.float)) break :return_value .init(.{
+ .register = registerAlias(abi.getCAbiSseReturnRegs(cc)[0], @max(ret_size, 16)),
+ }),
+ };
+ const ret_indirect_reg = param_gpr[0];
+ param_gpr = param_gpr[1..];
+ break :return_value .{
+ .short = .{ .indirect = .{ .reg = ret_gpr[0] } },
+ .long = .{ .indirect = .{ .reg = ret_indirect_reg } },
+ };
+ },
+ .fully_comptime => unreachable,
};
- // Input params
- for (param_types, result.args) |param_ty, *arg| {
- if (!param_ty.hasRuntimeBits(zcu)) {
- arg.* = .none;
- continue;
- }
- result.air_arg_count += 1;
- const param_size: u31 = @intCast(param_ty.abiSize(zcu));
- if (abi.zigcc.params_in_regs) switch (cg.regClassForType(param_ty)) {
- .general_purpose, .gphi => if (param_gpr.len >= 1 and param_size <= @as(u4, switch (cg.target.cpu.arch) {
- else => unreachable,
- .x86 => 4,
- .x86_64 => 8,
- })) {
- arg.* = .{ .register = registerAlias(param_gpr[0], param_size) };
- param_gpr = param_gpr[1..];
- continue;
- } else if (param_gpr.len >= 2 and param_ty.isSliceAtRuntime(zcu)) {
- arg.* = .{ .register_pair = param_gpr[0..2].* };
- param_gpr = param_gpr[2..];
- continue;
- },
- .segment, .mmx, .ip, .cr, .dr => unreachable,
- .x87 => if (param_x87.len >= 1 and param_size <= 16) {
- arg.* = .{ .register = param_x87[0] };
- param_x87 = param_x87[1..];
- continue;
- },
- .sse => if (param_sse.len >= 1 and param_size <= cg.vectorSize(.float)) {
- arg.* = .{
- .register = registerAlias(param_sse[0], @max(param_size, 16)),
- };
- param_sse = param_sse[1..];
- continue;
- },
- };
- const param_align = param_ty.abiAlignment(zcu);
- result.stack_byte_count = @intCast(param_align.forward(result.stack_byte_count));
- result.stack_align = result.stack_align.max(param_align);
- arg.* = .{ .load_frame = .{
- .index = stack_frame_base,
- .off = result.stack_byte_count,
- } };
- result.stack_byte_count += param_size;
- }
+ for (param_types, result.args) |param_ty, *arg| switch (param_ty.classify(zcu)) {
+ .no_possible_value => arg.* = .unreach,
+ .one_possible_value => arg.* = .none,
+ .runtime, .partially_comptime => {
+ result.air_arg_count += 1;
+ const param_size: u31 = @intCast(param_ty.abiSize(zcu));
+ if (abi.zigcc.params_in_regs) switch (cg.regClassForType(param_ty)) {
+ .general_purpose, .gphi => if (param_gpr.len >= 1 and param_size <= @as(u4, switch (cg.target.cpu.arch) {
+ else => unreachable,
+ .x86 => 4,
+ .x86_64 => 8,
+ })) {
+ arg.* = .{ .register = registerAlias(param_gpr[0], param_size) };
+ param_gpr = param_gpr[1..];
+ continue;
+ } else if (param_gpr.len >= 2 and param_ty.isSliceAtRuntime(zcu)) {
+ arg.* = .{ .register_pair = param_gpr[0..2].* };
+ param_gpr = param_gpr[2..];
+ continue;
+ },
+ .segment, .mmx, .ip, .cr, .dr => unreachable,
+ .x87 => if (param_x87.len >= 1 and param_size <= 16) {
+ arg.* = .{ .register = param_x87[0] };
+ param_x87 = param_x87[1..];
+ continue;
+ },
+ .sse => if (param_sse.len >= 1 and param_size <= cg.vectorSize(.float)) {
+ arg.* = .{
+ .register = registerAlias(param_sse[0], @max(param_size, 16)),
+ };
+ param_sse = param_sse[1..];
+ continue;
+ },
+ };
+ const param_align = param_ty.abiAlignment(zcu);
+ result.stack_byte_count = @intCast(param_align.forward(result.stack_byte_count));
+ result.stack_align = result.stack_align.max(param_align);
+ arg.* = .{ .load_frame = .{
+ .index = stack_frame_base,
+ .off = result.stack_byte_count,
+ } };
+ result.stack_byte_count += param_size;
+ },
+ .fully_comptime => unreachable,
+ };
},
else => return cg.fail("TODO implement function parameters and return values for {} on x86_64", .{cc}),
}
@@ -181593,14 +182362,17 @@ fn registerAlias(reg: Register, size_bytes: u32) Register {
};
}
-fn memSize(self: *CodeGen, ty: Type) Memory.Size {
+fn memSize(self: *CodeGen, ty: Type, class: Register.Class) Memory.Size {
const zcu = self.pt.zcu;
return if (self.floatBits(ty)) |float_bits|
.fromBitSize(float_bits)
else if (ty.isVector(zcu) and ty.vectorLen(zcu) == 1 and self.floatBits(ty.childType(zcu)) == 80)
.tbyte
else
- .fromSize(@intCast(ty.abiSize(zcu)));
+ .fromSize(@intCast(switch (class) {
+ .general_purpose, .gphi, .segment, .x87, .ip, .cr, .dr => self.unalignedSize(ty),
+ .mmx, .sse => ty.abiSize(zcu),
+ }));
}
fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Type {
@@ -181610,7 +182382,10 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty
var parts: [parts_len]Type = undefined;
switch (ip.indexToKey(ty.toIntern())) {
.vector_type => |vector_type| if (std.math.divExact(u32, vector_type.len, parts_len)) |vec_len| {
- return @splat(try pt.vectorType(.{ .len = vec_len, .child = vector_type.child }));
+ return @splat(switch (vec_len) {
+ 1 => .fromInterned(vector_type.child),
+ else => try pt.vectorType(.{ .len = vec_len, .child = vector_type.child }),
+ });
} else |err| switch (err) {
error.DivisionByZero => unreachable,
error.UnexpectedRemainder => {},
@@ -181656,7 +182431,7 @@ fn truncateRegister(self: *CodeGen, ty: Type, reg: Register) !void {
const zcu = pt.zcu;
const int_info: InternPool.Key.IntType = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else .{
.signedness = .unsigned,
- .bits = @intCast(ty.bitSize(zcu)),
+ .bits = @intCast(if (ty.hasBitRepresentation(zcu)) ty.bitSize(zcu) else ty.abiSize(zcu) * 8),
};
const shift = std.math.cast(u6, 64 - int_info.bits % 64) orelse return;
try self.spillEflagsIfOccupied();
@@ -181696,10 +182471,6 @@ fn regBitSize(self: *CodeGen, ty: Type) u64 {
};
}
-fn regExtraBits(self: *CodeGen, ty: Type) u64 {
- return self.regBitSize(ty) - ty.bitSize(self.pt.zcu);
-}
-
fn hasFeature(cg: *CodeGen, feature: std.Target.x86.Feature) bool {
return switch (feature) {
.@"64bit" => switch (cg.target.cpu.arch) {
@@ -181768,13 +182539,11 @@ fn typeOfIndex(self: *CodeGen, inst: Air.Inst.Index) Type {
return Temp.typeOf(.{ .index = inst }, self);
}
-fn promoteInt(self: *CodeGen, ty: Type) Type {
- const pt = self.pt;
+fn promoteInt(cg: *CodeGen, ty: Type) Type {
+ const pt = cg.pt;
const zcu = pt.zcu;
- const int_info: InternPool.Key.IntType = switch (ty.toIntern()) {
- .bool_type => .{ .signedness = .unsigned, .bits = 1 },
- else => if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else return ty,
- };
+ const int_info = cg.intInfo(ty) orelse return ty;
+ if (int_info.bits == 0) return .void;
for ([_]Type{
.c_int, .c_uint,
.c_long, .c_ulong,
@@ -181817,7 +182586,7 @@ fn nonBoolScalarBitSize(cg: *CodeGen, ty: Type) u32 {
.bool_type => vector_type.len,
else => @intCast(Type.fromInterned(vector_type.child).bitSize(zcu)),
},
- else => @intCast(ty.bitSize(zcu)),
+ else => if (ty.hasBitRepresentation(zcu) or ty.isAbiInt(zcu)) @intCast(ty.bitSize(zcu)) else @intCast(ty.abiSize(zcu) * 8),
};
}
@@ -181942,6 +182711,7 @@ const Temp = struct {
.memory,
.indirect,
.indirect_load_frame,
+ .indirect_mask,
.lea_frame,
.load_nav,
.lea_nav,
@@ -181951,7 +182721,12 @@ const Temp = struct {
.lea_lazy_sym,
.lea_extern_func,
.load_extern_func,
- .elementwise_args,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
.air_ref,
=> false,
@@ -182414,7 +183189,13 @@ const Temp = struct {
.register_overflow,
.register_mask,
.indirect_load_frame,
- .elementwise_args,
+ .indirect_mask,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
.air_ref,
=> unreachable, // not a valid pointer
@@ -182546,7 +183327,7 @@ const Temp = struct {
try cg.asmMemoryImmediate(
.{ ._, .mov },
try ptr.tracking(cg).short.deref().mem(cg, .{
- .size = cg.memSize(val_ty),
+ .size = cg.memSize(val_ty, .general_purpose),
}),
val_op,
);
@@ -182566,10 +183347,9 @@ const Temp = struct {
try ptr.tracking(cg).short.deref().mem(cg, .{ .size = .byte }),
);
},
- .register => |val_reg| try ptr.storeRegs(val_ty, &.{registerAlias(
- val_reg,
- @intCast(val_ty.abiSize(cg.pt.zcu)),
- )}, cg),
+ .register => |val_reg| try ptr.storeRegs(val_ty, &.{
+ registerAlias(val_reg, @intCast(cg.unalignedSize(val_ty))),
+ }, cg),
inline .register_pair,
.register_triple,
.register_quadruple,
@@ -182679,14 +183459,10 @@ const Temp = struct {
.s(val_simm32)
else
continue :val_to_gpr;
- try cg.asmMemoryImmediate(
- .{ ._, .mov },
- try dst.tracking(cg).short.mem(cg, .{
- .size = cg.memSize(val_ty),
- .disp = opts.disp,
- }),
- val_op,
- );
+ try cg.asmMemoryImmediate(.{ ._, .mov }, try dst.tracking(cg).short.mem(cg, .{
+ .size = cg.memSize(val_ty, .general_purpose),
+ .disp = opts.disp,
+ }), val_op);
},
.eflags => |cc| try cg.asmSetccMemory(
cc,
@@ -182758,7 +183534,7 @@ const Temp = struct {
while (try ptr.toRegClass(false, .general_purpose, cg)) {},
}
try strat.read(cg, dst_reg, try ptr.tracking(cg).short.deref().mem(cg, .{
- .size = cg.memSize(dst_ty),
+ .size = cg.memSize(dst_ty, dst_rc),
}));
}
@@ -182767,7 +183543,9 @@ const Temp = struct {
const ip = &zcu.intern_pool;
var part_disp: u31 = 0;
var deferred_disp: u31 = 0;
- var src_abi_size: u32 = @intCast(src_ty.abiSize(cg.pt.zcu));
+ const is_full = src_regs.len == 1 and
+ (src_regs[0].class() == .sse or !(src_ty.isRuntimeFloat() or src_ty.isVector(zcu)));
+ var src_size: u32 = @intCast(if (is_full) src_ty.abiSize(zcu) else cg.unalignedSize(src_ty));
for (src_regs, 0..) |src_reg, part_index| {
const part_ty: Type = if (src_regs.len == 1)
src_ty
@@ -182782,13 +183560,17 @@ const Temp = struct {
break :part_ty .usize;
},
.array_type => {
- assert(src_regs.len - part_index == std.math.divCeil(u32, src_abi_size, 8) catch unreachable);
- break :part_ty try cg.pt.intType(.unsigned, @as(u16, 8) * @min(src_abi_size, 8));
+ assert(src_regs.len - part_index == std.math.divCeil(u32, src_size, 8) catch unreachable);
+ break :part_ty try cg.pt.intType(.unsigned, @as(u16, 8) * @min(src_size, 8));
+ },
+ .vector_type => |vector_type| switch (@divExact(vector_type.len, src_regs.len)) {
+ 0 => unreachable,
+ 1 => .fromInterned(vector_type.child),
+ else => |len| try cg.pt.vectorType(.{
+ .len = @intCast(len),
+ .child = vector_type.child,
+ }),
},
- .vector_type => |vector_type| try cg.pt.vectorType(.{
- .len = @intCast(@divExact(vector_type.len, src_regs.len)),
- .child = vector_type.child,
- }),
.opt_type => |opt_child| switch (ip.indexToKey(opt_child)) {
else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, src_ty.fmt(cg.pt) }),
.ptr_type => |ptr_info| {
@@ -182798,8 +183580,8 @@ const Temp = struct {
},
},
.struct_type, .union_type => {
- assert(src_regs.len - part_index == std.math.divCeil(u32, src_abi_size, 8) catch unreachable);
- break :part_ty switch (src_abi_size) {
+ assert(src_regs.len - part_index == std.math.divCeil(u32, src_size, 8) catch unreachable);
+ break :part_ty switch (src_size) {
0, 3, 5...7 => unreachable,
1 => .u8,
2 => .u16,
@@ -182812,7 +183594,8 @@ const Temp = struct {
break :part_ty .fromInterned(tuple_type.types.get(ip)[part_index]);
},
};
- const part_size: u31 = @intCast(part_ty.abiSize(zcu));
+ const part_size: u31 =
+ @intCast(if (is_full) part_ty.abiSize(zcu) else cg.unalignedSize(part_ty));
const src_rc = src_reg.class();
if (src_rc == .x87 or std.math.isPowerOfTwo(part_size)) {
// hack around linker relocation bugs
@@ -182827,8 +183610,9 @@ const Temp = struct {
.x87 => switch (abi.classifySystemV(src_ty, zcu, cg.target, .other)[part_index]) {
else => unreachable,
.float => .dword,
- .float_combine, .sse => .qword,
- .x87 => .tbyte,
+ .float_combine, .sse, .sseup => .qword,
+ .x87, .x87up => .tbyte,
+ .none => .fromBitSize(8 * part_size),
},
},
.disp = part_disp,
@@ -182847,19 +183631,20 @@ const Temp = struct {
try ptr.toOffset(deferred_disp, cg);
deferred_disp = 0;
var src_ptr = try cg.tempInit(.usize, .{ .lea_frame = .{ .index = frame_index } });
- try ptr.memcpy(&src_ptr, src_abi_size, cg);
+ try ptr.memcpy(&src_ptr, src_size, cg);
try src_ptr.die(cg);
}
part_disp += part_size;
deferred_disp += part_size;
- src_abi_size -= part_size;
+ src_size -= part_size;
}
}
fn readReg(src: Temp, disp: i32, dst_ty: Type, dst_reg: Register, cg: *CodeGen) InnerError!void {
- const strat = try cg.moveStrategy(dst_ty, dst_reg.class(), false);
+ const dst_rc = dst_reg.class();
+ const strat = try cg.moveStrategy(dst_ty, dst_rc, false);
try strat.read(cg, dst_reg, try src.tracking(cg).short.mem(cg, .{
- .size = cg.memSize(dst_ty),
+ .size = cg.memSize(dst_ty, dst_rc),
.disp = disp,
}));
}
@@ -182870,7 +183655,7 @@ const Temp = struct {
if (src_rc == .x87 or std.math.isPowerOfTwo(src_abi_size)) {
const strat = try cg.moveStrategy(src_ty, src_rc, false);
try strat.write(cg, try dst.tracking(cg).short.mem(cg, .{
- .size = cg.memSize(src_ty),
+ .size = cg.memSize(src_ty, src_rc),
.disp = disp,
}), registerAlias(src_reg, src_abi_size));
} else {
@@ -182906,14 +183691,36 @@ const Temp = struct {
.integer, .memory, .float, .float_combine => class_index + 1,
.sse => std.mem.indexOfNonePos(abi.Class, classes, class_index + 1, &.{.sseup}) orelse classes.len,
.x87 => std.mem.indexOfNonePos(abi.Class, classes, class_index + 1, &.{.x87up}) orelse classes.len,
- .sseup, .x87up, .none, .win_i128, .integer_per_element => unreachable,
+ .sseup,
+ .x87up,
+ .none,
+ .win_i128,
+ .bool_vector_mask,
+ .integer_per_element,
+ .sse_per_element,
+ .sse_sse_x87_per_qword,
+ .sse_per_xword,
+ .sse_per_yword,
+ .sse_per_zword,
+ => unreachable,
});
const part_size = switch (class) {
.integer, .sse, .memory => @min(8 * @as(u7, next_class_index - class_index), remaining_abi_size),
.x87 => 16,
.float => 4,
.float_combine => 8,
- .sseup, .x87up, .none, .win_i128, .integer_per_element => unreachable,
+ .sseup,
+ .x87up,
+ .none,
+ .win_i128,
+ .bool_vector_mask,
+ .integer_per_element,
+ .sse_per_element,
+ .sse_sse_x87_per_qword,
+ .sse_per_xword,
+ .sse_per_yword,
+ .sse_per_zword,
+ => unreachable,
};
try dst.writeReg(part_disp, switch (class) {
.integer => .u64,
@@ -182926,7 +183733,19 @@ const Temp = struct {
.x87 => .f80,
.float => .f32,
.float_combine => .vector_2_f32,
- .sseup, .x87up, .memory, .none, .win_i128, .integer_per_element => unreachable,
+ .sseup,
+ .x87up,
+ .memory,
+ .none,
+ .win_i128,
+ .bool_vector_mask,
+ .integer_per_element,
+ .sse_per_element,
+ .sse_sse_x87_per_qword,
+ .sse_per_xword,
+ .sse_per_yword,
+ .sse_per_zword,
+ => unreachable,
}, src_reg, cg);
part_disp += part_size;
remaining_abi_size -= part_size;
@@ -182958,6 +183777,1331 @@ const Temp = struct {
try cg.asmOpOnly(.{ .@"rep _sb", .sto });
}
+ fn copyToMask(dst: *Temp, src: *Temp, cg: *CodeGen) Select.Error!void {
+ var ops: [2]Temp = .{ dst.*, src.* };
+ try cg.select(&.{}, &.{}, &ops, comptime &.{ .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 2 }, .{ .exact_bool_vec = 2 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .mem, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 8 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_b, .broadcast, .src0x, .src1b, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 2 }, .{ .exact_bool_vec = 2 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 8 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_b, .broadcast, .src0x, .src1x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 2 }, .{ .exact_bool_vec = 2 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .mem, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 8 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_b, .broadcast, .src0x, .src1b, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_, .xor, .tmp2x, .tmp2x, .tmp2x, ._ },
+ .{ ._, .vp_q, .sub, .src0x, .tmp2x, .src0x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 2 }, .{ .exact_bool_vec = 2 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 8 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_b, .broadcast, .src0x, .src1x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_, .xor, .tmp2x, .tmp2x, .tmp2x, ._ },
+ .{ ._, .vp_q, .sub, .src0x, .tmp2x, .src0x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 2 }, .{ .exact_bool_vec = 2 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 8 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_, .xor, .tmp2x, .tmp2x, .tmp2x, ._ },
+ .{ ._, .vp_b, .shuf, .src0x, .src1x, .tmp2x, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 2 }, .{ .exact_bool_vec = 2 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 8 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_, .xor, .tmp2x, .tmp2x, .tmp2x, ._ },
+ .{ ._, .vp_b, .shuf, .src0x, .src1x, .tmp2x, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_, .xor, .tmp2x, .tmp2x, .tmp2x, ._ },
+ .{ ._, .vp_q, .sub, .src0x, .tmp2x, .src0x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .ssse3, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 2 }, .{ .exact_bool_vec = 2 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 8 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .p_, .xor, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, ._dqa, .mov, .src0x, .src1x, ._, ._ },
+ .{ ._, .p_b, .shuf, .src0x, .tmp2x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .p_, .@"and", .src0x, .tmp2x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .src0x, .tmp2x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .ssse3, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 2 }, .{ .exact_bool_vec = 2 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_mut_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 8 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .p_, .xor, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_b, .shuf, .src1x, .src0x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._dqa, .mov, .src0x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .p_, .@"and", .src1x, .src0x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .src1x, .src0x, ._, ._ },
+ .{ ._, .p_, .xor, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_q, .sub, .src0x, .src1x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .sse2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 2 }, .{ .exact_bool_vec = 2 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 8 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._dqa, .mov, .src0x, .src1x, ._, ._ },
+ .{ ._, .p_, .unpcklbw, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_, .unpcklwd, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_, .unpckldq, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_, .unpcklqdq, .src0x, .src0x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .p_, .@"and", .src0x, .tmp2x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .src0x, .tmp2x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .sse2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 2 }, .{ .exact_bool_vec = 2 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_mut_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 8 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._dqa, .mov, .tmp2x, .src1x, ._, ._ },
+ .{ ._, .p_, .unpcklbw, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, .p_, .unpcklwd, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, .p_, .unpckldq, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, .p_, .unpcklqdq, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._dqa, .mov, .src0x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .p_, .@"and", .tmp2x, .src0x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .tmp2x, .src0x, ._, ._ },
+ .{ ._, .p_, .xor, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_q, .sub, .src0x, .tmp2x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 4 }, .{ .exact_bool_vec = 4 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .mem, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 4 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_b, .broadcast, .src0x, .src1b, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 4 }, .{ .exact_bool_vec = 4 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 4 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_b, .broadcast, .src0x, .src1x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 4 }, .{ .exact_bool_vec = 4 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .mem, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 4 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_b, .broadcast, .src0x, .src1b, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_, .xor, .tmp2x, .tmp2x, .tmp2x, ._ },
+ .{ ._, .vp_b, .sub, .src0x, .tmp2x, .src0x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 4 }, .{ .exact_bool_vec = 4 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 4 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_b, .broadcast, .src0x, .src1x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_, .xor, .tmp2x, .tmp2x, .tmp2x, ._ },
+ .{ ._, .vp_b, .sub, .src0x, .tmp2x, .src0x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 4 }, .{ .exact_bool_vec = 4 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 4 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_, .xor, .tmp2x, .tmp2x, .tmp2x, ._ },
+ .{ ._, .vp_b, .shuf, .src0x, .src1x, .tmp2x, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 4 }, .{ .exact_bool_vec = 4 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 4 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_, .xor, .tmp2x, .tmp2x, .tmp2x, ._ },
+ .{ ._, .vp_b, .shuf, .src0x, .src1x, .tmp2x, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_, .xor, .tmp2x, .tmp2x, .tmp2x, ._ },
+ .{ ._, .vp_b, .sub, .src0x, .tmp2x, .src0x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .ssse3, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 4 }, .{ .exact_bool_vec = 4 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 4 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .p_, .xor, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, ._dqa, .mov, .src0x, .src1x, ._, ._ },
+ .{ ._, .p_b, .shuf, .src0x, .tmp2x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .p_, .@"and", .src0x, .tmp2x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .src0x, .tmp2x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .ssse3, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 4 }, .{ .exact_bool_vec = 4 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_mut_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 4 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .p_, .xor, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_b, .shuf, .src1x, .src0x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._dqa, .mov, .src0x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .p_, .@"and", .src1x, .src0x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .src1x, .src0x, ._, ._ },
+ .{ ._, .p_, .xor, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_b, .sub, .src0x, .src1x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .sse2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 4 }, .{ .exact_bool_vec = 4 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 4 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._dqa, .mov, .src0x, .src1x, ._, ._ },
+ .{ ._, .p_, .unpcklbw, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_, .unpcklwd, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_, .unpckldq, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_, .unpcklqdq, .src0x, .src0x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .p_, .@"and", .src0x, .tmp2x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .src0x, .tmp2x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .sse2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 4 }, .{ .exact_bool_vec = 4 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 4 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._dqa, .mov, .tmp2x, .src1x, ._, ._ },
+ .{ ._, .p_, .unpcklbw, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, .p_, .unpcklwd, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, .p_, .unpckldq, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, .p_, .unpcklqdq, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._dqa, .mov, .src0x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .p_, .@"and", .tmp2x, .src0x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .tmp2x, .src0x, ._, ._ },
+ .{ ._, .p_, .xor, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_b, .sub, .src0x, .tmp2x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 8 }, .{ .exact_bool_vec = 8 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .mem, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 2 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_b, .broadcast, .src0x, .src1b, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 8 }, .{ .exact_bool_vec = 8 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 2 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_b, .broadcast, .src0x, .src1x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 8 }, .{ .exact_bool_vec = 8 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .mem, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 2 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_b, .broadcast, .src0x, .src1b, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_, .xor, .tmp2x, .tmp2x, .tmp2x, ._ },
+ .{ ._, .vp_b, .sub, .src0x, .tmp2x, .src0x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 8 }, .{ .exact_bool_vec = 8 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 2 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_b, .broadcast, .src0x, .src1x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_, .xor, .tmp2x, .tmp2x, .tmp2x, ._ },
+ .{ ._, .vp_b, .sub, .src0x, .tmp2x, .src0x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 8 }, .{ .exact_bool_vec = 8 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 2 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_, .xor, .tmp2x, .tmp2x, .tmp2x, ._ },
+ .{ ._, .vp_b, .shuf, .src0x, .src1x, .tmp2x, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 8 }, .{ .exact_bool_vec = 8 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 2 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_, .xor, .tmp2x, .tmp2x, .tmp2x, ._ },
+ .{ ._, .vp_b, .shuf, .src0x, .src1x, .tmp2x, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp2x, ._ },
+ .{ ._, .vp_, .xor, .tmp2x, .tmp2x, .tmp2x, ._ },
+ .{ ._, .vp_b, .sub, .src0x, .tmp2x, .src0x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .ssse3, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 8 }, .{ .exact_bool_vec = 8 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 2 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .p_, .xor, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, ._dqa, .mov, .src0x, .src1x, ._, ._ },
+ .{ ._, .p_b, .shuf, .src0x, .tmp2x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .p_, .@"and", .src0x, .tmp2x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .src0x, .tmp2x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .ssse3, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 8 }, .{ .exact_bool_vec = 8 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_mut_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 2 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .p_, .xor, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_b, .shuf, .src1x, .src0x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._dqa, .mov, .src0x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .p_, .@"and", .src1x, .src0x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .src1x, .src0x, ._, ._ },
+ .{ ._, .p_, .xor, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_b, .sub, .src0x, .src1x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .sse2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 8 }, .{ .exact_bool_vec = 8 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 2 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._dqa, .mov, .src0x, .src1x, ._, ._ },
+ .{ ._, .p_, .unpcklbw, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_, .unpcklwd, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_, .unpckldq, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_, .unpcklqdq, .src0x, .src0x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .p_, .@"and", .src0x, .tmp2x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .src0x, .tmp2x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .sse2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 8 }, .{ .exact_bool_vec = 8 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward, .smear = 2 } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._dqa, .mov, .tmp2x, .src1x, ._, ._ },
+ .{ ._, .p_, .unpcklbw, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, .p_, .unpcklwd, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, .p_, .unpckldq, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, .p_, .unpcklqdq, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._dqa, .mov, .src0x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .p_, .@"and", .tmp2x, .src0x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .tmp2x, .src0x, ._, ._ },
+ .{ ._, .p_, .xor, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_b, .sub, .src0x, .tmp2x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 16 }, .{ .exact_bool_vec = 16 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .forward, .size = .word, .smear = 8 } } },
+ .{ .type = .vector_8_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp0), ._, ._ },
+ .{ ._, .vp_b, .shuf, .src0x, .src1x, .lea(.tmp2x), ._ },
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp1), ._, ._ },
+ .{ ._, .vp_q, .broadcast, .tmp3x, .lea(.tmp2q), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp3x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp3x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 16 }, .{ .exact_bool_vec = 16 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .forward, .size = .word, .smear = 8 } } },
+ .{ .type = .vector_8_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp0), ._, ._ },
+ .{ ._, .vp_b, .shuf, .src0x, .src1x, .lea(.tmp2x), ._ },
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp1), ._, ._ },
+ .{ ._, .vp_q, .broadcast, .tmp3x, .lea(.tmp2q), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp3x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp3x, ._ },
+ .{ ._, .vp_, .xor, .tmp3x, .tmp3x, .tmp3x, ._ },
+ .{ ._, .vp_b, .sub, .src0x, .tmp3x, .src0x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 16 }, .{ .exact_bool_vec = 16 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .forward, .size = .word, .smear = 8 } } },
+ .{ .type = .vector_8_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp0), ._, ._ },
+ .{ ._, .vp_b, .shuf, .src0x, .src1x, .lea(.tmp2x), ._ },
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp1), ._, ._ },
+ .{ ._, .v_, .movddup, .tmp3x, .lea(.tmp2q), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp3x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp3x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 16 }, .{ .exact_bool_vec = 16 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .forward, .size = .word, .smear = 8 } } },
+ .{ .type = .vector_8_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_16_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp0), ._, ._ },
+ .{ ._, .vp_b, .shuf, .src0x, .src1x, .lea(.tmp2x), ._ },
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp1), ._, ._ },
+ .{ ._, .v_, .movddup, .tmp3x, .lea(.tmp2q), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp3x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp3x, ._ },
+ .{ ._, .vp_, .xor, .tmp3x, .tmp3x, .tmp3x, ._ },
+ .{ ._, .vp_b, .sub, .src0x, .tmp3x, .src0x, ._ },
+ } },
+ }, .{
+ .required_features = .{ .ssse3, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 16 }, .{ .exact_bool_vec = 16 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .forward, .size = .word, .smear = 8 } } },
+ .{ .type = .vector_8_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .usize, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._dqa, .mov, .src0x, .src1x, ._, ._ },
+ .{ ._, .p_b, .shuf, .src0x, .lea(.tmp2x), ._, ._ },
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp1), ._, ._ },
+ .{ ._, ._, .movddup, .tmp3x, .lea(.tmp2q), ._, ._ },
+ .{ ._, .p_, .@"and", .src0x, .tmp3x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .src0x, .tmp3x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .ssse3, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 16 }, .{ .exact_bool_vec = 16 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_mut_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .forward, .size = .word, .smear = 8 } } },
+ .{ .type = .vector_8_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp0), ._, ._ },
+ .{ ._, .p_b, .shuf, .src1x, .lea(.tmp2x), ._, ._ },
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp1), ._, ._ },
+ .{ ._, ._, .movddup, .src0x, .lea(.tmp2q), ._, ._ },
+ .{ ._, .p_, .@"and", .src1x, .src0x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .src1x, .src0x, ._, ._ },
+ .{ ._, .p_, .xor, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_b, .sub, .src0x, .src1x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .sse3, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 16 }, .{ .exact_bool_vec = 16 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_8_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .usize, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._dqa, .mov, .src0x, .src1x, ._, ._ },
+ .{ ._, .p_, .unpcklbw, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_, .unpcklwd, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_, .unpckldq, .src0x, .src0x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._, .movddup, .tmp2x, .lea(.tmp1q), ._, ._ },
+ .{ ._, .p_, .@"and", .src0x, .tmp2x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .src0x, .tmp2x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .sse3, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 16 }, .{ .exact_bool_vec = 16 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_8_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .usize, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._dqa, .mov, .tmp2x, .src1x, ._, ._ },
+ .{ ._, .p_, .unpcklbw, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, .p_, .unpcklwd, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, .p_, .unpckldq, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._, .movddup, .src0x, .lea(.tmp1q), ._, ._ },
+ .{ ._, .p_, .@"and", .tmp2x, .src0x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .tmp2x, .src0x, ._, ._ },
+ .{ ._, .p_, .xor, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_b, .sub, .src0x, .tmp2x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .sse2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 16 }, .{ .exact_bool_vec = 16 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .usize, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._dqa, .mov, .src0x, .src1x, ._, ._ },
+ .{ ._, .p_, .unpcklbw, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_, .unpcklwd, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_, .unpckldq, .src0x, .src0x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._dqa, .mov, .tmp2x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .p_, .@"and", .src0x, .tmp2x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .src0x, .tmp2x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .sse2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 16 }, .{ .exact_bool_vec = 16 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .xword, .kind = .from_zero_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .usize, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._dqa, .mov, .tmp2x, .src1x, ._, ._ },
+ .{ ._, .p_, .unpcklbw, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, .p_, .unpcklwd, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, .p_, .unpckldq, .tmp2x, .tmp2x, ._, ._ },
+ .{ ._, ._, .lea, .tmp1p, .mem(.tmp0), ._, ._ },
+ .{ ._, ._dqa, .mov, .src0x, .lea(.tmp1x), ._, ._ },
+ .{ ._, .p_, .@"and", .tmp2x, .src0x, ._, ._ },
+ .{ ._, .p_b, .cmpeq, .tmp2x, .src0x, ._, ._ },
+ .{ ._, .p_, .xor, .src0x, .src0x, ._, ._ },
+ .{ ._, .p_b, .sub, .src0x, .tmp2x, ._, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 32 }, .{ .exact_bool_vec = 32 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .yword, .kind = .from_sign_extend, .is = .uninverted } }, .mem, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_32_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .forward, .size = .dword, .smear = 8 } } },
+ .{ .type = .vector_8_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_32_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_d, .broadcast, .src0y, .src1d, ._, ._ },
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp0), ._, ._ },
+ .{ ._, .vp_b, .shuf, .src0y, .src0y, .lea(.tmp2y), ._ },
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp1), ._, ._ },
+ .{ ._, .vp_q, .broadcast, .tmp3y, .lea(.tmp2q), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0y, .src0y, .tmp3y, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0y, .src0y, .tmp3y, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 32 }, .{ .exact_bool_vec = 32 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .yword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_32_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .forward, .size = .dword, .smear = 8 } } },
+ .{ .type = .vector_8_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_32_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_d, .broadcast, .src0y, .src1x, ._, ._ },
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp0), ._, ._ },
+ .{ ._, .vp_b, .shuf, .src0y, .src0y, .lea(.tmp2y), ._ },
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp1), ._, ._ },
+ .{ ._, .vp_q, .broadcast, .tmp3y, .lea(.tmp2q), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0y, .src0y, .tmp3y, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0y, .src0y, .tmp3y, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 32 }, .{ .exact_bool_vec = 32 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .yword, .kind = .from_zero_extend, .is = .uninverted } }, .mem, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_32_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .forward, .size = .dword, .smear = 8 } } },
+ .{ .type = .vector_8_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_32_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_d, .broadcast, .src0y, .src1d, ._, ._ },
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp0), ._, ._ },
+ .{ ._, .vp_b, .shuf, .src0y, .src0y, .lea(.tmp2y), ._ },
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp1), ._, ._ },
+ .{ ._, .vp_q, .broadcast, .tmp3y, .lea(.tmp2q), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0y, .src0y, .tmp3y, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0y, .src0y, .tmp3y, ._ },
+ .{ ._, .vp_, .xor, .tmp3y, .tmp3y, .tmp3y, ._ },
+ .{ ._, .vp_b, .sub, .src0y, .tmp3y, .src0y, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx2, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 32 }, .{ .exact_bool_vec = 32 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .yword, .kind = .from_zero_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_32_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .forward, .size = .dword, .smear = 8 } } },
+ .{ .type = .vector_8_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_32_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, .vp_d, .broadcast, .src0y, .src1x, ._, ._ },
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp0), ._, ._ },
+ .{ ._, .vp_b, .shuf, .src0y, .src0y, .lea(.tmp2y), ._ },
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp1), ._, ._ },
+ .{ ._, .vp_q, .broadcast, .tmp3y, .lea(.tmp2q), ._, ._ },
+ .{ ._, .vp_, .@"and", .src0y, .src0y, .tmp3y, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0y, .src0y, .tmp3y, ._ },
+ .{ ._, .vp_, .xor, .tmp3y, .tmp3y, .tmp3y, ._ },
+ .{ ._, .vp_b, .sub, .src0y, .tmp3y, .src0y, ._ },
+ } },
+ }, .{
+ .required_features = .{ .avx, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 32 }, .{ .exact_bool_vec = 32 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .yword, .kind = .from_sign_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_32_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .forward, .size = .dword, .smear = 8 } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_32_u8, .kind = .{ .rc = .sse } },
+ .{ .type = .vector_32_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp0), ._, ._ },
+ .{ ._, .vp_b, .shuf, .tmp3x, .src1x, .lea(.tmp2y), ._ },
+ .{ ._, .vp_b, .shuf, .src0x, .src1x, .lead(.tmp2y, 16), ._ },
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp1), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp4x, .lea(.tmp2x), ._, ._ },
+ .{ ._, .vp_, .@"and", .tmp3x, .tmp3x, .tmp4x, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp4x, ._ },
+ .{ ._, .vp_b, .cmpeq, .tmp3x, .tmp3x, .tmp4x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp4x, ._ },
+ .{ ._, .v_f128, .insert, .src0y, .tmp3y, .src0x, .ui(1) },
+ } },
+ }, .{
+ .required_features = .{ .avx, null, null, null },
+ .src_constraints = .{ .{ .exact_bool_vec = 32 }, .{ .exact_bool_vec = 32 }, .any },
+ .patterns = &.{
+ .{ .src = .{ .{ .reg_mask = .{ .size = .yword, .kind = .from_zero_extend, .is = .uninverted } }, .to_sse, .none } },
+ },
+ .extra_temps = .{
+ .{ .type = .vector_32_u8, .kind = .{ .pshufb_bytes_mem = .{ .direction = .forward, .size = .dword, .smear = 8 } } },
+ .{ .type = .vector_16_u8, .kind = .{ .bits_mem = .{ .direction = .forward } } },
+ .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
+ .{ .type = .vector_32_u8, .kind = .{ .rc = .sse } },
+ .{ .type = .vector_32_u8, .kind = .{ .rc = .sse } },
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ .unused,
+ },
+ .each = .{ .once = &.{
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp0), ._, ._ },
+ .{ ._, .vp_b, .shuf, .tmp3x, .src1x, .lea(.tmp2y), ._ },
+ .{ ._, .vp_b, .shuf, .src0x, .src1x, .lead(.tmp2y, 16), ._ },
+ .{ ._, ._, .lea, .tmp2p, .mem(.tmp1), ._, ._ },
+ .{ ._, .v_dqa, .mov, .tmp4x, .lea(.tmp2x), ._, ._ },
+ .{ ._, .vp_, .@"and", .tmp3x, .tmp3x, .tmp4x, ._ },
+ .{ ._, .vp_, .@"and", .src0x, .src0x, .tmp4x, ._ },
+ .{ ._, .vp_b, .cmpeq, .tmp3x, .tmp3x, .tmp4x, ._ },
+ .{ ._, .vp_b, .cmpeq, .src0x, .src0x, .tmp4x, ._ },
+ .{ ._, .vp_, .xor, .tmp4x, .tmp4x, .tmp4x, ._ },
+ .{ ._, .vp_b, .sub, .tmp3x, .tmp4x, .tmp3x, ._ },
+ .{ ._, .vp_b, .sub, .src0x, .tmp4x, .src0x, ._ },
+ .{ ._, .v_f128, .insert, .src0y, .tmp3y, .src0x, .ui(1) },
+ } },
+ } });
+ dst.*, src.* = ops;
+ }
+
fn wrapInt(temp: *Temp, cg: *CodeGen) Select.Error!void {
var ops: [1]Temp = .{temp.*};
var res: [1]Temp = undefined;
@@ -187486,7 +189630,13 @@ const Temp = struct {
.unreach,
.dead,
.indirect_load_frame,
- .elementwise_args,
+ .indirect_mask,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
.reserved_frame,
.air_ref,
=> unreachable,
@@ -188336,25 +190486,60 @@ const Select = struct {
to_sse,
mut_sse,
to_mut_sse,
- reg_mask: RegMaskSpec,
- all_reg_mask: RegMaskSpec,
-
- const RegMaskSpec = struct {
+ reg_mask: struct {
size: Memory.Size,
+ kind: enum {
+ any,
+ lsb,
+ msb,
+ zero_extend,
+ sign_extend,
+ from_lsb,
+ from_msb,
+ from_zero_extend,
+ from_sign_extend,
+ },
is: enum {
any,
uninverted,
inverted,
-
- fn matches(is: @This(), inverted: bool) bool {
- return switch (is) {
- .any => true,
- .uninverted => !inverted,
- .inverted => inverted,
- };
- }
} = .any,
- };
+
+ fn matches(spec: @This(), info: MaskInfo) bool {
+ return switch (spec.kind) {
+ .any => true,
+ .lsb => switch (info.kind) {
+ .lsb, .msb, .zero_extend, .sign_extend => true,
+ },
+ .msb => switch (info.kind) {
+ .lsb, .zero_extend => false,
+ .msb, .sign_extend => true,
+ },
+ .zero_extend => info.kind == .zero_extend,
+ .sign_extend => info.kind == .sign_extend,
+ .from_lsb => switch (info.kind) {
+ .lsb => true,
+ .msb, .zero_extend, .sign_extend => false,
+ },
+ .from_msb => switch (info.kind) {
+ .lsb, .msb => true,
+ .zero_extend, .sign_extend => false,
+ },
+ .from_sign_extend => switch (info.kind) {
+ .lsb, .msb, .sign_extend => true,
+ .zero_extend => false,
+ },
+ .from_zero_extend => switch (info.kind) {
+ .lsb, .zero_extend => true,
+ .msb, .sign_extend => false,
+ },
+ } and switch (spec.is) {
+ .any => true,
+ .uninverted => !info.inverted,
+ .inverted => info.inverted,
+ };
+ }
+ },
fn matches(src: Src, temp: Temp, cg: *CodeGen) bool {
return switch (src) {
@@ -188439,13 +190624,7 @@ const Select = struct {
.reg_mask => |mask_spec| switch (temp.tracking(cg).short) {
.register_mask => |reg_mask| mask_spec.size.bitSize(cg.target) >=
reg_mask.info.scalar.bitSize(cg.target) * temp.typeOf(cg).vectorLen(cg.pt.zcu) and
- mask_spec.is.matches(reg_mask.info.inverted),
- else => false,
- },
- .all_reg_mask => |mask_spec| switch (temp.tracking(cg).short) {
- .register_mask => |reg_mask| mask_spec.size.bitSize(cg.target) ==
- reg_mask.info.scalar.bitSize(cg.target) * temp.typeOf(cg).vectorLen(cg.pt.zcu) and
- reg_mask.info.kind == .all and mask_spec.is.matches(reg_mask.info.inverted),
+ mask_spec.matches(reg_mask.info),
else => false,
},
};
@@ -188453,7 +190632,7 @@ const Select = struct {
fn convert(src: Src, temp: *Temp, cg: *CodeGen) InnerError!bool {
return switch (src) {
- .none, .any, .imm, .imm8, .imm16, .imm32, .simm32, .reg_mask, .all_reg_mask => false,
+ .none, .any, .imm, .imm8, .imm16, .imm32, .simm32, .reg_mask => false,
.mem, .to_mem => try temp.toBase(false, cg),
.mut_mem, .to_mut_mem => try temp.toBase(true, cg),
.to_reg => |reg| try temp.toReg(reg, cg),
@@ -188524,8 +190703,8 @@ const Select = struct {
pand_trunc_mem: struct { from: Memory.Size, to: Memory.Size },
pand_mask_mem: struct { ref: Select.Operand.Ref, invert: bool = false },
ptest_mask_mem: Select.Operand.Ref,
- pshufb_bswap_mem: struct { repeat: u4 = 1, size: Memory.Size, smear: u4 = 1 },
- bits_mem: enum { forward, reverse },
+ pshufb_bytes_mem: struct { direction: Direction, repeat: u4 = 1, size: Memory.Size, smear: u4 = 1 },
+ bits_mem: struct { direction: Direction, smear: u4 = 1 },
splat_int_mem: struct { ref: Select.Operand.Ref, inside: enum { umin, smin, smax } = .umin, outside: enum { smin, smax } },
splat_float_mem: struct { ref: Select.Operand.Ref, inside: enum { zero } = .zero, outside: f16 },
frame: FrameIndex,
@@ -188560,6 +190739,8 @@ const Select = struct {
}
};
+ const Direction = enum { forward, reverse };
+
fn lock(kind: Kind, cg: *CodeGen) ![2]?RegisterLock {
var reg_locks: [2]?RegisterLock = @splat(null);
const regs: [2]Register = switch (kind) {
@@ -188881,11 +191062,15 @@ const Select = struct {
var index: u7 = 0;
for (0..@intCast(ref_ty.vectorLen(zcu))) |_| {
switch (mask_info.kind) {
- .sign => {
+ .lsb, .zero_extend => {
+ elems[index] = 1;
+ @memset(elems[index + 1 ..][0 .. elem_bytes - 1], std.math.minInt(u8));
+ },
+ .msb => {
@memset(elems[index..][0 .. elem_bytes - 1], std.math.minInt(u8));
elems[index + elem_bytes - 1] = @bitCast(@as(i8, std.math.minInt(i8)));
},
- .all => @memset(elems[index..][0..elem_bytes], std.math.maxInt(u8)),
+ .sign_extend => @memset(elems[index..][0..elem_bytes], std.math.maxInt(u8)),
}
index += elem_bytes;
}
@@ -188894,31 +191079,40 @@ const Select = struct {
.storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) },
} }))), true };
},
- .pshufb_bswap_mem => |bswap_spec| {
+ .pshufb_bytes_mem => |bytes_spec| {
const zcu = pt.zcu;
assert(spec.type.isVector(zcu) and spec.type.childType(zcu).toIntern() == .u8_type);
var elem_buf: [32]u8 = @splat(1 << 7);
const elems = elem_buf[0..spec.type.vectorLen(zcu)];
- const len: usize = @intCast(@divExact(bswap_spec.size.bitSize(cg.target), 8));
+ const len: usize = @intCast(@divExact(bytes_spec.size.bitSize(cg.target), 8));
var to_index: u6 = 0;
- for (0..bswap_spec.repeat) |_| for (0..len) |from_index| {
- @memset(elems[to_index..][0..bswap_spec.smear], @intCast(len - 1 - from_index));
- to_index += bswap_spec.smear;
+ for (0..bytes_spec.repeat) |_| for (0..len) |from_index| {
+ @memset(elems[to_index..][0..bytes_spec.smear], @intCast(switch (bytes_spec.direction) {
+ .forward => from_index,
+ .reverse => len - 1 - from_index,
+ }));
+ to_index += bytes_spec.smear;
};
return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{
.ty = spec.type.toIntern(),
.storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) },
} }))), true };
},
- .bits_mem => |direction| {
+ .bits_mem => |bits_spec| {
const zcu = pt.zcu;
assert(spec.type.isVector(zcu) and spec.type.childType(zcu).toIntern() == .u8_type);
- var bytes: [32]u8 = undefined;
- const elems = bytes[0..spec.type.vectorLen(zcu)];
- for (elems, 0..) |*elem, index| elem.* = switch (direction) {
- .forward => @as(u8, 1 << 0) << @truncate(index),
- .reverse => @as(u8, 1 << 7) >> @truncate(index),
- };
+ var elem_buf: [32]u8 = @splat(1 << 7);
+ const elems = elem_buf[0..spec.type.vectorLen(zcu)];
+ var from_index: u6 = 0;
+ var to_index: u6 = 0;
+ while (elems.len - to_index > 0) {
+ @memset(elems[to_index..][0..bits_spec.smear], @intCast(switch (bits_spec.direction) {
+ .forward => @as(u8, 1 << 0) << @truncate(from_index),
+ .reverse => @as(u8, 1 << 7) >> @truncate(from_index),
+ }));
+ from_index += 1;
+ to_index += bits_spec.smear;
+ }
return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{
.ty = spec.type.toIntern(),
.storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) },
@@ -189053,6 +191247,9 @@ const Select = struct {
unaligned_size_add_elem_size,
unaligned_size_sub_elem_size,
unaligned_size_sub_2_elem_size,
+ size_sub_bit_size_div_8_down_1_sub_1,
+ bit_size_sub_1_div_8_down_1,
+ bit_size_last_byte_mask,
bit_size,
src0_bit_size,
@"8_size_sub_bit_size",
@@ -189105,6 +191302,9 @@ const Select = struct {
const add_unaligned_size_add_elem_size: Adjust = .{ .sign = .pos, .lhs = .unaligned_size_add_elem_size, .op = .mul, .rhs = .@"1" };
const add_unaligned_size_sub_elem_size: Adjust = .{ .sign = .pos, .lhs = .unaligned_size_sub_elem_size, .op = .mul, .rhs = .@"1" };
const add_unaligned_size_sub_2_elem_size: Adjust = .{ .sign = .pos, .lhs = .unaligned_size_sub_2_elem_size, .op = .mul, .rhs = .@"1" };
+ const add_size_sub_bit_size_div_8_down_1_sub_1: Adjust = .{ .sign = .pos, .lhs = .size_sub_bit_size_div_8_down_1_sub_1, .op = .mul, .rhs = .@"1" };
+ const add_bit_size_sub_1_div_8_down_1: Adjust = .{ .sign = .pos, .lhs = .bit_size_sub_1_div_8_down_1, .op = .mul, .rhs = .@"1" };
+ const bit_size_last_byte_mask: Adjust = .{ .sign = .pos, .lhs = .bit_size_last_byte_mask, .op = .mul, .rhs = .@"1" };
const add_2_bit_size: Adjust = .{ .sign = .pos, .lhs = .bit_size, .op = .mul, .rhs = .@"2" };
const add_bit_size: Adjust = .{ .sign = .pos, .lhs = .bit_size, .op = .mul, .rhs = .@"1" };
const add_bit_size_rem_8: Adjust = .{ .sign = .pos, .lhs = .bit_size, .op = .rem_8_mul, .rhs = .@"1" };
@@ -190041,11 +192241,26 @@ const Select = struct {
const ty = op.flags.base.ref.typeOf(s);
break :lhs @intCast(s.cg.unalignedSize(ty) - ty.scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu) * 2);
},
+ .size_sub_bit_size_div_8_down_1_sub_1 => {
+ const ty = op.flags.base.ref.typeOf(s);
+ const size: SignedImm = @intCast(ty.abiSize(s.cg.pt.zcu));
+ const bit_size: SignedImm = @intCast(s.cg.nonBoolScalarBitSize(ty));
+ break :lhs size - @divFloor(bit_size - 1, 8) - 1;
+ },
+ .bit_size_sub_1_div_8_down_1 => {
+ const bit_size: SignedImm = @intCast(s.cg.nonBoolScalarBitSize(op.flags.base.ref.typeOf(s)));
+ break :lhs @divFloor(bit_size - 1, 8);
+ },
+ .bit_size_last_byte_mask => {
+ const bit_size = s.cg.nonBoolScalarBitSize(op.flags.base.ref.typeOf(s));
+ break :lhs @as(u8, std.math.maxInt(u8)) >> @intCast(7 - (bit_size - 1) % 8);
+ },
.bit_size => @intCast(s.cg.nonBoolScalarBitSize(op.flags.base.ref.typeOf(s))),
.src0_bit_size => @intCast(s.cg.nonBoolScalarBitSize(Select.Operand.Ref.src0.typeOf(s))),
.@"8_size_sub_bit_size" => {
const ty = op.flags.base.ref.typeOf(s);
- break :lhs @intCast(8 * ty.abiSize(s.cg.pt.zcu) - ty.bitSize(s.cg.pt.zcu));
+ const bit_size = s.cg.intInfo(ty).?.bits;
+ break :lhs @intCast(8 * ty.abiSize(s.cg.pt.zcu) - bit_size);
},
.len => @intCast(op.flags.base.ref.typeOf(s).vectorLen(s.cg.pt.zcu)),
.elem_limbs => @intCast(@divExact(
@@ -190152,7 +192367,16 @@ const Select = struct {
.lea_lazy_sym => |lazy_sym| .{ .imm = .{ .lazy_sym = lazy_sym } },
.lea_extern_func => |extern_func| .{ .imm = .{ .extern_func = extern_func } },
else => |mcv| .{ .mem = try mcv.mem(s.cg, .{ .size = op.flags.base.size }) },
- .lea_frame, .elementwise_args, .reserved_frame, .air_ref => unreachable,
+ .lea_frame,
+ .register_tee,
+ .elementwise_gpr,
+ .elementwise_sse,
+ .xwordwise_sse,
+ .ywordwise_sse,
+ .zwordwise_sse,
+ .reserved_frame,
+ .air_ref,
+ => unreachable,
},
1...2 => |imm| switch (op.flags.base.ref.valueOf(s)) {
inline .register_pair, .register_triple, .register_quadruple => |regs| .{
diff --git a/src/codegen/x86_64/Emit.zig b/src/codegen/x86_64/Emit.zig
index babadbe96b8bf23db4ad0d4c10de06c11a7710ca..1e8e60ffb665fc70709a5291040a32a1bebcb5af 100644
--- a/src/codegen/x86_64/Emit.zig
+++ b/src/codegen/x86_64/Emit.zig
@@ -113,6 +113,7 @@ pub fn emitMir(emit: *Emit) Error!void {
.default => true,
.hidden, .protected => false,
},
+ .is_dll_import = @"extern".is_dll_import,
.force_pcrel_direct = switch (@"extern".relocation) {
.any => false,
.pcrel => true,
@@ -154,20 +155,13 @@ pub fn emitMir(emit: *Emit) Error!void {
@enumFromInt(try elf_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null))
else if (emit.bin_file.cast(.elf2)) |elf| try elf.externSymbol(.{
.name = extern_func.toSlice(&emit.lower.mir).?,
- .lib_name = switch (comp.compiler_rt_strat) {
- .none, .lib, .obj, .zcu => null,
- .dyn_lib => "compiler_rt",
- },
+ .lib_name = null,
.type = .FUNC,
}) else if (emit.bin_file.cast(.macho)) |macho_file|
@enumFromInt(try macho_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null))
- else if (emit.bin_file.cast(.coff2)) |coff| @enumFromInt(@intFromEnum(try coff.globalSymbol(
- extern_func.toSlice(&emit.lower.mir).?,
- switch (comp.compiler_rt_strat) {
- .none, .lib, .obj, .zcu => null,
- .dyn_lib => "compiler_rt",
- },
- ))) else return emit.fail("external symbol unimplemented for {s}", .{@tagName(emit.bin_file.tag)}),
+ else if (emit.bin_file.cast(.coff2)) |coff| @enumFromInt(@intFromEnum(try coff.globalSymbol(.{
+ .name = extern_func.toSlice(&emit.lower.mir).?,
+ }))) else return emit.fail("external symbol unimplemented for {s}", .{@tagName(emit.bin_file.tag)}),
.is_extern = true,
} },
},
@@ -179,7 +173,13 @@ pub fn emitMir(emit: *Emit) Error!void {
switch (lowered_inst.encoding.mnemonic) {
.call => {
reloc.target = .{ .branch = target };
- try emit.encodeInst(lowered_inst, reloc_info);
+ if (target.is_dll_import and emit.bin_file.cast(.coff2) != null) {
+ try emit.encodeInst(try .new(.none, .call, &.{
+ .{ .mem = .initRip(.ptr, 0) },
+ }, emit.lower.target), reloc_info);
+ } else {
+ try emit.encodeInst(lowered_inst, reloc_info);
+ }
continue :lowered_inst;
},
else => {},
@@ -255,7 +255,25 @@ pub fn emitMir(emit: *Emit) Error!void {
else => unreachable,
}
} else if (emit.bin_file.cast(.coff2)) |_| {
- switch (lowered_inst.encoding.mnemonic) {
+ if (target.is_dll_import) switch (lowered_inst.encoding.mnemonic) {
+ .lea => try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initRip(.ptr, 0) },
+ }, emit.lower.target), reloc_info),
+ .mov => {
+ try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initRip(.ptr, 0) },
+ }, emit.lower.target), reloc_info);
+ try emit.encodeInst(try .new(.none, .mov, &.{
+ lowered_inst.ops[0],
+ .{ .mem = .initSib(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, .{ .base = .{
+ .reg = lowered_inst.ops[0].reg.to64(),
+ } }) },
+ }, emit.lower.target), &.{});
+ },
+ else => unreachable,
+ } else switch (lowered_inst.encoding.mnemonic) {
.lea => try emit.encodeInst(try .new(.none, .lea, &.{
lowered_inst.ops[0],
.{ .mem = .initRip(.none, 0) },
@@ -374,7 +392,7 @@ pub fn emitMir(emit: *Emit) Error!void {
.op_index = 1,
.target = .{ .symbol = .{
.symbol = @enumFromInt(@intFromEnum(
- try coff.globalSymbol("__tls_index", null),
+ try coff.globalSymbol(.{ .name = "__tls_index" }),
)),
.is_extern = false,
} },
@@ -409,7 +427,7 @@ pub fn emitMir(emit: *Emit) Error!void {
.op_index = 1,
.target = .{ .symbol = .{
.symbol = @enumFromInt(@intFromEnum(
- try coff.globalSymbol("_tls_index", null),
+ try coff.globalSymbol(.{ .name = "_tls_index" }),
)),
.is_extern = false,
} },
@@ -725,6 +743,7 @@ const RelocInfo = struct {
const Symbol = struct {
symbol: link.File.SymbolId,
is_extern: bool,
+ is_dll_import: bool = false,
force_pcrel_direct: bool = false,
};
};
@@ -816,7 +835,7 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
@enumFromInt(@intFromEnum(emit.atom_id)),
end_offset - 4,
@enumFromInt(@intFromEnum(target.symbol)),
- reloc.off,
+ .{ .known = reloc.off },
.{ .AMD64 = .REL32 },
) else unreachable,
.branch => |target| if (emit.bin_file.cast(.elf)) |elf_file| {
@@ -854,7 +873,7 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
@enumFromInt(@intFromEnum(emit.atom_id)),
end_offset - 4,
@enumFromInt(@intFromEnum(target.symbol)),
- reloc.off,
+ .{ .known = reloc.off },
.{ .AMD64 = .REL32 },
) else return emit.fail("TODO implement {s} reloc for {s}", .{
@tagName(reloc.target), @tagName(emit.bin_file.tag),
@@ -912,7 +931,7 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
@enumFromInt(@intFromEnum(emit.atom_id)),
end_offset - 4,
@enumFromInt(@intFromEnum(target.symbol)),
- reloc.off,
+ .{ .known = reloc.off },
.{ .AMD64 = .SECREL },
) else return emit.fail("TODO implement {s} reloc for {s}", .{
@tagName(reloc.target), @tagName(emit.bin_file.tag),
diff --git a/src/codegen/x86_64/abi.zig b/src/codegen/x86_64/abi.zig
index 6f620876521aeb4a2f866028c406ade71ee10a8c..3e7a9a548d54baee16d64a54de9a42c4650f7ea5 100644
--- a/src/codegen/x86_64/abi.zig
+++ b/src/codegen/x86_64/abi.zig
@@ -24,59 +24,40 @@ pub const Class = enum {
float,
/// A `Class.sse` containing two `f32`s.
float_combine,
- /// Clang passes each vector element in a separate `Class.integer`, but returns as `Class.memory`.
+ /// Clang uses different element sizes depending on the vector length.
+ bool_vector_mask,
+ /// Clang passes each vector element in a separate `Class.integer`.
integer_per_element,
+ /// Clang passes each vector element in a separate `Class.sse`.
+ sse_per_element,
+ /// Just complete insanity, idk what to say.
+ sse_sse_x87_per_qword,
+ /// Clang passes each 16 bytes in a separate `Class.sse`.
+ sse_per_xword,
+ /// Clang passes each 32 bytes in a separate `Class.sse`.
+ sse_per_yword,
+ /// Clang passes each 64 bytes in a separate `Class.sse`.
+ sse_per_zword,
- pub const one_integer: [8]Class = .{
- .integer, .none, .none, .none,
- .none, .none, .none, .none,
- };
- pub const two_integers: [8]Class = .{
- .integer, .integer, .none, .none,
- .none, .none, .none, .none,
- };
- pub const three_integers: [8]Class = .{
- .integer, .integer, .integer, .none,
- .none, .none, .none, .none,
- };
- pub const four_integers: [8]Class = .{
- .integer, .integer, .integer, .integer,
- .none, .none, .none, .none,
- };
- pub const len_integers: [8]Class = .{
- .integer_per_element, .none, .none, .none,
- .none, .none, .none, .none,
- };
+ pub const zero_bit: [8]Class = .{ .none, .none, .none, .none, .none, .none, .none, .none };
+
+ pub const one_integer: [8]Class = .{ .integer, .none, .none, .none, .none, .none, .none, .none };
+ pub const two_integers: [8]Class = .{ .integer, .integer, .none, .none, .none, .none, .none, .none };
+ pub const three_integers: [8]Class = .{ .integer, .integer, .integer, .none, .none, .none, .none, .none };
+ pub const four_integers: [8]Class = .{ .integer, .integer, .integer, .integer, .none, .none, .none, .none };
+ pub const len_integers: [8]Class = .{ .integer_per_element, .none, .none, .none, .none, .none, .none, .none };
pub const @"f16" = @"f64";
- pub const @"f32": [8]Class = .{
- .float, .none, .none, .none,
- .none, .none, .none, .none,
- };
- pub const @"f64": [8]Class = .{
- .sse, .none, .none, .none,
- .none, .none, .none, .none,
- };
- pub const @"f80": [8]Class = .{
- .x87, .x87up, .none, .none,
- .none, .none, .none, .none,
- };
- pub const @"f128": [8]Class = .{
- .sse, .sseup, .none, .none,
- .none, .none, .none, .none,
- };
+ pub const @"f32": [8]Class = .{ .float, .none, .none, .none, .none, .none, .none, .none };
+ pub const @"f64": [8]Class = .{ .sse, .none, .none, .none, .none, .none, .none, .none };
+ pub const @"f80": [8]Class = .{ .x87, .x87up, .none, .none, .none, .none, .none, .none };
+ pub const @"f128": [8]Class = .{ .sse, .sseup, .none, .none, .none, .none, .none, .none };
/// COMPLEX_X87: This class consists of types that will be returned via the x87
/// FPU.
- pub const complex_x87: [8]Class = .{
- .x87, .x87up, .x87, .x87up,
- .none, .none, .none, .none,
- };
+ pub const complex_x87: [8]Class = .{ .x87, .x87up, .x87, .x87up, .none, .none, .none, .none };
- pub const stack: [8]Class = .{
- .memory, .none, .none, .none,
- .none, .none, .none, .none,
- };
+ pub const stack: [8]Class = .{ .memory, .none, .none, .none, .none, .none, .none, .none };
pub fn isX87(class: Class) bool {
return switch (class) {
@@ -112,7 +93,7 @@ pub const Class = enum {
pub const Context = enum { ret, arg, other };
-pub fn classifyWindows(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Context) Class {
+pub fn classifyWindows(init_ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Context) Class {
// https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017
// "There's a strict one-to-one correspondence between a function call's arguments
// and the registers used for those arguments. Any argument that doesn't fit in 8
@@ -121,13 +102,13 @@ pub fn classifyWindows(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
// "All floating point operations are done using the 16 XMM registers."
// "Structs and unions of size 8, 16, 32, or 64 bits, and __m64 types, are passed
// as if they were integers of the same size."
- return switch (ty.zigTypeTag(zcu)) {
+ var ty = init_ty;
+ while (true) return switch (ty.zigTypeTag(zcu)) {
+ .void => return .none,
+ .bool,
.pointer,
.int,
- .bool,
.@"enum",
- .void,
- .noreturn,
.error_set,
.@"struct",
.@"union",
@@ -137,7 +118,7 @@ pub fn classifyWindows(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
.@"anyframe",
.frame,
=> switch (ty.abiSize(zcu)) {
- 0 => unreachable,
+ 0 => .none,
1, 2, 4, 8 => .integer,
else => switch (ty.zigTypeTag(zcu)) {
.int => .win_i128,
@@ -148,15 +129,43 @@ pub fn classifyWindows(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
else => .memory,
},
},
-
+ .noreturn => unreachable,
.float => switch (ty.floatBits(target)) {
16, 32, 64 => .sse,
80 => .memory,
128 => if (ctx == .arg) .memory else .sse,
else => unreachable,
},
- .vector => .sse,
-
+ .vector => {
+ const len = ty.vectorLen(zcu);
+ if (len == 0) return .none;
+ const elem_ty = ty.childType(zcu);
+ if (len == 1) {
+ ty = elem_ty;
+ continue;
+ }
+ const reg_size: u64, const split_class: Class = if (target.cpu.has(.x86, .avx512f))
+ .{ 64, .sse_per_zword }
+ else if (target.cpu.has(.x86, .avx))
+ .{ 32, .sse_per_yword }
+ else
+ .{ 16, .sse_per_xword };
+ if (elem_ty.toIntern() == .bool_type) {
+ if (len > reg_size) return if (ctx == .arg) .integer_per_element else .memory;
+ return .bool_vector_mask;
+ }
+ const elem_size = elem_ty.abiSize(zcu);
+ const unaligned_size = elem_size * len;
+ if ((unaligned_size <= 8 or unaligned_size > reg_size) and !std.math.isPowerOfTwo(len)) {
+ if (ctx == .ret and len > Win64.c_abi_int_return_regs.len) return .memory;
+ if (!elem_ty.isRuntimeFloat()) return .integer_per_element;
+ if (ctx == .ret and len > 2 and elem_size == 8) return .sse_sse_x87_per_qword;
+ return .sse_per_element;
+ }
+ if (unaligned_size <= reg_size) return if (ctx == .arg) .memory else .sse;
+ if (ctx == .ret and unaligned_size > reg_size * Win64.c_abi_sse_return_regs.len) return .memory;
+ return split_class;
+ },
.type,
.comptime_float,
.comptime_int,
@@ -164,6 +173,7 @@ pub fn classifyWindows(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
.null,
.@"fn",
.@"opaque",
+ .spirv,
.enum_literal,
=> unreachable,
};
@@ -173,19 +183,18 @@ pub fn classifyWindows(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
/// the beginning of the array; unused slots are filled with .none.
pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Context) [8]Class {
switch (ty.zigTypeTag(zcu)) {
- .pointer => switch (ty.ptrSize(zcu)) {
- .slice => return Class.two_integers,
- else => return Class.one_integer,
- },
+ .void => return Class.zero_bit,
+ .bool => return Class.one_integer,
+ .noreturn => unreachable,
.int, .@"enum", .error_set => {
const bits = ty.intInfo(zcu).bits;
+ if (bits == 0) return Class.zero_bit;
if (bits <= 64 * 1) return Class.one_integer;
if (bits <= 64 * 2) return Class.two_integers;
if (bits <= 64 * 3) return Class.three_integers;
if (bits <= 64 * 4) return Class.four_integers;
return Class.stack;
},
- .bool, .void, .noreturn => return Class.one_integer,
.float => switch (ty.floatBits(target)) {
16 => {
if (ctx == .other) return Class.stack;
@@ -204,61 +213,61 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
80 => return Class.f80,
else => unreachable,
},
+ .pointer => switch (ty.ptrSize(zcu)) {
+ .slice => return Class.two_integers,
+ else => return Class.one_integer,
+ },
.vector => {
+ const len = ty.vectorLen(zcu);
+ if (len == 0) return Class.zero_bit;
const elem_ty = ty.childType(zcu);
- const bits = elem_ty.bitSize(zcu) * ty.arrayLen(zcu);
if (elem_ty.toIntern() == .bool_type) {
- if (bits <= 32) return Class.one_integer;
- if (bits <= 64) return Class.f64;
- if (ctx == .other) return Class.stack;
- if (bits <= 128) return Class.len_integers;
- if (bits <= 256 and target.cpu.has(.x86, .avx)) return Class.len_integers;
- if (bits <= 512 and target.cpu.has(.x86, .avx512f)) return Class.len_integers;
+ if (len <= 32) return Class.one_integer;
+ if (len <= 64) return Class.f64;
+ if (ctx != .arg) return Class.stack;
+ if (len <= 128) return Class.len_integers;
+ if (len <= 256 and target.cpu.has(.x86, .avx)) return Class.len_integers;
+ if (len <= 512 and target.cpu.has(.x86, .avx512f)) return Class.len_integers;
return Class.stack;
}
- if (elem_ty.isRuntimeFloat() and elem_ty.floatBits(target) == 80) {
- if (bits <= 80 * 1) return Class.f80;
- if (bits <= 80 * 2) return Class.complex_x87;
+ if (elem_ty.isRuntimeFloat() and elem_ty.floatBits(target) == 80) switch (len) {
+ 0 => unreachable,
+ 1 => return Class.f80,
+ 2 => return Class.complex_x87,
+ else => return Class.stack,
+ };
+ const unaligned_size = elem_ty.abiSize(zcu) * len;
+ if (unaligned_size <= 4) return Class.one_integer;
+ if (ctx == .arg and unaligned_size == 8 * 1 * 1 and len == 1 and
+ elem_ty.isRuntimeFloat()) return Class.stack; // what
+ if (unaligned_size <= 8 * 1) return .{ .sse, .none, .none, .none, .none, .none, .none, .none };
+ if (unaligned_size <= 8 * 2) return .{ .sse, .sseup, .none, .none, .none, .none, .none, .none };
+ if (!target.cpu.has(.x86, .avx)) {
+ if (ctx == .ret) switch (unaligned_size) {
+ else => {},
+ 8 * 3 => if (len == 3) return if (elem_ty.isRuntimeFloat()) .{
+ .sse_sse_x87_per_qword, .none, .none, .none, .none, .none, .none, .none, // how
+ } else Class.len_integers, // why
+ 8 * 2 * 2, 8 * 2 * 4 => return .{ .sse_per_xword, .none, .none, .none, .none, .none, .none, .none },
+ };
return Class.stack;
}
- if (bits <= 64 * 1) return .{
- .sse, .none, .none, .none,
- .none, .none, .none, .none,
- };
- if (bits <= 64 * 2) return .{
- .sse, .sseup, .none, .none,
- .none, .none, .none, .none,
- };
- if (ctx == .arg and !target.cpu.has(.x86, .avx)) return Class.stack;
- if (bits <= 64 * 3) return .{
- .sse, .sseup, .sseup, .none,
- .none, .none, .none, .none,
- };
- if (bits <= 64 * 4) return .{
- .sse, .sseup, .sseup, .sseup,
- .none, .none, .none, .none,
- };
- if (ctx == .arg and !target.cpu.has(.x86, .avx512f)) return Class.stack;
- if (bits <= 64 * 5) return .{
- .sse, .sseup, .sseup, .sseup,
- .sseup, .none, .none, .none,
- };
- if (bits <= 64 * 6) return .{
- .sse, .sseup, .sseup, .sseup,
- .sseup, .sseup, .none, .none,
- };
- if (bits <= 64 * 7) return .{
- .sse, .sseup, .sseup, .sseup,
- .sseup, .sseup, .sseup, .none,
- };
- if (bits <= 64 * 8 or (ctx == .ret and bits <= @as(u64, if (target.cpu.has(.x86, .avx512f))
- 64 * 32
- else if (target.cpu.has(.x86, .avx))
- 64 * 16
- else
- 64 * 8))) return .{
- .sse, .sseup, .sseup, .sseup,
- .sseup, .sseup, .sseup, .sseup,
+ if (unaligned_size <= 8 * 3) return .{ .sse, .sseup, .sseup, .none, .none, .none, .none, .none };
+ if (unaligned_size <= 8 * 4) return .{ .sse, .sseup, .sseup, .sseup, .none, .none, .none, .none };
+ if (!target.cpu.has(.x86, .avx512f)) {
+ if (ctx == .ret) switch (unaligned_size) {
+ else => {},
+ 8 * 4 * 2, 8 * 4 * 4 => return .{ .sse_per_yword, .none, .none, .none, .none, .none, .none, .none },
+ };
+ return Class.stack;
+ }
+ if (unaligned_size <= 8 * 5) return .{ .sse, .sseup, .sseup, .sseup, .sseup, .none, .none, .none };
+ if (unaligned_size <= 8 * 6) return .{ .sse, .sseup, .sseup, .sseup, .sseup, .sseup, .none, .none };
+ if (unaligned_size <= 8 * 7) return .{ .sse, .sseup, .sseup, .sseup, .sseup, .sseup, .sseup, .none };
+ if (unaligned_size <= 8 * 8) return .{ .sse, .sseup, .sseup, .sseup, .sseup, .sseup, .sseup, .sseup };
+ if (ctx == .ret) switch (unaligned_size) {
+ else => {},
+ 8 * 8 * 2, 8 * 8 * 4 => return .{ .sse_per_zword, .none, .none, .none, .none, .none, .none, .none },
};
return Class.stack;
},
@@ -274,6 +283,7 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
// "If the size of the aggregate exceeds a single eightbyte, each is classified
// separately.".
const ty_size = ty.abiSize(zcu);
+ if (ty_size == 0) return Class.zero_bit;
switch (ty.containerLayout(zcu)) {
.auto => unreachable,
.@"extern" => {},
@@ -324,6 +334,7 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
},
.array => {
const ty_size = ty.abiSize(zcu);
+ if (ty_size == 0) return Class.zero_bit;
if (ty_size <= 8) return Class.one_integer;
if (ty_size <= 16) return Class.two_integers;
return Class.stack;
@@ -456,7 +467,7 @@ pub const SysV = struct {
pub const c_abi_int_param_regs = [_]Register{ .rdi, .rsi, .rdx, .rcx, .r8, .r9 };
pub const c_abi_x87_param_regs = x87_regs[0..0];
pub const c_abi_sse_param_regs = sse_avx_regs[0..8];
- pub const c_abi_int_return_regs = [_]Register{ .rax, .rdx };
+ pub const c_abi_int_return_regs = [_]Register{ .rax, .rdx, .rcx };
pub const c_abi_x87_return_regs = x87_regs[0..2];
pub const c_abi_sse_return_regs = sse_avx_regs[0..4];
};
@@ -473,9 +484,9 @@ pub const Win64 = struct {
pub const c_abi_int_param_regs = [_]Register{ .rcx, .rdx, .r8, .r9 };
pub const c_abi_x87_param_regs = x87_regs[0..0];
pub const c_abi_sse_param_regs = sse_avx_regs[0..4];
- pub const c_abi_int_return_regs = [_]Register{.rax};
- pub const c_abi_x87_return_regs = x87_regs[0..0];
- pub const c_abi_sse_return_regs = sse_avx_regs[0..1];
+ pub const c_abi_int_return_regs = [_]Register{ .rax, .rdx, .rcx };
+ pub const c_abi_x87_return_regs = x87_regs[0..1];
+ pub const c_abi_sse_return_regs = sse_avx_regs[0..4];
};
pub fn getCalleePreservedRegs(cc: std.lang.CallingConvention.Tag) []const Register {
diff --git a/src/crash_report.zig b/src/crash_report.zig
index b177af3bb6033ffc4e10e15a8aaf7c7e74c0bf03..63370d0557d6799fe584794a84026963077b7a71 100644
--- a/src/crash_report.zig
+++ b/src/crash_report.zig
@@ -84,6 +84,25 @@ pub const CodegenFunc = if (enabled) struct {
pub fn stop(_: InternPool.Index) void {}
};
+pub const LinkerOp = if (enabled) struct {
+ lf: *link.File,
+ tid: Zcu.PerThread.Id,
+ threadlocal var current: ?LinkerOp = null;
+ pub fn start(lf: *link.File, tid: Zcu.PerThread.Id) void {
+ std.debug.assert(current == null);
+ current = .{ .lf = lf, .tid = tid };
+ }
+ pub fn stop(lf: *link.File, tid: Zcu.PerThread.Id) void {
+ std.debug.assert(current.?.lf == lf and current.?.tid == tid);
+ current = null;
+ }
+} else struct {
+ const current: ?noreturn = null;
+ // Dummy implementation
+ pub fn start(_: *link.File, _: Zcu.PerThread.Id) void {}
+ pub fn stop(_: *link.File, _: Zcu.PerThread.Id) void {}
+};
+
fn dumpCrashContext() Io.Writer.Error!void {
const S = struct {
/// In the case of recursive panics or segfaults, don't print the context for a second time.
@@ -111,6 +130,15 @@ fn dumpCrashContext() Io.Writer.Error!void {
try w.print("Generating function '{f}'\n\n", .{func_fqn.fmt(&cg.zcu.intern_pool)});
} else if (AnalyzeBody.current) |anal| {
try dumpCrashContextSema(anal, w, &S.crash_heap);
+ } else if (LinkerOp.current) |linker_op| {
+ try w.writeAll("Linker snapshot:\n");
+ switch (try linker_op.lf.dump(w, linker_op.tid)) {
+ .unimplemented => try w.writeAll("(backend does not support link snapshots)"),
+ .needs_extensions => try w.writeAll("(build with -Ddebug-extensions to dump linker state)"),
+ .disabled => try w.writeAll("(run with --debug-link-snapshot to dump linker state)"),
+ .enabled => {},
+ }
+ try w.writeAll("\n\n");
} else {
try w.writeAll("(no context)\n\n");
}
@@ -185,6 +213,7 @@ const Zir = std.zig.Zir;
const Sema = @import("Sema.zig");
const Zcu = @import("Zcu.zig");
+const link = @import("link.zig");
const InternPool = @import("InternPool.zig");
const dev = @import("dev.zig");
const print_zir = @import("print_zir.zig");
diff --git a/src/dev.zig b/src/dev.zig
index f3c4016faf2338e1f80b1e96953d207e7fed866f..bba67696f2f92cf522949f68ffc35370f3daf86d 100644
--- a/src/dev.zig
+++ b/src/dev.zig
@@ -52,6 +52,10 @@ pub const Env = enum {
/// - `zig build-* -fincremental -fno-llvm -fno-lld -target x86_64-linux --listen=-`
@"x86_64-linux",
+ /// - sema
+ /// - `zig build-* -fincremental -fno-llvm -fno-lld -target x86_64-windows --listen=-`
+ @"x86_64-windows",
+
pub inline fn supports(comptime dev_env: Env, comptime feature: Feature) bool {
return switch (dev_env) {
.full => true,
@@ -216,6 +220,16 @@ pub const Env = enum {
=> true,
else => Env.sema.supports(feature),
},
+ .@"x86_64-windows" => switch (feature) {
+ .build_command,
+ .stdio_listen,
+ .incremental,
+ .legalize,
+ .x86_64_backend,
+ .coff2_linker,
+ => true,
+ else => Env.sema.supports(feature),
+ },
};
}
diff --git a/src/fmt.zig b/src/fmt.zig
index a3cd7c8d74591f0ac85e52d5472de98f6709e7d4..73d8a1c162328f720e9687d17cf7e2129b431da2 100644
--- a/src/fmt.zig
+++ b/src/fmt.zig
@@ -23,6 +23,7 @@ const usage_fmt =
\\ --ast-check Run zig ast-check on every file
\\ --exclude [file] Exclude file or directory from formatting
\\ --zon Treat all input files as ZON, regardless of file extension
+ \\ --complexity Print a complexity report for each file as well as total
\\
\\
;
@@ -39,6 +40,10 @@ const Fmt = struct {
out_buffer: std.Io.Writer.Allocating,
stdout_writer: *Io.File.Writer,
+ complexity: bool,
+ total_tokens: u64,
+ total_nodes: u64,
+
const SeenMap = std.AutoHashMap(Io.File.INode, void);
};
@@ -48,8 +53,11 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
var check_flag = false;
var check_ast_flag = false;
var force_zon = false;
+ var complexity = false;
+
var input_files = std.array_list.Managed([]const u8).init(gpa);
defer input_files.deinit();
+
var excluded_files = std.array_list.Managed([]const u8).init(gpa);
defer excluded_files.deinit();
@@ -68,7 +76,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
i += 1;
const next_arg = args[i];
color = std.meta.stringToEnum(Color, next_arg) orelse {
- fatal("expected [auto|on|off] after --color, found '{s}'", .{next_arg});
+ fatal("expected [auto|on|off] after --color, found {q}", .{next_arg});
};
} else if (mem.eql(u8, arg, "--stdin")) {
stdin_flag = true;
@@ -76,6 +84,8 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
check_flag = true;
} else if (mem.eql(u8, arg, "--ast-check")) {
check_ast_flag = true;
+ } else if (mem.eql(u8, arg, "--complexity")) {
+ complexity = true;
} else if (mem.eql(u8, arg, "--exclude")) {
if (i + 1 >= args.len) {
fatal("expected parameter after --exclude", .{});
@@ -86,7 +96,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
} else if (mem.eql(u8, arg, "--zon")) {
force_zon = true;
} else {
- fatal("unrecognized parameter: '{s}'", .{arg});
+ fatal("unrecognized parameter: {q}", .{arg});
}
} else {
try input_files.append(arg);
@@ -175,6 +185,9 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
.color = color,
.out_buffer = .init(gpa),
.stdout_writer = &stdout_writer,
+ .complexity = complexity,
+ .total_tokens = 0,
+ .total_nodes = 0,
};
defer fmt.seen.deinit();
defer fmt.out_buffer.deinit();
@@ -198,7 +211,12 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
for (input_files.items) |file_path| {
try fmtPath(&fmt, file_path, check_flag, Io.Dir.cwd(), file_path);
}
- try fmt.stdout_writer.interface.flush();
+
+ if (complexity) {
+ std.log.info("total: tokens={d} nodes={d}", .{ fmt.total_tokens, fmt.total_nodes });
+ }
+
+ try fmt.stdout_writer.flush();
if (fmt.any_error) {
process.exit(1);
}
@@ -208,7 +226,7 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: Io.Dir, sub_
fmtPathFile(fmt, file_path, check_mode, dir, sub_path) catch |err| switch (err) {
error.IsDir, error.AccessDenied => return fmtPathDir(fmt, file_path, check_mode, dir, sub_path),
else => {
- std.log.err("unable to format '{s}': {s}", .{ file_path, @errorName(err) });
+ std.log.err("formatting {q}: {t}", .{ file_path, err });
fmt.any_error = true;
return;
},
@@ -244,7 +262,7 @@ fn fmtPathDir(
try fmtPathDir(fmt, full_path, check_mode, dir, entry.name);
} else {
fmtPathFile(fmt, full_path, check_mode, dir, entry.name) catch |err| {
- std.log.err("unable to format '{s}': {t}", .{ full_path, err });
+ std.log.err("unable to format {q}: {t}", .{ full_path, err });
fmt.any_error = true;
return;
};
@@ -341,6 +359,12 @@ fn fmtPathFile(
}
}
+ if (fmt.complexity) {
+ std.log.info("{s}: tokens={d} nodes={d}", .{ file_path, tree.tokens.len, tree.nodes.len });
+ fmt.total_tokens += tree.tokens.len;
+ fmt.total_nodes += tree.nodes.len;
+ }
+
// As a heuristic, we make enough capacity for the same as the input source.
fmt.out_buffer.clearRetainingCapacity();
try fmt.out_buffer.ensureTotalCapacity(source_code.len);
@@ -365,13 +389,7 @@ fn fmtPathFile(
}
/// Provided for debugging/testing purposes; unused by the compiler.
-pub fn main() !void {
- const gpa = std.heap.smp_allocator;
- var arena_instance = std.heap.ArenaAllocator.init(gpa);
- const arena = arena_instance.allocator();
- const args = try process.argsAlloc(arena);
- var threaded: std.Io.Threaded = .init(gpa, .{});
- defer threaded.deinit();
- const io = threaded.io();
- return run(gpa, arena, io, args[1..]);
+pub fn main(init: process.Init) !void {
+ const args = try init.minimal.args.toSlice(init.arena.allocator());
+ return run(init.gpa, init.arena.allocator(), init.io, args[1..]);
}
diff --git a/src/libs/mingw.zig b/src/libs/mingw.zig
index 384af94084d98f65316f16f74c019e5a57292dfc..a19a83e044ce28800257497b1e76bb9fc6cbf9cb 100644
--- a/src/libs/mingw.zig
+++ b/src/libs/mingw.zig
@@ -14,9 +14,12 @@ const dev = @import("../dev.zig");
const def = @import("mingw/def.zig");
const implib = @import("mingw/implib.zig");
+const Preprocessor = @import("mingw/Preprocessor.zig");
+
test {
_ = def;
_ = implib;
+ _ = Preprocessor;
}
pub const CrtFile = enum {
@@ -204,9 +207,14 @@ fn addCrtCcArgs(
});
}
-pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
+pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.Progress.Node) !Cache.Path {
dev.check(.build_import_lib);
+ log.debug("buildImportLib({s})", .{lib_name});
+
+ const sub_node = prog_node.start(lib_name, 0);
+ defer sub_node.end();
+
const gpa = comp.gpa;
const io = comp.io;
@@ -215,14 +223,11 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
const arena = arena_allocator.allocator();
const def_file_path = findDef(arena, io, comp.getTarget(), comp.dirs.zig_lib, lib_name) catch |err| switch (err) {
- error.FileNotFound => {
- log.debug("no {s}.def file available to make a DLL import {s}.lib", .{ lib_name, lib_name });
- // In this case we will end up putting foo.lib onto the linker line and letting the linker
- // use its library paths to look for libraries and report any problems.
- return;
- },
+ error.FileNotFound => return error.DefNotFound,
else => |e| return e,
};
+ // Only .def.in files need preprocessing
+ const def_needs_preprocessing = mem.endsWith(u8, def_file_path, ".def.in");
const target = comp.getTarget();
@@ -258,14 +263,16 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
comp.mutex.lockUncancelable(io);
defer comp.mutex.unlock(io);
try comp.crt_files.ensureUnusedCapacity(gpa, 1);
+
+ const crt_file_path: Cache.Path = .{
+ .root_dir = comp.dirs.global_cache,
+ .sub_path = sub_path,
+ };
comp.crt_files.putAssumeCapacityNoClobber(final_lib_basename, .{
- .full_object_path = .{
- .root_dir = comp.dirs.global_cache,
- .sub_path = sub_path,
- },
+ .full_object_path = crt_file_path,
.lock = man.toOwnedLock(),
});
- return;
+ return crt_file_path;
}
const digest = man.final();
@@ -273,22 +280,6 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
var o_dir = try comp.dirs.global_cache.handle.createDirPathOpen(io, o_sub_path, .{});
defer o_dir.close(io);
- const aro = @import("aro");
- var diagnostics: aro.Diagnostics = .{
- .output = .{ .to_list = .{ .arena = .init(gpa) } },
- };
- defer diagnostics.deinit();
- var aro_comp = try aro.Compilation.init(.{
- .gpa = gpa,
- .arena = arena,
- .io = io,
- .diagnostics = &diagnostics,
- .environ_map = null,
- });
- defer aro_comp.deinit();
-
- aro_comp.target = .fromZigTarget(target.*);
-
const include_dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "mingw", "def-include" });
if (comp.verbose_cc) {
@@ -304,39 +295,30 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
};
}
- try aro_comp.search_path.append(gpa, .{ .path = include_dir, .kind = .normal });
-
- const builtin_macros = try aro_comp.generateBuiltinMacros(.include_system_defines);
- const def_file_source = try aro_comp.addSourceFromPath(def_file_path);
-
- var pp = try aro.Preprocessor.init(&aro_comp, .{ .base_file = .unused });
- defer pp.deinit();
- pp.linemarkers = .none;
- pp.preserve_whitespace = true;
-
- try pp.preprocessSources(.{ .main = def_file_source, .builtin = builtin_macros });
-
- if (aro_comp.diagnostics.output.to_list.messages.items.len != 0) {
- var buffer: [64]u8 = undefined;
- const stderr = try io.lockStderr(&buffer, null);
- defer io.unlockStderr();
- for (aro_comp.diagnostics.output.to_list.messages.items) |msg| {
- if (msg.kind == .@"fatal error" or msg.kind == .@"error") {
- msg.write(stderr.terminal(), true) catch |err| switch (err) {
- error.WriteFailed => return stderr.file_writer.err.?,
- error.Canceled, error.Unexpected => |e| return e,
- };
- return error.AroPreprocessorFailed;
- }
- }
- }
-
const members = members: {
- var aw: Io.Writer.Allocating = .init(gpa);
- errdefer aw.deinit();
- try pp.prettyPrintTokens(&aw.writer, .result_only);
+ const members_node = sub_node.start("Members", 0);
+ defer members_node.end();
- const input = try aw.toOwnedSliceSentinel(0);
+ const input = switch (def_needs_preprocessing) {
+ true => pp: {
+ var aw: Io.Writer.Allocating = .init(gpa);
+ errdefer aw.deinit();
+
+ var pp_arena = std.heap.ArenaAllocator.init(gpa);
+ defer pp_arena.deinit();
+ var pp: Preprocessor = .{
+ .io = io,
+ .arena = pp_arena.allocator(),
+ .include_dir = include_dir,
+ .target = target,
+ };
+ try pp.preprocess(def_file_path);
+ try pp.prettyPrintTokens(&aw.writer);
+
+ break :pp try aw.toOwnedSliceSentinel(0);
+ },
+ false => try Io.Dir.cwd().readFileAllocOptions(io, def_file_path, gpa, .unlimited, .of(u8), 0),
+ };
defer gpa.free(input);
const machine_type = target.toCoffMachine();
@@ -380,13 +362,15 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
comp.mutex.lockUncancelable(io);
defer comp.mutex.unlock(io);
+ const crt_file_path: Cache.Path = .{
+ .root_dir = comp.dirs.global_cache,
+ .sub_path = lib_final_path,
+ };
try comp.crt_files.putNoClobber(gpa, final_lib_basename, .{
- .full_object_path = .{
- .root_dir = comp.dirs.global_cache,
- .sub_path = lib_final_path,
- },
+ .full_object_path = crt_file_path,
.lock = man.toOwnedLock(),
});
+ return crt_file_path;
}
pub fn libExists(
@@ -853,7 +837,6 @@ const mingw32_x86_src = [_][]const u8{
"math" ++ path.sep_str ++ "fmal.c",
"math" ++ path.sep_str ++ "llrintl.c",
"math" ++ path.sep_str ++ "llroundl.c",
- "math" ++ path.sep_str ++ "lroundl.c",
"math" ++ path.sep_str ++ "tgammal.c",
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "_chgsignl.S",
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "acoshl.c",
diff --git a/src/libs/mingw/Preprocessor.zig b/src/libs/mingw/Preprocessor.zig
new file mode 100644
index 0000000000000000000000000000000000000000..ee108e9644ce7a25c5fa1bb23d871337085f5464
--- /dev/null
+++ b/src/libs/mingw/Preprocessor.zig
@@ -0,0 +1,975 @@
+const std = @import("std");
+const Tokenizer = @import("./Tokenizer.zig");
+const Allocator = std.mem.Allocator;
+const Token = Tokenizer.Token;
+const mem = std.mem;
+const assert = std.debug.assert;
+
+test {
+ _ = Tokenizer;
+}
+
+const TokenList = std.MultiArrayList(Token);
+const RawTokenList = std.ArrayList(Token);
+
+const ExpandBuf = std.ArrayList(Token);
+
+const Preprocessor = @This();
+const DefineMap = std.StringArrayHashMapUnmanaged(Macro);
+
+const GeneratedTokens = std.ArrayList(u8);
+
+const MacroArgument = []const Token;
+
+pub const Source = struct {
+ pub const generated: Source.Id = std.math.maxInt(usize);
+ pub const Id = usize;
+ id: Id = generated,
+ path: []const u8,
+ buf: []const u8,
+};
+
+sources: std.StringArrayHashMapUnmanaged(Source) = .empty,
+
+arena: Allocator,
+io: std.Io,
+include_dir: []const u8,
+
+top_expansion_buf: ExpandBuf = .empty,
+add_expansion_nl: usize = 0,
+token_buf: RawTokenList = .empty,
+generated_tokens: GeneratedTokens = .empty,
+generated_line: u32 = 1,
+defines: DefineMap = .empty,
+tokens: TokenList = .empty,
+target: *const std.Target,
+
+const Macro = struct {
+ param: []const u8,
+ tokens: []const Token,
+ is_func: bool,
+};
+
+const IfContext = struct {
+ const Backing = u2;
+ const Nesting = enum(Backing) {
+ until_else,
+ until_endif,
+ until_endif_seen_else,
+ };
+
+ const buf_size_bits = @bitSizeOf(Backing) * 256;
+ kind: [buf_size_bits / std.mem.byte_size_in_bits]u8,
+ level: u8,
+
+ fn get(self: *const IfContext) Nesting {
+ return @enumFromInt(std.mem.readPackedInt(Backing, &self.kind, @as(usize, self.level) * 2, .native));
+ }
+
+ fn set(self: *IfContext, context: Nesting) void {
+ std.mem.writePackedInt(Backing, &self.kind, @as(usize, self.level) * 2, @intFromEnum(context), .native);
+ }
+
+ fn increment(self: *IfContext) void {
+ self.level += 1;
+ }
+
+ fn decrement(self: *IfContext) void {
+ self.level -= 1;
+ }
+
+ const default: IfContext = .{ .kind = @splat(0xFF), .level = 0 };
+};
+
+fn addToken(pp: *Preprocessor, tok: Token) !void {
+ try pp.tokens.append(pp.arena, tok);
+}
+
+fn addTokenAssumeCapacity(pp: *Preprocessor, tok: Token) void {
+ pp.tokens.appendAssumeCapacity(tok);
+}
+
+fn defineBuiltins(pp: *Preprocessor) !void {
+ var buf: [5]u8 = undefined;
+ var val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeBitSize(.longdouble)}) catch unreachable;
+ try pp.defineBuiltinValue("__SIZEOF_LONG_DOUBLE__", val, .pp_num);
+ val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeBitSize(.double)}) catch unreachable;
+ try pp.defineBuiltinValue("__SIZEOF_DOUBLE__", val, .pp_num);
+
+ if (pp.target.abi.isGnu()) {
+ try pp.defineBuiltinValue("__cdecl", "__attribute__((__cdecl__))", .identifier);
+ }
+
+ const arch = switch (pp.target.cpu.arch) {
+ .aarch64 => "__aarch64__",
+ .x86 => "__i386__",
+ .x86_64 => "__x86_64__",
+ .arm, .thumb => "__arm__",
+ else => return error.ArchitectureNotSupported,
+ };
+ try pp.defineBuiltin(arch);
+}
+
+fn defineBuiltinValue(pp: *Preprocessor, name: []const u8, value: []const u8, id: Token.Id) !void {
+ const start = pp.generated_tokens.items.len;
+ try pp.generated_tokens.appendSlice(pp.arena, value);
+ const end = pp.generated_tokens.items.len;
+
+ const token_list = try pp.arena.alloc(Token, 1);
+ token_list[0] = .{ .source = Source.generated, .id = id, .start = @intCast(start), .end = @intCast(end) };
+ try pp.defines.putNoClobber(pp.arena, name, .{
+ .is_func = false,
+ .param = "",
+ .tokens = token_list,
+ });
+}
+
+fn defineBuiltin(pp: *Preprocessor, name: []const u8) !void {
+ return pp.defines.putNoClobber(pp.arena, name, .{
+ .tokens = &.{},
+ .param = "",
+ .is_func = false,
+ });
+}
+
+pub fn preprocess(pp: *Preprocessor, file_path: []const u8) !void {
+ const source = try pp.addSourceFromPath(file_path);
+ try pp.preprocessFile(source);
+}
+
+fn preprocessFile(pp: *Preprocessor, src: Source) !void {
+ try pp.defineBuiltins();
+ const eof = try pp.preprocessFileExtra(src);
+ try pp.addToken(eof);
+}
+
+fn preprocessFileExtra(pp: *Preprocessor, src: Source) !Token {
+ var tokenizer: Tokenizer = .init(src.buf, src.id);
+ var if_context: IfContext = .default;
+
+ while (true) {
+ var tok = tokenizer.next();
+ switch (tok.id) {
+ .hash => {
+ const directive = tokenizer.nextNoWS();
+ switch (directive.id) {
+ .keyword_define => try pp.define(&tokenizer),
+ .keyword_if => {
+ if_context.increment();
+ if (try pp.expr(&tokenizer)) {
+ if_context.set(.until_endif);
+ } else {
+ if_context.set(.until_else);
+ try pp.skip(&tokenizer, .until_else);
+ }
+ },
+ .keyword_ifdef => {
+ if_context.increment();
+ const macro_name = pp.expectMacroName(&tokenizer);
+ skipToNl(&tokenizer);
+ if (pp.defines.get(macro_name) != null) {
+ if_context.set(.until_endif);
+ } else {
+ if_context.set(.until_else);
+ try pp.skip(&tokenizer, .until_else);
+ }
+ },
+ .keyword_ifndef => {
+ if_context.increment();
+ const macro_name = pp.expectMacroName(&tokenizer);
+ skipToNl(&tokenizer);
+ if (pp.defines.get(macro_name) == null) {
+ if_context.set(.until_endif);
+ } else {
+ if_context.set(.until_else);
+ try pp.skip(&tokenizer, .until_else);
+ }
+ },
+ .keyword_elif => {
+ assert(if_context.level > 0);
+ switch (if_context.get()) {
+ .until_else => if (try pp.expr(&tokenizer)) {
+ if_context.set(.until_endif);
+ } else {
+ try pp.skip(&tokenizer, .until_else);
+ },
+ .until_endif => try pp.skip(&tokenizer, .until_endif),
+ .until_endif_seen_else => unreachable, //elif after endif
+ }
+ },
+ .keyword_else => {
+ skipToNl(&tokenizer);
+ assert(if_context.level > 0);
+ switch (if_context.get()) {
+ .until_else => if_context.set(.until_endif_seen_else),
+ .until_endif => try pp.skip(&tokenizer, .until_endif),
+ .until_endif_seen_else => unreachable, // else after else
+ }
+ },
+ .keyword_endif => {
+ skipToNl(&tokenizer);
+ assert(if_context.level > 0);
+ if_context.decrement();
+ },
+ .keyword_undef => {
+ const macro_name = tokenizer.nextNoWS();
+ assert(macro_name.id == .identifier);
+ pp.undefineMacro(macro_name);
+ skipToNl(&tokenizer);
+ },
+ .keyword_include => {
+ try pp.include(&tokenizer);
+ continue;
+ },
+ .keyword_defined, .keyword_error => {},
+ else => unreachable,
+ }
+ tok.id = .nl;
+ try pp.addToken(tok);
+ },
+ .whitespace, .nl => try pp.addToken(tok),
+ .eof => {
+ assert(if_context.level == 0);
+ return tok;
+ },
+ else => try pp.expandMacro(&tokenizer, tok),
+ }
+ }
+}
+
+fn include(pp: *Preprocessor, tokenizer: *Tokenizer) anyerror!void {
+ const first = tokenizer.nextNoWS();
+ const src = try findIncludeSource(pp, tokenizer, first);
+
+ _ = try pp.preprocessFileExtra(src);
+ if (pp.tokens.items(.id)[pp.tokens.len - 1] != .nl) {
+ try pp.addToken(.{ .id = .nl, .source = Source.generated });
+ }
+}
+
+fn findIncludeSource(
+ pp: *Preprocessor,
+ tokenizer: *Tokenizer,
+ first: Token,
+) !Source {
+ const filename_tok = first;
+ skipToNl(tokenizer);
+ const tok_slice = pp.expandToken(filename_tok);
+ assert(tok_slice.len >= 3);
+ const filename = tok_slice[1 .. tok_slice.len - 1];
+ return (try pp.findInclude(filename, first)) orelse @panic("include not found");
+}
+
+fn expectMacroName(pp: *const Preprocessor, tokenizer: *Tokenizer) []const u8 {
+ const macro_name = tokenizer.nextNoWS();
+ assert(macro_name.id.isMacroIdentifier());
+ return pp.expandToken(macro_name);
+}
+
+fn skipToNl(tokenizer: *Tokenizer) void {
+ while (true) {
+ const tok = tokenizer.next();
+ if (tok.id == .nl or tok.id == .eof) return;
+ if (tok.id == .whitespace) continue;
+ }
+}
+
+fn define(pp: *Preprocessor, tokenizer: *Tokenizer) !void {
+ const macro_name = tokenizer.nextNoWS();
+ assert(macro_name.id == .identifier);
+
+ const first = tokenizer.nextNoWS();
+ switch (first.id) {
+ .nl, .eof => return pp.defineMacro(macro_name, .{
+ .is_func = false,
+ .tokens = &.{},
+ .param = "",
+ }),
+ .l_paren => return pp.defineFn(tokenizer, macro_name),
+ else => {},
+ }
+}
+
+fn defineMacro(pp: *Preprocessor, tok: Token, macro: Macro) !void {
+ const token_value = pp.expandToken(tok);
+ try pp.defines.putNoClobber(pp.arena, token_value, macro);
+}
+
+fn undefineMacro(pp: *Preprocessor, tok: Token) void {
+ const token_value = pp.expandToken(tok);
+ _ = pp.defines.orderedRemove(token_value);
+}
+
+fn defineFn(
+ pp: *Preprocessor,
+ tokenizer: *Tokenizer,
+ macro_name: Token,
+) !void {
+ var tok = tokenizer.nextNoWS();
+ assert(tok.id == .identifier);
+ const param = pp.expandToken(tok);
+ tok = tokenizer.nextNoWS();
+ assert(tok.id == .r_paren);
+
+ pp.token_buf.items.len = 0;
+ var need_ws = false;
+ while (true) {
+ tok = tokenizer.next();
+ switch (tok.id) {
+ .nl, .eof => break,
+ .whitespace => need_ws = pp.token_buf.items.len != 0,
+ .hash => unreachable,
+ .hash_hash => {
+ need_ws = false;
+ try pp.token_buf.append(pp.arena, tok);
+ },
+ else => {
+ if (need_ws) {
+ need_ws = false;
+ try pp.token_buf.append(pp.arena, .{ .id = .whitespace, .source = Source.generated });
+ }
+
+ if (tok.id.isMacroIdentifier()) {
+ tok.id = .identifier;
+ const s = pp.expandToken(tok);
+ if (mem.eql(u8, param, s)) {
+ tok.id = .macro_param;
+ tok.end = 0;
+ }
+ }
+ try pp.token_buf.append(pp.arena, tok);
+ },
+ }
+ }
+
+ const token_list = try pp.arena.dupe(Token, pp.token_buf.items);
+ try pp.defineMacro(macro_name, .{
+ .tokens = token_list,
+ .is_func = true,
+ .param = param,
+ });
+}
+
+fn expandToken(pp: *const Preprocessor, tok: Token) []const u8 {
+ return switch (tok.source) {
+ Source.generated => pp.generated_tokens.items,
+ else => blk: {
+ const src = pp.sources.values()[tok.source];
+ break :blk src.buf;
+ },
+ }[@intCast(tok.start)..@intCast(tok.end)];
+}
+
+fn skip(
+ pp: *Preprocessor,
+ tokenizer: *Tokenizer,
+ cont: IfContext.Nesting,
+) !void {
+ var ifs_seen: u32 = 0;
+ var line_start = true;
+ while (tokenizer.index < tokenizer.buf.len) {
+ if (line_start) {
+ const tokenizer_bkp = tokenizer.*;
+ const hash = tokenizer.nextNoWS();
+ if (hash.id == .nl) continue;
+ line_start = false;
+ if (hash.id != .hash) continue;
+ const directive = tokenizer.nextNoWS();
+ switch (directive.id) {
+ .keyword_else => {
+ if (ifs_seen != 0) continue;
+ assert(cont != .until_endif_seen_else); // else after else;
+ tokenizer.* = tokenizer_bkp;
+ return;
+ },
+ .keyword_elif => {
+ if (ifs_seen != 0 or cont == .until_endif) continue;
+ assert(cont != .until_endif_seen_else); // elif after else;
+ tokenizer.* = tokenizer_bkp;
+ return;
+ },
+ .keyword_endif => {
+ if (ifs_seen == 0) {
+ tokenizer.* = tokenizer_bkp;
+ return;
+ }
+ ifs_seen -= 1;
+ },
+ .keyword_if, .keyword_ifdef, .keyword_ifndef => ifs_seen += 1,
+ else => {},
+ }
+ } else if (tokenizer.buf[tokenizer.index] == '\n') {
+ line_start = true;
+ tokenizer.index += 1;
+ try pp.addToken(.{ .id = .nl, .source = Source.generated });
+ } else {
+ line_start = false;
+ tokenizer.index += 1;
+ }
+ }
+}
+
+fn ensureUnusedTokenCapacity(pp: *Preprocessor, capacity: usize) !void {
+ try pp.tokens.ensureUnusedCapacity(pp.arena, capacity);
+}
+
+fn expr(pp: *Preprocessor, tokenizer: *Tokenizer) !bool {
+ const token_state = pp.tokens.len;
+ defer pp.tokens.len = token_state;
+
+ pp.top_expansion_buf.items.len = 0;
+ while (true) {
+ const tok = tokenizer.next();
+ switch (tok.id) {
+ .nl, .eof => break,
+ .whitespace => if (pp.top_expansion_buf.items.len == 0) continue,
+ else => {},
+ }
+ try pp.top_expansion_buf.append(pp.arena, tok);
+ } else unreachable;
+ if (pp.top_expansion_buf.items.len != 0) {
+ try pp.expandMacroExhaustive(tokenizer, &pp.top_expansion_buf, 0, pp.top_expansion_buf.items.len, false, .expr);
+ }
+ try pp.ensureUnusedTokenCapacity(pp.top_expansion_buf.items.len);
+ var i: usize = 0;
+ const items = pp.top_expansion_buf.items;
+ while (i < items.len) : (i += 1) {
+ var tok = items[i];
+ switch (tok.id) {
+ .string_literal,
+ .semicolon,
+ .hash_hash,
+ => unreachable,
+ .whitespace => continue,
+ else => if (tok.id == .keyword_defined) {
+ i += try pp.handleKeywordDefined(&tok, items[i + 1 ..]);
+ },
+ }
+ pp.addTokenAssumeCapacity(tok);
+ }
+
+ try pp.addToken(.{ .id = .eof, .source = Source.generated });
+ return pp.evalExpression(token_state);
+}
+
+fn handleKeywordDefined(
+ pp: *Preprocessor,
+ macro_tok: *Token,
+ tokens: []const Token,
+) !usize {
+ assert(macro_tok.id == .keyword_defined);
+ var it = TokenIterator.init(tokens);
+
+ _ = it.expectNoWS(.l_paren);
+ const second = it.expectNoWS(.identifier);
+ _ = it.expectNoWS(.r_paren);
+
+ macro_tok.id = if (pp.defines.contains(pp.expandToken(second))) .one else .zero;
+
+ return it.i;
+}
+
+const TokenIterator = struct {
+ toks: []const Token,
+ i: usize,
+
+ fn init(toks: []const Token) TokenIterator {
+ return .{ .toks = toks, .i = 0 };
+ }
+
+ fn nextNoWS(self: *TokenIterator) ?Token {
+ while (self.i < self.toks.len) : (self.i += 1) {
+ const tok = self.toks[self.i];
+ if (tok.id == .whitespace) continue;
+
+ self.i += 1;
+ return tok;
+ }
+ return null;
+ }
+
+ fn expectNext(self: *TokenIterator) Token {
+ assert(self.i < self.toks.len);
+ const t = self.toks[self.i];
+ self.i += 1;
+ return t;
+ }
+
+ fn expectNoWS(self: *TokenIterator, expected: Token.Id) Token {
+ if (self.nextNoWS()) |tok| {
+ if (tok.id != expected) {
+ std.debug.panic("expected token {any} but got {any}\n", .{ expected, tok.id });
+ }
+ return tok;
+ }
+ std.debug.panic("expected token {any} but got null\n", .{expected});
+ }
+};
+
+fn expandMacro(pp: *Preprocessor, tokenizer: *Tokenizer, tok: Token) !void {
+ if (!tok.id.isMacroIdentifier()) {
+ return pp.addToken(tok);
+ }
+ pp.top_expansion_buf.items.len = 0;
+ try pp.top_expansion_buf.append(pp.arena, tok);
+ try pp.expandMacroExhaustive(tokenizer, &pp.top_expansion_buf, 0, 1, true, .non_expr);
+ try pp.addTokensFromExpandBuf(pp.top_expansion_buf.items, .{ .id = .nl, .source = Source.generated });
+}
+
+fn addTokensFromExpandBuf(pp: *Preprocessor, tokens: []Token, tokenizer_nl: Token) !void {
+ try pp.ensureUnusedTokenCapacity(tokens.len);
+ for (tokens) |tok| {
+ pp.addTokenAssumeCapacity(tok);
+ }
+ try pp.ensureUnusedTokenCapacity(pp.add_expansion_nl);
+ while (pp.add_expansion_nl > 0) : (pp.add_expansion_nl -= 1) {
+ pp.addTokenAssumeCapacity(tokenizer_nl);
+ }
+}
+
+const EvalContext = enum {
+ expr,
+ non_expr,
+};
+
+fn expandMacroExhaustive(
+ pp: *Preprocessor,
+ tokenizer: *Tokenizer,
+ buf: *ExpandBuf,
+ start_idx: usize,
+ end_idx: usize,
+ extend_buf: bool,
+ eval_ctx: EvalContext,
+) !void {
+ var moving_end_idx = end_idx;
+ var advance_index: usize = 0;
+ var do_rescan = true;
+ while (do_rescan) {
+ do_rescan = false;
+ var idx: usize = start_idx + advance_index;
+ while (idx < moving_end_idx) {
+ const macro_tok = buf.items[idx];
+ if (macro_tok.id == .keyword_defined and eval_ctx == .expr) {
+ idx += 1;
+ var it = TokenIterator.init(buf.items[idx..moving_end_idx]);
+ if (it.nextNoWS()) |tok| {
+ switch (tok.id) {
+ .l_paren => {
+ _ = it.nextNoWS();
+ _ = it.nextNoWS();
+ },
+ else => {},
+ }
+ }
+ idx += it.i;
+ continue;
+ }
+ if (!macro_tok.id.isMacroIdentifier()) {
+ idx += 1;
+ continue;
+ }
+ const expanded = pp.expandToken(macro_tok);
+ const macro = pp.defines.getPtr(expanded) orelse {
+ idx += 1;
+ continue;
+ };
+
+ if (macro.is_func) {
+ var macro_scan_idx = idx;
+ const arg = try pp.collectMacroArgument(
+ tokenizer,
+ buf,
+ ¯o_scan_idx,
+ &moving_end_idx,
+ extend_buf,
+ );
+ const expanded_arg = arg: {
+ var expand_buf: ExpandBuf = .empty;
+ errdefer expand_buf.deinit(pp.arena);
+ try expand_buf.appendSlice(pp.arena, arg);
+ try pp.expandMacroExhaustive(tokenizer, &expand_buf, 0, expand_buf.items.len, false, eval_ctx);
+ break :arg try expand_buf.toOwnedSlice(pp.arena);
+ };
+
+ const res = try pp.expandFuncMacro(macro, arg, expanded_arg);
+ const tokens_added = res.items.len;
+ const tokens_removed = macro_scan_idx - idx + 1;
+ try buf.replaceRange(pp.arena, idx, tokens_removed, res.items);
+
+ moving_end_idx += tokens_added;
+ moving_end_idx -|= tokens_removed;
+ idx += tokens_added;
+ do_rescan = true;
+ } else {
+ var res = try pp.expandObjMacro(macro);
+ defer res.deinit(pp.arena);
+ var increment_idx_by = res.items.len;
+
+ for (res.items, 0..) |*tok, i| {
+ if (i < increment_idx_by and pp.defines.contains(pp.expandToken(tok.*))) {
+ increment_idx_by = i;
+ }
+ }
+ try buf.replaceRange(pp.arena, idx, 1, res.items);
+ idx += res.items.len;
+ moving_end_idx = moving_end_idx + res.items.len - 1;
+ do_rescan = true;
+ }
+ if (idx - start_idx == advance_index + 1 and !do_rescan) {
+ advance_index += 1;
+ }
+ }
+ }
+ buf.items.len = moving_end_idx;
+}
+
+fn collectMacroArgument(
+ pp: *Preprocessor,
+ tokenizer: *Tokenizer,
+ buf: *ExpandBuf,
+ start_idx: *usize,
+ end_idx: *usize,
+ extend_buf: bool,
+) !MacroArgument {
+ var parens: u32 = 0;
+ var argument: std.ArrayList(Token) = .empty;
+ defer argument.deinit(pp.arena);
+
+ while (true) {
+ const tok = try nextBufToken(pp, tokenizer, buf, start_idx, end_idx, extend_buf);
+ switch (tok.id) {
+ .nl, .whitespace => {},
+ .l_paren => break,
+ else => unreachable,
+ }
+ }
+
+ while (true) {
+ const tok = try nextBufToken(pp, tokenizer, buf, start_idx, end_idx, extend_buf);
+ switch (tok.id) {
+ .l_paren => {
+ try argument.append(pp.arena, tok);
+ parens += 1;
+ },
+ .r_paren => {
+ if (parens == 0) {
+ return try argument.toOwnedSlice(pp.arena);
+ } else {
+ try argument.append(pp.arena, tok);
+ parens -= 1;
+ }
+ },
+ .nl, .whitespace => try argument.append(pp.arena, .{ .id = .whitespace, .source = Source.generated }),
+ .eof => unreachable,
+ else => try argument.append(pp.arena, tok),
+ }
+ }
+}
+
+fn expandObjMacro(pp: *Preprocessor, simple_macro: *const Macro) !ExpandBuf {
+ var buf: ExpandBuf = .empty;
+ errdefer buf.deinit(pp.arena);
+ try buf.appendSlice(pp.arena, simple_macro.tokens);
+ return buf;
+}
+
+fn expandFuncMacro(
+ pp: *Preprocessor,
+ func_macro: *const Macro,
+ arg: MacroArgument,
+ expanded_arg: MacroArgument,
+) !ExpandBuf {
+ var buf: ExpandBuf = .empty;
+ errdefer buf.deinit(pp.arena);
+ try buf.ensureTotalCapacity(pp.arena, func_macro.tokens.len);
+
+ var tok_i: usize = 0;
+ while (tok_i < func_macro.tokens.len) : (tok_i += 1) {
+ const tok = func_macro.tokens[tok_i];
+ switch (tok.id) {
+ .hash_hash => while (tok_i + 1 < func_macro.tokens.len) {
+ tok_i += 1;
+ const tok_next = func_macro.tokens[tok_i];
+ const next = switch (tok_next.id) {
+ .whitespace => continue,
+ .hash_hash => continue,
+ .macro_param => arg,
+ else => &[1]Token{tok_next},
+ };
+ try pp.pasteTokens(&buf, next);
+ if (next.len != 0) break;
+ },
+ .macro_param => {
+ try buf.appendSlice(pp.arena, expanded_arg);
+ },
+ else => try buf.append(pp.arena, tok),
+ }
+ }
+
+ return buf;
+}
+
+fn pasteTokens(
+ pp: *Preprocessor,
+ lhs_toks: *ExpandBuf,
+ rhs_toks: []const Token,
+) !void {
+ const lhs = while (lhs_toks.pop()) |lhs| {
+ if (lhs.id != .whitespace) break lhs;
+ } else {
+ return lhs_toks.appendSlice(pp.arena, rhs_toks);
+ };
+
+ var rhs_rest: u32 = 1;
+ const rhs = for (rhs_toks) |rhs| {
+ if (rhs.id != .whitespace) break rhs;
+ rhs_rest += 1;
+ } else {
+ return lhs_toks.appendAssumeCapacity(lhs);
+ };
+
+ const start = pp.generated_tokens.items.len;
+ const end = start + pp.expandToken(lhs).len + pp.expandToken(rhs).len;
+ try pp.generated_tokens.ensureTotalCapacity(pp.arena, end + 1);
+ pp.generated_tokens.appendSliceAssumeCapacity(pp.expandToken(lhs));
+ pp.generated_tokens.appendSliceAssumeCapacity(pp.expandToken(rhs));
+ pp.generated_tokens.appendAssumeCapacity('\n');
+
+ var tmp_tokenizer: Tokenizer = .{
+ .index = @intCast(start),
+ .buf = pp.generated_tokens.items,
+ .source = Source.generated,
+ };
+ const pasted_token = tmp_tokenizer.nextNoWS();
+ const next = tmp_tokenizer.nextNoWS();
+
+ try lhs_toks.append(pp.arena, pp.makeGeneratedToken(start, end, pasted_token.id));
+ assert(next.id == .nl or next.id == .eof);
+
+ return lhs_toks.appendSlice(pp.arena, rhs_toks[rhs_rest..]);
+}
+
+fn nextBufToken(
+ pp: *Preprocessor,
+ tokenizer: *Tokenizer,
+ buf: *ExpandBuf,
+ start_idx: *usize,
+ end_idx: *usize,
+ extend_buf: bool,
+) !Token {
+ start_idx.* += 1;
+ if (start_idx.* == buf.items.len and start_idx.* >= end_idx.*) {
+ if (extend_buf) {
+ const tok = tokenizer.next();
+ if (tok.id == .nl) pp.add_expansion_nl += 1;
+
+ end_idx.* += 1;
+ try buf.append(pp.arena, tok);
+ return tok;
+ }
+ return .{ .id = .eof, .source = Source.generated };
+ }
+
+ return buf.items[start_idx.*];
+}
+
+fn makeGeneratedToken(
+ pp: *Preprocessor,
+ start: usize,
+ end: usize,
+ id: Token.Id,
+) Token {
+ const pasted_token: Token = .{
+ .id = id,
+ .source = Source.generated,
+ .start = @intCast(start),
+ .end = @intCast(end),
+ };
+ pp.generated_line += 1;
+ return pasted_token;
+}
+
+fn findInclude(
+ pp: *Preprocessor,
+ filename: []const u8,
+ includer_token: Token,
+) !?Source {
+ const other_file = pp.sources.values()[includer_token.source].path;
+ const dir = std.fs.path.dirname(other_file) orelse ".";
+ if (try pp.checkIncludeDir(filename, dir)) |res| return res;
+
+ return pp.checkIncludeDir(filename, pp.include_dir);
+}
+
+fn checkIncludeDir(
+ pp: *Preprocessor,
+ include_path: []const u8,
+ include_dir: []const u8,
+) !?Source {
+ const format = "{s}{c}{s}";
+ var bfa_buf: [1024]u8 = undefined;
+ var bfa_state: std.heap.BufferFirstAllocator = .init(&bfa_buf, pp.arena);
+ const bfa = bfa_state.allocator();
+ const header_path = try std.fmt.allocPrint(bfa, format, .{
+ include_dir,
+ std.fs.path.sep,
+ include_path,
+ });
+ defer bfa.free(header_path);
+
+ return pp.addSourceFromPath(header_path) catch |err| switch (err) {
+ error.OutOfMemory => |e| return e,
+ else => return null,
+ };
+}
+
+pub fn addSourceFromPath(pp: *Preprocessor, path: []const u8) !Source {
+ if (pp.sources.get(path)) |src| return src;
+ try pp.sources.ensureUnusedCapacity(pp.arena, 1);
+
+ const contents = try std.Io.Dir.cwd().readFileAlloc(pp.io, path, pp.arena, .limited(std.math.maxInt(u32)));
+ const duped_path = try pp.arena.dupe(u8, path);
+
+ const src: Source = .{
+ .buf = contents,
+ .path = duped_path,
+ .id = pp.sources.count(),
+ };
+
+ pp.sources.putAssumeCapacityNoClobber(duped_path, src);
+ return src;
+}
+
+fn evalExpression(
+ pp: *Preprocessor,
+ start: usize,
+) !bool {
+ const s = pp.tokens.slice();
+ const len = s.len - start;
+ const ss = s.subslice(start, len);
+
+ const ids: []Token.Id = ss.items(.id);
+ const starts: []u32 = ss.items(.start);
+ const ends: []u32 = ss.items(.end);
+ const srcs: []usize = ss.items(.source);
+
+ var toks = try pp.arena.alloc(Token, len);
+ defer pp.arena.free(toks);
+
+ for (0..len) |i| {
+ toks[i] = .{
+ .id = ids[i],
+ .source = srcs[i],
+ .start = starts[i],
+ .end = ends[i],
+ };
+ }
+
+ return pp.evaluateExpressionTokens(toks);
+}
+
+fn evaluateExpressionTokens(
+ pp: *const Preprocessor,
+ toks: []const Token,
+) bool {
+ var it = TokenIterator.init(toks);
+
+ const left = evalToken(&it);
+ assert(!left.id.isInfix());
+
+ const op = evalToken(&it);
+ if (op.id == .eof) return left.id == .one;
+
+ assert(op.id.isInfix());
+ const right = evalToken(&it);
+
+ return pp.evalInfix(left, op, right);
+}
+
+fn evalToken(it: *TokenIterator) Token {
+ const tok = it.expectNext();
+ if (tok.id != .bang) {
+ return tok;
+ }
+
+ var op = it.expectNext();
+ const flipped: Token.Id = switch (op.id) {
+ .one => .zero,
+ .zero => .one,
+ else => unreachable,
+ };
+ op.id = flipped;
+ return op;
+}
+
+fn evalInfix(
+ pp: *const Preprocessor,
+ left: Token,
+ op: Token,
+ right: Token,
+) bool {
+ switch (op.id) {
+ .pipe_pipe => return (left.id == .one) or (right.id == .one),
+ .equal_equal => {
+ switch (left.id) {
+ .one, .zero => {
+ assert(right.id == .one or right.id == .zero);
+ return left.id == right.id;
+ },
+ .pp_num => {
+ assert(right.id == .pp_num);
+ const lval = pp.expandToken(left);
+ const rval = pp.expandToken(right);
+ return std.mem.eql(u8, lval, rval);
+ },
+ else => unreachable,
+ }
+ },
+ else => unreachable,
+ }
+}
+
+pub fn prettyPrintTokens(pp: *Preprocessor, w: *std.Io.Writer) !void {
+ const tok_ids = pp.tokens.items(.id);
+ var i: usize = 0;
+ var last_nl = true;
+ outer: while (true) : (i += 1) {
+ const cur: Token = pp.tokens.get(i);
+ switch (cur.id) {
+ .eof => {
+ if (!last_nl) try w.writeByte('\n');
+ try w.flush();
+ return;
+ },
+ .nl => {
+ var newlines: u32 = 0;
+ for (tok_ids[i..], i..) |id, j| {
+ if (id == .nl) {
+ newlines += 1;
+ } else if (id == .eof) {
+ if (!last_nl) try w.writeByte('\n');
+ try w.flush();
+ return;
+ } else if (id != .whitespace) {
+ if (newlines < 2) break;
+
+ i = @intCast((j - 1) - @intFromBool(tok_ids[j - 1] == .whitespace));
+ if (!last_nl) try w.writeAll("\n");
+ continue :outer;
+ }
+ }
+ last_nl = true;
+ try w.writeAll("\n");
+ },
+ .whitespace => {
+ try w.writeByte(' ');
+ last_nl = false;
+ },
+ else => {
+ const slice = pp.expandToken(cur);
+ try w.writeAll(slice);
+ last_nl = false;
+ },
+ }
+ }
+}
diff --git a/src/libs/mingw/Tokenizer.zig b/src/libs/mingw/Tokenizer.zig
new file mode 100644
index 0000000000000000000000000000000000000000..07db83108fa9f168f99a56d496e439cc39416dcc
--- /dev/null
+++ b/src/libs/mingw/Tokenizer.zig
@@ -0,0 +1,359 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Source = @import("Preprocessor.zig").Source;
+
+const Tokenizer = @This();
+
+pub fn init(buf: []const u8, source: Source.Id) Tokenizer {
+ return .{ .buf = buf, .source = source };
+}
+
+buf: []const u8,
+index: u32 = 0,
+source: Source.Id,
+
+pub const Token = struct {
+ pub const Id = enum {
+ bang,
+ eof,
+ equal_equal,
+ hash,
+ hash_hash,
+ macro_param,
+ identifier,
+ keyword_if,
+ keyword_ifndef,
+ keyword_ifdef,
+ keyword_define,
+ keyword_endif,
+ keyword_defined,
+ keyword_include,
+ keyword_elif,
+ keyword_else,
+ keyword_undef,
+ keyword_error,
+ l_paren,
+ nl,
+ pp_num,
+ pipe_pipe,
+ r_paren,
+ semicolon,
+ string_literal,
+ whitespace,
+ one,
+ zero,
+
+ pub fn isInfix(id: Id) bool {
+ switch (id) {
+ .pipe_pipe, .equal_equal => return true,
+ else => return false,
+ }
+ }
+
+ pub fn isMacroIdentifier(id: Id) bool {
+ switch (id) {
+ .keyword_if,
+ .keyword_ifndef,
+ .keyword_ifdef,
+ .keyword_define,
+ .keyword_endif,
+ .keyword_defined,
+ .keyword_include,
+ .keyword_elif,
+ .keyword_else,
+ .keyword_undef,
+ .keyword_error,
+ .identifier,
+ => return true,
+ else => return false,
+ }
+ }
+ };
+
+ const all_kws = std.StaticStringMap(Id).initComptime(.{
+ .{ "define", .keyword_define },
+ .{ "defined", .keyword_defined },
+ .{ "else", .keyword_else },
+ .{ "endif", .keyword_endif },
+ .{ "if", .keyword_if },
+ .{ "elif", .keyword_elif },
+ .{ "ifdef", .keyword_ifdef },
+ .{ "ifndef", .keyword_ifndef },
+ .{ "include", .keyword_include },
+ .{ "undef", .keyword_undef },
+ .{ "error", .keyword_error },
+ });
+
+ id: Id,
+ source: Source.Id,
+ start: u32 = 0,
+ end: u32 = 0,
+
+ fn getTokenId(str: []const u8) Id {
+ return all_kws.get(str) orelse .identifier;
+ }
+};
+
+pub fn next(self: *Tokenizer) Token {
+ var state: enum {
+ start,
+ cr,
+ string_literal,
+ identifier,
+ equal,
+ slash,
+ line_comment,
+ hash,
+ pipe,
+ pp_num,
+ } = .start;
+
+ const start = self.index;
+ var id: Token.Id = .eof;
+
+ while (self.index < self.buf.len) : (self.index += 1) {
+ const c = self.buf[self.index];
+ switch (state) {
+ .start => switch (c) {
+ '\r' => {
+ id = .nl;
+ state = .cr;
+ },
+ '\n' => {
+ id = .nl;
+ self.index += 1;
+ break;
+ },
+ '!' => {
+ id = .bang;
+ self.index += 1;
+ break;
+ },
+ '"' => {
+ id = .string_literal;
+ state = .string_literal;
+ },
+ '|' => state = .pipe,
+ '=' => state = .equal,
+ '(' => {
+ id = .l_paren;
+ self.index += 1;
+ break;
+ },
+ ')' => {
+ id = .r_paren;
+ self.index += 1;
+ break;
+ },
+ ';' => {
+ id = .semicolon;
+ self.index += 1;
+ break;
+ },
+ '/' => state = .slash,
+ '#' => state = .hash,
+ '0'...'9' => state = .pp_num,
+ ' ' => {
+ id = .whitespace;
+ self.index += 1;
+ break;
+ },
+ else => state = .identifier,
+ },
+ .cr => switch (c) {
+ '\n' => {
+ self.index += 1;
+ break;
+ },
+ else => break,
+ },
+ .pipe => switch (c) {
+ '|' => {
+ id = .pipe_pipe;
+ self.index += 1;
+ break;
+ },
+ else => unreachable,
+ },
+ .hash => switch (c) {
+ '#' => {
+ id = .hash_hash;
+ self.index += 1;
+ break;
+ },
+ else => {
+ id = .hash;
+ break;
+ },
+ },
+ .string_literal => switch (c) {
+ '"' => {
+ self.index += 1;
+ break;
+ },
+ else => {},
+ },
+ .identifier => switch (c) {
+ 'a'...'z', 'A'...'Z', '_', '0'...'9' => {},
+ else => {
+ id = Token.getTokenId(self.buf[start..self.index]);
+ break;
+ },
+ },
+ .equal => switch (c) {
+ '=' => {
+ id = .equal_equal;
+ self.index += 1;
+ break;
+ },
+ else => unreachable,
+ },
+ .slash => switch (c) {
+ '/' => state = .line_comment,
+ else => {
+ id = .identifier;
+ break;
+ },
+ },
+ .line_comment => switch (c) {
+ '\n' => {
+ self.index -= 1;
+ state = .start;
+ },
+ else => {},
+ },
+ .pp_num => switch (c) {
+ '0'...'9' => {},
+ else => {
+ id = .pp_num;
+ break;
+ },
+ },
+ }
+ } else if (self.index == self.buf.len) {
+ switch (state) {
+ .start, .line_comment, .cr => {},
+ .identifier => id = Token.getTokenId(self.buf[start..self.index]),
+ .hash => id = .hash,
+ .pp_num => id = .pp_num,
+ else => unreachable,
+ }
+ }
+
+ return .{
+ .id = id,
+ .start = start,
+ .end = self.index,
+ .source = self.source,
+ };
+}
+
+pub fn nextNoWS(self: *Tokenizer) Token {
+ var tok = self.next();
+ while (tok.id == .whitespace) tok = self.next();
+ return tok;
+}
+
+fn expectToken(expected: Token.Id, actual: Token) !void {
+ try std.testing.expectEqual(expected, actual.id);
+}
+
+fn testToken(buf: []const u8, expected: Token.Id) !void {
+ var tokenizer = Tokenizer.init(buf, Source.generated);
+ const t = tokenizer.next();
+ try expectToken(expected, t);
+ try expectToken(.eof, tokenizer.next());
+}
+
+test "tokens" {
+ try testToken("TEST", .identifier);
+ try testToken("__x86_64__", .identifier);
+ try testToken("122", .pp_num);
+ try testToken("==", .equal_equal);
+ try testToken("#", .hash);
+ try testToken("##", .hash_hash);
+ try testToken("undef", .keyword_undef);
+ try testToken("||", .pipe_pipe);
+ try testToken("!", .bang);
+ try testToken("else", .keyword_else);
+ try testToken("endif", .keyword_endif);
+ try testToken("include", .keyword_include);
+ try testToken("define", .keyword_define);
+ try testToken("defined", .keyword_defined);
+ try testToken("if", .keyword_if);
+ try testToken("ifdef", .keyword_ifdef);
+ try testToken("ifndef", .keyword_ifndef);
+ try testToken("(", .l_paren);
+ try testToken("\n", .nl);
+ try testToken("\r", .nl);
+ try testToken("\r\n", .nl);
+ try testToken("5", .pp_num);
+ try testToken(")", .r_paren);
+ try testToken("\"str\"", .string_literal);
+ try testToken(" ", .whitespace);
+}
+
+fn expectTokens(contents: []const u8, expected_tokens: []const Token.Id) !void {
+ var tokenizer: Tokenizer = .init(contents, Source.generated);
+ var i: usize = 0;
+ while (i < expected_tokens.len) {
+ const token = tokenizer.next();
+ if (token.id == .whitespace) continue;
+ const expected_token_id = expected_tokens[i];
+ i += 1;
+ if (!std.meta.eql(token.id, expected_token_id)) {
+ std.debug.print("expected {s}, found {s}\n", .{ @tagName(expected_token_id), @tagName(token.id) });
+ return error.TokensDoNotEqual;
+ }
+ }
+ const last_token = tokenizer.next();
+ try std.testing.expect(last_token.id == .eof);
+}
+
+test "preprocessor keywords" {
+ try expectTokens(
+ \\#if
+ \\#ifndef
+ \\#ifdef
+ \\#define
+ \\#endif
+ \\defined
+ \\#include
+ \\#elif
+ \\#else
+ \\#undef
+ \\#error
+ , &.{
+ .hash,
+ .keyword_if,
+ .nl,
+ .hash,
+ .keyword_ifndef,
+ .nl,
+ .hash,
+ .keyword_ifdef,
+ .nl,
+ .hash,
+ .keyword_define,
+ .nl,
+ .hash,
+ .keyword_endif,
+ .nl,
+ .keyword_defined,
+ .nl,
+ .hash,
+ .keyword_include,
+ .nl,
+ .hash,
+ .keyword_elif,
+ .nl,
+ .hash,
+ .keyword_else,
+ .nl,
+ .hash,
+ .keyword_undef,
+ .nl,
+ .hash,
+ .keyword_error,
+ });
+}
diff --git a/src/libs/mingw/implib.zig b/src/libs/mingw/implib.zig
index 525129fe119046846ca70b798bd38fc0c4cfadd0..f3cf24b3b88cf41323fbe62d4890277ca8ca5f8b 100644
--- a/src/libs/mingw/implib.zig
+++ b/src/libs/mingw/implib.zig
@@ -245,7 +245,7 @@ pub fn getMembers(
};
var renames: std.ArrayList(DeferredExport) = .empty;
defer renames.deinit(allocator);
- var regular_imports: std.StringArrayHashMapUnmanaged([]const u8) = .empty;
+ var regular_imports: std.array_hash_map.String([]const u8) = .empty;
defer regular_imports.deinit(allocator);
for (module_def.exports.items) |*e| {
@@ -1012,7 +1012,7 @@ fn getShortImport(
fn writeSymbol(writer: *std.Io.Writer, symbol: std.coff.Symbol) !void {
try writer.writeAll(&symbol.name);
try writer.writeInt(u32, symbol.value, .little);
- try writer.writeInt(u16, @intFromEnum(symbol.section_number), .little);
+ try writer.writeInt(i16, @intFromEnum(symbol.section_number), .little);
try writer.writeInt(u8, @intFromEnum(symbol.type.base_type), .little);
try writer.writeInt(u8, @intFromEnum(symbol.type.complex_type), .little);
try writer.writeInt(u8, @intFromEnum(symbol.storage_class), .little);
diff --git a/src/libs/musl.zig b/src/libs/musl.zig
index 2f56a417f2984e66d696830c5ecdf9dd40e4816a..fcf179894c6d6f0d542f04fb925788c76f82ca1a 100644
--- a/src/libs/musl.zig
+++ b/src/libs/musl.zig
@@ -784,8 +784,6 @@ const src_files = [_][]const u8{
"musl/src/math/aarch64/llrintf.c",
"musl/src/math/aarch64/llround.c",
"musl/src/math/aarch64/llroundf.c",
- "musl/src/math/aarch64/lround.c",
- "musl/src/math/aarch64/lroundf.c",
"musl/src/math/aarch64/nearbyint.c",
"musl/src/math/aarch64/nearbyintf.c",
"musl/src/math/acosh.c",
@@ -891,9 +889,6 @@ const src_files = [_][]const u8{
"musl/src/math/logbf.c",
"musl/src/math/logbl.c",
"musl/src/math/logl.c",
- "musl/src/math/lround.c",
- "musl/src/math/lroundf.c",
- "musl/src/math/lroundl.c",
"musl/src/math/__math_divzero.c",
"musl/src/math/__math_divzerof.c",
"musl/src/math/__math_invalid.c",
@@ -919,8 +914,6 @@ const src_files = [_][]const u8{
"musl/src/math/pow_data.c",
"musl/src/math/powerpc64/fma.c",
"musl/src/math/powerpc64/fmaf.c",
- "musl/src/math/powerpc64/lround.c",
- "musl/src/math/powerpc64/lroundf.c",
"musl/src/math/powerpc/fma.c",
"musl/src/math/powerpc/fmaf.c",
"musl/src/math/powf.c",
diff --git a/src/libs/wasi_libc.zig b/src/libs/wasi_libc.zig
index f5025666f61406a430b51ac582d147358803eefe..561966b01707194d277afc0d5afecb241a68f732 100644
--- a/src/libs/wasi_libc.zig
+++ b/src/libs/wasi_libc.zig
@@ -725,9 +725,6 @@ const libc_top_half_src_files = [_][]const u8{
"musl/src/math/logbf.c",
"musl/src/math/logbl.c",
"musl/src/math/logl.c",
- "musl/src/math/lround.c",
- "musl/src/math/lroundf.c",
- "musl/src/math/lroundl.c",
"musl/src/math/__math_divzero.c",
"musl/src/math/__math_divzerof.c",
"musl/src/math/__math_invalid.c",
diff --git a/src/link.zig b/src/link.zig
index 12d12a959bbd626d505f544a9972bc044e6efab4..4764e0c291f4c048812f5f30dc94d1f948c9b442 100644
--- a/src/link.zig
+++ b/src/link.zig
@@ -25,12 +25,15 @@ const Package = @import("Package.zig");
const dev = @import("dev.zig");
const target_util = @import("target.zig");
const codegen = @import("codegen.zig");
+const crash_report = @import("crash_report.zig");
pub const aarch64 = @import("link/aarch64.zig");
pub const LdScript = @import("link/LdScript.zig");
pub const Queue = @import("link/Queue.zig");
pub const ConstPool = @import("link/ConstPool.zig");
+pub const loongarch = @import("link/loongarch.zig");
+
pub const Error = Allocator.Error || Io.Cancelable || error{
/// An error message has already been stored in persistent state on `Compilation` or `Zcu`, for
/// instance in `Compilation.link_diags`.
@@ -471,7 +474,7 @@ pub const File = struct {
/// wrapper for a system function. The wrapper function should be called
/// __wrap_symbol. If it wishes to call the system function, it should call
/// __real_symbol.
- symbol_wrap_set: std.StringArrayHashMapUnmanaged(void),
+ symbol_wrap_set: std.array_hash_map.String(void),
compatibility_version: ?std.SemanticVersion,
@@ -481,7 +484,7 @@ pub const File = struct {
rpath_list: []const []const u8,
/// Zig compiler development linker flags.
- /// Enable dumping of linker's state as JSON.
+ /// Enable dumping of linker's state.
enable_link_snapshots: bool,
/// Darwin-specific linker flags:
@@ -790,6 +793,7 @@ pub const File = struct {
assert(base.comp.zcu.?.llvm_object == null);
const nav = pt.zcu.intern_pool.getNav(nav_index);
assert(nav.resolved.?.value != .none);
+
switch (base.tag) {
.lld => unreachable,
.plan9 => unreachable,
@@ -841,7 +845,6 @@ pub const File = struct {
assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
.lld => unreachable,
- .spirv => unreachable, // see corresponding special case in `Zcu.PerThread.runCodegenInner`
.plan9 => unreachable,
inline else => |tag| {
dev.check(tag.devFeature());
@@ -925,6 +928,9 @@ pub const File = struct {
/// Commit pending changes and write headers. Takes into account final output mode.
/// `arena` has the lifetime of the call to `Compilation.update`.
pub fn flush(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) Error!void {
+ crash_report.LinkerOp.start(base, tid);
+ defer crash_report.LinkerOp.stop(base, tid);
+
const comp = base.comp;
const io = comp.io;
if (comp.clang_preprocessor_mode == .yes or comp.clang_preprocessor_mode == .pch) {
@@ -934,8 +940,8 @@ pub const File = struct {
// Until then, we do `lld -r -o output.o input.o` even though the output is the same
// as the input. For the preprocessing case (`zig cc -E -o foo`) we copy the file
// to the final location. See also the corresponding TODO in Coff linking.
- assert(comp.c_object_table.count() == 1);
- const the_key = comp.c_object_table.keys()[0];
+ assert(comp.c_objects.items.len == 1);
+ const the_key = comp.c_objects.items[0];
const cached_pp_file_path = the_key.status.success.object_path;
Io.Dir.copyFile(
cached_pp_file_path.root_dir.handle,
@@ -976,6 +982,10 @@ pub const File = struct {
export_indices: []const Zcu.Export.Index,
) Error!void {
assert(base.comp.zcu.?.llvm_object == null);
+
+ crash_report.LinkerOp.start(base, pt.tid);
+ defer crash_report.LinkerOp.stop(base, pt.tid);
+
switch (base.tag) {
.lld => unreachable,
.plan9 => unreachable,
@@ -1007,6 +1017,7 @@ pub const File = struct {
/// Never called when LLVM is codegenning the ZCU.
pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) Error!u64 {
assert(base.comp.zcu.?.llvm_object == null);
+
switch (base.tag) {
.lld => unreachable,
.c => unreachable,
@@ -1028,6 +1039,7 @@ pub const File = struct {
decl_align: InternPool.Alignment,
) Error!SymbolId {
assert(base.comp.zcu.?.llvm_object == null);
+
switch (base.tag) {
.lld => unreachable,
.c => unreachable,
@@ -1044,6 +1056,7 @@ pub const File = struct {
/// Never called when LLVM is codegenning the ZCU.
pub fn getUavVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) Error!u64 {
assert(base.comp.zcu.?.llvm_object == null);
+
switch (base.tag) {
.lld => unreachable,
.c => unreachable,
@@ -1064,6 +1077,7 @@ pub const File = struct {
name: InternPool.NullTerminatedString,
) void {
assert(base.comp.zcu.?.llvm_object == null);
+
switch (base.tag) {
.lld => unreachable,
.plan9 => unreachable,
@@ -1078,6 +1092,31 @@ pub const File = struct {
}
}
+ pub const DumpResult = enum {
+ unimplemented,
+ needs_extensions,
+ disabled,
+ enabled,
+ };
+
+ pub fn dump(base: *File, w: *Io.Writer, tid: Zcu.PerThread.Id) !DumpResult {
+ if (!build_options.enable_debug_extensions) return .not_built;
+ switch (base.tag) {
+ .elf,
+ .macho,
+ .c,
+ .wasm,
+ .spirv,
+ .plan9,
+ .lld,
+ => return .unimplemented,
+ inline else => |tag| {
+ dev.check(tag.devFeature());
+ return @as(*tag.Type(), @fieldParentPtr("base", base)).dump(w, tid);
+ },
+ }
+ }
+
/// Opens a path as an object file and parses it into the linker.
fn openLoadObject(base: *File, path: Path) anyerror!void {
if (base.tag == .lld) return;
@@ -1179,8 +1218,9 @@ pub const File = struct {
pub fn loadInput(base: *File, input: Input) anyerror!void {
if (base.tag == .lld) return;
assert(!base.post_prelink);
+
switch (base.tag) {
- inline .elf, .elf2, .wasm => |tag| {
+ inline .coff2, .elf, .elf2, .wasm, .spirv => |tag| {
dev.check(tag.devFeature());
return @as(*tag.Type(), @fieldParentPtr("base", base)).loadInput(input);
},
@@ -1442,7 +1482,8 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
const target = &comp.root_mod.resolved_target.result;
const flags = target_util.libcFullLinkFlags(target);
- const crt_dir = comp.libc_installation.?.crt_dir.?;
+ const libc_installation = comp.libc_installation.?;
+ const crt_dir = libc_installation.crt_dir.?;
const sep = std.fs.path.sep_str;
for (flags) |flag| {
assert(mem.startsWith(u8, flag, "-l"));
@@ -1494,6 +1535,54 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
},
}
}
+
+ if (target.os.tag == .windows and target.abi == .msvc) {
+ const inputs: []const struct {
+ dir: enum { crt, msvc_lib, kernel32_lib },
+ name: []const u8,
+ } = switch (comp.config.link_mode) {
+ .dynamic => &.{
+ .{ .dir = .msvc_lib, .name = "msvcrt.lib" },
+ .{ .dir = .msvc_lib, .name = "vcruntime.lib" },
+ .{ .dir = .msvc_lib, .name = "legacy_stdio_definitions.lib" },
+ .{ .dir = .crt, .name = "ucrt.lib" },
+ .{ .dir = .kernel32_lib, .name = "kernel32.lib" },
+ .{ .dir = .kernel32_lib, .name = "ntdll.lib" },
+ },
+ .static => &.{
+ .{ .dir = .msvc_lib, .name = "libcmt.lib" },
+ .{ .dir = .msvc_lib, .name = "libvcruntime.lib" },
+ .{ .dir = .msvc_lib, .name = "legacy_stdio_definitions.lib" },
+ .{ .dir = .crt, .name = "libucrt.lib" },
+ .{ .dir = .kernel32_lib, .name = "kernel32.lib" },
+ .{ .dir = .kernel32_lib, .name = "ntdll.lib" },
+ },
+ };
+
+ for (inputs) |lib| {
+ const path = Path.initCwd(
+ std.fmt.allocPrint(comp.arena, "{s}" ++ sep ++ "{s}", .{
+ switch (lib.dir) {
+ .crt => crt_dir,
+ .msvc_lib => libc_installation.msvc_lib_dir.?,
+ .kernel32_lib => libc_installation.kernel32_lib_dir.?,
+ },
+ lib.name,
+ }) catch return diags.setAllocFailure(),
+ );
+ if (std.mem.endsWith(u8, lib.name, "lib")) {
+ base.openLoadArchive(path, false) catch |err| switch (err) {
+ error.LinkFailure => return, // error reported via diags
+ else => |e| diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(e)}),
+ };
+ } else {
+ base.openLoadObject(path) catch |err| switch (err) {
+ error.LinkFailure => return, // error reported via diags
+ else => |e| diags.addParseError(path, "failed to parse object: {s}", .{@errorName(e)}),
+ };
+ }
+ }
+ }
},
.load_object => |path| {
const prog_node = comp.link_prog_node.start("Parse Object", 0);
@@ -1529,8 +1618,9 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
const diags = &comp.link_diags;
const zcu = comp.zcu.?;
const ip = &zcu.intern_pool;
- const pt: Zcu.PerThread = .activate(zcu, tid);
- defer pt.deactivate();
+ const active = zcu.activate(tid);
+ defer active.deactivate();
+ const pt = active.pt;
var timer = comp.startTimer();
diff --git a/src/link/C.zig b/src/link/C.zig
index 23225d7b7a86ea3fdba3c5dbed401f14e3b72599..127485171314adc352096f6e13b448b28d12e173 100644
--- a/src/link/C.zig
+++ b/src/link/C.zig
@@ -44,10 +44,10 @@ type_dependencies: std.ArrayList(link.ConstPool.Index),
align_dependency_masks: std.ArrayList(u64),
/// All NAVs, regardless of whether they are functions or simple constants, are put in this map.
-navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, RenderedDecl),
+navs: std.array_hash_map.Auto(InternPool.Nav.Index, RenderedDecl),
/// All UAVs which may be referenced are in this map. The UAV alignment is not included in the
/// rendered C code stored here, because we don't know the alignment a UAV needs until `flush`.
-uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, RenderedDecl),
+uavs: std.array_hash_map.Auto(InternPool.Index, RenderedDecl),
/// Contains all types which are needed by some other rendered code. Does not contain any constants
/// other than types.
type_pool: link.ConstPool,
@@ -59,10 +59,10 @@ types: std.ArrayList(RenderedType),
/// The set of big int types required by *any* generated code so far. These are always safe to emit,
/// so they do not participate in the dependency graph traversal in `flush`. Therefore, redundant
/// big-int types may be emitted under incremental compilation.
-bigint_types: std.AutoArrayHashMapUnmanaged(codegen.CType.BigInt, void),
+bigint_types: std.array_hash_map.Auto(codegen.CType.BigInt, void),
-exported_navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, String),
-exported_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, String),
+exported_navs: std.array_hash_map.Auto(InternPool.Nav.Index, String),
+exported_uavs: std.array_hash_map.Auto(InternPool.Index, String),
/// A reference into `string_bytes`.
const String = extern struct {
@@ -133,10 +133,10 @@ const RenderedDecl = struct {
fwd_decl: String,
code: String,
ctype_deps: CTypeDependencies,
- need_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
- need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
- need_never_tail_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void),
- need_never_inline_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void),
+ need_uavs: std.array_hash_map.Auto(InternPool.Index, Alignment),
+ need_tag_name_funcs: std.array_hash_map.Auto(InternPool.Index, void),
+ need_never_tail_funcs: std.array_hash_map.Auto(InternPool.Nav.Index, void),
+ need_never_inline_funcs: std.array_hash_map.Auto(InternPool.Nav.Index, void),
const init: RenderedDecl = .{
.fwd_decl = .empty,
@@ -728,8 +728,9 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
const zcu = c.base.comp.zcu.?;
const ip = &zcu.intern_pool;
const target = zcu.getTarget();
- const pt: Zcu.PerThread = .activate(zcu, tid);
- defer pt.deactivate();
+ const active = zcu.activate(tid);
+ defer active.deactivate();
+ const pt = active.pt;
// If it's somehow not made it into the pool, we need to generate the type `[:0]const u8` for
// error names.
@@ -745,7 +746,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
// incremental updates which is invalid C (due to e.g. types changing). Machine code backends
// don't have this problem because there are, of course, no type checking performed when you
// *execute* a binary!
- var need_navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty;
+ var need_navs: std.array_hash_map.Auto(InternPool.Nav.Index, void) = .empty;
defer need_navs.deinit(gpa);
{
const unit_references = try zcu.resolveReferences();
@@ -773,23 +774,23 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
//
// At the same time, we will discover the set of lazy functions which are referenced.
- var need_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .empty;
+ var need_uavs: std.array_hash_map.Auto(InternPool.Index, Alignment) = .empty;
defer need_uavs.deinit(gpa);
- var need_types: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, void) = .empty;
+ var need_types: std.array_hash_map.Auto(link.ConstPool.Index, void) = .empty;
defer need_types.deinit(gpa);
- var need_errunion_types: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, void) = .empty;
+ var need_errunion_types: std.array_hash_map.Auto(link.ConstPool.Index, void) = .empty;
defer need_errunion_types.deinit(gpa);
- var need_aligned_types: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, u64) = .empty;
+ var need_aligned_types: std.array_hash_map.Auto(link.ConstPool.Index, u64) = .empty;
defer need_aligned_types.deinit(gpa);
- var need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .empty;
+ var need_tag_name_funcs: std.array_hash_map.Auto(InternPool.Index, void) = .empty;
defer need_tag_name_funcs.deinit(gpa);
- var need_never_tail_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty;
+ var need_never_tail_funcs: std.array_hash_map.Auto(InternPool.Nav.Index, void) = .empty;
defer need_never_tail_funcs.deinit(gpa);
- var need_never_inline_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty;
+ var need_never_inline_funcs: std.array_hash_map.Auto(InternPool.Nav.Index, void) = .empty;
defer need_never_inline_funcs.deinit(gpa);
// As mentioned above, we need this type for error names.
@@ -1283,9 +1284,9 @@ pub fn deleteExport(
fn mergeNeededCTypes(
c: *C,
- need_types: *std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, void),
- need_errunion_types: *std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, void),
- need_aligned_types: *std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, u64),
+ need_types: *std.array_hash_map.Auto(link.ConstPool.Index, void),
+ need_errunion_types: *std.array_hash_map.Auto(link.ConstPool.Index, void),
+ need_aligned_types: *std.array_hash_map.Auto(link.ConstPool.Index, u64),
deps: *const CTypeDependencies,
) Allocator.Error!void {
const gpa = c.base.comp.gpa;
@@ -1311,8 +1312,8 @@ fn mergeNeededCTypes(
fn mergeNeededUavs(
zcu: *const Zcu,
- global: *std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
- new: *const std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
+ global: *std.array_hash_map.Auto(InternPool.Index, Alignment),
+ new: *const std.array_hash_map.Auto(InternPool.Index, Alignment),
) Allocator.Error!void {
const gpa = zcu.comp.gpa;
@@ -1421,12 +1422,12 @@ const FlushTypes = struct {
c: *C,
f: *Flush,
- aligned_types: *const std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, u64),
+ aligned_types: *const std.array_hash_map.Auto(link.ConstPool.Index, u64),
aligned_type_strings: []const []const u8,
- status: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, bool),
- errunion_status: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, bool),
- aligned_status: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, void),
+ status: std.array_hash_map.Auto(link.ConstPool.Index, bool),
+ errunion_status: std.array_hash_map.Auto(link.ConstPool.Index, bool),
+ aligned_status: std.array_hash_map.Auto(link.ConstPool.Index, void),
fn processDeps(ft: *FlushTypes, deps: *const CTypeDependencies) void {
const resolved = deps.get(ft.c);
diff --git a/src/link/Coff.zig b/src/link/Coff.zig
index 2d41c3bc582ccd62799e8b8fa1ec6ec178d8c460..fcb4dcc2a50b7e4e00aa0526056e75ffbd77863b 100644
--- a/src/link/Coff.zig
+++ b/src/link/Coff.zig
@@ -7,6 +7,7 @@ const std = @import("std");
const Io = std.Io;
const assert = std.debug.assert;
const log = std.log.scoped(.link);
+const Crc32 = std.hash.crc.@"CRC-32/JAMCRC";
const codegen = @import("../codegen.zig");
const Compilation = @import("../Compilation.zig");
@@ -17,11 +18,40 @@ const target_util = @import("../target.zig");
const Type = @import("../Type.zig");
const Value = @import("../Value.zig");
const Zcu = @import("../Zcu.zig");
+const ModuleDefinition = @import("../libs/mingw/def.zig").ModuleDefinition;
+const implib = @import("../libs/mingw/implib.zig");
+const Path = std.Build.Cache.Path;
base: link.File,
+options: link.File.OpenOptions,
mf: MappedFile,
nodes: std.MultiArrayList(Node),
+members: std.ArrayList(Member),
+pending_members: std.array_hash_map.Auto(Member.Index, void),
+lib_string_table: std.ArrayList(String),
+lib_string_len: u32,
+long_names_table: LongNamesTable,
import_table: ImportTable,
+export_table: ExportTable,
+symbol_table: SymbolTable,
+inputs: std.array_hash_map.Custom(std.Build.Cache.Path, void, std.Build.Cache.Path.TableAdapter, false),
+input_archives: std.ArrayList(InputArchive),
+input_archive_members: std.ArrayList(InputArchive.Member),
+input_archive_symbols: std.ArrayList(InputArchive.Member.Symbol),
+input_archive_symbol_indices: std.array_hash_map.Auto(String, InputArchive.SearchList),
+pending_input: ?InputArchive.Member.Index,
+pending_default_libs: std.ArrayList(struct {
+ path: []const u8,
+ ioi: InputObject.Index,
+}),
+alternate_names: std.array_hash_map.Auto(String, String),
+input_objects: std.ArrayList(InputObject),
+input_symbols: std.ArrayList(struct { si: Symbol.Index, name: String }),
+input_sections: std.ArrayList(Node.InputSection),
+input_section_pending_index: u32,
+inputs_complete: bool,
+exports_complete: bool,
+pending_special_symbol: SpecialSymbol,
strings: std.HashMapUnmanaged(
u32,
void,
@@ -29,24 +59,31 @@ strings: std.HashMapUnmanaged(
std.hash_map.default_max_load_percentage,
),
string_bytes: std.ArrayList(u8),
-image_section_table: std.ArrayList(Symbol.Index),
-pseudo_section_table: std.AutoArrayHashMapUnmanaged(String, Symbol.Index),
-object_section_table: std.AutoArrayHashMapUnmanaged(String, Symbol.Index),
-symbol_table: std.ArrayList(Symbol),
-globals: std.AutoArrayHashMapUnmanaged(GlobalName, Symbol.Index),
+section_table: std.array_hash_map.Auto(String, Section),
+pseudo_section_table: std.array_hash_map.Auto(String, Symbol.Index),
+object_section_table: std.array_hash_map.Auto(String, Symbol.Index),
+section_merges: std.array_hash_map.Auto(String, String),
+section_merge_pending_index: u32,
+symbols: std.ArrayList(Symbol),
+globals: std.array_hash_map.Auto(String, Global),
global_pending_index: u32,
-navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Symbol.Index),
-uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Symbol.Index),
+navs: std.array_hash_map.Auto(InternPool.Nav.Index, Symbol.Index),
+uavs: std.array_hash_map.Auto(InternPool.Index, Symbol.Index),
lazy: std.EnumArray(link.File.LazySymbol.Kind, struct {
- map: std.AutoArrayHashMapUnmanaged(InternPool.Index, Symbol.Index),
+ map: std.array_hash_map.Auto(InternPool.Index, Symbol.Index),
pending_index: u32,
}),
-pending_uavs: std.AutoArrayHashMapUnmanaged(Node.UavMapIndex, struct {
+pending_uavs: std.array_hash_map.Auto(Node.UavMapIndex, struct {
alignment: InternPool.Alignment,
}),
relocs: std.ArrayList(Reloc),
+first_free_reloc: Reloc.Index,
+last_free_reloc: Reloc.Index,
const_prog_node: std.Progress.Node,
synth_prog_node: std.Progress.Node,
+symbol_prog_node: std.Progress.Node,
+member_prog_node: std.Progress.Node,
+input_prog_node: std.Progress.Node,
pub const default_file_alignment: u16 = 0x200;
pub const default_size_of_stack_reserve: u32 = 0x1000000;
@@ -54,6 +91,17 @@ pub const default_size_of_stack_commit: u32 = 0x1000;
pub const default_size_of_heap_reserve: u32 = 0x100000;
pub const default_size_of_heap_commit: u32 = 0x1000;
+pub const imp_prefix = "__imp_";
+
+const header_name_max_len = @typeInfo(@FieldType(std.coff.SectionHeader, "name")).array.len;
+
+const Error = link.Error || error{MappedFileIo};
+const LoadInputError = Error ||
+ Io.File.SeekError ||
+ Io.File.Reader.SizeError ||
+ Io.Reader.Error ||
+ MappedFile.Error;
+
/// This is the start of a Portable Executable (PE) file.
/// It starts with a MS-DOS header followed by a MS-DOS stub program.
/// This data does not change so we include it as follows in all binaries.
@@ -134,25 +182,53 @@ pub const msdos_stub: [120]u8 = .{
pub const Node = union(enum) {
file,
header,
+ /// Images and archives only.
signature,
+ /// Archives only.
+ archive_member_header: Member.Index,
+ archive_member: Member.Index,
+
coff_header,
+
+ /// Image only
optional_header,
data_directories,
+
section_table,
+
+ /// Archives and objects only
+ symbol_table,
+ string_table,
+ relocation_table: Symbol.SectionNumber,
+ relocation_table_entry: Reloc.Index,
+
image_section: Symbol.Index,
+ /// Images only
import_directory_table,
import_lookup_table: ImportTable.Index,
import_address_table: ImportTable.Index,
import_hint_name_table: ImportTable.Index,
+ /// Images only
+ export_directory_table,
+ export_address_table,
+ export_name_pointer_table,
+ export_ordinal_table,
+ export_name_table,
+
pseudo_section: PseudoSectionMapIndex,
object_section: ObjectSectionMapIndex,
- global: GlobalMapIndex,
+ input_section: InputSection.Index,
+ import_thunk: GlobalMapIndex,
nav: NavMapIndex,
uav: UavMapIndex,
lazy_code: LazyMapRef.Index(.code),
lazy_const_data: LazyMapRef.Index(.const_data),
+ builtin: Symbol.Index,
+
+ /// Takes the place of a known node index when that node is not present in the output
+ placeholder,
pub const PseudoSectionMapIndex = enum(u32) {
_,
@@ -179,14 +255,30 @@ pub const Node = union(enum) {
};
pub const GlobalMapIndex = enum(u32) {
+ none,
_,
- pub fn globalName(gmi: GlobalMapIndex, coff: *const Coff) GlobalName {
- return coff.globals.keys()[@intFromEnum(gmi)];
+ pub fn wrap(i: ?u32) GlobalMapIndex {
+ return @enumFromInt((i orelse return .none) + 1);
+ }
+
+ pub fn unwrap(gmi: GlobalMapIndex) ?u32 {
+ return switch (gmi) {
+ .none => null,
+ _ => @intFromEnum(gmi) - 1,
+ };
+ }
+
+ pub fn name(gmi: GlobalMapIndex, coff: *const Coff) String {
+ return coff.globals.keys()[gmi.unwrap().?];
}
pub fn symbol(gmi: GlobalMapIndex, coff: *const Coff) Symbol.Index {
- return coff.globals.values()[@intFromEnum(gmi)];
+ return coff.globals.values()[gmi.unwrap().?].si;
+ }
+
+ pub fn libName(gmi: GlobalMapIndex, coff: *const Coff) String.Optional {
+ return coff.globals.values()[gmi.unwrap().?].lib_name;
}
};
@@ -214,6 +306,47 @@ pub const Node = union(enum) {
}
};
+ const InputSection = struct {
+ ioi: InputObject.Index,
+ si: Symbol.Index,
+ comdat_si: Symbol.Index,
+ file_location: MappedFile.Node.FileLocation,
+ first_li: Node.InputSection.LocalIndex,
+ crc: u32,
+
+ pub const Index = enum(u32) {
+ _,
+
+ pub fn inputSection(isi: Index, coff: *const Coff) *InputSection {
+ return &coff.input_sections.items[@intFromEnum(isi)];
+ }
+
+ pub fn input(isi: Index, coff: *const Coff) InputObject.Index {
+ return coff.input_sections.items[@intFromEnum(isi)].ioi;
+ }
+
+ pub fn fileLocation(isi: Index, coff: *const Coff) MappedFile.Node.FileLocation {
+ return coff.input_sections.items[@intFromEnum(isi)].file_location;
+ }
+
+ pub fn symbol(isi: Index, coff: *const Coff) Symbol.Index {
+ return coff.input_sections.items[@intFromEnum(isi)].si;
+ }
+
+ pub fn firstSymbol(isi: Index, coff: *const Coff) LocalIndex {
+ return coff.input_sections.items[@intFromEnum(isi)].first_li;
+ }
+ };
+
+ const LocalIndex = enum(u32) {
+ _,
+
+ pub fn name(isli: LocalIndex, coff: *const Coff) String {
+ return coff.input_symbols.items[@intFromEnum(isli)].name;
+ }
+ };
+ };
+
pub const LazyMapRef = struct {
kind: link.File.LazySymbol.Kind,
index: u32,
@@ -253,6 +386,14 @@ pub const Node = union(enum) {
file,
header,
signature,
+ first_linker_member_header,
+ first_linker_member,
+ second_linker_member_header,
+ second_linker_member,
+ longnames_member_header,
+ longnames_member,
+ zcu_member_header,
+ zcu_member,
coff_header,
optional_header,
data_directories,
@@ -270,14 +411,338 @@ pub const Node = union(enum) {
}
};
+pub const InputArchive = struct {
+ path: std.Build.Cache.Path,
+
+ const Index = enum(u32) {
+ _,
+
+ pub fn path(iai: InputArchive.Index, coff: *Coff) std.Build.Cache.Path {
+ return coff.input_archives.items[@intFromEnum(iai)].path;
+ }
+ };
+
+ pub const Member = struct {
+ iai: InputArchive.Index,
+ name: String,
+ content: union(enum) {
+ // This range includes the member header
+ object: MappedFile.Node.FileLocation,
+ import: struct {
+ symbol_name: String,
+ lib_name: String,
+ // Either ordinal or hint, depending on value of name_type
+ import_ordinal_hint: u16,
+ type: std.coff.ImportType,
+ name_type: std.coff.ImportNameType,
+ },
+ },
+ flags: packed struct {
+ // Set if an attempt was made to load this member
+ is_loaded: bool,
+ },
+
+ const Index = enum(u32) {
+ _,
+
+ pub fn member(iami: InputArchive.Member.Index, coff: *Coff) *InputArchive.Member {
+ return &coff.input_archive_members.items[@intFromEnum(iami)];
+ }
+ };
+
+ pub const Symbol = struct {
+ iami: InputArchive.Member.Index,
+ // Set to its own index to indicate its the last in the list
+ next: InputArchive.Member.Symbol.Index,
+
+ const Index = enum(u32) {
+ _,
+ };
+ };
+ };
+
+ pub const SearchList = struct {
+ first: InputArchive.Member.Symbol.Index,
+ last: InputArchive.Member.Symbol.Index,
+ };
+};
+
+pub const InputObject = struct {
+ path: std.Build.Cache.Path,
+ member_name: ?[]const u8,
+ source_name: String.Optional,
+
+ pub const Index = enum(u32) {
+ _,
+
+ pub fn path(ioi: Index, coff: *const Coff) std.Build.Cache.Path {
+ return coff.input_objects.items[@intFromEnum(ioi)].path;
+ }
+
+ pub fn memberName(ioi: Index, coff: *const Coff) ?[]const u8 {
+ return coff.input_objects.items[@intFromEnum(ioi)].member_name;
+ }
+ };
+};
+
+pub const Member = struct {
+ kind: std.coff.ArchiveMemberHeader.Kind,
+ header_ni: MappedFile.Node.Index,
+ content_ni: MappedFile.Node.Index,
+ first_linker_indices: std.array_hash_map.Auto(struct {
+ mi: Member.Index,
+ name: String,
+ }, FirstLinkerIndex),
+
+ pub const Index = enum(u16) {
+ first,
+ second,
+ longnames,
+ _,
+
+ const known_count = @typeInfo(Index).@"enum".field_names.len;
+
+ pub fn get(member_index: Member.Index, coff: *Coff) *Member {
+ return &coff.members.items[@intFromEnum(member_index)];
+ }
+ };
+
+ pub const FirstLinkerIndex = enum(u32) {
+ _,
+ };
+
+ pub fn headerPtr(member: *Member, coff: *Coff) *std.coff.ArchiveMemberHeader {
+ return @ptrCast(@alignCast(member.header_ni.slice(&coff.mf)));
+ }
+
+ /// Sets `name` as the name field of this member's header, either directly (if it's short enough),
+ /// or by creating an entry in the longnames member and storing a reference to that entry.
+ pub fn initHeader(member: *Member, coff: *Coff, name: []const u8, timestamp: u32) !void {
+ const max_name_len = @typeInfo(@FieldType(std.coff.ArchiveMemberHeader, "name")).array.len;
+ const opt_name_offset = if (name.len >= max_name_len) offset: {
+ const gpa = coff.base.comp.gpa;
+ const entries_ctx = LongNamesTable.Adapter{ .coff = coff };
+ const gop = try coff.long_names_table.entries.getOrPutAdapted(
+ gpa,
+ name,
+ entries_ctx,
+ );
+
+ if (!gop.found_existing) {
+ errdefer _ = coff.export_table.entries.pop();
+
+ _, const old_size = Node.known.longnames_member.location(&coff.mf).resolve(&coff.mf);
+ const new_size = old_size + name.len + 1;
+ assert(new_size < comptime try std.math.powi(u64, 10, max_name_len - 1));
+
+ try Node.known.longnames_member.resize(&coff.mf, gpa, new_size);
+ const name_table_slice = Node.known.longnames_member.slice(&coff.mf);
+ const name_slice = name_table_slice[@intCast(old_size)..][0 .. name.len + 1];
+ @memcpy(name_slice[0..name.len], name);
+ name_slice[name.len] = 0;
+
+ gop.value_ptr.* = .{
+ .offset = old_size,
+ .len = name.len,
+ };
+ }
+
+ break :offset gop.value_ptr.offset;
+ } else null;
+
+ const header = member.headerPtr(coff);
+ if (opt_name_offset) |name_offset| {
+ header.name[0] = '/';
+ storeHeaderDecimalStr(header.name[1..], name_offset);
+ } else {
+ @memcpy(header.name[0..name.len], name);
+ header.name[name.len] = '/';
+ const padding = max_name_len - name.len - 1;
+ @memset(header.name[max_name_len - padding ..], ' ');
+ }
+
+ storeHeaderDecimalStr(&header.date, timestamp);
+
+ // Matching the Microsoft behaviour of emitting blanks for these fields
+ header.user_id = @splat(' ');
+ header.group_id = @splat(' ');
+
+ // file_mode is actually octal, but we only ever write 0 to it
+ storeHeaderDecimalStr(&header.file_mode, 0);
+ if (!member.content_ni.hasResized(&coff.mf))
+ storeHeaderDecimalStr(
+ &header.size,
+ member.content_ni.location(&coff.mf).resolve(&coff.mf)[1],
+ );
+
+ @memcpy(&header.end_of_header, std.coff.archive_end_of_header);
+ }
+
+ pub fn storeHeaderDecimalStr(field_ptr: anytype, value: u64) void {
+ const array_info = @typeInfo(@typeInfo(@TypeOf(field_ptr)).pointer.child).array;
+ assert(array_info.child == u8);
+ assert(value < comptime try std.math.powi(u64, 10, array_info.len));
+ _ = std.fmt.printInt(field_ptr, value, 10, .lower, .{
+ .width = array_info.len,
+ .alignment = .left,
+ .fill = ' ',
+ });
+ }
+
+ pub fn loadHeaderDecimalStr(field_ptr: anytype, value: u64) void {
+ const array_info = @typeInfo(@typeInfo(@TypeOf(field_ptr)).pointer.child).array;
+ assert(array_info.child == u8);
+ assert(value < comptime try std.math.powi(u64, 10, array_info.len));
+ _ = std.fmt.printInt(field_ptr, value, 10, .lower, .{
+ .width = array_info.len,
+ .alignment = .left,
+ .fill = ' ',
+ });
+ }
+};
+
+pub const LongNamesTable = struct {
+ ni: MappedFile.Node.Index = .none,
+ entries: std.array_hash_map.Auto(void, Entry),
+
+ pub const Entry = struct {
+ offset: u64,
+ len: u64,
+ };
+
+ const Adapter = struct {
+ coff: *Coff,
+
+ pub fn eql(adapter: Adapter, lhs_key: []const u8, _: void, rhs_index: usize) bool {
+ assert(adapter.coff.isArchive());
+ const longnames_slice = Node.known.longnames_member.slice(&adapter.coff.mf);
+ const rhs = adapter.coff.long_names_table.entries.values()[rhs_index];
+ return std.mem.eql(u8, longnames_slice[@intCast(rhs.offset)..][0..@intCast(rhs.len)], lhs_key);
+ }
+
+ pub fn hash(_: Adapter, key: []const u8) u32 {
+ assert(std.mem.indexOfScalar(u8, key, 0) == null);
+ return std.array_hash_map.hashString(key);
+ }
+ };
+};
+
+pub const SymbolTable = struct {
+ ni: MappedFile.Node.Index,
+ strings_ni: MappedFile.Node.Index,
+ strings: std.array_hash_map.Auto(String, StringIndex),
+ symbols: std.array_hash_map.Auto(Symbol.Index, SymbolTable.Index),
+ pending_symbol_index: u32,
+
+ // Resizing the symbol table node has the result of accumulating padding
+ // between the last symbol in the symbol table node and the start of the
+ // string table node, due to the shifting method when resizing the parent in MappedFile.
+ // The spec requires the string table begin immediately after the last symbol,
+ // so we compact the symbol table node and move the string table back if needed.
+ pending_shrink: bool,
+
+ pub const StringIndex = enum(u32) {
+ _,
+ };
+
+ pub const SymbolName = union(enum) {
+ short: []const u8,
+ long: StringIndex,
+
+ pub fn store(name: SymbolName, coff: *const Coff, field: *[8]u8) void {
+ switch (name) {
+ .short => |s| {
+ @memcpy(field[0..s.len], s);
+ @memset(field[s.len..], 0);
+ },
+ .long => |l| {
+ @memset(field[0..4], 0);
+ std.mem.writePackedInt(u32, field[4..], 0, @intFromEnum(l), coff.targetEndian());
+ },
+ }
+ }
+ };
+
+ // Symbol.Index does not map 1:1 with SymbolTable.Index:
+ // - Not all symbols need a symbol table entry
+ // - A variable number of auxiliary entries may trail each symbol
+ pub const Index = enum(u32) {
+ none,
+ _,
+
+ pub fn wrap(i: u32) Index {
+ return @enumFromInt(i + 1);
+ }
+
+ pub fn unwrap(sti: Index) ?u32 {
+ return switch (sti) {
+ .none => null,
+ _ => @intFromEnum(sti) - 1,
+ };
+ }
+ };
+};
+
+pub const ExportTable = struct {
+ ni: MappedFile.Node.Index,
+ export_directory_table_ni: MappedFile.Node.Index,
+ export_address_table_si: Symbol.Index,
+ name_pointer_table_ni: MappedFile.Node.Index,
+ ordinal_table_ni: MappedFile.Node.Index,
+ name_table_ni: MappedFile.Node.Index,
+ entries: std.array_hash_map.Auto(void, Entry),
+ pending_sort: bool = false,
+
+ pub const Entry = struct {
+ si: Symbol.Index,
+ name_index: u32,
+ name_len: u32,
+ export_address_table_ri: Reloc.Index,
+ };
+
+ const Adapter = struct {
+ coff: *Coff,
+
+ pub fn eql(adapter: Adapter, lhs_key: []const u8, _: void, rhs_index: usize) bool {
+ const coff = adapter.coff;
+ const name_table_slice = coff.export_table.name_table_ni.slice(&coff.mf);
+ const rhs = coff.export_table.entries.values()[rhs_index];
+ return std.mem.eql(u8, name_table_slice[rhs.name_index..][0..rhs.name_len], lhs_key);
+ }
+
+ pub fn hash(_: Adapter, key: []const u8) u32 {
+ assert(std.mem.indexOfScalar(u8, key, 0) == null);
+ return std.array_hash_map.hashString(key);
+ }
+ };
+
+ pub const Ordinal = enum(u16) {
+ _,
+
+ pub fn get(export_index: ExportTable.Ordinal, coff: *Coff) *Entry {
+ return &coff.export_table.entries.values()[@intFromEnum(export_index)];
+ }
+ };
+};
+
pub const ImportTable = struct {
ni: MappedFile.Node.Index,
- entries: std.AutoArrayHashMapUnmanaged(void, Entry),
+ entries: std.array_hash_map.Auto(void, Entry),
+ iat_symbol_indices: std.array_hash_map.Auto(struct {
+ iti: ImportTable.Index,
+ name: String.Optional,
+ // If name == .none this is the ordinal, otherwise the hint
+ ordinal_hint: u16,
+ }, u32),
pub const Entry = struct {
import_lookup_table_ni: MappedFile.Node.Index,
import_address_table_si: Symbol.Index,
import_hint_name_table_ni: MappedFile.Node.Index,
+ // All .iat_ptr globals that reference this table.
+ // This is separate from `iat_symbol_indices` because multiple symbols
+ // can reference to the same iat entry, after name demangling.
+ import_address_table_symbols: std.ArrayList(Symbol.Index),
len: u32,
hint_name_len: u32,
};
@@ -314,13 +779,32 @@ pub const String = enum(u32) {
@".rdata" = 13,
@".text" = 20,
@".tls$" = 26,
+ @".edata" = 32,
+ @".ctors" = 39,
+ @".ctors$ZZZ" = 46,
+ @".dtors" = 57,
+ @".dtors$ZZZ" = 64,
+ @".bss" = 75,
+ @".fptable" = 80,
+ @".tls" = 89,
+ @".thunks" = 94,
_,
pub const Optional = enum(u32) {
@".data" = @intFromEnum(String.@".data"),
+ @".idata" = @intFromEnum(String.@".idata"),
@".rdata" = @intFromEnum(String.@".rdata"),
@".text" = @intFromEnum(String.@".text"),
@".tls$" = @intFromEnum(String.@".tls$"),
+ @".edata" = @intFromEnum(String.@".edata"),
+ @".ctors" = @intFromEnum(String.@".ctors"),
+ @".ctors$ZZZ" = @intFromEnum(String.@".ctors$ZZZ"),
+ @".dtors" = @intFromEnum(String.@".dtors"),
+ @".dtors$ZZZ" = @intFromEnum(String.@".dtors$ZZZ"),
+ @".bss" = @intFromEnum(String.@".bss"),
+ @".fptable" = @intFromEnum(String.@".fptable"),
+ @".tls" = @intFromEnum(String.@".tls"),
+ @".thunks" = @intFromEnum(String.@".thunks"),
none = std.math.maxInt(u32),
_,
@@ -346,20 +830,176 @@ pub const String = enum(u32) {
}
};
-pub const GlobalName = struct { name: String, lib_name: String.Optional };
+pub const Section = struct {
+ si: Symbol.Index,
+ relocation_table_ni: MappedFile.Node.Index,
+
+ pub const RelocationIndex = enum(u16) {
+ none,
+ _,
+
+ pub fn wrap(i: ?u16) RelocationIndex {
+ return @enumFromInt((i orelse return .none) + 1);
+ }
+
+ pub fn unwrap(sri: RelocationIndex) ?u16 {
+ return switch (sri) {
+ .none => null,
+ _ => @intFromEnum(sri) - 1,
+ };
+ }
+
+ pub fn entry(
+ sri: RelocationIndex,
+ coff: *Coff,
+ sn: Symbol.SectionNumber,
+ ) ?*align(2) std.coff.Relocation {
+ if (sri == .none) return null;
+ const table_slice = sn.section(coff).relocation_table_ni.slice(&coff.mf);
+ return @ptrCast(@alignCast(&table_slice[@as(u32, sri.unwrap().?) * std.coff.Relocation.sizeOf()]));
+ }
+ };
+};
+
+pub const Global = struct {
+ si: Symbol.Index,
+ lib_name: String.Optional,
+};
+
+pub const WeakExternalStrat = enum(u3) {
+ none,
+ no_library,
+ library,
+ alias,
+ anti_dependency,
+
+ pub fn fromFlag(flag: std.coff.WeakExternalFlag) WeakExternalStrat {
+ return switch (flag) {
+ .SEARCH_NOLIBRARY => .no_library,
+ .SEARCH_LIBRARY => .library,
+ .SEARCH_ALIAS => .alias,
+ .ANTI_DEPENDENCY => .anti_dependency,
+ _ => unreachable,
+ };
+ }
+};
+
+const SpecialSymbol = enum {
+ entry,
+ tls,
+ none,
+};
pub const Symbol = struct {
ni: MappedFile.Node.Index,
rva: u32,
- size: u32,
+ value: std.meta.BareUnion(Symbol.Value),
+ extra: std.meta.BareUnion(Symbol.Extra),
+ flags: packed struct(u16) {
+ value_tag: ValueTag,
+ extra_tag: ExtraTag,
+ type: Symbol.Type,
+ dll_storage_class: DllStorageClass,
+ weak_external_strat: WeakExternalStrat,
+ _: u5 = 0,
+ },
/// Relocations contained within this symbol
loc_relocs: Reloc.Index,
/// Relocations targeting this symbol
target_relocs: Reloc.Index,
section_number: SectionNumber,
- unused0: u32 = 0,
- unused1: u32 = 0,
- unused2: u16 = 0,
+ gmi: Node.GlobalMapIndex,
+
+ pub const DllStorageClass = enum(u2) {
+ default,
+ dllimport,
+ dllexport,
+ };
+
+ pub const Type = enum(u2) {
+ unknown,
+ code,
+ data,
+ };
+
+ const ValueTag = enum(u2) {
+ none,
+ node_offset,
+ weak_alias_si,
+ weak_alias_name,
+ };
+
+ pub const Value = union(ValueTag) {
+ none,
+ /// The offset of the symbol within its node. Used with symbols that
+ /// don't create their own nodes: .input_section, .import_address_table
+ /// Images only.
+ node_offset: u32,
+ /// Images: the weak alias that should replace this symbol if it is not resolved.
+ /// Objects: he target of a weak external that hasn't been assigned an sti yet.
+ /// Globals only.
+ weak_alias_si: Symbol.Index,
+ /// For weak externals that have an alias that is also an undef
+ /// external, this is the name of the alias global that should
+ /// be generated and resolved if this symbol is not resolved.
+ /// Globals only, images only.
+ weak_alias_name: String,
+ };
+
+ const ExtraTag = enum(u2) {
+ size,
+ isli,
+ next_alias_si,
+ };
+
+ pub const Extra = union(ExtraTag) {
+ // The size of the symbol
+ size: u32,
+ /// Only valid when .ni == .input_section and .value_tag == .node_offset
+ isli: Node.InputSection.LocalIndex,
+ /// The next symbol in the list of aliases of this symbol.
+ next_alias_si: Symbol.Index,
+ };
+
+ pub fn setValue(sym: *Symbol, value: Symbol.Value) void {
+ sym.flags.value_tag = std.meta.activeTag(value);
+ sym.value = switch (sym.flags.value_tag) {
+ inline else => |t| @unionInit(
+ @FieldType(Symbol, "value"),
+ @tagName(t),
+ @field(value, @tagName(t)),
+ ),
+ };
+ }
+
+ pub fn setExtra(sym: *Symbol, extra: Symbol.Extra) void {
+ sym.flags.extra_tag = std.meta.activeTag(extra);
+ sym.extra = switch (sym.flags.extra_tag) {
+ inline else => |t| @unionInit(
+ @FieldType(Symbol, "extra"),
+ @tagName(t),
+ @field(extra, @tagName(t)),
+ ),
+ };
+ }
+
+ pub fn nodeOffset(sym: *const Symbol, coff: *Coff) u32 {
+ return switch (sym.flags.value_tag) {
+ .node_offset => offset: {
+ assert(switch (coff.getNode(sym.ni)) {
+ // Separate nodes are not created for these entries per-symbol
+ .input_section, .import_address_table => true,
+ else => false,
+ });
+ break :offset sym.value.node_offset;
+ },
+ else => 0,
+ };
+ }
+
+ pub fn size(sym: *const Symbol) u32 {
+ return if (sym.flags.extra_tag == .size) sym.extra.size else 0;
+ }
pub const SectionNumber = enum(i16) {
UNDEFINED = 0,
@@ -371,8 +1011,20 @@ pub const Symbol = struct {
return @intCast(@intFromEnum(sn) - 1);
}
+ fn hasIndex(sn: SectionNumber) bool {
+ return @intFromEnum(sn) > 0;
+ }
+
pub fn symbol(sn: SectionNumber, coff: *const Coff) Symbol.Index {
- return coff.image_section_table.items[sn.toIndex()];
+ return sn.section(coff).si;
+ }
+
+ pub fn name(sn: SectionNumber, coff: *const Coff) String {
+ return coff.section_table.keys()[sn.toIndex()];
+ }
+
+ pub fn section(sn: SectionNumber, coff: *const Coff) *Section {
+ return &coff.section_table.values()[sn.toIndex()];
}
pub fn header(sn: SectionNumber, coff: *Coff) *std.coff.SectionHeader {
@@ -382,6 +1034,7 @@ pub const Symbol = struct {
pub const Index = enum(u32) {
null,
+ bss,
data,
rdata,
text,
@@ -390,7 +1043,12 @@ pub const Symbol = struct {
const known_count = @typeInfo(Index).@"enum".field_names.len;
pub fn get(si: Symbol.Index, coff: *Coff) *Symbol {
- return &coff.symbol_table.items[@intFromEnum(si)];
+ return &coff.symbols.items[@intFromEnum(si)];
+ }
+
+ pub fn unwrap(si: Symbol.Index) ?Symbol.Index {
+ if (si == .null) return null;
+ return si;
}
pub fn node(si: Symbol.Index, coff: *Coff) MappedFile.Node.Index {
@@ -399,37 +1057,92 @@ pub const Symbol = struct {
return ni;
}
- pub fn flushMoved(si: Symbol.Index, coff: *Coff) void {
+ pub fn sti(si: Symbol.Index, coff: *Coff) SymbolTable.Index {
+ assert(!coff.isImage());
+ return coff.symbol_table.symbols.get(si) orelse .none;
+ }
+
+ pub fn next(si: Symbol.Index) Symbol.Index {
+ return @enumFromInt(@intFromEnum(si) + 1);
+ }
+
+ pub fn knownString(si: Symbol.Index) String.Optional {
+ return switch (si) {
+ .null, _ => .none,
+ inline else => |tag| @field(String.Optional, "." ++ @tagName(tag)),
+ };
+ }
+
+ pub fn flushMoved(si: Symbol.Index, coff: *Coff) !void {
const sym = si.get(coff);
- sym.rva = coff.computeNodeRva(sym.ni);
- si.applyLocationRelocs(coff);
- si.applyTargetRelocs(coff);
- }
+ sym.rva = coff.computeNodeRva(sym.ni) + sym.nodeOffset(coff);
+ try si.applyLocationRelocs(coff);
+ try si.applyTargetRelocs(coff, .none);
- pub fn applyLocationRelocs(si: Symbol.Index, coff: *Coff) void {
- for (coff.relocs.items[@intFromEnum(si.get(coff).loc_relocs)..]) |*reloc| {
- if (reloc.loc != si) break;
- reloc.apply(coff);
+ var alias_sym = sym;
+ while (alias_sym.flags.extra_tag == .next_alias_si) {
+ const alias_si = alias_sym.extra.next_alias_si;
+ alias_sym = alias_si.get(coff);
+ assert(alias_sym.ni == sym.ni);
+ alias_sym.rva = sym.rva;
+ try alias_si.applyTargetRelocs(coff, .none);
}
}
- pub fn applyTargetRelocs(si: Symbol.Index, coff: *Coff) void {
- var ri = si.get(coff).target_relocs;
+ pub fn flushSymbolTableIndex(si: Symbol.Index, coff: *Coff) void {
+ const sym = si.get(coff);
+ const index = si.sti(coff).unwrap().?;
+ var ri = sym.target_relocs;
while (ri != .none) {
const reloc = ri.get(coff);
assert(reloc.target == si);
- reloc.apply(coff);
+ if (reloc.sri.entry(coff, reloc.loc.get(coff).section_number)) |entry|
+ coff.targetStore(&entry.symbol_table_index, index);
+ ri = reloc.next;
+ }
+ }
+
+ pub fn applyLocationRelocs(si: Symbol.Index, coff: *Coff) !void {
+ const sym = si.get(coff);
+ switch (sym.loc_relocs) {
+ .none => {},
+ else => |loc_relocs| {
+ for (coff.relocs.items[@intFromEnum(loc_relocs)..]) |*reloc| {
+ if (reloc.loc != si) break;
+ if (reloc.sri.entry(coff, sym.section_number)) |entry| coff.targetStore(
+ &entry.virtual_address,
+ @intCast(coff.computeSymbolSectionOffset(sym, .image) + reloc.offset),
+ );
+ try reloc.apply(coff);
+ }
+ },
+ }
+ }
+
+ pub fn applyTargetRelocs(si: Symbol.Index, coff: *Coff, end: Reloc.Index) !void {
+ const sym = si.get(coff);
+
+ var ri = sym.target_relocs;
+ while (ri != end) {
+ const reloc = ri.get(coff);
+ assert(reloc.target == si);
+ try reloc.apply(coff);
ri = reloc.next;
}
}
pub fn deleteLocationRelocs(si: Symbol.Index, coff: *Coff) void {
const sym = si.get(coff);
- for (coff.relocs.items[@intFromEnum(sym.loc_relocs)..]) |*reloc| {
- if (reloc.loc != si) break;
- reloc.delete(coff);
+ switch (sym.loc_relocs) {
+ .none => {},
+ else => |loc_relocs| {
+ for (coff.relocs.items[@intFromEnum(loc_relocs)..]) |*reloc| {
+ if (reloc.loc != si) break;
+ reloc.delete(coff);
+ }
+ sym.loc_relocs = .none;
+ },
}
- sym.loc_relocs = .none;
}
};
@@ -439,14 +1152,24 @@ pub const Symbol = struct {
};
pub const Reloc = extern struct {
+ offset: u64,
+ addend: i64,
type: Reloc.Type,
+ sri: Section.RelocationIndex,
prev: Reloc.Index,
next: Reloc.Index,
loc: Symbol.Index,
target: Symbol.Index,
- unused: u32,
- offset: u64,
- addend: i64,
+ flags: packed struct(u8) {
+ /// Indicates the addend is not known and should be recovered from the location itself.
+ /// COFF relocation tables don't encode the addend, only the location.
+ recover_addend: bool,
+ /// Set if this reloc is in the free list.
+ /// When set, `prev` / `next` refer to other relocs in the free list.
+ /// All other fields are undefined.
+ free: bool,
+ _: u6 = 0,
+ },
pub const Type = extern union {
AMD64: std.coff.IMAGE.REL.AMD64,
@@ -458,141 +1181,326 @@ pub const Reloc = extern struct {
IA64: std.coff.IMAGE.REL.IA64,
MIPS: std.coff.IMAGE.REL.MIPS,
M32R: std.coff.IMAGE.REL.M32R,
+ u16: u16,
};
pub const Index = enum(u32) {
none = std.math.maxInt(u32),
_,
- pub fn get(si: Reloc.Index, coff: *Coff) *Reloc {
- return &coff.relocs.items[@intFromEnum(si)];
+ pub fn wrap(i: ?u32) Reloc.Index {
+ return @enumFromInt((i orelse return .none) + 1);
+ }
+
+ pub fn get(ri: Reloc.Index, coff: *Coff) *Reloc {
+ return &coff.relocs.items[@intFromEnum(ri)];
}
};
- pub fn apply(reloc: *const Reloc, coff: *Coff) void {
+ pub fn apply(reloc: *Reloc, coff: *Coff) !void {
const loc_sym = reloc.loc.get(coff);
switch (loc_sym.ni) {
.none => return,
else => |ni| if (ni.hasMoved(&coff.mf)) return,
}
- const target_sym = reloc.target.get(coff);
- switch (target_sym.ni) {
- .none => return,
- else => |ni| if (ni.hasMoved(&coff.mf)) return,
- }
+
const loc_slice = loc_sym.ni.slice(&coff.mf)[@intCast(reloc.offset)..];
+ const target_endian = coff.targetEndian();
+ const target_machine = coff.targetLoad(&coff.headerPtr().machine);
+
+ if (!coff.isImage()) {
+ assert(!reloc.flags.recover_addend);
+ switch (target_machine) {
+ else => |machine| @panic(@tagName(machine)),
+ .AMD64 => switch (reloc.type.AMD64) {
+ else => |kind| @panic(@tagName(kind)),
+ .ABSOLUTE => {},
+ .ADDR64 => std.mem.writeInt(
+ u64,
+ loc_slice[0..8],
+ @intCast(reloc.addend),
+ target_endian,
+ ),
+ .ADDR32,
+ .ADDR32NB,
+ .SECREL,
+ => std.mem.writeInt(
+ u32,
+ loc_slice[0..4],
+ @intCast(reloc.addend),
+ target_endian,
+ ),
+ .REL32,
+ .REL32_1,
+ .REL32_2,
+ .REL32_3,
+ .REL32_4,
+ .REL32_5,
+ => std.mem.writeInt(
+ i32,
+ loc_slice[0..4],
+ @intCast(reloc.addend),
+ target_endian,
+ ),
+ },
+ .I386 => switch (reloc.type.I386) {
+ else => |kind| @panic(@tagName(kind)),
+ .ABSOLUTE => {},
+ .DIR16,
+ => std.mem.writeInt(
+ u16,
+ loc_slice[0..2],
+ @intCast(reloc.addend),
+ target_endian,
+ ),
+ .REL16,
+ => std.mem.writeInt(
+ i16,
+ loc_slice[0..2],
+ @intCast(reloc.addend),
+ target_endian,
+ ),
+ .DIR32,
+ .DIR32NB,
+ .SECREL,
+ => std.mem.writeInt(
+ u32,
+ loc_slice[0..4],
+ @intCast(reloc.addend),
+ target_endian,
+ ),
+ .REL32,
+ => std.mem.writeInt(
+ i32,
+ loc_slice[0..4],
+ @intCast(reloc.addend),
+ target_endian,
+ ),
+ },
+ }
+
+ return;
+ } else if (reloc.flags.recover_addend) {
+ reloc.flags.recover_addend = false;
+ reloc.addend = switch (target_machine) {
+ else => |machine| @panic(@tagName(machine)),
+ .AMD64 => switch (reloc.type.AMD64) {
+ else => |kind| @panic(@tagName(kind)),
+ .ABSOLUTE => 0,
+ .ADDR64 => @bitCast(std.mem.readInt(
+ u64,
+ loc_slice[0..8],
+ target_endian,
+ )),
+ .ADDR32,
+ .ADDR32NB,
+ .SECREL,
+ .REL32,
+ .REL32_1,
+ .REL32_2,
+ .REL32_3,
+ .REL32_4,
+ .REL32_5,
+ => std.mem.readInt(
+ i32,
+ loc_slice[0..4],
+ target_endian,
+ ),
+ },
+ .I386 => switch (reloc.type.I386) {
+ else => |kind| @panic(@tagName(kind)),
+ .ABSOLUTE => 0,
+ .DIR16,
+ .REL16,
+ => std.mem.readInt(
+ i16,
+ loc_slice[0..2],
+ target_endian,
+ ),
+ .DIR32,
+ .DIR32NB,
+ .SECREL,
+ .REL32,
+ => std.mem.readInt(
+ i32,
+ loc_slice[0..4],
+ target_endian,
+ ),
+ },
+ };
+ }
+
+ const target_sym = reloc.target.get(coff);
+ const is_abs = switch (target_sym.ni) {
+ .none => if (target_sym.section_number == .ABSOLUTE) true else return,
+ else => |ni| if (ni.hasMoved(&coff.mf)) return else false,
+ };
+
const target_rva = target_sym.rva +% @as(u64, @bitCast(reloc.addend));
- const target_endian = coff.targetEndian();
- switch (coff.targetLoad(&coff.headerPtr().machine)) {
- else => |machine| @panic(@tagName(machine)),
- .AMD64 => switch (reloc.type.AMD64) {
- else => |kind| @panic(@tagName(kind)),
- .ABSOLUTE => {},
- .ADDR64 => std.mem.writeInt(
- u64,
- loc_slice[0..8],
- coff.optionalHeaderField(.image_base) + target_rva,
- target_endian,
- ),
- .ADDR32 => std.mem.writeInt(
- u32,
- loc_slice[0..4],
- @intCast(coff.optionalHeaderField(.image_base) + target_rva),
- target_endian,
- ),
- .ADDR32NB => std.mem.writeInt(
- u32,
- loc_slice[0..4],
- @intCast(target_rva),
- target_endian,
- ),
- .REL32 => std.mem.writeInt(
- i32,
- loc_slice[0..4],
- @intCast(@as(i64, @bitCast(target_rva -% (loc_sym.rva + reloc.offset + 4)))),
- target_endian,
- ),
- .REL32_1 => std.mem.writeInt(
- i32,
- loc_slice[0..4],
- @intCast(@as(i64, @bitCast(target_rva -% (loc_sym.rva + reloc.offset + 5)))),
- target_endian,
- ),
- .REL32_2 => std.mem.writeInt(
- i32,
- loc_slice[0..4],
- @intCast(@as(i64, @bitCast(target_rva -% (loc_sym.rva + reloc.offset + 6)))),
- target_endian,
- ),
- .REL32_3 => std.mem.writeInt(
- i32,
- loc_slice[0..4],
- @intCast(@as(i64, @bitCast(target_rva -% (loc_sym.rva + reloc.offset + 7)))),
- target_endian,
- ),
- .REL32_4 => std.mem.writeInt(
- i32,
- loc_slice[0..4],
- @intCast(@as(i64, @bitCast(target_rva -% (loc_sym.rva + reloc.offset + 8)))),
- target_endian,
- ),
- .REL32_5 => std.mem.writeInt(
- i32,
- loc_slice[0..4],
- @intCast(@as(i64, @bitCast(target_rva -% (loc_sym.rva + reloc.offset + 9)))),
- target_endian,
- ),
- .SECREL => std.mem.writeInt(
- u32,
- loc_slice[0..4],
- coff.computeNodeSectionOffset(target_sym.ni),
- target_endian,
- ),
- },
- .I386 => switch (reloc.type.I386) {
- else => |kind| @panic(@tagName(kind)),
- .ABSOLUTE => {},
- .DIR16 => std.mem.writeInt(
- u16,
- loc_slice[0..2],
- @intCast(coff.optionalHeaderField(.image_base) + target_rva),
- target_endian,
- ),
- .REL16 => std.mem.writeInt(
- i16,
- loc_slice[0..2],
- @intCast(@as(i64, @bitCast(target_rva -% (loc_sym.rva + reloc.offset + 2)))),
- target_endian,
- ),
- .DIR32 => std.mem.writeInt(
- u32,
- loc_slice[0..4],
- @intCast(coff.optionalHeaderField(.image_base) + target_rva),
- target_endian,
- ),
- .DIR32NB => std.mem.writeInt(
- u32,
- loc_slice[0..4],
- @intCast(target_rva),
- target_endian,
- ),
- .REL32 => std.mem.writeInt(
- i32,
- loc_slice[0..4],
- @intCast(@as(i64, @bitCast(target_rva -% (loc_sym.rva + reloc.offset + 4)))),
- target_endian,
- ),
- .SECREL => std.mem.writeInt(
- u32,
- loc_slice[0..4],
- coff.computeNodeSectionOffset(target_sym.ni),
- target_endian,
- ),
- },
+ if (is_abs) {
+ switch (target_machine) {
+ else => |machine| @panic(@tagName(machine)),
+ .AMD64 => switch (reloc.type.AMD64) {
+ // TODO: Could wait to report these later, in reportUndefs -> reportRelocErrs,
+ // so that this function doesn't return an err
+ else => |kind| return coff.base.comp.link_diags.fail(
+ "absolute symbol '{s}' targeted by invalid relocation type: {t}",
+ .{ target_sym.gmi.name(coff).toSlice(coff), kind },
+ ),
+ .ABSOLUTE => {},
+ .ADDR64 => std.mem.writeInt(
+ u64,
+ loc_slice[0..8],
+ target_rva,
+ target_endian,
+ ),
+ .ADDR32 => std.mem.writeInt(
+ u32,
+ loc_slice[0..4],
+ @intCast(target_rva),
+ target_endian,
+ ),
+ },
+ .I386 => switch (reloc.type.I386) {
+ else => |kind| return coff.base.comp.link_diags.fail(
+ "absolute symbol '{s}' targeted by invalid relocation type: {t}",
+ .{ target_sym.gmi.name(coff).toSlice(coff), kind },
+ ),
+ .ABSOLUTE => {},
+ .DIR16 => std.mem.writeInt(
+ u16,
+ loc_slice[0..2],
+ @intCast(target_rva),
+ target_endian,
+ ),
+ .DIR32 => std.mem.writeInt(
+ u32,
+ loc_slice[0..4],
+ @intCast(target_rva),
+ target_endian,
+ ),
+ },
+ }
+ } else {
+ switch (target_machine) {
+ else => |machine| @panic(@tagName(machine)),
+ .AMD64 => switch (reloc.type.AMD64) {
+ else => |kind| @panic(@tagName(kind)),
+ .ABSOLUTE => {},
+ .ADDR64 => std.mem.writeInt(
+ u64,
+ loc_slice[0..8],
+ coff.optionalHeaderField(.image_base) + target_rva,
+ target_endian,
+ ),
+ .ADDR32 => std.mem.writeInt(
+ u32,
+ loc_slice[0..4],
+ @intCast(coff.optionalHeaderField(.image_base) + target_rva),
+ target_endian,
+ ),
+ .ADDR32NB => std.mem.writeInt(
+ u32,
+ loc_slice[0..4],
+ @intCast(target_rva),
+ target_endian,
+ ),
+ .REL32 => std.mem.writeInt(
+ i32,
+ loc_slice[0..4],
+ @intCast(@as(i64, @bitCast(target_rva -% (loc_sym.rva + reloc.offset + 4)))),
+ target_endian,
+ ),
+ .REL32_1 => std.mem.writeInt(
+ i32,
+ loc_slice[0..4],
+ @intCast(@as(i64, @bitCast(target_rva -% (loc_sym.rva + reloc.offset + 5)))),
+ target_endian,
+ ),
+ .REL32_2 => std.mem.writeInt(
+ i32,
+ loc_slice[0..4],
+ @intCast(@as(i64, @bitCast(target_rva -% (loc_sym.rva + reloc.offset + 6)))),
+ target_endian,
+ ),
+ .REL32_3 => std.mem.writeInt(
+ i32,
+ loc_slice[0..4],
+ @intCast(@as(i64, @bitCast(target_rva -% (loc_sym.rva + reloc.offset + 7)))),
+ target_endian,
+ ),
+ .REL32_4 => std.mem.writeInt(
+ i32,
+ loc_slice[0..4],
+ @intCast(@as(i64, @bitCast(target_rva -% (loc_sym.rva + reloc.offset + 8)))),
+ target_endian,
+ ),
+ .REL32_5 => std.mem.writeInt(
+ i32,
+ loc_slice[0..4],
+ @intCast(@as(i64, @bitCast(target_rva -% (loc_sym.rva + reloc.offset + 9)))),
+ target_endian,
+ ),
+ .SECREL => std.mem.writeInt(
+ u32,
+ loc_slice[0..4],
+ @intCast(coff.computeSymbolSectionOffset(target_sym, .pseudo) + reloc.addend),
+ target_endian,
+ ),
+ },
+ .I386 => switch (reloc.type.I386) {
+ else => |kind| @panic(@tagName(kind)),
+ .ABSOLUTE => {},
+ .DIR16 => std.mem.writeInt(
+ u16,
+ loc_slice[0..2],
+ @intCast(coff.optionalHeaderField(.image_base) + target_rva),
+ target_endian,
+ ),
+ .REL16 => std.mem.writeInt(
+ i16,
+ loc_slice[0..2],
+ @intCast(@as(i64, @bitCast(target_rva -% (loc_sym.rva + reloc.offset + 2)))),
+ target_endian,
+ ),
+ .DIR32 => std.mem.writeInt(
+ u32,
+ loc_slice[0..4],
+ @intCast(coff.optionalHeaderField(.image_base) + target_rva),
+ target_endian,
+ ),
+ .DIR32NB => std.mem.writeInt(
+ u32,
+ loc_slice[0..4],
+ @intCast(target_rva),
+ target_endian,
+ ),
+ .REL32 => std.mem.writeInt(
+ i32,
+ loc_slice[0..4],
+ @intCast(@as(i64, @bitCast(target_rva -% (loc_sym.rva + reloc.offset + 4)))),
+ target_endian,
+ ),
+ .SECREL => std.mem.writeInt(
+ u32,
+ loc_slice[0..4],
+ @intCast(coff.computeSymbolSectionOffset(target_sym, .pseudo) + reloc.addend),
+ target_endian,
+ ),
+ },
+ }
}
}
pub fn delete(reloc: *Reloc, coff: *Coff) void {
+ if (reloc.sri != .none) {
+ // TODO: Need to remove this from the COFF relocation table (maybe removeswap?)
+ // TODO: If this was the last reloc causing something to be in the symbol table, we should remove
+ // the symbol table entry (and unset sti). That will require flushSymbolTableIndex on the
+ // swapped symbol if we exchange indices
+ @panic("TODO implement symbol table reloc deletions");
+ }
+
switch (reloc.prev) {
.none => {
const target = reloc.target.get(coff);
@@ -605,7 +1513,24 @@ pub const Reloc = extern struct {
.none => {},
else => |next| next.get(coff).prev = reloc.prev,
}
+
reloc.* = undefined;
+ reloc.flags = .{
+ .recover_addend = false,
+ .free = true,
+ };
+
+ const ri: Reloc.Index = .wrap(@intCast(reloc - coff.relocs.items.ptr));
+ if (coff.last_free_reloc == .none) {
+ assert(coff.first_free_reloc == .none);
+ coff.first_free_reloc = ri;
+ coff.last_free_reloc = ri;
+ } else {
+ coff.last_free_reloc.get(coff).next = ri;
+ reloc.prev = coff.last_free_reloc;
+ reloc.next = .none;
+ coff.last_free_reloc = ri;
+ }
}
comptime {
@@ -639,14 +1564,6 @@ fn create(
assert(target.ofmt == .coff);
if (target.cpu.arch.endian() != comptime targetEndian(undefined))
return error.UnsupportedCOFFArchitecture;
- const is_image = switch (comp.config.output_mode) {
- .Exe => true,
- .Lib => switch (comp.config.link_mode) {
- .static => false,
- .dynamic => true,
- },
- .Obj => false,
- };
const machine = target.toCoffMachine();
const timestamp: u32 = 0;
const major_subsystem_version = options.major_subsystem_version orelse 6;
@@ -689,18 +1606,61 @@ fn create(
.allow_shlib_undefined = false,
.stack_size = 0,
},
+ .options = options,
.mf = try .init(file, comp.gpa, io),
.nodes = .empty,
+ .members = .empty,
+ .pending_members = .empty,
+ .lib_string_table = .empty,
+ .lib_string_len = 0,
+ .long_names_table = .{
+ .entries = .empty,
+ },
.import_table = .{
.ni = .none,
.entries = .empty,
+ .iat_symbol_indices = .empty,
},
+ .export_table = .{
+ .ni = .none,
+ .export_directory_table_ni = .none,
+ .export_address_table_si = .null,
+ .name_pointer_table_ni = .none,
+ .ordinal_table_ni = .none,
+ .name_table_ni = .none,
+ .entries = .empty,
+ },
+ .symbol_table = .{
+ .ni = .none,
+ .strings_ni = .none,
+ .strings = .empty,
+ .symbols = .empty,
+ .pending_symbol_index = 0,
+ .pending_shrink = false,
+ },
+ .inputs = .empty,
+ .input_archives = .empty,
+ .input_archive_members = .empty,
+ .input_archive_symbols = .empty,
+ .input_archive_symbol_indices = .empty,
+ .pending_input = null,
+ .pending_default_libs = .empty,
+ .alternate_names = .empty,
+ .input_objects = .empty,
+ .input_symbols = .empty,
+ .input_sections = .empty,
+ .input_section_pending_index = 0,
+ .inputs_complete = false,
+ .exports_complete = false,
+ .pending_special_symbol = .entry,
.strings = .empty,
.string_bytes = .empty,
- .image_section_table = .empty,
+ .section_table = .empty,
.pseudo_section_table = .empty,
.object_section_table = .empty,
- .symbol_table = .empty,
+ .section_merges = .empty,
+ .section_merge_pending_index = 0,
+ .symbols = .empty,
.globals = .empty,
.global_pending_index = 0,
.navs = .empty,
@@ -711,8 +1671,13 @@ fn create(
}),
.pending_uavs = .empty,
.relocs = .empty,
+ .first_free_reloc = .none,
+ .last_free_reloc = .none,
.const_prog_node = .none,
.synth_prog_node = .none,
+ .symbol_prog_node = .none,
+ .member_prog_node = .none,
+ .input_prog_node = .none,
};
errdefer coff.deinit();
@@ -725,14 +1690,20 @@ fn create(
}
try coff.initHeaders(
- is_image,
machine,
timestamp,
major_subsystem_version,
minor_subsystem_version,
magic,
+ if (options.subsystem) |s| switch (s) {
+ .console => .WINDOWS_CUI,
+ .windows => .WINDOWS_GUI,
+ else => return error.UnsupportedCOFFSubsystem,
+ } else .WINDOWS_CUI,
section_align,
+ std.fs.path.basename(path.sub_path),
);
+ try coff.initBuiltins();
return coff;
}
@@ -740,13 +1711,31 @@ pub fn deinit(coff: *Coff) void {
const gpa = coff.base.comp.gpa;
coff.mf.deinit(gpa);
coff.nodes.deinit(gpa);
+ coff.pending_members.deinit(gpa);
+ coff.lib_string_table.deinit(gpa);
+ coff.long_names_table.entries.deinit(gpa);
coff.import_table.entries.deinit(gpa);
+ coff.import_table.iat_symbol_indices.deinit(gpa);
+ coff.export_table.entries.deinit(gpa);
+ coff.symbol_table.strings.deinit(gpa);
+ coff.symbol_table.symbols.deinit(gpa);
+ coff.inputs.deinit(gpa);
+ coff.input_archives.deinit(gpa);
+ coff.input_archive_members.deinit(gpa);
+ coff.input_archive_symbols.deinit(gpa);
+ coff.input_archive_symbol_indices.deinit(gpa);
+ for (coff.pending_default_libs.items) |l| gpa.free(l.path);
+ coff.pending_default_libs.deinit(gpa);
+ coff.alternate_names.deinit(gpa);
+ coff.input_objects.deinit(gpa);
+ coff.input_symbols.deinit(gpa);
+ coff.input_sections.deinit(gpa);
coff.strings.deinit(gpa);
coff.string_bytes.deinit(gpa);
- coff.image_section_table.deinit(gpa);
+ coff.section_table.deinit(gpa);
coff.pseudo_section_table.deinit(gpa);
coff.object_section_table.deinit(gpa);
- coff.symbol_table.deinit(gpa);
+ coff.symbols.deinit(gpa);
coff.globals.deinit(gpa);
coff.navs.deinit(gpa);
coff.uavs.deinit(gpa);
@@ -756,21 +1745,65 @@ pub fn deinit(coff: *Coff) void {
coff.* = undefined;
}
+fn isImage(coff: *const Coff) bool {
+ const comp = coff.base.comp;
+ return switch (comp.config.output_mode) {
+ .Exe => true,
+ .Lib => switch (comp.config.link_mode) {
+ .static => false,
+ .dynamic => true,
+ },
+ .Obj => false,
+ };
+}
+
+fn isArchive(coff: *const Coff) bool {
+ const comp = coff.base.comp;
+ return switch (comp.config.output_mode) {
+ .Exe => false,
+ .Lib => switch (comp.config.link_mode) {
+ .static => true,
+ .dynamic => false,
+ },
+ .Obj => false,
+ };
+}
+
+fn isExe(coff: *const Coff) bool {
+ return coff.base.comp.config.output_mode == .Exe;
+}
+
+fn isObj(coff: *const Coff) bool {
+ return coff.base.comp.config.output_mode == .Obj;
+}
+
+fn hasCoffHeader(coff: *const Coff) bool {
+ return coff.base.comp.zcu != null or !coff.isArchive();
+}
+
+fn sectionParent(coff: *Coff) MappedFile.Node.Index {
+ assert(coff.hasCoffHeader());
+ return if (coff.isArchive()) Node.known.zcu_member else Node.known.file;
+}
+
fn initHeaders(
coff: *Coff,
- is_image: bool,
machine: std.coff.IMAGE.FILE.MACHINE,
timestamp: u32,
major_subsystem_version: u16,
minor_subsystem_version: u16,
magic: std.coff.OptionalHeader.Magic,
+ subsystem: std.coff.Subsystem,
section_align: std.mem.Alignment,
+ file_name: []const u8,
) !void {
const comp = coff.base.comp;
const gpa = comp.gpa;
const target_endian = coff.targetEndian();
const file_align: std.mem.Alignment = comptime .fromByteUnits(default_file_alignment);
-
+ const is_image = coff.isImage();
+ const is_archive = coff.isArchive();
+ const target = &comp.root_mod.resolved_target.result;
const optional_header_size: u16 = if (is_image) switch (magic) {
_ => unreachable,
inline else => |ct_magic| @sizeOf(@field(std.coff.OptionalHeader, @tagName(ct_magic))),
@@ -780,33 +1813,120 @@ fn initHeaders(
else
0;
- const expected_nodes_len = Node.known_count + 6 +
- @as(usize, @intFromBool(comp.config.any_non_single_threaded)) * 2;
+ var expected_nodes_len: usize = Node.known_count;
+ if (coff.hasCoffHeader()) {
+ // Sections
+ expected_nodes_len += 4;
+
+ if (is_image) {
+ // Pseudo-sections and import / export table
+ expected_nodes_len += 9;
+ if (comp.config.link_libc and target.abi == .msvc)
+ expected_nodes_len += 1;
+ } else
+ // Symbol table
+ expected_nodes_len += 2;
+
+ // TLS section
+ if (comp.config.any_non_single_threaded) {
+ if (!is_image) expected_nodes_len += 1;
+ expected_nodes_len += 1;
+ }
+ }
+ defer assert(coff.nodes.len == expected_nodes_len);
+
try coff.nodes.ensureTotalCapacity(gpa, expected_nodes_len);
coff.nodes.appendAssumeCapacity(.file);
const header_ni = Node.known.header;
- assert(header_ni == try coff.mf.addOnlyChildNode(gpa, .root, .{
+ assert(header_ni == try coff.mf.addOnlyChildNode(gpa, Node.known.file, .{
.alignment = coff.mf.flags.block_size,
.fixed = true,
}));
coff.nodes.appendAssumeCapacity(.header);
const signature_ni = Node.known.signature;
- assert(signature_ni == try coff.mf.addOnlyChildNode(gpa, header_ni, .{
- .size = (if (is_image) msdos_stub.len else 0) + "PE\x00\x00".len,
+ assert(signature_ni == try coff.mf.addLastChildNode(gpa, if (is_image or !is_archive) header_ni else Node.known.file, .{
+ .size = if (is_image)
+ msdos_stub.len + std.coff.pe_signature.len
+ else if (is_archive)
+ std.coff.archive_signature.len
+ else
+ 0,
.alignment = .@"4",
.fixed = true,
}));
coff.nodes.appendAssumeCapacity(.signature);
- {
- const signature_slice = signature_ni.slice(&coff.mf);
- if (is_image) @memcpy(signature_slice[0..msdos_stub.len], &msdos_stub);
- @memcpy(signature_slice[signature_slice.len - 4 ..], "PE\x00\x00");
+
+ const signature_slice = signature_ni.slice(&coff.mf);
+ if (is_image) {
+ @memcpy(signature_slice[0..msdos_stub.len], &msdos_stub);
+ @memcpy(signature_slice[signature_slice.len - std.coff.pe_signature.len ..], std.coff.pe_signature);
+ } else if (is_archive) {
+ @memcpy(signature_slice, std.coff.archive_signature);
}
+ const opt_coff_parent_ni = if (is_archive) parent: {
+ const initial_member_count = Member.Index.known_count + @intFromBool(comp.zcu != null);
+ try coff.members.ensureTotalCapacity(gpa, initial_member_count);
+
+ assert(Member.Index.first == try coff.addMemberAssumeCapacity(.first_linker, @sizeOf(u32)));
+ coff.targetStore(coff.firstLinkerMemberNumSymbolsPtr(), 0);
+
+ assert(Member.Index.second == try coff.addMemberAssumeCapacity(.second_linker, 2 * @sizeOf(u32)));
+ coff.targetStore(coff.secondLinkerMemberNumMembersPtr(), 0);
+ coff.targetStore(coff.secondLinkerMemberNumSymbolsPtr(), 0);
+
+ assert(Member.Index.longnames == try coff.addMemberAssumeCapacity(.longnames, 0));
+
+ const first_linker_member = Member.Index.first.get(coff);
+ const second_linker_member = Member.Index.second.get(coff);
+ const longnames_member = Member.Index.longnames.get(coff);
+
+ try first_linker_member.initHeader(coff, "", timestamp);
+ try second_linker_member.initHeader(coff, "", timestamp);
+ try longnames_member.initHeader(coff, "/", timestamp);
+
+ if (comp.zcu) |zcu| {
+ const zcu_mi = try coff.addMemberAssumeCapacity(.coff, @sizeOf(std.coff.Header));
+ const zcu_member = zcu_mi.get(coff);
+ try zcu_member.initHeader(coff, zcu.main_mod.fully_qualified_name, timestamp);
+
+ break :parent zcu_member.content_ni;
+ }
+
+ // These placeholder nodes are placed before the first member - if there are
+ // no other members then the last linker member (longnames) needs to expand
+ // to fill the padding at the end of the file.
+ assert(Node.known.zcu_member_header == try coff.mf.addNodeAfter(gpa, Node.known.header, .{}));
+ assert(Node.known.zcu_member == try coff.mf.addNodeAfter(gpa, Node.known.header, .{}));
+ coff.nodes.appendAssumeCapacity(.placeholder);
+ coff.nodes.appendAssumeCapacity(.placeholder);
+
+ break :parent null;
+ } else parent: {
+ // TODO: Not ideal to have this many placeholder nodes - use two distinct `Node.known` types?
+ while (true) {
+ const placeholder_ni = try coff.mf.addLastChildNode(gpa, Node.known.file, .{});
+ coff.nodes.appendAssumeCapacity(.placeholder);
+ if (placeholder_ni == Node.known.zcu_member) break;
+ }
+
+ break :parent Node.known.header;
+ };
+
+ const coff_parent_ni = opt_coff_parent_ni orelse {
+ // If we're not generating any code, no more known nodes are used
+ while (coff.nodes.len < Node.known_count) {
+ _ = try coff.mf.addNodeAfter(gpa, Node.known.header, .{});
+ coff.nodes.appendAssumeCapacity(.placeholder);
+ }
+
+ return;
+ };
+
const coff_header_ni = Node.known.coff_header;
- assert(coff_header_ni == try coff.mf.addLastChildNode(gpa, header_ni, .{
+ assert(coff_header_ni == try coff.mf.addLastChildNode(gpa, coff_parent_ni, .{
.size = @sizeOf(std.coff.Header),
.alignment = .@"4",
.fixed = true,
@@ -834,7 +1954,7 @@ fn initHeaders(
}
const optional_header_ni = Node.known.optional_header;
- assert(optional_header_ni == try coff.mf.addLastChildNode(gpa, header_ni, .{
+ assert(optional_header_ni == try coff.mf.addLastChildNode(gpa, coff_parent_ni, .{
.size = optional_header_size,
.alignment = .@"4",
.fixed = true,
@@ -876,7 +1996,7 @@ fn initHeaders(
.size_of_image = 0,
.size_of_headers = 0,
.checksum = 0,
- .subsystem = .WINDOWS_CUI,
+ .subsystem = subsystem,
.dll_flags = .{
.HIGH_ENTROPY_VA = true,
.DYNAMIC_BASE = true,
@@ -925,7 +2045,7 @@ fn initHeaders(
.size_of_image = 0,
.size_of_headers = 0,
.checksum = 0,
- .subsystem = .WINDOWS_CUI,
+ .subsystem = subsystem,
.dll_flags = .{
.HIGH_ENTROPY_VA = true,
.DYNAMIC_BASE = true,
@@ -946,13 +2066,13 @@ fn initHeaders(
}
const data_directories_ni = Node.known.data_directories;
- assert(data_directories_ni == try coff.mf.addLastChildNode(gpa, header_ni, .{
+ assert(data_directories_ni == try coff.mf.addLastChildNode(gpa, coff_parent_ni, .{
.size = data_directories_size,
.alignment = .@"4",
.fixed = true,
}));
coff.nodes.appendAssumeCapacity(.data_directories);
- {
+ if (is_image) {
const data_directories = coff.dataDirectorySlice();
@memset(data_directories, .{ .virtual_address = 0, .size = 0 });
if (target_endian != native_endian) std.mem.byteSwapAllFields(
@@ -962,7 +2082,7 @@ fn initHeaders(
}
const section_table_ni = Node.known.section_table;
- assert(section_table_ni == try coff.mf.addLastChildNode(gpa, header_ni, .{
+ assert(section_table_ni == try coff.mf.addLastChildNode(gpa, coff_parent_ni, .{
.alignment = .@"4",
.fixed = true,
}));
@@ -970,65 +2090,292 @@ fn initHeaders(
assert(coff.nodes.len == Node.known_count);
- try coff.symbol_table.ensureTotalCapacity(gpa, Symbol.Index.known_count);
- coff.symbol_table.addOneAssumeCapacity().* = .{
- .ni = .none,
- .rva = 0,
- .size = 0,
- .loc_relocs = .none,
- .target_relocs = .none,
- .section_number = .UNDEFINED,
- };
- assert(try coff.addSection(".data", .{
+ if (!is_image) {
+ // TODO: These two nodes could be inside one movable node?
+ coff.symbol_table.ni = try coff.mf.addLastChildNode(gpa, coff_parent_ni, .{
+ .alignment = .@"2",
+ .fixed = true,
+ .moved = true,
+ });
+ coff.nodes.appendAssumeCapacity(.symbol_table);
+
+ coff.symbol_table.strings_ni = try coff.mf.addLastChildNode(gpa, coff_parent_ni, .{
+ .size = @sizeOf(u32),
+ .fixed = true,
+ .resized = true,
+ });
+ coff.nodes.appendAssumeCapacity(.string_table);
+ coff.targetStore(coff.symbolTableStringLenPtr(), @sizeOf(u32));
+ }
+
+ try coff.symbols.ensureTotalCapacity(gpa, Symbol.Index.known_count);
+ assert(coff.addSymbolAssumeCapacity() == .null);
+
+ // TODO: How do we tell MappedFile not to allocate physical space for .bss?
+ // TODO: Could have a node flag 'virtual' that can never have slice* or fileLocation called on it
+ // TODO: Instead of it's own section, place .bss as a pseudo-section at the end of .text in the extra space
+ assert(try coff.addSection(.@".bss", .{
+ .CNT_UNINITIALIZED_DATA = true,
+ .MEM_READ = true,
+ .MEM_WRITE = true,
+ }) == .bss);
+ assert(try coff.addSection(.@".data", .{
.CNT_INITIALIZED_DATA = true,
.MEM_READ = true,
.MEM_WRITE = true,
}) == .data);
- assert(try coff.addSection(".rdata", .{
+ assert(try coff.addSection(.@".rdata", .{
.CNT_INITIALIZED_DATA = true,
.MEM_READ = true,
}) == .rdata);
- assert(try coff.addSection(".text", .{
+ assert(try coff.addSection(.@".text", .{
.CNT_CODE = true,
.MEM_EXECUTE = true,
.MEM_READ = true,
}) == .text);
- coff.import_table.ni = try coff.mf.addLastChildNode(
- gpa,
- (try coff.objectSectionMapIndex(
- .@".idata",
+ if (is_image) {
+ if (comp.config.link_libc and target.abi == .msvc) {
+ // This section contains a function pointer table used by control flow guard:
+ // https://learn.microsoft.com/en-us/windows/win32/secbp/control-flow-guard
+ // The page containing it is set to PAGE_READONLY during startup, so this can't
+ // be merged into .data this protection would overlap writable memory.
+ _ = try coff.addSection(.@".fptable", .{
+ .CNT_INITIALIZED_DATA = true,
+ .MEM_READ = true,
+ .MEM_WRITE = true,
+ });
+ }
+
+ // TODO: Lazily initialize this instead, avoid the extra logic for this in flushMoved / flushResized
+ coff.import_table.ni = try coff.mf.addLastChildNode(
+ gpa,
+ (try coff.objectSectionMapIndex(
+ .@".idata",
+ coff.mf.flags.block_size,
+ .{ .read = true, .initialized = true },
+ )).symbol(coff).node(coff),
+ .{ .alignment = .@"4" },
+ );
+ coff.nodes.appendAssumeCapacity(.import_directory_table);
+
+ coff.export_table.ni = (try coff.pseudoSectionMapIndex(
+ .@".edata",
+ .of(std.coff.ExportDirectoryTable),
+ .{ .read = true, .initialized = true },
+ )).symbol(coff).node(coff);
+
+ coff.export_table.export_directory_table_ni = try coff.mf.addLastChildNode(
+ gpa,
+ coff.export_table.ni,
+ .{
+ .size = @sizeOf(std.coff.ExportDirectoryTable) + file_name.len + 1,
+ .moved = true,
+ .fixed = true,
+ },
+ );
+ coff.nodes.appendAssumeCapacity(.export_directory_table);
+
+ const name_index = @sizeOf(std.coff.ExportDirectoryTable);
+ const table_slice = coff.export_table.export_directory_table_ni.slice(&coff.mf);
+ @memcpy(table_slice[name_index..][0..file_name.len], file_name[0..file_name.len]);
+ @memset(table_slice[name_index + file_name.len ..], 0);
+
+ const export_address_table_ni = try coff.mf.addLastChildNode(gpa, coff.export_table.ni, .{
+ .alignment = .of(std.coff.ExportAddressTableEntry),
+ .moved = true,
+ });
+ coff.nodes.appendAssumeCapacity(.export_address_table);
+
+ try coff.symbols.ensureUnusedCapacity(gpa, 1);
+ coff.export_table.export_address_table_si = coff.addSymbolAssumeCapacity();
+
+ const export_address_table_sym = coff.export_table.export_address_table_si.get(coff);
+ export_address_table_sym.ni = export_address_table_ni;
+ assert(export_address_table_sym.loc_relocs == .none);
+ export_address_table_sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
+ export_address_table_sym.section_number =
+ coff.getNode(coff.export_table.ni).pseudo_section.symbol(coff).get(coff).section_number;
+
+ coff.export_table.name_pointer_table_ni = try coff.mf.addLastChildNode(gpa, coff.export_table.ni, .{
+ .alignment = .of(std.coff.ExportNamePointerTableEntry),
+ .moved = true,
+ });
+ coff.nodes.appendAssumeCapacity(.export_name_pointer_table);
+
+ coff.export_table.ordinal_table_ni = try coff.mf.addLastChildNode(gpa, coff.export_table.ni, .{
+ .alignment = .of(std.coff.ExportOrdinalTableEntry),
+ .moved = true,
+ });
+ coff.nodes.appendAssumeCapacity(.export_ordinal_table);
+
+ coff.export_table.name_table_ni = try coff.mf.addLastChildNode(gpa, coff.export_table.ni, .{
+ .alignment = .of(u8),
+ .moved = true,
+ });
+ coff.nodes.appendAssumeCapacity(.export_name_table);
+
+ const export_directory_table = coff.exportDirectoryTable();
+ export_directory_table.* = .{
+ .flags = 0,
+ .time_date_stamp = timestamp,
+ .major_version = 0,
+ .minor_version = 0,
+ .name_rva = 0,
+ .ordinal_base = 1,
+ .number_of_entries = 0,
+ .number_of_names = 0,
+ .export_address_table_rva = 0,
+ .name_pointer_table_rva = 0,
+ .ordinal_table_rva = 0,
+ };
+ if (target_endian != native_endian)
+ std.mem.byteSwapAllFields(std.coff.ExportDirectoryTable, export_directory_table);
+ }
+
+ if (comp.config.any_non_single_threaded) {
+ if (!is_image)
+ _ = try coff.addSection(.@".tls$", .{
+ .CNT_INITIALIZED_DATA = true,
+ .MEM_READ = true,
+ .MEM_WRITE = true,
+ });
+
+ // While tls variables allocated at runtime are writable, the template itself is not.
+ // In images, the template is in a .tls pseudo section in .rdata.
+ // In objects / archives, this section is part of the above .tls$ section. The suffix
+ // is maintained so merging can occur with other input tls symbols when linked later.
+ _ = try coff.pseudoSectionMapIndex(
+ if (is_image) .@".tls" else .@".tls$",
coff.mf.flags.block_size,
- .{ .read = true },
- )).symbol(coff).node(coff),
- .{ .alignment = .@"4", .moved = true },
- );
- coff.nodes.appendAssumeCapacity(.import_directory_table);
-
- // While tls variables allocated at runtime are writable, the template itself is not
- if (comp.config.any_non_single_threaded) _ = try coff.objectSectionMapIndex(
- .@".tls$",
- coff.mf.flags.block_size,
- .{ .read = true },
- );
-
- assert(coff.nodes.len == expected_nodes_len);
+ .{ .read = true, .write = !is_image, .initialized = true },
+ );
+ }
+}
+
+pub fn initBuiltins(coff: *Coff) !void {
+ const comp = coff.base.comp;
+ const gpa = comp.gpa;
+ const target = &comp.root_mod.resolved_target.result;
+ if (coff.isImage()) {
+ const si = try coff.globalSymbol(.{ .name = "__ImageBase", .type = .data });
+ const sym = si.get(coff);
+ sym.ni = Node.known.header;
+ }
+
+ defer coff.flushSectionMerges() catch unreachable;
+ if (coff.isImage() and target.isMinGW() and comp.config.link_libc) {
+ try coff.symbols.ensureUnusedCapacity(gpa, 8);
+ try coff.globals.ensureUnusedCapacity(gpa, 2);
+ try coff.nodes.ensureUnusedCapacity(gpa, 8);
+ try coff.section_merges.ensureUnusedCapacity(gpa, 2);
+
+ const lists: []const struct { global: []const u8, start: String, end: String } = &.{
+ .{ .global = "__CTOR_LIST__", .start = .@".ctors", .end = .@".ctors$ZZZ" },
+ .{ .global = "__DTOR_LIST__", .start = .@".dtors", .end = .@".dtors$ZZZ" },
+ };
+
+ // We need to explicitly merge these into .rdata as in objects they can be marked
+ // as MEM_WRITE, and would have mismatced section flags.
+ try coff.section_merges.put(gpa, .@".ctors", .@".rdata");
+ try coff.section_merges.put(gpa, .@".dtors", .@".rdata");
+
+ for (lists) |list| {
+ const addr_info = coff.targetAddrInfo();
+
+ // Any .(c|d)tor$(.*) input sections will merge in between these sections
+ const start_osmi = try coff.objectSectionMapIndex(
+ list.start,
+ addr_info.alignment,
+ .{ .read = true, .initialized = true },
+ );
+ const end_osmi = try coff.objectSectionMapIndex(
+ list.end,
+ addr_info.alignment,
+ .{ .read = true, .initialized = true },
+ );
+
+ // Additional nodes are used here, instead of just adding the sentinel
+ // directly to the section data, since once input sections are added
+ // as children, they would overwrite that data.
+ const start_sym = start_osmi.symbol(coff).get(coff);
+ const list_len_si = try coff.globalSymbol(.{ .name = list.global, .type = .data });
+ const list_len_sym = list_len_si.get(coff);
+ list_len_sym.setExtra(.{ .size = addr_info.size });
+ list_len_sym.ni = try coff.mf.addFirstChildNode(gpa, start_sym.ni, .{
+ .size = addr_info.size,
+ .fixed = true,
+ });
+ coff.nodes.appendAssumeCapacity(.{ .builtin = list_len_si });
+ list_len_sym.section_number = start_sym.section_number;
+
+ const start_slice = list_len_sym.ni.slice(&coff.mf);
+ switch (addr_info.magic) {
+ _ => unreachable,
+ inline .PE32, .@"PE32+" => |t| {
+ const addr: *TargetAddr(t) = @ptrCast(@alignCast(start_slice));
+ // For __CTOR_LIST__ -1 indicates that the list is null terminated.
+ // For __DTOR_LIST__, this value is ignored, the list is always null terminated
+ coff.targetStore(addr, std.math.maxInt(TargetAddr(t)));
+ },
+ }
+
+ const end_sym = end_osmi.symbol(coff).get(coff);
+ const list_end_si = coff.addSymbolAssumeCapacity();
+ const list_end_sym = list_end_si.get(coff);
+ list_end_sym.setExtra(.{ .size = addr_info.size });
+ list_end_sym.ni = try coff.mf.addFirstChildNode(gpa, end_sym.ni, .{
+ .size = addr_info.size,
+ .fixed = true,
+ });
+ coff.nodes.appendAssumeCapacity(.{ .builtin = list_end_si });
+ list_end_sym.section_number = start_sym.section_number;
+
+ @memset(list_end_sym.ni.slice(&coff.mf), 0);
+
+ try list_len_si.flushMoved(coff);
+ try list_end_si.flushMoved(coff);
+ }
+ }
}
pub fn startProgress(coff: *Coff, prog_node: std.Progress.Node) void {
prog_node.increaseEstimatedTotalItems(3);
coff.const_prog_node = prog_node.start("Constants", coff.pending_uavs.count());
coff.synth_prog_node = prog_node.start("Synthetics", count: {
- var count = coff.globals.count() - coff.global_pending_index;
+ var count =
+ coff.globals.count() - coff.global_pending_index +
+ coff.section_merges.count() - coff.section_merge_pending_index;
+
for (&coff.lazy.values) |*lazy| count += lazy.map.count() - lazy.pending_index;
break :count count;
});
+ if (!isImage(coff)) {
+ prog_node.increaseEstimatedTotalItems(2);
+ coff.symbol_prog_node = prog_node.start(
+ "Symbols",
+ coff.symbol_table.symbols.count() - coff.symbol_table.pending_symbol_index,
+ );
+ coff.member_prog_node = prog_node.start("Members", coff.pending_members.count());
+ }
+ coff.input_prog_node = prog_node.start(
+ "Inputs",
+ coff.input_sections.items.len - coff.input_section_pending_index,
+ );
coff.mf.update_prog_node = prog_node.start("Relocations", coff.mf.updates.items.len);
}
pub fn endProgress(coff: *Coff) void {
coff.mf.update_prog_node.end();
coff.mf.update_prog_node = .none;
+ coff.input_prog_node.end();
+ coff.input_prog_node = .none;
+ if (!coff.isImage()) {
+ coff.member_prog_node.end();
+ coff.member_prog_node = .none;
+ coff.symbol_prog_node.end();
+ coff.symbol_prog_node = .none;
+ }
coff.synth_prog_node.end();
coff.synth_prog_node = .none;
coff.const_prog_node.end();
@@ -1044,10 +2391,20 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 {
.file,
.header,
.signature,
+ .archive_member_header,
+ .archive_member,
.coff_header,
.optional_header,
.data_directories,
.section_table,
+ .export_name_table,
+ .placeholder,
+ .symbol_table,
+ .string_table,
+ .relocation_table,
+ .relocation_table_entry,
+ .input_section,
+ .builtin,
=> unreachable,
.image_section => |si| si,
.import_directory_table => break :parent_rva coff.targetLoad(
@@ -1062,9 +2419,21 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 {
.import_hint_name_table => |import_index| break :parent_rva coff.targetLoad(
&coff.importDirectoryEntryPtr(import_index).name_rva,
),
+ .export_directory_table => break :parent_rva coff.targetLoad(
+ &coff.dataDirectoryPtr(.EXPORT).virtual_address,
+ ),
+ .export_address_table => break :parent_rva coff.targetLoad(
+ &coff.exportDirectoryTable().export_address_table_rva,
+ ),
+ .export_name_pointer_table => break :parent_rva coff.targetLoad(
+ &coff.exportDirectoryTable().name_pointer_table_rva,
+ ),
+ .export_ordinal_table => break :parent_rva coff.targetLoad(
+ &coff.exportDirectoryTable().ordinal_table_rva,
+ ),
inline .pseudo_section,
.object_section,
- .global,
+ .import_thunk,
.nav,
.uav,
.lazy_code,
@@ -1076,24 +2445,55 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 {
const offset, _ = ni.location(&coff.mf).resolve(&coff.mf);
return @intCast(parent_rva + offset);
}
-fn computeNodeSectionOffset(coff: *Coff, ni: MappedFile.Node.Index) u32 {
- var section_offset: u32 = 0;
- var parent_ni = ni;
+
+fn computeSymbolSectionOffset(
+ coff: *Coff,
+ sym: *const Symbol,
+ relative_to: enum { image, pseudo },
+) u32 {
+ var section_offset: u32 = sym.nodeOffset(coff);
+ var parent_ni = sym.ni;
while (true) {
const offset, _ = parent_ni.location(&coff.mf).resolve(&coff.mf);
section_offset += @intCast(offset);
parent_ni = parent_ni.parent(&coff.mf);
switch (coff.getNode(parent_ni)) {
else => unreachable,
- .image_section, .pseudo_section => return section_offset,
- .object_section => {},
+ .image_section => break,
+ .pseudo_section => if (relative_to == .pseudo) break,
+ .object_section,
+ => {},
}
}
+
+ return section_offset;
}
pub inline fn targetEndian(_: *const Coff) std.lang.Endian {
return .little;
}
+
+fn targetAddrInfo(coff: *Coff) struct {
+ size: u8,
+ alignment: std.mem.Alignment,
+ magic: std.coff.OptionalHeader.Magic,
+} {
+ const magic = coff.targetLoad(&coff.optionalHeaderStandardPtr().magic);
+ switch (magic) {
+ _ => unreachable,
+ .PE32 => return .{ .size = 4, .alignment = .@"4", .magic = magic },
+ .@"PE32+" => return .{ .size = 8, .alignment = .@"8", .magic = magic },
+ }
+}
+
+fn TargetAddr(comptime magic: std.coff.OptionalHeader.Magic) type {
+ return switch (magic) {
+ _ => comptime unreachable,
+ .PE32 => u32,
+ .@"PE32+" => u64,
+ };
+}
+
fn targetLoad(coff: *const Coff, ptr: anytype) @typeInfo(@TypeOf(ptr)).pointer.child {
const Child = @typeInfo(@TypeOf(ptr)).pointer.child;
return switch (@typeInfo(Child)) {
@@ -1122,9 +2522,55 @@ fn targetStore(coff: *const Coff, ptr: anytype, val: @typeInfo(@TypeOf(ptr)).poi
}
pub fn headerPtr(coff: *Coff) *std.coff.Header {
+ assert(coff.hasCoffHeader());
return @ptrCast(@alignCast(Node.known.coff_header.slice(&coff.mf)));
}
+pub fn firstLinkerMemberNumSymbolsPtr(coff: *Coff) *u32 {
+ assert(coff.isArchive());
+ return @ptrCast(@alignCast(Node.known.first_linker_member.slice(&coff.mf)));
+}
+
+pub fn firstLinkerMemberOffsetsSlice(coff: *Coff) []u32 {
+ const len = std.mem.toNative(u32, coff.firstLinkerMemberNumSymbolsPtr().*, .big);
+ return @ptrCast(@alignCast(Node.known.first_linker_member.slice(&coff.mf)[@sizeOf(u32)..][0 .. len * @sizeOf(u32)]));
+}
+
+pub fn secondLinkerMemberNumMembersPtr(coff: *Coff) *align(2) u32 {
+ assert(coff.isArchive());
+ return @ptrCast(@alignCast(Node.known.second_linker_member.slice(&coff.mf)));
+}
+
+pub fn secondLinkerMemberOffsetsSlice(coff: *Coff) []align(2) u32 {
+ const num_members = coff.targetLoad(coff.secondLinkerMemberNumMembersPtr());
+ return @ptrCast(@alignCast(
+ Node.known.second_linker_member.slice(&coff.mf)[@sizeOf(u32)..][0 .. num_members * @sizeOf(u32)],
+ ));
+}
+
+pub fn secondLinkerMemberNumSymbolsPtr(coff: *Coff) *align(2) u32 {
+ const num_members = coff.targetLoad(coff.secondLinkerMemberNumMembersPtr());
+ return @ptrCast(@alignCast(
+ Node.known.second_linker_member.slice(&coff.mf)[(1 + num_members) * @sizeOf(u32) ..],
+ ));
+}
+
+pub fn secondLinkerMemberIndicesSlice(coff: *Coff) []u16 {
+ const num_members = coff.targetLoad(coff.secondLinkerMemberNumMembersPtr());
+ const num_symbols = coff.targetLoad(coff.secondLinkerMemberNumSymbolsPtr());
+ return @ptrCast(@alignCast(
+ Node.known.second_linker_member.slice(&coff.mf)[(2 + num_members) * @sizeOf(u32) ..][0 .. num_symbols * @sizeOf(u16)],
+ ));
+}
+
+pub fn secondLinkerMemberStringsSlice(coff: *Coff) []u8 {
+ const num_members = coff.targetLoad(coff.secondLinkerMemberNumMembersPtr());
+ const num_symbols = coff.targetLoad(coff.secondLinkerMemberNumSymbolsPtr());
+ return @ptrCast(@alignCast(
+ Node.known.second_linker_member.slice(&coff.mf)[(2 + num_members) * @sizeOf(u32) + num_symbols * @sizeOf(u16) ..],
+ ));
+}
+
pub fn optionalHeaderStandardPtr(coff: *Coff) *std.coff.OptionalHeader {
return @ptrCast(@alignCast(
Node.known.optional_header.slice(&coff.mf)[0..@sizeOf(std.coff.OptionalHeader)],
@@ -1136,6 +2582,7 @@ pub const OptionalHeaderPtr = union(std.coff.OptionalHeader.Magic) {
@"PE32+": *std.coff.OptionalHeader.@"PE32+",
};
pub fn optionalHeaderPtr(coff: *Coff) OptionalHeaderPtr {
+ assert(coff.isImage());
const slice = Node.known.optional_header.slice(&coff.mf);
return switch (coff.targetLoad(&coff.optionalHeaderStandardPtr().magic)) {
_ => unreachable,
@@ -1150,6 +2597,7 @@ pub fn optionalHeaderField(
coff: *Coff,
comptime field: std.meta.FieldEnum(std.coff.OptionalHeader.@"PE32+"),
) @FieldType(std.coff.OptionalHeader.@"PE32+", @tagName(field)) {
+ assert(coff.isImage());
return switch (coff.optionalHeaderPtr()) {
inline else => |optional_header| coff.targetLoad(&@field(optional_header, @tagName(field))),
};
@@ -1158,6 +2606,7 @@ pub fn optionalHeaderField(
pub fn dataDirectorySlice(
coff: *Coff,
) *[std.coff.IMAGE.DIRECTORY_ENTRY.len]std.coff.ImageDataDirectory {
+ assert(coff.isImage());
return @ptrCast(@alignCast(Node.known.data_directories.slice(&coff.mf)));
}
pub fn dataDirectoryPtr(
@@ -1168,10 +2617,48 @@ pub fn dataDirectoryPtr(
}
pub fn sectionTableSlice(coff: *Coff) []std.coff.SectionHeader {
- return @ptrCast(@alignCast(Node.known.section_table.slice(&coff.mf)));
+ return @ptrCast(@alignCast(
+ Node.known.section_table.slice(&coff.mf)[0 .. coff.section_table.count() * @sizeOf(std.coff.SectionHeader)],
+ ));
+}
+
+pub fn symbolTableEntryStoragePtr(coff: *Coff, index: u32) *[std.coff.Symbol.sizeOf()]u8 {
+ assert(!coff.isImage());
+ const offset = index * std.coff.Symbol.sizeOf();
+ return @ptrCast(@alignCast(coff.symbol_table.ni.slice(&coff.mf)[offset..][0..std.coff.Symbol.sizeOf()]));
+}
+
+pub fn symbolTableEntryPtr(coff: *Coff, sti: SymbolTable.Index) ?*align(2) std.coff.Symbol {
+ if (sti.unwrap()) |index|
+ return @ptrCast(@alignCast(symbolTableEntryStoragePtr(coff, index)))
+ else
+ return null;
+}
+
+pub fn symbolTableSectionAuxEntryPtr(coff: *Coff, sti: SymbolTable.Index) ?*align(2) std.coff.SectionDefinition {
+ if (symbolTableEntryPtr(coff, sti)) |entry| {
+ assert(entry.storage_class == .STATIC and entry.number_of_aux_symbols == 1);
+ return @ptrCast(@alignCast(symbolTableEntryStoragePtr(coff, sti.unwrap().? + 1)));
+ } else {
+ return null;
+ }
+}
+
+pub fn symbolTableWeakExternalAuxEntryPtr(coff: *Coff, sti: SymbolTable.Index) ?*align(2) std.coff.WeakExternalDefinition {
+ if (symbolTableEntryPtr(coff, sti)) |entry| {
+ assert(entry.storage_class == .WEAK_EXTERNAL and entry.number_of_aux_symbols == 1);
+ return @ptrCast(@alignCast(symbolTableEntryStoragePtr(coff, sti.unwrap().? + 1)));
+ } else {
+ return null;
+ }
+}
+
+pub fn symbolTableStringLenPtr(coff: *Coff) *align(1) u32 {
+ return @ptrCast(@alignCast(coff.symbol_table.strings_ni.slice(&coff.mf)[0..@sizeOf(u32)]));
}
pub fn importDirectoryTableSlice(coff: *Coff) []std.coff.ImportDirectoryEntry {
+ assert(coff.isImage());
return @ptrCast(@alignCast(coff.import_table.ni.slice(&coff.mf)));
}
pub fn importDirectoryEntryPtr(
@@ -1181,16 +2668,40 @@ pub fn importDirectoryEntryPtr(
return &coff.importDirectoryTableSlice()[@intFromEnum(import_index)];
}
+pub fn exportDirectoryTable(coff: *Coff) *std.coff.ExportDirectoryTable {
+ return @ptrCast(@alignCast(coff.export_table.export_directory_table_ni.slice(&coff.mf)));
+}
+
+pub fn exportNamePointerTableSlice(coff: *Coff) []std.coff.ExportNamePointerTableEntry {
+ const debug = coff.export_table.name_pointer_table_ni.slice(&coff.mf);
+ _ = debug;
+
+ return @ptrCast(@alignCast(coff.export_table.name_pointer_table_ni.slice(&coff.mf)));
+}
+
+pub fn exportOrdinalTableSlice(coff: *Coff) []std.coff.ExportOrdinalTableEntry {
+ return @ptrCast(@alignCast(coff.export_table.ordinal_table_ni.slice(&coff.mf)));
+}
+
fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {
- defer coff.symbol_table.addOneAssumeCapacity().* = .{
+ defer coff.symbols.addOneAssumeCapacity().* = .{
.ni = .none,
.rva = 0,
- .size = 0,
+ .value = .{ .none = {} },
+ .extra = .{ .size = 0 },
+ .flags = .{
+ .value_tag = .none,
+ .extra_tag = .size,
+ .type = .unknown,
+ .dll_storage_class = .default,
+ .weak_external_strat = .none,
+ },
.loc_relocs = .none,
.target_relocs = .none,
.section_number = .UNDEFINED,
+ .gmi = .none,
};
- return @enumFromInt(coff.symbol_table.items.len);
+ return @enumFromInt(coff.symbols.items.len);
}
fn initSymbolAssumeCapacity(coff: *Coff) !Symbol.Index {
@@ -1205,12 +2716,55 @@ fn getOrPutString(coff: *Coff, string: []const u8) !String {
fn getOrPutOptionalString(coff: *Coff, string: ?[]const u8) !String.Optional {
return (try coff.getOrPutString(string orelse return .none)).toOptional();
}
+fn getString(coff: *Coff, string: []const u8) String.Optional {
+ if (coff.strings.getKeyAdapted(
+ string,
+ std.hash_map.StringIndexAdapter{ .bytes = &coff.string_bytes },
+ )) |key|
+ return @as(String, @enumFromInt(key)).toOptional()
+ else
+ return .none;
+}
+/// If the name does not fit in the symbol header, adds it to the symbol table string table.
+/// If the caller knows this name already has a String associated with it, they can avoid
+/// a redundant call to `getOrPutString` by specifying `opt_string`.
+/// The lifetime of the return value matches that of `name`.
+fn getOrPutSymbolName(coff: *Coff, name: []const u8, opt_string: ?String) !SymbolTable.SymbolName {
+ assert(!coff.isImage());
+ const gpa = coff.base.comp.gpa;
+
+ return if (name.len > header_name_max_len) name: {
+ const string = opt_string orelse try coff.getOrPutString(name);
+ const string_gop = try coff.symbol_table.strings.getOrPut(gpa, string);
+ if (!string_gop.found_existing) {
+ const string_index = coff.symbol_table.strings_ni.location(&coff.mf).resolve(&coff.mf)[1];
+ string_gop.value_ptr.* = @enumFromInt(string_index);
+
+ try coff.symbol_table.strings_ni.resize(&coff.mf, gpa, string_index + name.len + 1);
+ const slice = coff.symbol_table.strings_ni.slice(&coff.mf);
+ @memcpy(slice[@intCast(string_index)..][0..name.len], name);
+ slice[@intCast(string_index + name.len)] = 0;
+ }
+
+ break :name .{ .long = string_gop.value_ptr.* };
+ } else .{ .short = name };
+}
+
+/// `len` does not include null terminators
fn ensureUnusedStringCapacity(coff: *Coff, len: usize) !void {
const gpa = coff.base.comp.gpa;
try coff.strings.ensureUnusedCapacityContext(gpa, 1, .{ .bytes = &coff.string_bytes });
try coff.string_bytes.ensureUnusedCapacity(gpa, len + 1);
}
+
+/// `total_len` includes null terminators
+fn ensureManyUnusedStringCapacity(coff: *Coff, num_strings: u32, total_len: usize) !void {
+ const gpa = coff.base.comp.gpa;
+ try coff.strings.ensureUnusedCapacityContext(gpa, num_strings, .{ .bytes = &coff.string_bytes });
+ try coff.string_bytes.ensureUnusedCapacity(gpa, total_len + num_strings);
+}
+
fn getOrPutStringAssumeCapacity(coff: *Coff, string: []const u8) String {
const gop = coff.strings.getOrPutAssumeCapacityAdapted(
string,
@@ -1225,18 +2779,78 @@ fn getOrPutStringAssumeCapacity(coff: *Coff, string: []const u8) String {
return @enumFromInt(gop.key_ptr.*);
}
-pub fn globalSymbol(coff: *Coff, name: []const u8, lib_name: ?[]const u8) !Symbol.Index {
- const gpa = coff.base.comp.gpa;
- try coff.symbol_table.ensureUnusedCapacity(gpa, 1);
- const sym_gop = try coff.globals.getOrPut(gpa, .{
- .name = try coff.getOrPutString(name),
- .lib_name = try coff.getOrPutOptionalString(lib_name),
- });
+const GlobalOptions = struct {
+ name: []const u8,
+ lib_name: ?[]const u8 = null,
+ type: Symbol.Type = .unknown,
+ dll_storage_class: Symbol.DllStorageClass = .default,
+};
+
+fn getOrPutGlobalSymbol(
+ coff: *Coff,
+ opts: GlobalOptions,
+) !std.array_hash_map.Auto(String, Global).GetOrPutResult {
+ const comp = coff.base.comp;
+ const gpa = comp.gpa;
+ try coff.symbols.ensureUnusedCapacity(gpa, 1);
+
+ const lib_name: String.Optional = if (opts.lib_name) |lib_name| lib_name: {
+ const is_libc = std.zig.target.isLibCLibName(&comp.root_mod.resolved_target.result, lib_name);
+ if (is_libc) {
+ // This is guaranteed by Sema.handleExternLibName
+ if (!comp.config.link_libc) unreachable;
+
+ // TODO: The user has requested this symbol come from libc, but this logic allows
+ // it to come from anywhere. We need to know what inputs are libc inputs,
+ // and set a flag to only search them for this symbol.
+ break :lib_name .none;
+ }
+
+ break :lib_name (try coff.getOrPutString(lib_name)).toOptional();
+ } else .none;
+
+ const sym_gop = try coff.globals.getOrPut(gpa, try coff.getOrPutString(opts.name));
if (!sym_gop.found_existing) {
- sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();
+ const si = coff.addSymbolAssumeCapacity();
+ const sym = si.get(coff);
+ sym.gmi = .wrap(@intCast(sym_gop.index));
+ sym.flags.type = opts.type;
+ sym.flags.dll_storage_class = opts.dll_storage_class;
+ sym_gop.value_ptr.* = .{
+ .si = si,
+ .lib_name = lib_name,
+ };
coff.synth_prog_node.increaseEstimatedTotalItems(1);
+
+ log.debug("globalSymbol({s}, {?s}) = {d}", .{ opts.name, opts.lib_name, si });
+ }
+
+ return sym_gop;
+}
+
+fn getDefinedGlobal(coff: *Coff, name: []const u8) Symbol.Index {
+ if (coff.globals.get(
+ coff.getString(name).unwrap() orelse return .null,
+ )) |global| if (global.si.get(coff).ni != .none) return global.si;
+ return .null;
+}
+
+pub fn globalSymbol(coff: *Coff, opts: GlobalOptions) !Symbol.Index {
+ const gop = try coff.getOrPutGlobalSymbol(opts);
+ return gop.value_ptr.si;
+}
+
+pub fn pendingSymbolTableEntry(coff: *Coff, si: Symbol.Index) !void {
+ assert(!coff.isImage());
+ const sym = si.get(coff);
+
+ assert(sym.ni != .none or sym.gmi != .none);
+ const gpa = coff.base.comp.gpa;
+ const gop = try coff.symbol_table.symbols.getOrPut(gpa, si);
+ if (!gop.found_existing) {
+ coff.symbol_prog_node.increaseEstimatedTotalItems(1);
+ gop.value_ptr.* = .none;
}
- return sym_gop.value_ptr.*;
}
fn navSection(
@@ -1247,13 +2861,13 @@ fn navSection(
const ip = &zcu.intern_pool;
const default: String, const attributes: ObjectSectionAttributes =
if (nav_resolved.@"threadlocal" and coff.base.comp.config.any_non_single_threaded) .{
- .@".tls$", .{ .read = true, .write = true },
+ .@".tls$", .{ .read = true, .write = true, .initialized = true },
} else if (ip.isFunctionType(nav_resolved.type)) .{
.@".text", .{ .read = true, .execute = true },
} else if (nav_resolved.@"const") .{
- .@".rdata", .{ .read = true },
+ .@".rdata", .{ .read = true, .initialized = true },
} else .{
- .@".data", .{ .read = true, .write = true },
+ .@".data", .{ .read = true, .write = true, .initialized = true },
};
return (try coff.objectSectionMapIndex(
@@ -1270,7 +2884,7 @@ fn navSection(
}
fn navMapIndex(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavMapIndex {
const gpa = zcu.gpa;
- try coff.symbol_table.ensureUnusedCapacity(gpa, 1);
+ try coff.symbols.ensureUnusedCapacity(gpa, 1);
const sym_gop = try coff.navs.getOrPut(gpa, nav_index);
if (!sym_gop.found_existing) sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();
return @enumFromInt(sym_gop.index);
@@ -1278,17 +2892,20 @@ fn navMapIndex(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.Na
pub fn navSymbol(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.Index {
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
- if (nav.getExtern(ip)) |@"extern"| return coff.globalSymbol(
- @"extern".name.toSlice(ip),
- @"extern".lib_name.toSlice(ip),
- );
+ if (nav.getExtern(ip)) |@"extern"| return coff.globalSymbol(.{
+ .name = @"extern".name.toSlice(ip),
+ .lib_name = @"extern".lib_name.toSlice(ip),
+ // TODO: Threadlocal as well?
+ .type = if (ip.isFunctionType(nav.resolved.?.type)) .code else .data,
+ .dll_storage_class = if (@"extern".is_dll_import) .dllimport else .default,
+ });
const nmi = try coff.navMapIndex(zcu, nav_index);
return nmi.symbol(coff);
}
fn uavMapIndex(coff: *Coff, uav_val: InternPool.Index) !Node.UavMapIndex {
const gpa = coff.base.comp.gpa;
- try coff.symbol_table.ensureUnusedCapacity(gpa, 1);
+ try coff.symbols.ensureUnusedCapacity(gpa, 1);
const sym_gop = try coff.uavs.getOrPut(gpa, uav_val);
if (!sym_gop.found_existing) sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();
return @enumFromInt(sym_gop.index);
@@ -1300,7 +2917,7 @@ pub fn uavSymbol(coff: *Coff, uav_val: InternPool.Index) !Symbol.Index {
pub fn lazySymbol(coff: *Coff, lazy: link.File.LazySymbol) !Symbol.Index {
const gpa = coff.base.comp.gpa;
- try coff.symbol_table.ensureUnusedCapacity(gpa, 1);
+ try coff.symbols.ensureUnusedCapacity(gpa, 1);
const sym_gop = try coff.lazy.getPtr(lazy.kind).map.getOrPut(gpa, lazy.ty);
if (!sym_gop.found_existing) {
sym_gop.value_ptr.* = try coff.initSymbolAssumeCapacity();
@@ -1314,7 +2931,7 @@ pub fn getNavVAddr(
pt: Zcu.PerThread,
nav: InternPool.Nav.Index,
reloc_info: link.File.RelocInfo,
-) !u64 {
+) link.Error!u64 {
return coff.getVAddr(reloc_info, try coff.navSymbol(pt.zcu, nav));
}
@@ -1322,30 +2939,426 @@ pub fn getUavVAddr(
coff: *Coff,
uav: InternPool.Index,
reloc_info: link.File.RelocInfo,
-) !u64 {
+) link.Error!u64 {
return coff.getVAddr(reloc_info, try coff.uavSymbol(uav));
}
-pub fn getVAddr(coff: *Coff, reloc_info: link.File.RelocInfo, target_si: Symbol.Index) !u64 {
+pub fn getVAddr(coff: *Coff, reloc_info: link.File.RelocInfo, target_si: Symbol.Index) link.Error!u64 {
try coff.addReloc(
@enumFromInt(@intFromEnum(reloc_info.parent.atom_index)),
reloc_info.offset,
target_si,
- reloc_info.addend,
+ .{ .known = reloc_info.addend },
switch (coff.targetLoad(&coff.headerPtr().machine)) {
else => unreachable,
.AMD64 => .{ .AMD64 = .ADDR64 },
.I386 => .{ .I386 = .DIR32 },
},
);
- return coff.optionalHeaderField(.image_base) + target_si.get(coff).rva;
+
+ var vaddr: u64 = target_si.get(coff).rva;
+ if (coff.isImage()) vaddr += coff.optionalHeaderField(.image_base);
+ return vaddr;
+}
+
+/// Caller guarantees there is capacity for one member and two nodes
+fn addMemberAssumeCapacity(coff: *Coff, kind: std.coff.ArchiveMemberHeader.Kind, size: u64) !Member.Index {
+ const comp = coff.base.comp;
+ const gpa = comp.gpa;
+
+ // TODO: These two nodes could to be inside a movable node if kind == .coff|.import
+ const header_ni = try coff.mf.addLastChildNode(gpa, Node.known.file, .{
+ .size = @sizeOf(std.coff.ArchiveMemberHeader),
+ .alignment = .@"2",
+ .fixed = true,
+ .moved = true,
+ });
+
+ const content_ni = try coff.mf.addLastChildNode(gpa, Node.known.file, .{
+ // The actual alignment required by the spec is 2, but to allow aligned access to
+ // the various COFF data structures in-place during linking we overalign
+ .alignment = switch (kind) {
+ .coff => .@"4",
+ else => .@"2",
+ },
+ .size = size,
+ .resized = size > 0,
+ .fixed = true,
+ });
+
+ const mi: Member.Index = @enumFromInt(coff.members.items.len);
+ coff.members.appendAssumeCapacity(.{
+ .kind = kind,
+ .header_ni = header_ni,
+ .content_ni = content_ni,
+ .first_linker_indices = .empty,
+ });
+
+ coff.nodes.appendAssumeCapacity(.{ .archive_member_header = mi });
+ coff.nodes.appendAssumeCapacity(.{ .archive_member = mi });
+
+ switch (kind) {
+ .first_linker, .second_linker, .longnames => {},
+ else => {
+ const new_num_members = coff.members.items.len - Member.Index.known_count;
+ coff.targetStore(
+ coff.secondLinkerMemberNumMembersPtr(),
+ @intCast(new_num_members),
+ );
+
+ const old_size = Node.known.second_linker_member.location(&coff.mf).resolve(&coff.mf)[1];
+ const old_header_size = new_num_members * @sizeOf(u32);
+ const trailing_size: usize = @intCast(old_size - old_header_size);
+ try Node.known.second_linker_member.resize(&coff.mf, gpa, old_size + @sizeOf(u32));
+
+ const slice = Node.known.second_linker_member.slice(&coff.mf);
+ @memmove(
+ slice[old_header_size + @sizeOf(u32) ..][0..trailing_size],
+ slice[old_header_size..][0..trailing_size],
+ );
+
+ // Offset will be written by flushMoved on header_ni
+ },
+ }
+
+ switch (kind) {
+ .first_linker,
+ .longnames,
+ .import,
+ => {},
+ .second_linker,
+ .coff,
+ => {
+ try coff.pending_members.ensureTotalCapacity(
+ gpa,
+ coff.pending_members.capacity() + 1,
+ );
+ coff.member_prog_node.increaseEstimatedTotalItems(1);
+ },
+ }
+
+ return mi;
+}
+
+fn appendMemberSymbolString(
+ coff: *Coff,
+ strings_ni: MappedFile.Node.Index,
+ new_size: u64,
+ name: []const u8,
+ offset: u64,
+) !void {
+ try strings_ni.resize(&coff.mf, coff.base.comp.gpa, new_size);
+ const name_slice = strings_ni.slice(&coff.mf)[offset..][0 .. name.len + 1];
+ @memcpy(name_slice[0..name.len], name);
+ name_slice[name.len] = 0;
}
-fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags) !Symbol.Index {
+fn ensureMemberSymbol(coff: *Coff, mi: Member.Index, name: String) !void {
+ const gpa = coff.base.comp.gpa;
+ const member = mi.get(coff);
+ assert(member.kind == .coff);
+
+ const gop = try member.first_linker_indices.getOrPut(gpa, .{ .mi = mi, .name = name });
+ if (gop.found_existing) return;
+
+ const mfli: Member.FirstLinkerIndex = blk: {
+ const num_symbols_ptr = coff.firstLinkerMemberNumSymbolsPtr();
+ const num_symbols = std.mem.toNative(u32, num_symbols_ptr.*, .big);
+ num_symbols_ptr.* = std.mem.nativeTo(u32, num_symbols + 1, .big);
+ break :blk @enumFromInt(num_symbols);
+ };
+
+ gop.value_ptr.* = mfli;
+
+ // Linker member fields are not modeled as nodes because MappedFile
+ // can't guarantee that they will be tightly packed after resizing
+
+ const name_slice = name.toSlice(coff);
+ const new_string_table_size: u32 = @intCast(coff.lib_string_len + name_slice.len + 1);
+ defer coff.lib_string_len = new_string_table_size;
+
+ {
+ const old_header_size: usize = @intCast(@sizeOf(u32) + @intFromEnum(mfli) * @sizeOf(u32));
+ const new_header_size: usize = @intCast(old_header_size + @sizeOf(u32));
+ try Node.known.first_linker_member.resize(&coff.mf, gpa, new_header_size + new_string_table_size);
+
+ const slice = Node.known.first_linker_member.slice(&coff.mf);
+ @memmove(slice[new_header_size..][0..coff.lib_string_len], slice[old_header_size..][0..coff.lib_string_len]);
+ @memcpy(slice[new_header_size + coff.lib_string_len ..][0..name_slice.len], name_slice[0..name_slice.len]);
+ slice[new_header_size + coff.lib_string_len + name_slice.len] = 0;
+
+ // New offset entry is written in flushMember
+ }
+
+ {
+ const num_members = coff.targetLoad(coff.secondLinkerMemberNumMembersPtr());
+ const old_header_size = 2 * @sizeOf(u32) + num_members * @sizeOf(u32) + @intFromEnum(mfli) * @sizeOf(u16);
+ const new_header_size = old_header_size + @sizeOf(u16);
+ try Node.known.second_linker_member.resize(&coff.mf, gpa, new_header_size + new_string_table_size);
+
+ const old_needs_sort = coff.pending_members.get(Member.Index.second) != null;
+ const needs_sort = old_needs_sort or (if (coff.lib_string_table.items.len > 0)
+ std.mem.lessThan(
+ u8,
+ name_slice,
+ coff.lib_string_table.items[coff.lib_string_table.items.len - 1].toSlice(coff),
+ )
+ else
+ false);
+
+ try coff.lib_string_table.append(gpa, name);
+
+ const slice = Node.known.second_linker_member.slice(&coff.mf);
+ coff.targetStore(coff.secondLinkerMemberNumSymbolsPtr(), @intFromEnum(mfli) + 1);
+ if (!needs_sort) {
+ @memmove(slice[new_header_size..][0..coff.lib_string_len], slice[old_header_size..][0..coff.lib_string_len]);
+ @memcpy(slice[new_header_size + coff.lib_string_len ..][0..name_slice.len], name_slice[0..name_slice.len]);
+ slice[new_header_size + coff.lib_string_len + name_slice.len] = 0;
+ } else if (!old_needs_sort) {
+ // The entire string table is rebuilt in flushMember after sorting
+ coff.pending_members.putAssumeCapacity(Member.Index.second, {});
+ }
+
+ // Indices in this table are 1-based
+ const index_ptr: *u16 = @ptrCast(@alignCast(slice[old_header_size..]));
+ coff.targetStore(index_ptr, @intCast(@intFromEnum(mi) - Member.Index.known_count + 1));
+ }
+
+ coff.pending_members.putAssumeCapacity(mi, {});
+ coff.member_prog_node.increaseEstimatedTotalItems(1);
+}
+
+fn flushSymbolTableEntry(coff: *Coff, index: u32, pt: Zcu.PerThread) !void {
+ assert(!coff.isImage());
+ const gpa = coff.base.comp.gpa;
+
+ const si = coff.symbol_table.symbols.keys()[index];
+ const sti = &coff.symbol_table.symbols.values()[index];
+
+ const sym = si.get(coff);
+ assert(sym.ni != .none or sym.gmi != .none);
+
+ const entry = coff.symbolTableEntryPtr(sti.*) orelse entry: {
+ var buf: [15]u8 = undefined;
+ const symbol_name, const num_aux_symbols: u8, const complex_type: std.coff.ComplexType =
+ if (sym.gmi != .none) blk: {
+ const name = sym.gmi.name(coff);
+ break :blk .{
+ try coff.getOrPutSymbolName(name.toSlice(coff), name),
+ @intFromBool(sym.flags.weak_external_strat != .none),
+ if (Symbol.Index.text.get(coff).section_number == sym.section_number)
+ .FUNCTION
+ else
+ .NULL,
+ };
+ } else blk: switch (coff.getNode(sym.ni)) {
+ .image_section => .{
+ try coff.getOrPutSymbolName(&sym.section_number.header(coff).name, null),
+ 1,
+ .NULL,
+ },
+ .nav => |nmi| {
+ const zcu = coff.base.comp.zcu.?;
+ const ip = &zcu.intern_pool;
+ const nav = ip.getNav(nmi.navIndex(coff));
+ break :blk .{
+ try coff.getOrPutSymbolName(nav.fqn.toSlice(ip), null),
+ 0,
+ if (ip.isFunctionType(nav.resolved.?.type)) .FUNCTION else .NULL,
+ };
+ },
+ .uav => |umi| {
+ var w = Io.Writer.fixed(&buf);
+ w.print("__anon_{x}", .{umi.uavValue(coff)}) catch unreachable;
+ break :blk .{
+ try coff.getOrPutSymbolName(w.buffered(), null),
+ 0,
+ .NULL,
+ };
+ },
+ inline .lazy_code, .lazy_const_data => |mi, tag| {
+ const lazy_sym = mi.lazySymbol(coff);
+ const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{
+ @tagName(lazy_sym.kind),
+ Type.fromInterned(lazy_sym.ty).fmt(pt),
+ });
+ defer gpa.free(name);
+
+ const string = try coff.getOrPutString(name);
+ break :blk .{
+ try coff.getOrPutSymbolName(string.toSlice(coff), string),
+ 0,
+ if (tag == .lazy_code) .FUNCTION else .NULL,
+ };
+ },
+ else => {
+ log.err("TODO implement symbol table init for {s} ({d})", .{ @tagName(coff.getNode(sym.ni)), si });
+ unreachable;
+ },
+ };
+
+ const old_num_symbols = coff.targetLoad(&coff.headerPtr().number_of_symbols);
+ const new_num_symbols = old_num_symbols + 1 + num_aux_symbols;
+ coff.targetStore(&coff.headerPtr().number_of_symbols, new_num_symbols);
+
+ try coff.symbol_table.ni.resize(&coff.mf, gpa, new_num_symbols * std.coff.Symbol.sizeOf());
+
+ sti.* = .wrap(old_num_symbols);
+ si.flushSymbolTableIndex(coff);
+
+ const entry = coff.symbolTableEntryPtr(sti.*).?;
+ symbol_name.store(coff, &entry.name);
+
+ entry.section_number = @enumFromInt(@intFromEnum(sym.section_number));
+ entry.type = .{
+ .complex_type = complex_type,
+ .base_type = .NULL,
+ };
+
+ entry.storage_class = if (sym.gmi != .none)
+ .EXTERNAL
+ else if (sym.flags.extra_tag == .next_alias_si) storage: {
+ var alias_sym = sym;
+ const weak_external = while (alias_sym.flags.extra_tag == .next_alias_si) {
+ const alias_si = alias_sym.extra.next_alias_si;
+ alias_sym = alias_si.get(coff);
+ assert(alias_sym.ni == sym.ni);
+ if (alias_sym.flags.weak_external_strat != .none)
+ break true;
+ } else false;
+ break :storage if (weak_external) .EXTERNAL else .STATIC;
+ } else .STATIC;
+
+ entry.number_of_aux_symbols = num_aux_symbols;
+ if (coff.targetEndian() != native_endian)
+ std.mem.byteSwapAllFieldsAligned(std.coff.Symbol, .@"2", entry);
+
+ if (num_aux_symbols > 0) aux_init: {
+ if (sym.gmi != .none) {
+ entry.section_number = .UNDEFINED;
+ entry.storage_class = .WEAK_EXTERNAL;
+
+ const tag_index = sym.value.weak_alias_si.sti(coff).unwrap().?;
+ const aux_ptr = coff.symbolTableWeakExternalAuxEntryPtr(sti.*).?;
+ aux_ptr.* = .{
+ .tag_index = tag_index,
+ .flag = switch (sym.flags.weak_external_strat) {
+ .none => unreachable,
+ .no_library => .SEARCH_NOLIBRARY,
+ .library => .SEARCH_LIBRARY,
+ .alias => .SEARCH_ALIAS,
+ .anti_dependency => .ANTI_DEPENDENCY,
+ },
+ .unused = @splat(0),
+ };
+ if (coff.targetEndian() != native_endian)
+ std.mem.byteSwapAllFieldsAligned(std.coff.WeakExternalDefinition, .@"2", aux_ptr);
+
+ break :aux_init;
+ } else switch (coff.getNode(sym.ni)) {
+ .image_section => |sec_si| {
+ assert(si == sec_si);
+ const header = sym.section_number.header(coff);
+ const aux_ptr = coff.symbolTableSectionAuxEntryPtr(sti.*).?;
+ aux_ptr.* = .{
+ .length = @intCast(sym.ni.location(&coff.mf).resolve(&coff.mf)[1]),
+ .number_of_relocations = header.number_of_relocations,
+ .number_of_linenumbers = header.number_of_linenumbers,
+ .checksum = 0,
+ .number = 0,
+ .selection = .NONE,
+ .unused = @splat(0),
+ };
+ if (coff.targetEndian() != native_endian)
+ std.mem.byteSwapAllFieldsAligned(std.coff.SectionDefinition, .@"2", aux_ptr);
+
+ break :aux_init;
+ },
+ else => {},
+ }
+
+ unreachable;
+ }
+
+ break :entry entry;
+ };
+
+ coff.targetStore(&entry.value, switch (sym.section_number) {
+ .UNDEFINED => if (entry.storage_class == .WEAK_EXTERNAL) 0 else sym.size(),
+ .ABSOLUTE,
+ .DEBUG,
+ => unreachable,
+ else => switch (coff.getNode(sym.ni)) {
+ .image_section => 0,
+ else => coff.computeSymbolSectionOffset(sym, .image),
+ },
+ });
+
+ log.debug("flushSymbolTableEntry({d}) = {d}", .{ si, sti.* });
+}
+
+fn flushInputMember(coff: *Coff, iami: InputArchive.Member.Index) !void {
+ const member = iami.member(coff);
+ assert(!member.flags.is_loaded);
+ defer member.flags.is_loaded = true;
+ switch (member.content) {
+ .import => unreachable,
+ .object => |file_location| {
+ if (file_location.size == 0) return;
+ const comp = coff.base.comp;
+ const io = comp.io;
+ const path = member.iai.path(coff);
+ const file = try path.root_dir.handle.openFile(io, path.sub_path, .{});
+ defer file.close(io);
+ var buffer: [4096]u8 = undefined;
+ var fr = file.reader(io, &buffer);
+ const offset = file_location.offset + @sizeOf(std.coff.ArchiveMemberHeader);
+ try fr.seekTo(offset);
+ log.debug("flushInputMember({f}({s}))", .{ path, member.name.toSlice(coff) });
+ try coff.loadObject(path, member.name.toSlice(coff), &fr, .{
+ .offset = offset,
+ .size = file_location.size,
+ });
+ },
+ }
+}
+
+fn flushInputSection(coff: *Coff, isi: Node.InputSection.Index) !void {
+ const file_loc = isi.fileLocation(coff);
+ if (file_loc.size == 0) return;
+ const comp = coff.base.comp;
+ const io = comp.io;
+ const gpa = comp.gpa;
+ const ioi = isi.input(coff);
+ const path = ioi.path(coff);
+ const file = try path.root_dir.handle.openFile(io, path.sub_path, .{});
+ defer file.close(io);
+ var fr = file.reader(io, &.{});
+ try fr.seekTo(file_loc.offset);
+ var nw: MappedFile.Node.Writer = undefined;
+ const si = isi.symbol(coff);
+ si.node(coff).writer(&coff.mf, gpa, &nw);
+ defer nw.deinit();
+ log.debug("flushInputSection({f}{f}, {s}, {d}, n{d})", .{
+ path,
+ fmtMemberNameString(ioi.memberName(coff)),
+ si.get(coff).section_number.name(coff).toSlice(coff),
+ si,
+ si.node(coff),
+ });
+ if (try nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) != file_loc.size)
+ return error.EndOfStream;
+ try si.applyLocationRelocs(coff);
+}
+
+fn addSection(coff: *Coff, name: String, flags: std.coff.SectionHeader.Flags) !Symbol.Index {
+ assert(coff.hasCoffHeader());
+
const gpa = coff.base.comp.gpa;
try coff.nodes.ensureUnusedCapacity(gpa, 1);
- try coff.image_section_table.ensureUnusedCapacity(gpa, 1);
- try coff.symbol_table.ensureUnusedCapacity(gpa, 1);
+ try coff.section_table.ensureUnusedCapacity(gpa, 1);
+ try coff.symbols.ensureUnusedCapacity(gpa, 1);
+ if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1);
const coff_header = coff.headerPtr();
const section_index = coff.targetLoad(&coff_header.number_of_sections);
@@ -1356,21 +3369,32 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags
gpa,
@sizeOf(std.coff.SectionHeader) * section_table_len,
);
- const ni = try coff.mf.addLastChildNode(gpa, .root, .{
+
+ const ni = try coff.mf.addLastChildNode(gpa, coff.sectionParent(), .{
.alignment = coff.mf.flags.block_size,
.moved = true,
.bubbles_moved = false,
});
+
const si = coff.addSymbolAssumeCapacity();
- coff.image_section_table.appendAssumeCapacity(si);
+ coff.section_table.putAssumeCapacity(name, .{
+ .si = si,
+ .relocation_table_ni = .none,
+ });
coff.nodes.appendAssumeCapacity(.{ .image_section = si });
const section_table = coff.sectionTableSlice();
- const virtual_size = coff.optionalHeaderField(.section_alignment);
- const rva: u32 = switch (section_index) {
- 0 => @intCast(Node.known.header.location(&coff.mf).resolve(&coff.mf)[1]),
- else => coff.image_section_table.items[section_index - 1].get(coff).rva +
- coff.targetLoad(§ion_table[section_index - 1].virtual_size),
- };
+
+ const virtual_size, const rva = if (coff.isImage()) block: {
+ const virtual_size = coff.optionalHeaderField(.section_alignment);
+ const rva: u32 = switch (section_index) {
+ 0 => @intCast(Node.known.header.location(&coff.mf).resolve(&coff.mf)[1]),
+ else => coff.section_table.values()[section_index - 1].si.get(coff).rva +
+ coff.targetLoad(§ion_table[section_index - 1].virtual_size),
+ };
+
+ break :block .{ virtual_size, rva };
+ } else .{ 0, 0 };
+
{
const sym = si.get(coff);
sym.ni = ni;
@@ -1390,16 +3414,24 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags
.number_of_linenumbers = 0,
.flags = flags,
};
- @memcpy(section.name[0..name.len], name);
- @memset(section.name[name.len..], 0);
if (coff.targetEndian() != native_endian)
std.mem.byteSwapAllFields(std.coff.SectionHeader, section);
- switch (coff.optionalHeaderPtr()) {
- inline else => |optional_header| coff.targetStore(
- &optional_header.size_of_image,
- @intCast(rva + virtual_size),
- ),
+
+ const name_slice = name.toSlice(coff);
+ if (coff.isImage()) {
+ @memcpy(section.name[0..name_slice.len], name_slice);
+ @memset(section.name[name_slice.len..], 0);
+ switch (coff.optionalHeaderPtr()) {
+ inline else => |optional_header| coff.targetStore(
+ &optional_header.size_of_image,
+ @intCast(rva + virtual_size),
+ ),
+ }
+ } else {
+ (try coff.getOrPutSymbolName(name_slice, name)).store(coff, §ion.name);
+ try coff.pendingSymbolTableEntry(si);
}
+
return si;
}
@@ -1412,7 +3444,40 @@ const ObjectSectionAttributes = packed struct {
nocache: bool = false,
discard: bool = false,
remove: bool = false,
+ initialized: bool = false,
+ uninitialized: bool = false,
+
+ pub fn fromFlags(flags: std.coff.SectionHeader.Flags) ObjectSectionAttributes {
+ return .{
+ .read = flags.MEM_READ,
+ .write = flags.MEM_WRITE,
+ .execute = flags.MEM_EXECUTE,
+ .shared = flags.MEM_SHARED,
+ .nopage = flags.MEM_NOT_PAGED,
+ .nocache = flags.MEM_NOT_CACHED,
+ .discard = flags.MEM_DISCARDABLE,
+ .remove = flags.LNK_REMOVE,
+ .initialized = flags.CNT_INITIALIZED_DATA,
+ .uninitialized = flags.CNT_UNINITIALIZED_DATA,
+ };
+ }
+
+ pub fn asFlags(attr: ObjectSectionAttributes) std.coff.SectionHeader.Flags {
+ return .{
+ .MEM_READ = attr.read,
+ .MEM_WRITE = attr.write,
+ .MEM_EXECUTE = attr.execute,
+ .MEM_SHARED = attr.shared,
+ .MEM_NOT_PAGED = attr.nopage,
+ .MEM_NOT_CACHED = attr.nocache,
+ .MEM_DISCARDABLE = attr.discard,
+ .LNK_REMOVE = attr.remove,
+ .CNT_INITIALIZED_DATA = attr.uninitialized,
+ .CNT_UNINITIALIZED_DATA = attr.uninitialized,
+ };
+ }
};
+
fn pseudoSectionMapIndex(
coff: *Coff,
name: String,
@@ -1422,15 +3487,25 @@ fn pseudoSectionMapIndex(
const gpa = coff.base.comp.gpa;
const pseudo_section_gop = try coff.pseudo_section_table.getOrPut(gpa, name);
const psmi: Node.PseudoSectionMapIndex = @enumFromInt(pseudo_section_gop.index);
- if (!pseudo_section_gop.found_existing) {
- const parent: Symbol.Index = if (attributes.execute)
- .text
- else if (attributes.write)
- .data
- else
- .rdata;
+ const parent_sn = if (!pseudo_section_gop.found_existing) sn: {
+ const effective_name = coff.section_merges.get(name) orelse name;
+ const parent = if (coff.section_table.get(effective_name)) |existing_sec|
+ existing_sec.si
+ else if (coff.isImage()) parent: {
+ const parent: Symbol.Index = if (attributes.uninitialized)
+ .bss
+ else if (attributes.execute)
+ .text
+ else if (attributes.write)
+ .data
+ else
+ .rdata;
+
+ break :parent parent;
+ } else try coff.addSection(effective_name, attributes.asFlags());
+
try coff.nodes.ensureUnusedCapacity(gpa, 1);
- try coff.symbol_table.ensureUnusedCapacity(gpa, 1);
+ try coff.symbols.ensureUnusedCapacity(gpa, 1);
const ni = try coff.mf.addLastChildNode(gpa, parent.node(coff), .{ .alignment = alignment });
const si = coff.addSymbolAssumeCapacity();
pseudo_section_gop.value_ptr.* = si;
@@ -1441,9 +3516,30 @@ fn pseudoSectionMapIndex(
assert(sym.loc_relocs == .none);
sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
coff.nodes.appendAssumeCapacity(.{ .pseudo_section = psmi });
- }
+ break :sn sym.section_number;
+ } else pseudo_section_gop.value_ptr.get(coff).section_number;
+
+ try coff.verifyParentSectionAttributes(
+ parent_sn,
+ name,
+ .pseudo,
+ .fromFlags(parent_sn.header(coff).flags),
+ attributes,
+ );
+
return psmi;
}
+
+fn objectSectionParentName(coff: *Coff, name: []const u8) []const u8 {
+ // In images we want to sort object sections into the final root section name.
+ // Otherwise, we want to keep the full name so that this sort can occur correctly when
+ // the object is finally linked into an image.
+ return if (coff.isImage())
+ name[0 .. std.mem.indexOfScalar(u8, name, '$') orelse name.len]
+ else
+ name;
+}
+
fn objectSectionMapIndex(
coff: *Coff,
name: String,
@@ -1451,16 +3547,23 @@ fn objectSectionMapIndex(
attributes: ObjectSectionAttributes,
) !Node.ObjectSectionMapIndex {
const gpa = coff.base.comp.gpa;
+ const name_slice = name.toSlice(coff);
+ // TODO: Should this be a section merge instead?
+ const effective_attributes = if (coff.isImage() and std.mem.startsWith(u8, name_slice, ".tls")) attr: {
+ // In images, the .tls section is a read-only template
+ var attr = attributes;
+ attr.write = false;
+ break :attr attr;
+ } else attributes;
+
const object_section_gop = try coff.object_section_table.getOrPut(gpa, name);
const osmi: Node.ObjectSectionMapIndex = @enumFromInt(object_section_gop.index);
- if (!object_section_gop.found_existing) {
- try coff.ensureUnusedStringCapacity(name.toSlice(coff).len);
- const name_slice = name.toSlice(coff);
- const parent = (try coff.pseudoSectionMapIndex(coff.getOrPutStringAssumeCapacity(
- name_slice[0 .. std.mem.indexOfScalar(u8, name_slice, '$') orelse name_slice.len],
- ), alignment, attributes)).symbol(coff);
+ const sym = if (!object_section_gop.found_existing) sym: {
+ try coff.ensureUnusedStringCapacity(name_slice.len);
+ const parent_name = coff.getOrPutStringAssumeCapacity(coff.objectSectionParentName(name_slice));
+ const parent = (try coff.pseudoSectionMapIndex(parent_name, alignment, effective_attributes)).symbol(coff);
try coff.nodes.ensureUnusedCapacity(gpa, 1);
- try coff.symbol_table.ensureUnusedCapacity(gpa, 1);
+ try coff.symbols.ensureUnusedCapacity(gpa, 1);
const parent_ni = parent.node(coff);
var prev_ni: MappedFile.Node.Index = .none;
var next_it = parent_ni.children(&coff.mf);
@@ -1492,30 +3595,219 @@ fn objectSectionMapIndex(
assert(sym.loc_relocs == .none);
sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
coff.nodes.appendAssumeCapacity(.{ .object_section = osmi });
+ break :sym sym;
+ } else object_section_gop.value_ptr.get(coff);
+
+ const parent_ni = sym.ni.parent(&coff.mf);
+ const parent_alignment = parent_ni.alignment(&coff.mf);
+ if (alignment.compare(.gt, parent_alignment)) {
+ log.debug("realignParent({s}, {d}) {d}->{d}", .{ name.toSlice(coff), parent_ni, parent_alignment, alignment });
+ try parent_ni.realign(&coff.mf, gpa, alignment, .{ .set_alignment = true });
}
+
+ const old_alignment = sym.ni.alignment(&coff.mf);
+ if (alignment.compare(.gt, old_alignment)) {
+ log.debug("realignObject({s}) {d}->{d}", .{ name.toSlice(coff), old_alignment, alignment });
+ try sym.ni.realign(&coff.mf, gpa, alignment, .{ .set_alignment = true });
+ }
+
+ try coff.verifyParentSectionAttributes(
+ sym.section_number,
+ name,
+ .object,
+ .fromFlags(sym.section_number.header(coff).flags),
+ effective_attributes,
+ );
+
return osmi;
}
+fn verifyParentSectionAttributes(
+ coff: *Coff,
+ parent: Symbol.SectionNumber,
+ child_name: String,
+ child_kind: enum { pseudo, object },
+ parent_attrs: ObjectSectionAttributes,
+ child_attrs: ObjectSectionAttributes,
+) !void {
+ if (parent_attrs == child_attrs) return;
+
+ const was_merged = switch (child_kind) {
+ .pseudo => coff.section_merges.contains(child_name),
+ .object => if (coff.getString(
+ coff.objectSectionParentName(child_name.toSlice(coff)),
+ ).unwrap()) |pseudo_name|
+ coff.section_merges.contains(pseudo_name)
+ else
+ false,
+ };
+
+ // The section was intentionally merged by the user or builtin rule
+ if (was_merged) return;
+
+ const BackingT = @typeInfo(ObjectSectionAttributes).@"struct".backing_integer.?;
+ const num_notes = @popCount(@as(BackingT, @bitCast(parent_attrs)) ^ @as(BackingT, @bitCast(child_attrs)));
+ var err = try coff.base.comp.link_diags.addErrorWithNotes(num_notes);
+ try err.addMsg("{t} section '{s}' was placed in parent section '{s}' with mismatched flags", .{
+ child_kind,
+ child_name.toSlice(coff),
+ parent.name(coff).toSlice(coff),
+ });
+
+ inline for (comptime std.meta.fieldNames(ObjectSectionAttributes)) |field| {
+ if (@field(child_attrs, field) != @field(parent_attrs, field)) {
+ err.addNote("flags.{s} was {d} in {s}, but {d} in {s}", .{
+ field,
+ @intFromBool(@field(child_attrs, field)),
+ child_name.toSlice(coff),
+ @intFromBool(@field(parent_attrs, field)),
+ parent.name(coff).toSlice(coff),
+ });
+ }
+ }
+
+ return error.AlreadyReported;
+}
+
+const RelocAddend = union(enum) {
+ known: i64,
+ /// Relocs tables in input objects don't include the addend.
+ /// The value needs to be recovered from the reloc location.
+ pending: void,
+};
+
+// TODO: There should be an API where the caller can indicate how many contiguous relocs they need
+// and it should attempt to allocate these from from the free list if available. We can cache
+// the run length of each segment on Reloc when `free` is set.
pub fn addReloc(
coff: *Coff,
loc_si: Symbol.Index,
offset: u64,
target_si: Symbol.Index,
- addend: i64,
+ addend: RelocAddend,
+ @"type": Reloc.Type,
+) link.Error!void {
+ const diags = &coff.base.comp.link_diags;
+ try coff.ensureUnusedRelocCapacity(loc_si, 1);
+ coff.addRelocAssumeCapacity(loc_si, offset, target_si, addend, @"type") catch |err| switch (err) {
+ error.MappedFileIo => return diags.fail(
+ "failed to write output file: {t}",
+ .{coff.mf.io_err.?},
+ ),
+ else => |e| return e,
+ };
+}
+
+fn ensureUnusedRelocCapacity(coff: *Coff, loc_si: Symbol.Index, len: usize) !void {
+ const gpa = coff.base.comp.gpa;
+ try coff.relocs.ensureUnusedCapacity(gpa, len);
+ if (isImage(coff)) return;
+ switch (loc_si.get(coff).section_number) {
+ .UNDEFINED, .ABSOLUTE, .DEBUG => {},
+ else => |loc_sn| {
+ const section = loc_sn.section(coff);
+ if (section.relocation_table_ni == .none)
+ try coff.nodes.ensureUnusedCapacity(gpa, 1);
+ },
+ }
+}
+
+fn addRelocAssumeCapacity(
+ coff: *Coff,
+ loc_si: Symbol.Index,
+ offset: u64,
+ target_si: Symbol.Index,
+ addend: RelocAddend,
@"type": Reloc.Type,
) !void {
const gpa = coff.base.comp.gpa;
const target = target_si.get(coff);
+
const ri: Reloc.Index = @enumFromInt(coff.relocs.items.len);
- (try coff.relocs.addOne(gpa)).* = .{
+ log.debug("addReloc({d}@{d}+0x{x} -> {d}@{d}+0x{x}{s}) = {d}", .{
+ loc_si,
+ loc_si.get(coff).section_number,
+ offset,
+ target_si,
+ target_si.get(coff).section_number,
+ if (addend == .pending) 0 else addend.known,
+ if (addend == .pending) "p" else "k",
+ ri,
+ });
+
+ const sri: Section.RelocationIndex = if (isImage(coff))
+ .none
+ else switch (loc_si.get(coff).section_number) {
+ .UNDEFINED,
+ .ABSOLUTE,
+ .DEBUG,
+ => .none,
+ else => |loc_sn| sri: {
+ // The target may not have a node yet, or it could be an extern that will never
+ // have a node. In that case, flushGlobal will create the symbol table entry.
+ const existing_sti = target_si.sti(coff);
+ const sti: SymbolTable.Index = if (existing_sti != .none)
+ existing_sti
+ else if (target.ni != .none) sti: {
+ try coff.pendingSymbolTableEntry(target_si);
+ break :sti .none;
+ } else .none;
+
+ const sri: Section.RelocationIndex = blk: {
+ const section = loc_sn.section(coff);
+ const header = loc_sn.header(coff);
+ const old_num_relocations = coff.targetLoad(&header.number_of_relocations);
+ const new_num_relocations = old_num_relocations + 1;
+ const new_size = @as(u32, new_num_relocations) * std.coff.Relocation.sizeOf();
+
+ coff.targetStore(&header.number_of_relocations, new_num_relocations);
+ if (coff.symbolTableSectionAuxEntryPtr(loc_sn.symbol(coff).sti(coff))) |aux_ptr|
+ coff.targetStore(&aux_ptr.number_of_relocations, new_num_relocations);
+
+ if (section.relocation_table_ni == .none) {
+ section.relocation_table_ni = try coff.mf.addLastChildNode(
+ gpa,
+ coff.sectionParent(),
+ .{
+ .size = new_size,
+ .alignment = .@"2",
+ .moved = true,
+ .resized = true,
+ },
+ );
+ coff.nodes.appendAssumeCapacity(.{ .relocation_table = loc_sn });
+ } else {
+ try section.relocation_table_ni.resize(&coff.mf, gpa, new_size);
+ }
+
+ // TODO: These need to allocate from a free list, once deleting relocs from the table is supported
+ break :blk .wrap(old_num_relocations);
+ };
+
+ const entry = sri.entry(coff, loc_sn).?;
+ if (sti.unwrap()) |index| coff.targetStore(&entry.symbol_table_index, index);
+
+ // applyLocationRelocs updates `virtual_address`
+ // flushSymbolTableIndex updates `symbol_table_index`
+ coff.targetStore(&entry.type, @"type".u16);
+
+ break :sri sri;
+ },
+ };
+
+ coff.relocs.addOneAssumeCapacity().* = .{
.type = @"type",
.prev = .none,
.next = target.target_relocs,
.loc = loc_si,
.target = target_si,
- .unused = 0,
+ .sri = sri,
.offset = offset,
- .addend = addend,
+ .addend = if (addend == .pending) 0 else addend.known,
+ .flags = .{
+ .recover_addend = addend == .pending,
+ .free = false,
+ },
};
switch (target.target_relocs) {
.none => {},
@@ -1524,15 +3816,1641 @@ pub fn addReloc(
target.target_relocs = ri;
}
+fn failLoadInput(
+ coff: *Coff,
+ err: LoadInputError,
+ fr: *Io.File.Reader,
+ path: std.Build.Cache.Path,
+) link.Error {
+ const diags = &coff.base.comp.link_diags;
+ switch (err) {
+ else => |e| return e,
+ error.MappedFileIo => return diags.fail(
+ "failed to write output file: {t}",
+ .{coff.mf.io_err.?},
+ ),
+ error.EndOfStream => return diags.failParse(
+ path,
+ "unexpected eof",
+ .{},
+ ),
+ error.AccessDenied,
+ error.Unexpected,
+ error.Unseekable,
+ => |e| return diags.fail(
+ "failed to read \"{f}\": {t}",
+ .{ path.fmtEscapeString(), e },
+ ),
+ error.PermissionDenied,
+ error.SystemResources,
+ error.Streaming,
+ => |e| return diags.fail(
+ "failed to stat \"{f}\": {t}",
+ .{ path.fmtEscapeString(), e },
+ ),
+ error.ReadFailed => switch (fr.err.?) {
+ error.Canceled => |e| return e,
+ else => |e| return diags.fail(
+ "failed to read \"{f}\": {t}",
+ .{ path.fmtEscapeString(), e },
+ ),
+ },
+ }
+}
+
+pub fn loadInput(coff: *Coff, input: link.Input) link.Error!void {
+ const comp = coff.base.comp;
+ const io = comp.io;
+
+ const path = input.path() orelse unreachable;
+ const gop = try coff.inputs.getOrPut(comp.gpa, path);
+ if (gop.found_existing) return;
+ errdefer _ = coff.inputs.swapRemove(path);
+
+ var buf: [4096]u8 = undefined;
+ switch (input) {
+ .object => |object| {
+ var fr = object.file.reader(io, &buf);
+ coff.loadObject(object.path, null, &fr, .{
+ .offset = fr.logicalPos(),
+ .size = fr.getSize() catch |err|
+ return coff.failLoadInput(err, &fr, object.path),
+ }) catch |err| return coff.failLoadInput(err, &fr, object.path);
+ },
+ .archive => |archive| {
+ var fr = archive.file.reader(io, &buf);
+ coff.loadArchive(archive.path, &fr) catch |err|
+ return coff.failLoadInput(err, &fr, archive.path);
+ },
+ .res => |res| {
+ var fr = res.file.reader(io, &buf);
+ coff.loadRes(res.path, &fr) catch |err|
+ return coff.failLoadInput(err, &fr, res.path);
+ },
+ .dso => |dso| {
+ var fr = dso.file.reader(io, &buf);
+ coff.loadDll(dso.path, &fr) catch |err|
+ return coff.failLoadInput(err, &fr, dso.path);
+ },
+ .dso_exact => unreachable,
+ }
+}
+
+fn fmtMemberNameString(memberName: ?[]const u8) std.fmt.Alt(?[]const u8, memberNameStringEscape) {
+ return .{ .data = memberName };
+}
+
+fn memberNameStringEscape(memberName: ?[]const u8, w: *std.Io.Writer) std.Io.Writer.Error!void {
+ try w.print("({f})", .{std.zig.fmtString(memberName orelse return)});
+}
+
+fn inputSectionHeaderNameSlice(
+ coff: *Coff,
+ header: *const std.coff.SectionHeader,
+ string_table: []const u8,
+ path: std.Build.Cache.Path,
+ section_i: usize,
+) ![]const u8 {
+ const diags = &coff.base.comp.link_diags;
+ return if (header.name[0] == '/') name: {
+ const offset_str = std.mem.sliceTo(header.name[1..], 0);
+ const name_offset = std.fmt.parseUnsigned(u24, offset_str, 10) catch
+ return diags.failParse(path, "ill-formed section name in section {d}: '{s}'", .{
+ section_i,
+ header.name[0 .. offset_str.len + 1],
+ });
+
+ if (name_offset > string_table.len)
+ return diags.failParse(path, "out-of-bounds section name offset in section {d}: {d}", .{ section_i, name_offset });
+
+ break :name std.mem.sliceTo(string_table[name_offset..], 0);
+ } else std.mem.sliceTo(&header.name, 0);
+}
+
+fn loadObject(
+ coff: *Coff,
+ path: std.Build.Cache.Path,
+ member_name: ?[]const u8,
+ fr: *Io.File.Reader,
+ fl: MappedFile.Node.FileLocation,
+) LoadInputError!void {
+ const comp = coff.base.comp;
+ const gpa = comp.gpa;
+ const diags = &comp.link_diags;
+ const r = &fr.interface;
+ const target = &comp.root_mod.resolved_target.result;
+ const target_endian = coff.targetEndian();
+ const is_archive = coff.isArchive();
+ assert(!coff.isObj());
+ // We want to evaluate new merges as we see them in .drectve sections to avoid redundant work
+ assert(coff.section_merge_pending_index == coff.section_merges.count());
+
+ log.debug("loadObject({f}{f})", .{ path.fmtEscapeString(), fmtMemberNameString(member_name) });
+
+ const header = try r.peekStruct(std.coff.Header, .little);
+ if (header.machine != target.toCoffMachine())
+ return diags.failParse(path, "machine mismatch: expected {t}, found {t}", .{
+ target.toCoffMachine(),
+ header.machine,
+ });
+ if (header.number_of_sections == 0) return;
+ if (@sizeOf(std.coff.Header) + @as(usize, header.number_of_sections) * @sizeOf(std.coff.SectionHeader) > fl.size)
+ return diags.failParse(path, "invalid section table", .{});
+ const unexpected_header_flags: []const std.meta.FieldEnum(std.coff.Header.Flags) = &.{
+ .RELOCS_STRIPPED,
+ .EXECUTABLE_IMAGE,
+ .AGGRESSIVE_WS_TRIM,
+ .RESERVED,
+ .BYTES_REVERSED_LO,
+ .DLL,
+ .BYTES_REVERSED_HI,
+ };
+ inline for (unexpected_header_flags) |flag|
+ if (@field(header.flags, @tagName(flag)))
+ return diags.failParse(path, "unexpected flag set: {t}", .{flag});
+
+ if (header.size_of_optional_header != 0)
+ return diags.failParse(path, "unexpected optional header", .{});
+
+ const symbol_table_len = header.number_of_symbols * std.coff.Symbol.sizeOf();
+ const symbol_table_end = header.pointer_to_symbol_table + symbol_table_len;
+ // String table length (which includes the length field) immediately trails the symbol table
+ if (symbol_table_end + @sizeOf(u32) > fl.size)
+ return diags.failParse(path, "bad symbol table location", .{});
+
+ try fr.seekTo(fl.offset + symbol_table_end);
+ const string_table_len = try r.peekInt(u32, target_endian);
+ if (string_table_len < @sizeOf(u32) or
+ symbol_table_end + string_table_len > fl.size)
+ return diags.failParse(path, "bad string table length: 0x{x}", .{string_table_len});
+
+ const ioi: InputObject.Index = @enumFromInt(coff.input_objects.items.len);
+ try coff.input_objects.ensureUnusedCapacity(gpa, 1);
+ const input = coff.input_objects.addOneAssumeCapacity();
+ input.* = .{
+ .path = path,
+ .member_name = if (member_name) |m| try gpa.dupe(u8, m) else null,
+ .source_name = .none,
+ };
+
+ const string_table = string_table: {
+ const string_table = try gpa.alloc(u8, string_table_len);
+ errdefer gpa.free(string_table);
+ try r.readSliceAll(string_table);
+ break :string_table string_table;
+ };
+ defer gpa.free(string_table);
+
+ try coff.ensureManyUnusedStringCapacity(
+ header.number_of_sections + header.number_of_symbols,
+ header.number_of_sections * 9 +
+ header.number_of_symbols * 9 +
+ string_table_len - @sizeOf(u32),
+ );
+
+ const PendingSymbolIndex = enum(u32) {
+ none,
+ _,
+
+ pub fn wrap(i: ?u32) @This() {
+ return @enumFromInt((i orelse return .none) + 1);
+ }
+
+ pub fn unwrap(i: @This()) ?u32 {
+ return switch (i) {
+ .none => null,
+ _ => @intFromEnum(i) - 1,
+ };
+ }
+ };
+
+ const PendingInputSection = struct {
+ header: std.coff.SectionHeader,
+ name: String,
+ si: Symbol.Index,
+ parent_si: Symbol.Index,
+ psi: PendingSymbolIndex,
+ num_symbols: u32,
+ comdat: std.coff.ComdatSelection,
+ comdat_psi: PendingSymbolIndex,
+ comdat_crc: u32,
+ comdat_association: Symbol.SectionNumber,
+ comdat_result: union(enum) {
+ pending,
+ // Root of the association chain
+ pending_association: Symbol.SectionNumber,
+ include,
+ skip,
+ },
+ };
+
+ const sections: []PendingInputSection = if (coff.isImage()) sections: {
+ const sections = try gpa.alloc(PendingInputSection, header.number_of_sections);
+ errdefer gpa.free(sections);
+
+ try fr.seekTo(fl.offset + @sizeOf(std.coff.Header));
+ for (sections, 0..) |*section, section_i| {
+ section.* = .{
+ .header = try r.takeStruct(std.coff.SectionHeader, target_endian),
+ .name = undefined,
+ .si = .null,
+ .parent_si = .null,
+ .psi = .none,
+ .num_symbols = 0,
+ .comdat = .NONE,
+ .comdat_psi = .none,
+ .comdat_crc = 0,
+ .comdat_association = .UNDEFINED,
+ .comdat_result = .pending,
+ };
+
+ const section_name_slice = if (section.header.name[0] == '/') name: {
+ const offset_str = std.mem.sliceTo(section.header.name[1..], 0);
+ const name_offset = std.fmt.parseUnsigned(u24, offset_str, 10) catch
+ return diags.failParse(path, "ill-formed section name offset in section {d}: '{s}'", .{
+ section_i,
+ section.header.name[0 .. offset_str.len + 1],
+ });
+
+ if (name_offset > string_table.len)
+ return diags.failParse(
+ path,
+ "out-of-bounds section name offset in section {d}: {d}",
+ .{ section_i, name_offset },
+ );
+
+ break :name std.mem.sliceTo(string_table[name_offset..], 0);
+ } else std.mem.sliceTo(§ion.header.name, 0);
+ section.name = coff.getOrPutStringAssumeCapacity(section_name_slice);
+
+ if (section.header.pointer_to_linenumbers +
+ @as(u32, section.header.number_of_linenumbers) * std.coff.LineNumber.sizeOf() > fl.size)
+ return diags.failParse(path, "bad line numbers location in section {d} `{s}`", .{
+ section_i,
+ section_name_slice,
+ });
+
+ if (section.header.pointer_to_relocations +
+ @as(u32, section.header.number_of_relocations) * std.coff.Relocation.sizeOf() > fl.size)
+ return diags.failParse(path, "bad relocations location in section {d} `{s}`", .{
+ section_i,
+ section_name_slice,
+ });
+
+ if (section.header.pointer_to_raw_data + section.header.size_of_raw_data > fl.size)
+ return diags.failParse(path, "bad raw data location in section {d} `{s}`", .{
+ section_i,
+ section_name_slice,
+ });
+ }
+
+ break :sections sections;
+ } else &.{};
+ defer gpa.free(sections);
+
+ const mi = if (is_archive) mi: {
+ try coff.nodes.ensureUnusedCapacity(gpa, 2);
+ try coff.members.ensureUnusedCapacity(gpa, 1);
+ const path_str = try path.toString(gpa);
+ defer gpa.free(path_str);
+
+ const mi = try coff.addMemberAssumeCapacity(.coff, fl.size);
+ const member = mi.get(coff);
+ try member.initHeader(coff, path_str, header.time_date_stamp);
+
+ {
+ // TODO: This should be deferred to an idle task (but resize it here!)
+ var nw: MappedFile.Node.Writer = undefined;
+ member.content_ni.writer(&coff.mf, gpa, &nw);
+ defer nw.deinit();
+
+ try fr.seekTo(fl.offset);
+ const written = nw.interface.sendFileAll(fr, .limited64(fl.size)) catch |err| switch (err) {
+ error.WriteFailed => return nw.err.?,
+ else => |e| return e,
+ };
+
+ if (written != fl.size) return error.EndOfStream;
+ }
+
+ break :mi mi;
+ } else undefined;
+
+ try fr.seekTo(fl.offset + header.pointer_to_symbol_table);
+ const symbol_size = std.coff.Symbol.sizeOf();
+
+ const PendingSymbol = struct {
+ name: String,
+ value: union(enum) {
+ // Size of the section
+ section: u32,
+ // If section is absolute, the symbol value.
+ // Otherwise, offset within the section.
+ static: u32,
+ // If section is undefined, the symbol size.
+ // If section is absolute, the symbol value.
+ // Otherwise offset within the section.
+ external: u32,
+ // The index of the target symbol of this weak external
+ weak_external: u32,
+ // Trails .weak_external
+ weak_external_aux: WeakExternalStrat,
+ },
+ section_number: Symbol.SectionNumber,
+ si: Symbol.Index,
+ // If a weak external targets this symbol, the index of the weak external
+ weak_external_psi: PendingSymbolIndex,
+ };
+
+ var num_global_symbols: u32 = 0;
+ var pending_symbols: std.array_hash_map.Auto(u32, PendingSymbol) = .empty;
+ defer pending_symbols.deinit(gpa);
+ if (!is_archive)
+ try pending_symbols.ensureUnusedCapacity(gpa, header.number_of_symbols);
+
+ var section_merges: std.ArrayList(struct {
+ from: String,
+ to: String,
+ }) = .empty;
+ defer section_merges.deinit(gpa);
+
+ // Discover symbol names and COMDAT symbol mappings
+ var symbol_i: u32 = 0;
+ var num_included_symbols: u32 = 0;
+ while (symbol_i < header.number_of_symbols) {
+ var symbol: std.coff.Symbol = undefined;
+ @memcpy(std.mem.asBytes(&symbol)[0..symbol_size], try r.take(symbol_size));
+ if (target_endian != native_endian)
+ std.mem.byteSwapAllFields(std.coff.Symbol, &symbol);
+
+ const aux_symbols = if (symbol.number_of_aux_symbols > 0)
+ try r.take(symbol_size * symbol.number_of_aux_symbols)
+ else
+ &.{};
+ defer symbol_i += symbol.number_of_aux_symbols + 1;
+
+ const name = std.mem.sliceTo(if (std.mem.eql(u8, symbol.name[0..4], "\x00\x00\x00\x00")) name: {
+ const index = std.mem.readInt(u32, symbol.name[4..], target_endian);
+ if (index >= string_table.len)
+ return diags.failParse(path, "bad string offset for symbol 0x{x}", .{symbol_i});
+ break :name string_table[index..];
+ } else &symbol.name, 0);
+
+ if (is_archive) {
+ if (switch (symbol.storage_class) {
+ .WEAK_EXTERNAL => true,
+ .EXTERNAL => symbol.section_number != .UNDEFINED,
+ else => false,
+ }) try coff.ensureMemberSymbol(mi, coff.getOrPutStringAssumeCapacity(name));
+
+ continue;
+ }
+
+ switch (symbol.section_number) {
+ .UNDEFINED, .DEBUG, .ABSOLUTE => {},
+ else => |sn| if (@intFromEnum(sn) > sections.len)
+ return diags.failParse(path, "out-of-bounds section number {d} in symbol 0x{x}", .{ sn, symbol_i }),
+ }
+
+ const psi: PendingSymbolIndex = .wrap(@intCast(pending_symbols.count()));
+ const section_number: Symbol.SectionNumber = @enumFromInt(@intFromEnum(symbol.section_number));
+
+ const values: []const @FieldType(PendingSymbol, "value") = pending_symbols: switch (symbol.storage_class) {
+ .STATIC, .LABEL => |storage_class| switch (section_number) {
+ // TODO: Do we need to do anything with @feat.00?
+ // https://llvm.org/doxygen/namespacellvm_1_1COFF.html#aeffa16735e18df727a173beaf748c392
+ .UNDEFINED,
+ .DEBUG,
+ => &.{},
+ .ABSOLUTE => &.{.{ .static = symbol.value }},
+ else => |sn| {
+ const section = §ions[sn.toIndex()];
+
+ // Section symbol
+ const is_section = storage_class == .STATIC and
+ symbol.value == 0 and
+ symbol.type == std.coff.SymType{
+ .complex_type = .NULL,
+ .base_type = .NULL,
+ } and
+ symbol.number_of_aux_symbols > 0;
+
+ if (is_section) {
+ if (symbol.number_of_aux_symbols > 1)
+ return diags.failParse(path, "invalid number of aux symbols for section symbol 0x{x}: {d}", .{
+ symbol_i,
+ symbol.number_of_aux_symbols,
+ });
+
+ var section_def: std.coff.SectionDefinition = undefined;
+ @memcpy(std.mem.asBytes(§ion_def)[0..symbol_size], aux_symbols[0..symbol_size]);
+ if (target_endian != native_endian)
+ std.mem.byteSwapAllFields(std.coff.SectionDefinition, §ion_def);
+
+ if (section_def.number_of_relocations != section.header.number_of_relocations)
+ return diags.failParse(
+ path,
+ "section aux symbol 0x{x} for '{s}' relocation count did not match section header: {d} vs {d}",
+ .{ symbol_i + 1, name, section_def.number_of_relocations, section.header.number_of_relocations },
+ );
+
+ if (section_def.number_of_linenumbers != section.header.number_of_linenumbers)
+ return diags.failParse(
+ path,
+ "section aux symbol 0x{x} for '{s}' line number count did not match section header: {d} vs {d}",
+ .{ symbol_i + 1, name, section_def.number_of_linenumbers, section.header.number_of_linenumbers },
+ );
+
+ if (section.header.flags.LNK_COMDAT) {
+ if (section_def.selection == .ASSOCIATIVE) {
+ if (section_def.number == 0 or section_def.number > sections.len)
+ return diags.failParse(
+ path,
+ "section aux symbol 0x{x} for '{s}' contained an invalid associated section number: 0x{x}",
+ .{ symbol_i + 1, name, section_def.number },
+ );
+
+ section.comdat_association = @enumFromInt(section_def.number);
+ }
+
+ section.comdat = section_def.selection;
+ section.comdat_crc = section_def.checksum;
+ }
+
+ section.psi = psi;
+ }
+
+ break :pending_symbols &.{if (is_section)
+ .{ .section = section.header.size_of_raw_data }
+ else
+ .{ .static = symbol.value }};
+ },
+ },
+ .WEAK_EXTERNAL => switch (symbol.section_number) {
+ .UNDEFINED => {
+ if (symbol.value != 0)
+ return diags.failParse(
+ path,
+ "invalid value {d} for weak external symbol 0x{x}",
+ .{ symbol.value, symbol_i },
+ );
+
+ var weak_external: std.coff.WeakExternalDefinition = undefined;
+ @memcpy(std.mem.asBytes(&weak_external)[0..symbol_size], aux_symbols[0..symbol_size]);
+ if (target_endian != native_endian)
+ std.mem.byteSwapAllFields(std.coff.WeakExternalDefinition, &weak_external);
+
+ if (weak_external.tag_index >= header.number_of_symbols)
+ return diags.failParse(
+ path,
+ "invalid tag_index 0x{x} for weak external symbol 0x{x}",
+ .{ weak_external.tag_index, symbol_i },
+ );
+
+ break :pending_symbols switch (weak_external.flag) {
+ else => |flag| &.{
+ .{ .weak_external = weak_external.tag_index },
+ .{ .weak_external_aux = WeakExternalStrat.fromFlag(flag) },
+ },
+ _ => return diags.failParse(
+ path,
+ "encountered unknown weak external characteristic 0x{x} for symbol 0x{x}",
+ .{ weak_external.flag, symbol_i },
+ ),
+ };
+ },
+ else => |sn| return diags.failParse(
+ path,
+ "invalid section number {d} for weak external symbol 0x{x}",
+ .{ sn, symbol_i },
+ ),
+ },
+ .EXTERNAL => switch (section_number) {
+ .UNDEFINED,
+ .ABSOLUTE,
+ => &.{.{ .external = symbol.value }},
+ .DEBUG => return diags.failParse(
+ path,
+ "unexpected external symbol 0x{x} in DEBUG section: '{s}'",
+ .{ symbol_i, name },
+ ),
+ else => &.{.{ .external = symbol.value }},
+ },
+ .FILE => {
+ if (!std.mem.eql(u8, name, ".file"))
+ return diags.failParse(
+ path,
+ "unexpected symbol name '{s}' for file symbol 0x{x}",
+ .{ name, symbol_i },
+ );
+
+ var file: std.coff.FileDefinition = undefined;
+ @memcpy(std.mem.asBytes(&file)[0..symbol_size], aux_symbols[0..symbol_size]);
+
+ input.source_name = (try coff.getOrPutString(file.getFileName())).toOptional();
+ break :pending_symbols &.{};
+ },
+ else => |storage_class| return diags.failParse(
+ path,
+ "TODO handle storage class {t} for symbol 0x{x}",
+ .{ storage_class, symbol_i },
+ ),
+ };
+
+ for (values, 0..) |value, i| {
+ if (section_number == .ABSOLUTE)
+ num_included_symbols += 1;
+
+ switch (value) {
+ .section => {},
+ .static,
+ .external,
+ .weak_external,
+ => {
+ num_global_symbols += 1;
+ if (section_number.hasIndex()) {
+ const section = §ions[section_number.toIndex()];
+ section.num_symbols += 1;
+ if (section.header.flags.LNK_COMDAT and section.comdat_psi == .none)
+ section.comdat_psi = psi;
+ }
+ },
+ .weak_external_aux => {},
+ }
+
+ const symbol_name = coff.getOrPutStringAssumeCapacity(name);
+ pending_symbols.putAssumeCapacity(symbol_i + @as(u32, @intCast(i)), .{
+ .name = symbol_name,
+ .value = value,
+ .section_number = section_number,
+ .si = .null,
+ .weak_external_psi = .none,
+ });
+ }
+ }
+
+ try coff.globals.ensureUnusedCapacity(gpa, num_global_symbols);
+ for (sections) |*section| {
+ if (section.header.flags.LNK_INFO) {
+ if (std.mem.eql(u8, §ion.header.name, ".drectve")) {
+ try fr.seekTo(fl.offset + section.header.pointer_to_raw_data);
+ // TODO: Don't really want an additional buffer here, but want to limit to size_of_raw_data
+ var buf: [128]u8 = undefined;
+ var section_r = r.limited(.limited(section.header.size_of_raw_data), &buf);
+ while (section_r.interface.takeDelimiter(' ') catch |err| switch (err) {
+ error.StreamTooLong => return diags.failParse(path, "unexpectedly long .drectve argument", .{}),
+ else => |e| return e,
+ }) |arg| {
+ // Microsoft tools emit 3 space characters into this section even with /Zl
+ if (arg.len == 0) continue;
+
+ if (std.ascii.startsWithIgnoreCase(arg, "-exclude-symbols:")) {
+ // TODO: When implementing mingw auto-exports (if at all?), track this to not export this symbol
+ } else if (std.ascii.startsWithIgnoreCase(arg, "/include:")) {
+ _ = try coff.globalSymbol(.{ .name = arg["/include:".len..] });
+ } else if (std.ascii.startsWithIgnoreCase(arg, "/alternatename:")) {
+ var split = std.mem.splitScalar(u8, arg["/alternatename:".len..], '=');
+ const orig = split.first();
+ const alt = split.next() orelse
+ return diags.failParse(path, "malformed .drectve argument: '{s}'", .{arg});
+
+ try coff.ensureManyUnusedStringCapacity(2, orig.len + alt.len + 2);
+ const orig_str = coff.getOrPutStringAssumeCapacity(orig);
+ const alt_str = coff.getOrPutStringAssumeCapacity(alt);
+ const gop = try coff.alternate_names.getOrPut(gpa, orig_str);
+ if (!gop.found_existing) {
+ log.debug("alternateName({s}={s})", .{ orig, alt });
+ gop.value_ptr.* = alt_str;
+ } else if (gop.value_ptr.* != alt_str)
+ return diags.failParse(
+ path,
+ "conflicting /alternatename .drectve arguments: first seen as {s}={s}, now seen as {s}={s}",
+ .{ orig, gop.value_ptr.toSlice(coff), orig, alt },
+ );
+ } else if (std.ascii.startsWithIgnoreCase(arg, "/guardsym:")) {
+ // TODO: https://learn.microsoft.com/en-us/windows/win32/secbp/pe-metadata
+ } else if (std.ascii.startsWithIgnoreCase(arg, "/merge:")) merge: {
+ var split = std.mem.splitScalar(u8, arg["/merge:".len..], '=');
+ const from = split.first();
+ const to = split.next() orelse
+ return diags.failParse(path, "malformed .drectve argument: '{s}'", .{arg});
+ if (to.len > header_name_max_len)
+ return diags.failParse(
+ path,
+ "/merge .drectve target exceeds max length of {d}: '{s}'",
+ .{ header_name_max_len, arg },
+ );
+ if (std.mem.eql(u8, from, to)) break :merge;
+
+ try coff.ensureManyUnusedStringCapacity(2, from.len + to.len + 2);
+ const from_str = coff.getOrPutStringAssumeCapacity(from);
+ const to_str = coff.getOrPutStringAssumeCapacity(to);
+
+ {
+ var iter = to_str;
+ while (coff.section_merges.get(iter)) |next_to| {
+ if (next_to == from_str)
+ return diags.failParse(
+ path,
+ "/merge .drectve argument would create a cycle: {s}={s} leads to {s}={s}",
+ .{ from, to, iter.toSlice(coff), to },
+ );
+
+ iter = next_to;
+ }
+ }
+
+ try coff.section_merges.ensureUnusedCapacity(gpa, 1);
+ const gop = coff.section_merges.getOrPutAssumeCapacity(from_str);
+ if (!gop.found_existing) {
+ coff.synth_prog_node.increaseEstimatedTotalItems(1);
+ gop.value_ptr.* = to_str;
+ } else if (gop.value_ptr.* != to_str)
+ return diags.failParse(
+ path,
+ "conflicting /merge .drectve arguments: first seen as {s}={s}, now seen as {s}={s}",
+ .{ from, gop.value_ptr.toSlice(coff), from, to },
+ );
+ } else if (std.ascii.startsWithIgnoreCase(arg, "/disallowlib:")) {
+ const lib_name = arg["/disallowlib:".len..];
+ // TODO: Track these and issue error in prelink if any match
+ _ = lib_name;
+ } else if (std.ascii.startsWithIgnoreCase(arg, "/defaultlib:")) {
+ const lib_path = arg["/defaultlib:".len..];
+ const trim = std.mem.trim(u8, lib_path, "\"");
+ if (lib_path.len == trim.len or lib_path.len - 2 == trim.len) {
+ if (!comp.config.link_libc or comp.libc_installation == null)
+ return diags.failParse(path, "encountered /DEFAULTLIB .drectve argument when libc was not available: {s}", .{arg});
+
+ (try coff.pending_default_libs.addOne(gpa)).* = .{
+ .path = try gpa.dupe(u8, lib_path),
+ .ioi = ioi,
+ };
+ } else return diags.failParse(
+ path,
+ "malformed /DEFAULTLIB .drectve argument: `{s}`",
+ .{arg},
+ );
+ } else return diags.failParse(path, "unsupported argument in .drectve section: `{s}`", .{arg});
+ }
+ }
+
+ section.comdat_result = .skip;
+ continue;
+ }
+
+ if (section.header.flags.LNK_REMOVE or
+ section.header.flags.MEM_DISCARDABLE)
+ {
+ // TODO: Convert .debug$* sections into PDB
+ section.comdat_result = .skip;
+ continue;
+ }
+
+ section.comdat_result = comdat: switch (section.comdat) {
+ .NONE => .include,
+ .ASSOCIATIVE => {
+ // Associative COMDAT sections have no COMDAT symbol.
+ // They are linked if the assocated section is linked.
+ var iter = section;
+ var iter_sn = iter.comdat_association;
+ while (iter.comdat == .ASSOCIATIVE) {
+ iter = §ions[iter_sn.toIndex()];
+ iter_sn = iter.comdat_association;
+ if (iter == section)
+ return diags.failParse(
+ path,
+ "circular COMDAT association loop detected, starting at symbol 0x{x}",
+ .{pending_symbols.keys()[section.psi.unwrap().?]},
+ );
+ }
+
+ assert(iter != section);
+ break :comdat switch (iter.comdat_result) {
+ .pending => .{ .pending_association = iter_sn },
+ else => |iter_result| iter_result,
+ };
+ },
+ else => |comdat| {
+ const psi = section.comdat_psi.unwrap() orelse section.psi.unwrap().?;
+ const symbol = &pending_symbols.values()[psi];
+ const si = existing: switch (symbol.value) {
+ .weak_external => unreachable,
+ .weak_external_aux => unreachable,
+ .static => break :comdat .include,
+ .section => {
+ assert(section.comdat_psi == .none);
+ if (coff.object_section_table.get(section.name)) |si|
+ break :existing si
+ else if (coff.pseudo_section_table.get(section.name)) |si|
+ break :existing si
+ else if (coff.section_table.get(section.name)) |s|
+ break :existing s.si
+ else
+ break :comdat .include;
+ },
+ .external => {
+ const global_gop = try coff.getOrPutGlobalSymbol(.{
+ .name = symbol.name.toSlice(coff),
+ });
+
+ // TODO: What if the same symbol is incorrectly defined twice in this obj?
+ // Would need to mark this global as pending, or notice it later when .ni != none
+ if (!global_gop.found_existing or global_gop.value_ptr.si.get(coff).ni == .none) {
+ symbol.si = global_gop.value_ptr.si;
+ break :comdat .include;
+ }
+
+ break :existing global_gop.value_ptr.si;
+ },
+ };
+
+ const index = pending_symbols.keys()[psi];
+ switch (comdat) {
+ .NODUPLICATES => return coff.failMultipleDefinitions(
+ path,
+ member_name,
+ symbol.name,
+ index,
+ si,
+ .duplicate,
+ ),
+ .ANY => {
+ symbol.si = si;
+ break :comdat .skip;
+ },
+ .SAME_SIZE => {
+ // TODO: Verify that this node isn't resized after creation
+ _, const size = si.get(coff).ni.location(&coff.mf).resolve(&coff.mf);
+ if (size == section.header.size_of_raw_data) {
+ symbol.si = si;
+ break :comdat .skip;
+ }
+
+ return coff.failMultipleDefinitions(
+ path,
+ member_name,
+ symbol.name,
+ index,
+ si,
+ .{ .size = .{ .a = size, .b = section.header.size_of_raw_data } },
+ );
+ },
+ .EXACT_MATCH => {
+ const sym = si.get(coff);
+ const existing_crc = switch (coff.getNode(sym.ni)) {
+ .input_section => |isi| isi.inputSection(coff).crc,
+ else => Crc32.hash(sym.ni.sliceConst(&coff.mf)),
+ };
+
+ if (existing_crc == section.comdat_crc) {
+ symbol.si = si;
+ break :comdat .skip;
+ }
+
+ return coff.failMultipleDefinitions(
+ path,
+ member_name,
+ symbol.name,
+ index,
+ si,
+ .{ .crc = .{ .a = existing_crc, .b = section.comdat_crc } },
+ );
+ },
+ .LARGEST => {
+ // TODO: Resize existing .ni and replace with this section's contents
+ // TODO: This will be tricky, what to do about existing InputSection?
+ unreachable;
+ },
+ .NONE, .ASSOCIATIVE, _ => unreachable,
+ }
+ },
+ };
+ }
+
+ try coff.flushSectionMerges();
+
+ // Resolve pending associations, create parent sections
+ var num_included_sections: u16 = 0;
+ var num_included_relocs: u32 = 0;
+ for (sections) |*section| {
+ comdat: switch (section.comdat_result) {
+ .pending_association => |root_assoc_sn| {
+ const root_result = sections[root_assoc_sn.toIndex()].comdat_result;
+ assert(root_result != .pending_association);
+ section.comdat_result = root_result;
+ continue :comdat root_result;
+ },
+ .include => {},
+ .skip => {
+ assert(switch (section.comdat) {
+ .NONE, .ASSOCIATIVE => true,
+ else => if (section.comdat_psi.unwrap()) |psi|
+ pending_symbols.values()[psi].si != .null
+ else
+ pending_symbols.values()[section.psi.unwrap().?].si != .null,
+ });
+ continue;
+ },
+ .pending => unreachable,
+ }
+
+ // Until we support sorting .pdata, we shouldn't merge these in, the result would be invalid
+ const section_name = section.name.toSlice(coff);
+ if (std.mem.startsWith(u8, section_name, ".pdata"))
+ continue;
+
+ num_included_sections += 1;
+ num_included_symbols += section.num_symbols;
+ num_included_relocs += section.header.number_of_relocations;
+
+ section.parent_si = (try coff.objectSectionMapIndex(
+ section.name,
+ section.header.flags.ALIGN.alignment() orelse .@"1",
+ .fromFlags(section.header.flags),
+ )).symbol(coff);
+ }
+
+ try coff.nodes.ensureUnusedCapacity(gpa, num_included_sections);
+ try coff.relocs.ensureUnusedCapacity(gpa, num_included_relocs);
+ try coff.symbols.ensureUnusedCapacity(gpa, num_included_symbols + num_included_sections);
+ try coff.input_sections.ensureUnusedCapacity(gpa, num_included_sections);
+
+ for (sections) |*section| {
+ if (section.parent_si == .null) continue;
+
+ const ni = try coff.mf.addLastChildNode(gpa, section.parent_si.node(coff), .{
+ .size = section.header.size_of_raw_data,
+ .alignment = section.header.flags.ALIGN.alignment() orelse .@"1",
+ .moved = true,
+ });
+ coff.nodes.appendAssumeCapacity(.{ .input_section = @enumFromInt(coff.input_sections.items.len) });
+
+ section.si = coff.addSymbolAssumeCapacity();
+ if (section.psi.unwrap()) |psi|
+ pending_symbols.values()[psi].si = section.si;
+
+ const sym = section.si.get(coff);
+ sym.ni = ni;
+ sym.section_number = section.parent_si.get(coff).section_number;
+
+ coff.input_sections.addOneAssumeCapacity().* = .{
+ .ioi = ioi,
+ .si = section.si,
+ .file_location = .{
+ .offset = fl.offset + section.header.pointer_to_raw_data,
+ .size = section.header.size_of_raw_data,
+ },
+ .first_li = @enumFromInt(coff.input_symbols.items.len),
+ .crc = section.comdat_crc,
+ .comdat_si = if (section.comdat_psi.unwrap()) |psi|
+ pending_symbols.values()[psi].si
+ else
+ .null,
+ };
+
+ log.debug(
+ "addInputSection({s}, 0x{x}) = {d}@{d}",
+ .{ section.name.toSlice(coff), section.comdat_crc, section.si, sym.section_number },
+ );
+ coff.synth_prog_node.increaseEstimatedTotalItems(1);
+ }
+
+ for (pending_symbols.values(), pending_symbols.keys(), 0..) |*symbol, index, i| {
+ switch (symbol.value) {
+ .weak_external_aux => continue,
+ else => {},
+ }
+
+ defer log.debug("addInputSymbol({s}, 0x{x}@{d}, {t}=0x{x}) = n{d} {d}@{d}", .{
+ symbol.name.toSlice(coff),
+ index,
+ symbol.section_number,
+ symbol.value,
+ switch (symbol.value) {
+ .weak_external_aux => unreachable,
+ inline else => |v| v,
+ },
+ symbol.si.get(coff).ni,
+ symbol.si,
+ symbol.si.get(coff).section_number,
+ });
+
+ const section = switch (symbol.section_number) {
+ .UNDEFINED => switch (symbol.value) {
+ .section,
+ .static,
+ .weak_external_aux,
+ => unreachable,
+ .external => {
+ if (symbol.weak_external_psi.unwrap()) |weak_external_i| {
+ // If the alias itself is an undef external, we need to wait until flushing the weak
+ // external global before creating a global for the alias, as another input could
+ // still provide the weak external.
+ const weak_sym = pending_symbols.values()[weak_external_i].si.get(coff);
+ weak_sym.setValue(.{ .weak_alias_name = symbol.name });
+ weak_sym.flags.weak_external_strat = pending_symbols.values()[weak_external_i + 1].value.weak_external_aux;
+ }
+
+ // Deferred until referenced by a reloc in this object.
+ // vcruntime.lib defines symbols like this (ie. memcpy_$fo$) that are not referenced
+ continue;
+ },
+ .weak_external => |alias_index| {
+ const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name.toSlice(coff) });
+ symbol.si = global_gop.value_ptr.si;
+ if (!global_gop.found_existing or symbol.si.get(coff).ni == .none) {
+ const sym = symbol.si.get(coff);
+ const alias = pending_symbols.getPtr(alias_index) orelse
+ return diags.failParse(
+ path,
+ "weak external 0x{x} {s}{f} targets unknown symbol index 0x{x}",
+ .{
+ index,
+ symbol.name.toSlice(coff),
+ fmtMemberNameString(member_name),
+ alias_index,
+ },
+ );
+
+ if (alias.si == .null and alias_index > index) {
+ // Resolve this once we see alias
+ alias.weak_external_psi = .wrap(@intCast(i));
+ } else {
+ sym.setValue(if (alias.si.unwrap()) |alias_si| .{
+ .weak_alias_si = alias_si,
+ } else .{
+ .weak_alias_name = alias.name,
+ });
+ sym.flags.weak_external_strat = pending_symbols.values()[i + 1].value.weak_external_aux;
+ }
+ }
+
+ continue;
+ },
+ },
+ .ABSOLUTE => {
+ const value = sym: switch (symbol.value) {
+ .static => |value| {
+ symbol.si = coff.addSymbolAssumeCapacity();
+ break :sym value;
+ },
+ .external => |value| {
+ const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name.toSlice(coff) });
+ symbol.si = global_gop.value_ptr.si;
+ if (global_gop.found_existing)
+ return coff.failMultipleDefinitions(
+ path,
+ member_name,
+ symbol.name,
+ index,
+ global_gop.value_ptr.si,
+ .none,
+ );
+ break :sym value;
+ },
+ else => unreachable,
+ };
+
+ const sym = symbol.si.get(coff);
+ sym.rva = value;
+ sym.section_number = .ABSOLUTE;
+ continue;
+ },
+ .DEBUG => continue,
+ else => |sn| §ions[sn.toIndex()],
+ };
+
+ if (section.si == .null)
+ continue;
+
+ if (symbol.si == .null) {
+ switch (symbol.value) {
+ .section => unreachable,
+ .static => {
+ symbol.si = coff.addSymbolAssumeCapacity();
+ },
+ .external => {
+ assert(index != section.comdat_psi.unwrap());
+ const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name.toSlice(coff) });
+ symbol.si = global_gop.value_ptr.si;
+
+ const sym = symbol.si.get(coff);
+ if (global_gop.found_existing and sym.ni != .none)
+ return coff.failMultipleDefinitions(
+ path,
+ member_name,
+ symbol.name,
+ index,
+ global_gop.value_ptr.si,
+ .none,
+ );
+ },
+ .weak_external,
+ .weak_external_aux,
+ => unreachable,
+ }
+
+ if (section.comdat_psi.unwrap() == @as(u32, @intCast(i)))
+ coff.getNode(section.si.get(coff).ni).input_section.inputSection(coff).comdat_si = symbol.si;
+ }
+
+ if (symbol.weak_external_psi.unwrap()) |weak_external_i| {
+ assert(symbol.si != .null);
+ const weak_sym = pending_symbols.values()[weak_external_i].si.get(coff);
+ weak_sym.setValue(.{ .weak_alias_si = symbol.si });
+ weak_sym.flags.weak_external_strat = pending_symbols.values()[weak_external_i + 1].value.weak_external_aux;
+ }
+
+ if (section.si != symbol.si) {
+ const sym = symbol.si.get(coff);
+ assert(sym.ni == .none);
+ sym.ni = section.si.get(coff).ni;
+ switch (symbol.value) {
+ .section => |v| sym.setExtra(.{ .size = v }),
+ .static => |v| sym.setValue(.{ .node_offset = v }),
+ .external => |v| switch (symbol.section_number) {
+ .UNDEFINED, .ABSOLUTE, .DEBUG => unreachable,
+ else => sym.setValue(.{ .node_offset = v }),
+ },
+ .weak_external,
+ .weak_external_aux,
+ => unreachable,
+ }
+
+ sym.section_number = section.si.get(coff).section_number;
+ }
+ }
+
+ const relocation_size = std.coff.Relocation.sizeOf();
+ for (sections) |section| {
+ if (section.si == .null) continue;
+
+ const loc_sym = section.si.get(coff);
+ assert(loc_sym.loc_relocs == .none);
+ loc_sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
+
+ if (section.header.number_of_relocations == 0) continue;
+
+ try fr.seekTo(fl.offset + section.header.pointer_to_relocations);
+ for (0..section.header.number_of_relocations) |reloc_i| {
+ var reloc: std.coff.Relocation = undefined;
+ @memcpy(std.mem.asBytes(&reloc)[0..relocation_size], try r.take(relocation_size));
+ if (target_endian != native_endian)
+ std.mem.byteSwapAllFields(std.coff.Relocation, &reloc);
+
+ const symbol = pending_symbols.getPtr(reloc.symbol_table_index) orelse
+ return diags.failParse(
+ path,
+ "relocation 0x{x} in section '{s}' of {f}{f} targets invalid symbol index 0x{x}",
+ .{
+ reloc_i,
+ section.name.toSlice(coff),
+ path.fmtEscapeString(),
+ fmtMemberNameString(member_name),
+ reloc.symbol_table_index,
+ },
+ );
+
+ if (symbol.si == .null) {
+ assert(symbol.section_number == .UNDEFINED);
+ switch (symbol.value) {
+ .external => |size| {
+ const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name.toSlice(coff) });
+ symbol.si = global_gop.value_ptr.si;
+ if (!global_gop.found_existing or symbol.si.get(coff).ni == .none) {
+ const sym = symbol.si.get(coff);
+ sym.setExtra(.{ .size = @max(sym.size(), size) });
+ }
+ },
+ else => unreachable,
+ }
+ }
+
+ assert(symbol.si != .null);
+ try coff.addReloc(
+ section.si,
+ reloc.virtual_address - section.header.virtual_address,
+ symbol.si,
+ .pending,
+ .{ .u16 = reloc.type },
+ );
+ }
+ }
+
+ // Set up contiguous symbol ranges in `input_symbols` for both symbols we just created,
+ // and symbols that were previously created as undefined, but we just defined.
+ const SortContext = struct {
+ v: []const PendingSymbol,
+
+ pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {
+ const lhs = &ctx.v[a_index];
+ const rhs = &ctx.v[b_index];
+ if (lhs.section_number == rhs.section_number)
+ return @intFromEnum(lhs.si) < @intFromEnum(rhs.si);
+ return @intFromEnum(lhs.section_number) < @intFromEnum(rhs.section_number);
+ }
+ };
+
+ pending_symbols.sortUnstable(SortContext{ .v = pending_symbols.values() });
+
+ try coff.input_symbols.ensureUnusedCapacity(gpa, num_included_symbols + num_included_sections);
+ var prev_sn: Symbol.SectionNumber = .DEBUG;
+ var include_section = false;
+ for (pending_symbols.values()) |symbol| {
+ // The symbol may have not been included, or it's an undefined external / aux
+ if (symbol.si == .null or symbol.si.get(coff).ni == .none) continue;
+
+ if (prev_sn != symbol.section_number) {
+ prev_sn = symbol.section_number;
+ if (symbol.section_number.hasIndex()) {
+ const section = §ions[symbol.section_number.toIndex()];
+ include_section = section.comdat_result == .include;
+ if (include_section) {
+ const isi = coff.getNode(section.si.get(coff).ni).input_section;
+ isi.inputSection(coff).first_li = @enumFromInt(coff.input_symbols.items.len);
+ }
+ }
+ }
+
+ if (include_section) {
+ assert(coff.getNode(symbol.si.get(coff).ni) == .input_section);
+ symbol.si.get(coff).setExtra(.{ .isli = @enumFromInt(coff.input_symbols.items.len) });
+ coff.input_symbols.addOneAssumeCapacity().* = .{
+ .si = symbol.si,
+ .name = symbol.name,
+ };
+ }
+ }
+}
+
+fn failMultipleDefinitions(
+ coff: *Coff,
+ path: std.Build.Cache.Path,
+ member_name: ?[]const u8,
+ name: String,
+ index: u32,
+ existing_si: Symbol.Index,
+ comdat_reason: union(enum) {
+ none: void,
+ duplicate: void,
+ size: struct { a: u64, b: u64 },
+ crc: struct { a: u32, b: u32 },
+ },
+) error{ AlreadyReported, OutOfMemory } {
+ const num_notes: usize = 2 + @as(usize, @intFromBool(comdat_reason != .none));
+ var err = try coff.base.comp.link_diags.addErrorWithNotes(num_notes);
+ try err.addMsg("multiple definitions of '{s}'", .{name.toSlice(coff)});
+
+ switch (coff.getNode(existing_si.get(coff).ni)) {
+ .input_section => |isi| {
+ const other_ioi = isi.input(coff);
+ err.addNote("first seen in input '{f}{f}'", .{
+ other_ioi.path(coff).fmtEscapeString(),
+ fmtMemberNameString(other_ioi.memberName(coff)),
+ });
+ },
+ .nav, .uav => err.addNote("first seen in module '{s}'", .{
+ coff.base.comp.zcu.?.root_mod.fully_qualified_name,
+ }),
+ else => unreachable,
+ }
+
+ err.addNote("defined again in input '{f}{f}' (0x{x}))", .{ path, fmtMemberNameString(member_name), index });
+ switch (comdat_reason) {
+ .none => {},
+ .duplicate => err.addNote("COMDAT rule requires no duplicates", .{}),
+ .size => |s| err.addNote(
+ "COMDAT rule require duplicates to have the same size ({d} vs {d})",
+ .{ s.a, s.b },
+ ),
+ .crc => |s| err.addNote(
+ "COMDAT rule require duplicates to have the same CRC (0x{x} vs 0x{x})",
+ .{ s.a, s.b },
+ ),
+ }
+
+ return error.AlreadyReported;
+}
+
+const ArchiveMemberHeader = struct {
+ name: []const u8,
+ size: u34,
+};
+
+/// Return value lifetime is that of `header`
+fn parseArchiveMemberHeader(
+ diags: *link.Diags,
+ path: std.Build.Cache.Path,
+ header: *const std.coff.ArchiveMemberHeader,
+ opt_longnames: ?[]const u8,
+) !ArchiveMemberHeader {
+ return parseArchiveMemberHeaderInner(header, opt_longnames) catch |err| switch (err) {
+ error.BadName => return diags.failParse(path, "malformed member name: '{s}'", .{&header.name}),
+ error.BadSize => return diags.failParse(path, "malformed member size: '{s}'", .{&header.size}),
+ error.BadEndOfHeader => return diags.failParse(path, "end of header was invalid", .{}),
+ error.NoLongNames => return diags.failParse(path, "long name used without longnames member", .{}),
+ };
+}
+
+fn parseArchiveMemberHeaderInner(
+ header: *const std.coff.ArchiveMemberHeader,
+ opt_longnames: ?[]const u8,
+) !ArchiveMemberHeader {
+ const name = try header.parseName(opt_longnames);
+ const size = header.parseSize() catch return error.BadSize;
+
+ if (!std.mem.eql(u8, &header.end_of_header, std.coff.archive_end_of_header))
+ return error.BadEndOfHeader;
+
+ return .{
+ .name = name,
+ .size = size,
+ };
+}
+
+fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) LoadInputError!void {
+ const comp = coff.base.comp;
+ const gpa = comp.gpa;
+ const diags = &comp.link_diags;
+ const r = &fr.interface;
+ const target_endian = coff.targetEndian();
+
+ log.debug("loadArchive({f})", .{path.fmtEscapeString()});
+
+ const signature = try r.take(std.coff.archive_signature.len);
+ if (!std.mem.eql(u8, signature, std.coff.archive_signature))
+ return diags.failParse(path, "bad signature", .{});
+
+ var opt_expected_kind: ?std.coff.ArchiveMemberHeader.Kind = .first_linker;
+ var opt_longnames: ?[]const u8 = null;
+ defer if (opt_longnames) |l| gpa.free(l);
+
+ var members: std.ArrayList(struct {
+ offset: u32,
+ iami: ?InputArchive.Member.Index,
+ }) = .empty;
+ var symbol_member_indices: std.ArrayList(u32) = .empty;
+
+ const iai: InputArchive.Index = @enumFromInt(coff.input_archives.items.len);
+ (try coff.input_archives.addOne(gpa)).* = .{
+ .path = path,
+ };
+
+ const first_iami = coff.input_archive_members.items.len;
+ const first_iamsi = coff.input_archive_symbols.items.len;
+ const first_symbol_indices_index = coff.input_archive_symbol_indices.count();
+
+ errdefer {
+ for (coff.input_archive_symbol_indices.values()) |*v| {
+ if (@intFromEnum(v.last) < first_iamsi) continue;
+ if (@intFromEnum(v.first) >= first_iamsi) continue;
+
+ var iter = v.first;
+ v.last = while (iter != v.last) {
+ const sym = &coff.input_archive_symbols.items[@intFromEnum(iter)];
+ if (@intFromEnum(sym.next) >= first_iamsi) {
+ sym.next = iter;
+ break iter;
+ }
+
+ iter = sym.next;
+ } else unreachable;
+ }
+
+ // New entries in this map will only have pointed to iamsi we also just added
+ coff.input_archive_symbol_indices.shrinkRetainingCapacity(first_symbol_indices_index);
+ coff.input_archive_symbols.shrinkRetainingCapacity(first_iamsi);
+ coff.input_archive_members.shrinkRetainingCapacity(first_iami);
+ _ = coff.input_archives.pop();
+ }
+
+ var pos = fr.logicalPos();
+ const size = try fr.getSize();
+ while (pos < size) : (pos = fr.logicalPos()) {
+ if ((pos & 1) != 0) try r.discardAll(1);
+ const header = try r.takeStruct(std.coff.ArchiveMemberHeader, target_endian);
+ const res = try parseArchiveMemberHeader(diags, path, &header, opt_longnames);
+
+ const member_end = fr.logicalPos() + res.size;
+ if (member_end > size)
+ return diags.failParse(path, "out-of-bounds length 0x{x} in member '{s}'", .{ res.size, res.name });
+
+ log.debug("loadArchiveMember({s})", .{res.name});
+
+ if (opt_expected_kind) |expected_kind| switch (expected_kind) {
+ .first_linker => {
+ if (!std.mem.eql(u8, res.name, "/"))
+ return diags.failParse(path, "expected first linker member, found '{s}'", .{res.name});
+
+ try fr.seekTo(fr.logicalPos() + res.size);
+ opt_expected_kind = .second_linker;
+ continue;
+ },
+ .second_linker => {
+ if (!std.mem.eql(u8, res.name, "/"))
+ return diags.failParse(path, "expected second linker member, found '{s}'", .{res.name});
+
+ const num_members = try r.takeInt(u32, target_endian);
+ pos = fr.logicalPos();
+ if (pos + num_members * @sizeOf(u32) > member_end)
+ return diags.failParse(path, "invalid member count 0x{x} in second linker member", .{num_members});
+
+ try members.ensureTotalCapacity(gpa, num_members);
+ for (0..num_members) |_|
+ members.addOneAssumeCapacity().* = .{
+ .offset = try r.takeInt(u32, target_endian),
+ .iami = null,
+ };
+
+ const num_symbols = try r.takeInt(u32, target_endian);
+ pos = fr.logicalPos();
+ if (pos + num_symbols * @sizeOf(u16) > member_end)
+ return diags.failParse(path, "invalid symbol count 0x{x} in second linker member", .{num_symbols});
+
+ try symbol_member_indices.ensureTotalCapacity(gpa, num_symbols);
+ for (0..num_symbols) |_|
+ symbol_member_indices.addOneAssumeCapacity().* = (try r.takeInt(u16, target_endian)) - 1;
+
+ pos = fr.logicalPos();
+ try coff.ensureManyUnusedStringCapacity(num_symbols, @intCast(member_end - pos));
+ try coff.input_archive_members.ensureUnusedCapacity(gpa, num_members);
+ try coff.input_archive_symbols.ensureUnusedCapacity(gpa, num_symbols);
+ try coff.input_archive_symbol_indices.ensureUnusedCapacity(gpa, num_symbols);
+
+ var symbol_i: u32 = 0;
+ while (pos < member_end and symbol_i < num_symbols) : ({
+ pos = fr.logicalPos();
+ symbol_i += 1;
+ }) {
+ const name = if (r.takeDelimiter(0) catch |err| switch (err) {
+ error.StreamTooLong => null,
+ else => |e| return e,
+ }) |n| n else return diags.failParse(path, "unterminated string found in second linker member", .{});
+
+ const string = coff.getOrPutStringAssumeCapacity(name);
+ const iamsi: InputArchive.Member.Symbol.Index = @enumFromInt(coff.input_archive_symbols.items.len);
+ const symbol_gop = coff.input_archive_symbol_indices.getOrPutAssumeCapacity(string);
+ if (!symbol_gop.found_existing) {
+ symbol_gop.value_ptr.* = .{
+ .first = iamsi,
+ .last = iamsi,
+ };
+ } else {
+ coff.input_archive_symbols.items[@intFromEnum(symbol_gop.value_ptr.last)].next = iamsi;
+ symbol_gop.value_ptr.last = iamsi;
+ }
+
+ const iami = members.items[symbol_member_indices.items[symbol_i]].iami orelse iami: {
+ const iami: InputArchive.Member.Index = @enumFromInt(coff.input_archive_members.items.len);
+ const member_offset = members.items[symbol_member_indices.items[symbol_i]].offset;
+ coff.input_archive_members.addOneAssumeCapacity().* = .{
+ .iai = iai,
+ .name = undefined,
+ .content = .{
+ .object = .{
+ .offset = member_offset,
+ .size = undefined,
+ },
+ },
+ .flags = .{
+ .is_loaded = false,
+ },
+ };
+
+ members.items[symbol_member_indices.items[symbol_i]].iami = iami;
+ break :iami iami;
+ };
+
+ log.debug("loadArchiveMemberSymbol({s}) = ({d}, {d}, {d})", .{ name, iai, iami, iamsi });
+
+ coff.input_archive_symbols.addOneAssumeCapacity().* = .{
+ .iami = iami,
+ .next = iamsi,
+ };
+ }
+
+ if (symbol_i != num_symbols)
+ return diags.failParse(
+ path,
+ " expected {d} entries in second linker member string table, but found {d}",
+ .{ num_symbols, symbol_i },
+ );
+
+ try fr.seekTo(member_end);
+ opt_expected_kind = .longnames;
+ continue;
+ },
+ .longnames => {
+ // This member is optional
+ if (std.mem.eql(u8, res.name, "//"))
+ opt_longnames = try r.readAlloc(gpa, @intCast(res.size));
+
+ opt_expected_kind = null;
+ break;
+ },
+ else => unreachable,
+ };
+ }
+
+ if (opt_expected_kind) |expected_kind| switch (expected_kind) {
+ .first_linker => return diags.failParse(path, "missing first linker member", .{}),
+ .second_linker => return diags.failParse(path, "missing second linker member", .{}),
+ else => {},
+ };
+
+ // Validate / read names and sizes of all the referenced members, enumerate imports
+ for (coff.input_archive_members.items[first_iami..]) |*member| {
+ try fr.seekTo(member.content.object.offset);
+
+ const header = try r.takeStruct(std.coff.ArchiveMemberHeader, target_endian);
+ const res = try parseArchiveMemberHeader(diags, path, &header, opt_longnames);
+
+ try coff.ensureUnusedStringCapacity(res.name.len);
+ member.name = coff.getOrPutStringAssumeCapacity(res.name);
+
+ const member_sig = try r.peek(4);
+ const machine: std.coff.IMAGE.FILE.MACHINE =
+ @enumFromInt(std.mem.readInt(u16, member_sig[0..2], target_endian));
+ const sig = std.mem.readInt(u16, member_sig[2..4], target_endian);
+
+ log.debug("verifyArchiveMember({s}) = 0x{x}+{x}", .{
+ res.name,
+ member.content.object.offset,
+ res.size,
+ });
+
+ const expected_machine = comp.root_mod.resolved_target.result.toCoffMachine();
+ if (machine == std.coff.IMAGE.FILE.MACHINE.UNKNOWN and sig == 0xffff) {
+ const import_header = try r.takeStruct(std.coff.ImportHeader, target_endian);
+ const strings = r.take(import_header.size_of_data) catch |err| switch (err) {
+ error.EndOfStream => return diags.failParse(path, "invalid data size in import header '{s}'", .{res.name}),
+ else => |e| return e,
+ };
+
+ var split = std.mem.splitScalar(u8, strings, 0);
+ const symbol_name = split.next() orelse
+ return diags.failParse(path, "invalid symbol name string in import header '{s}'", .{res.name});
+ var lib_name = split.next() orelse
+ return diags.failParse(path, "invalid dll name string in import header '{s}' ('{s}')", .{ res.name, symbol_name });
+
+ if (import_header.machine != expected_machine)
+ return diags.failParse(path, "machine mismatch in import header '{s}' ('{s}'): expected {t}, found {t}", .{
+ res.name,
+ symbol_name,
+ expected_machine,
+ machine,
+ });
+
+ const ext = ".dll";
+ if (!std.mem.endsWith(u8, lib_name, ext))
+ return diags.failParse(
+ path,
+ "unexpected extension for import '{s} ('{s}'): '{s}'",
+ .{ res.name, symbol_name, lib_name },
+ );
+
+ lib_name = lib_name[0 .. lib_name.len - ext.len];
+ log.debug("verifyArchiveImportHeader({s}, {s}, {s}) = {t} ({t})", .{
+ res.name,
+ symbol_name,
+ lib_name,
+ import_header.types.type,
+ import_header.types.name_type,
+ });
+
+ try coff.ensureManyUnusedStringCapacity(2, strings.len - ext.len);
+ member.content = .{
+ .import = .{
+ .symbol_name = coff.getOrPutStringAssumeCapacity(symbol_name),
+ .lib_name = coff.getOrPutStringAssumeCapacity(lib_name),
+ .import_ordinal_hint = import_header.hint,
+ .type = import_header.types.type,
+ .name_type = import_header.types.name_type,
+ },
+ };
+ } else {
+ member.content.object.size = res.size;
+ // Microsoft's CRT contains members that set .UNKNOWN but do have undef symbols
+ if (machine != expected_machine and machine != .UNKNOWN) {
+ return diags.failParse(path, "machine mismatch in member header '{s}': expected {t}, found {t}", .{
+ res.name,
+ expected_machine,
+ machine,
+ });
+ }
+ }
+ }
+}
+
+fn loadRes(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) LoadInputError!void {
+ const comp = coff.base.comp;
+ const gpa = comp.gpa;
+ const diags = &comp.link_diags;
+ const r = &fr.interface;
+
+ log.debug("loadRes({f})", .{path.fmtEscapeString()});
+
+ _ = gpa;
+ _ = diags;
+ _ = r;
+}
+
+fn loadDll(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) LoadInputError!void {
+ const comp = coff.base.comp;
+ const gpa = comp.gpa;
+ const diags = &comp.link_diags;
+ const r = &fr.interface;
+
+ log.debug("loadDll({f})", .{path.fmtEscapeString()});
+
+ _ = gpa;
+ _ = diags;
+ _ = r;
+}
+
pub fn prelink(coff: *Coff, prog_node: std.Progress.Node) link.Error!void {
- _ = coff;
_ = prog_node;
+ const base = coff.base;
+ const comp = base.comp;
+
+ log.debug("prelink()", .{});
+
+ if (coff.pending_default_libs.items.len > 0) {
+ // Libs provided by /DEFAULTLIB arguments in objects are searched after all other inputs
+ const gpa = comp.gpa;
+ const arena = comp.arena;
+ const target = &comp.root_mod.resolved_target.result;
+
+ defer {
+ for (coff.pending_default_libs.items) |l| gpa.free(l.path);
+ coff.pending_default_libs.clearAndFree(gpa);
+ }
+
+ assert(comp.config.link_libc);
+ const libc_installation = comp.libc_installation.?;
+ const all_paths: [3]?[]const u8 = .{
+ libc_installation.crt_dir,
+ libc_installation.msvc_lib_dir,
+ libc_installation.kernel32_lib_dir,
+ };
+ const search_paths = all_paths[0..if (target.abi == .msvc or target.abi == .itanium) 3 else 1];
+ lib: for (coff.pending_default_libs.items) |lib| {
+ if (!std.mem.eql(u8, std.fs.path.extension(lib.path), ".lib"))
+ return comp.link_diags.failParse(
+ lib.ioi.path(coff),
+ "/DEFAULTLIB library '{s}' had unexpected extension",
+ .{lib.path},
+ );
+
+ log.debug("loadDefaultLib({s}, {f})", .{ lib.path, lib.ioi.path(coff) });
+ for (search_paths) |opt_path| if (opt_path) |search_path| {
+ const lib_path = try Path.initCwd(search_path).join(arena, lib.path);
+ const archive = link.openObject(comp.io, lib_path, false, false) catch |err| switch (err) {
+ error.FileNotFound => {
+ arena.free(lib_path.sub_path);
+ continue;
+ },
+ else => |e| return comp.link_diags.failParse(
+ lib.ioi.path(coff),
+ "error opening /DEFAULTLIB library '{s}': {t}",
+ .{ lib.path, e },
+ ),
+ };
+ errdefer archive.file.close(comp.io);
+
+ coff.loadInput(.{ .archive = archive }) catch |err| switch (err) {
+ else => |e| return comp.link_diags.failParse(
+ lib.ioi.path(coff),
+ "error loading /DEFAULTLIB library '{s}': {t}",
+ .{ lib.path, e },
+ ),
+ };
+
+ break :lib;
+ };
+
+ return comp.link_diags.failParse(
+ lib.ioi.path(coff),
+ "/DEFAULTLIB library '{s}' was not found",
+ .{lib.path},
+ );
+ }
+ }
+
+ coff.inputs_complete = true;
+ if (comp.zcu == null)
+ coff.exports_complete = true;
}
-pub fn updateNav(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
+pub fn updateNav(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) link.Error!void {
coff.updateNavInner(pt, nav_index) catch |err| switch (err) {
+ error.MappedFileIo => return coff.base.cgFail(
+ nav_index,
+ "linker failed to update variable: {t}",
+ .{coff.mf.io_err.?},
+ ),
else => |e| return e,
- error.MappedFileIo => return coff.base.cgFail(nav_index, "linker failed to update variable: {t}", .{coff.mf.io_err.?}),
};
}
fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
@@ -1546,11 +5464,13 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
const nmi = try coff.navMapIndex(zcu, nav_index);
const si = nmi.symbol(coff);
+ log.debug("updateNav({f}) = {d}", .{ nav.fqn.fmt(ip), si });
const ni = ni: {
switch (si.get(coff).ni) {
.none => {
const sec_si = try coff.navSection(zcu, nav.resolved.?);
try coff.nodes.ensureUnusedCapacity(gpa, 1);
+ if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1);
const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{
.alignment = zcu.navAlignment(nav_index).toStdMem(),
.moved = true,
@@ -1565,6 +5485,9 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
const sym = si.get(coff);
assert(sym.loc_relocs == .none);
sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
+ if (!isImage(coff) and sym.target_relocs != .none)
+ try coff.pendingSymbolTableEntry(si);
+
break :ni sym.ni;
};
@@ -1582,12 +5505,12 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
error.WriteFailed => return nw.err.?,
else => |e| return e,
};
- si.get(coff).size = @intCast(nw.interface.end);
- si.applyLocationRelocs(coff);
+ si.get(coff).extra.size = @intCast(nw.interface.end);
+ try si.applyLocationRelocs(coff);
}
if (nav.resolved.?.@"linksection".unwrap()) |_| {
- try ni.resize(&coff.mf, gpa, si.get(coff).size);
+ try ni.resize(&coff.mf, gpa, si.get(coff).extra.size);
var parent_ni = ni;
while (true) {
parent_ni = parent_ni.parent(&coff.mf);
@@ -1610,7 +5533,7 @@ pub fn lowerUav(
pt: Zcu.PerThread,
uav_val: InternPool.Index,
uav_align: InternPool.Alignment,
-) !link.File.SymbolId {
+) link.Error!link.File.SymbolId {
const zcu = pt.zcu;
const gpa = zcu.gpa;
@@ -1639,7 +5562,7 @@ pub fn updateFunc(
pt: Zcu.PerThread,
func_index: InternPool.Index,
mir: *const codegen.AnyMir,
-) !void {
+) link.Error!void {
coff.updateFuncInner(pt, func_index, mir) catch |err| switch (err) {
else => |e| return e,
error.MappedFileIo => return coff.base.cgFail(
@@ -1669,6 +5592,7 @@ fn updateFuncInner(
.none => {
const sec_si = try coff.navSection(zcu, nav.resolved.?);
try coff.nodes.ensureUnusedCapacity(gpa, 1);
+ if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1);
const mod = zcu.navFileScope(func.owner_nav).mod.?;
const target = &mod.resolved_target.result;
const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{
@@ -1694,6 +5618,8 @@ fn updateFuncInner(
const sym = si.get(coff);
assert(sym.loc_relocs == .none);
sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
+ if (!isImage(coff) and sym.target_relocs != .none)
+ try coff.pendingSymbolTableEntry(si);
break :ni sym.ni;
};
@@ -1712,8 +5638,8 @@ fn updateFuncInner(
error.WriteFailed => return nw.err.?,
else => |e| return e,
};
- si.get(coff).size = @intCast(nw.interface.end);
- si.applyLocationRelocs(coff);
+ si.get(coff).extra.size = @intCast(nw.interface.end);
+ try si.applyLocationRelocs(coff);
}
pub fn updateErrorData(coff: *Coff, pt: Zcu.PerThread) !void {
@@ -1729,40 +5655,308 @@ pub fn updateErrorData(coff: *Coff, pt: Zcu.PerThread) !void {
};
}
+fn flushImplib(
+ coff: *Coff,
+ implib_file: []const u8,
+) !void {
+ // Emitting implibs is only valid for images
+ assert(coff.export_table.ni != .none);
+
+ const comp = coff.base.comp;
+ const gpa = comp.gpa;
+ const io = comp.io;
+
+ const image_name = std.mem.sliceTo(
+ coff.export_table.ni.slice(&coff.mf)[@sizeOf(std.coff.ExportDirectoryTable)..],
+ 0,
+ );
+ const machine_type = coff.targetLoad(&coff.headerPtr().machine);
+ const members = members: {
+ const def_arena: std.heap.ArenaAllocator = .init(gpa);
+ var def: ModuleDefinition = .{
+ .name = image_name,
+ .arena = def_arena,
+ .type = .mingw,
+ };
+ defer def.deinit();
+
+ try def.exports.ensureUnusedCapacity(
+ def.arena.allocator(),
+ coff.export_table.entries.count(),
+ );
+
+ const name_table_slice = coff.export_table.name_table_ni.slice(&coff.mf);
+ for (coff.export_table.entries.values(), 0..) |entry, ord| {
+ const name = name_table_slice[entry.name_index..][0..entry.name_len];
+ const section_number = entry.si.get(coff).section_number;
+ const import_type: std.coff.ImportType = switch (section_number.symbol(coff)) {
+ .data, .rdata => .DATA,
+ .text => .CODE,
+ else => return comp.link_diags.fail(
+ "unsupported section for export '{s}': {s}",
+ .{ name, §ion_number.header(coff).name },
+ ),
+ };
+
+ def.exports.appendAssumeCapacity(.{
+ .name = name,
+ .mangled_symbol_name = null,
+ .ext_name = null,
+ .import_name = null,
+ .export_as = null,
+ .no_name = false,
+ .ordinal = @intCast(ord),
+ .type = import_type,
+ .private = false,
+ });
+ }
+
+ def.fixupForImportLibraryGeneration(machine_type);
+ break :members try implib.getMembers(gpa, def, machine_type);
+ };
+ defer members.deinit();
+
+ const lib_sub_path = try std.fs.path.join(gpa, &.{
+ std.fs.path.dirname(coff.base.emit.sub_path) orelse "",
+ implib_file,
+ });
+ defer gpa.free(lib_sub_path);
+
+ const lib_final_file = try coff.base.emit.root_dir.handle.createFile(io, lib_sub_path, .{ .truncate = true });
+ defer lib_final_file.close(io);
+ var buffer: [1024]u8 = undefined;
+ var file_writer = lib_final_file.writer(io, &buffer);
+ try implib.writeCoffArchive(gpa, &file_writer.interface, members);
+ try file_writer.interface.flush();
+}
+
+fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void {
+ const comp = coff.base.comp;
+ const gpa = comp.gpa;
+ const max_notes = 4;
+
+ var undef_indices: std.ArrayListUnmanaged(u32) = .empty;
+ for (coff.relocs.items, 0..) |reloc, reloc_i| {
+ if (reloc.flags.free) continue;
+ const target_sym = reloc.target.get(coff);
+ switch (target_sym.ni) {
+ .none => {
+ assert(target_sym.gmi != .none);
+ if (target_sym.section_number == .ABSOLUTE) continue;
+ (try undef_indices.addOne(gpa)).* = @intCast(reloc_i);
+ },
+ else => continue,
+ }
+ }
+
+ if (undef_indices.items.len == 0) return;
+
+ const undefLessThan = struct {
+ fn lessThan(ctx: *const Coff, lhs: u32, rhs: u32) bool {
+ const reloc_l = &ctx.relocs.items[lhs];
+ const reloc_r = &ctx.relocs.items[rhs];
+ if (reloc_l.target == reloc_r.target)
+ return @intFromEnum(reloc_l.loc) < @intFromEnum(reloc_r.loc)
+ else
+ return @intFromEnum(reloc_l.target) < @intFromEnum(reloc_r.target);
+ }
+ }.lessThan;
+
+ std.mem.sortUnstable(u32, undef_indices.items, coff, undefLessThan);
+
+ var start_i: usize = 0;
+ var num_unique_references: usize = 1;
+ for (0..undef_indices.items.len) |i| {
+ const target = coff.relocs.items[undef_indices.items[start_i]].target;
+ if (i == undef_indices.items.len - 1 or target != coff.relocs.items[undef_indices.items[i + 1]].target) {
+ defer {
+ start_i = i + 1;
+ num_unique_references = 1;
+ }
+
+ const num_full_notes = @min(max_notes, num_unique_references);
+ var err = try comp.link_diags.addErrorWithNotes(
+ num_full_notes + @intFromBool(num_unique_references > max_notes),
+ );
+ const target_sym = target.get(coff);
+ try err.addMsg("undefined symbol: {s}", .{target_sym.gmi.name(coff).toSlice(coff)});
+
+ // TODO: If lib_name is set, show the user
+
+ var prev_loc_si: Symbol.Index = .null;
+ for (undef_indices.items[start_i .. i + 1]) |reference_i| {
+ if (err.note_slot == num_full_notes) break;
+
+ const reloc = &coff.relocs.items[reference_i];
+ const loc_si = reloc.loc;
+ if (loc_si == prev_loc_si) continue;
+ defer prev_loc_si = loc_si;
+
+ const loc_sym = loc_si.get(coff);
+
+ // TODO: Make this a helper for anything that needs to report "referenced by" notes
+ switch (coff.getNode(loc_sym.ni)) {
+ .data_directories => {
+ const dir: std.coff.IMAGE.DIRECTORY_ENTRY =
+ @enumFromInt(reloc.offset / @sizeOf(std.coff.ImageDataDirectory));
+ err.addNote("referenced by data directory entry: {t}", .{dir});
+ },
+ .optional_header => err.addNote("referenced by optional header field", .{}),
+ .input_section => |isi| {
+ const other_ioi = isi.input(coff);
+ if (loc_sym.gmi == .none) {
+ const section = isi.inputSection(coff);
+ const section_name = coff.getNode(loc_sym.ni.parent(&coff.mf))
+ .object_section.name(coff).toSlice(coff);
+
+ if (section.comdat_si != .null) {
+ const comdat_sym = section.comdat_si.get(coff);
+ const comdat_name = if (comdat_sym.gmi != .none)
+ comdat_sym.gmi.name(coff).toSlice(coff)
+ else
+ comdat_sym.extra.isli.name(coff).toSlice(coff);
+
+ err.addNote("referenced by input COMDAT section '{s}={s}' '{f}{f}'", .{
+ section_name,
+ comdat_name,
+ other_ioi.path(coff).fmtEscapeString(),
+ fmtMemberNameString(other_ioi.memberName(coff)),
+ });
+ } else {
+ err.addNote("referenced by input section '{s}' '{f}{f}'", .{
+ section_name,
+ other_ioi.path(coff).fmtEscapeString(),
+ fmtMemberNameString(other_ioi.memberName(coff)),
+ });
+ }
+ } else {
+ err.addNote("referenced by input symbol '{s}' from '{f}{f}'", .{
+ loc_sym.gmi.name(coff).toSlice(coff),
+ other_ioi.path(coff).fmtEscapeString(),
+ fmtMemberNameString(other_ioi.memberName(coff)),
+ });
+ }
+ },
+ .import_thunk => |gmi| err.addNote("referenced by import thunk for '{s}'", .{
+ gmi.name(coff).toSlice(coff),
+ }),
+ inline .nav,
+ .uav,
+ .lazy_code,
+ .lazy_const_data,
+ => |val, tag| {
+ err.addNote("referenced by '{f}'", .{
+ format: switch (tag) {
+ .nav => {
+ const ip = &comp.zcu.?.intern_pool;
+ break :format ip.getNav(val.navIndex(coff)).fqn.fmt(ip);
+ },
+ .uav => Value.fromInterned(val.uavValue(coff)).fmtValue(.{
+ .zcu = coff.base.comp.zcu.?,
+ .tid = tid,
+ }),
+ inline .lazy_code, .lazy_const_data => Type.fromInterned(val.lazySymbol(coff).ty).fmt(.{
+ .zcu = coff.base.comp.zcu.?,
+ .tid = tid,
+ }),
+ else => unreachable,
+ },
+ });
+ },
+ else => unreachable,
+ }
+ }
+
+ if (num_unique_references > max_notes)
+ err.addNote("referenced {d} more times", .{num_unique_references - max_notes});
+ } else if (i != start_i and
+ coff.relocs.items[undef_indices.items[i - 1]].loc != coff.relocs.items[undef_indices.items[i]].loc)
+ {
+ num_unique_references += 1;
+ }
+ }
+
+ return error.AlreadyReported;
+}
+
pub fn flush(
coff: *Coff,
arena: std.mem.Allocator,
tid: Zcu.PerThread.Id,
prog_node: std.Progress.Node,
-) !void {
+) link.Error!void {
_ = arena;
_ = prog_node;
- while (try coff.idle(tid)) {}
-
- // hack for stage2_x86_64 + coff
const comp = coff.base.comp;
- if (comp.compiler_rt_dyn_lib) |crt_file| {
- const gpa = comp.gpa;
- const io = comp.io;
- const compiler_rt_sub_path = try std.fs.path.join(gpa, &.{
- std.fs.path.dirname(coff.base.emit.sub_path) orelse "",
- std.fs.path.basename(crt_file.full_object_path.sub_path),
- });
- defer gpa.free(compiler_rt_sub_path);
- std.Io.Dir.copyFile(
- crt_file.full_object_path.root_dir.handle,
- crt_file.full_object_path.sub_path,
- coff.base.emit.root_dir.handle,
- compiler_rt_sub_path,
- io,
- .{},
- ) catch |err| return comp.link_diags.fail("copy '{s}' failed: {t}", .{ compiler_rt_sub_path, err });
+
+ // TODO: When https://github.com/ziglang/zig/issues/23617 is in,
+ // this should be set after updateExports instead
+ coff.exports_complete = true;
+
+ while (try coff.resolve(tid)) {}
+ while (try coff.idle(tid)) {}
+
+ // This has to occur after all other flushMoved / flushResized have resolved,
+ // but it will also generate one more set of resizes and moves.
+ if (coff.symbol_table.pending_shrink) {
+ coff.symbol_table.pending_shrink = false;
+
+ const number_of_symbols = coff.targetLoad(&coff.headerPtr().number_of_symbols);
+ coff.symbol_table.ni.shrink(
+ &coff.mf,
+ comp.gpa,
+ number_of_symbols * std.coff.Symbol.sizeOf(),
+ true,
+ ) catch |err| return comp.link_diags.fail(
+ "linker failed to compact symbol table: {t}",
+ .{err},
+ );
}
+ while (try coff.idle(tid)) {}
+
+ if (coff.isImage())
+ try coff.reportUndefs(tid);
+
+ if (comp.emit_implib) |implib_file|
+ coff.flushImplib(implib_file) catch |err|
+ return comp.link_diags.fail("flushing implib '{s}' failed: {t}", .{ implib_file, err });
+
+ coff.mf.flush() catch |err| switch (err) {
+ error.Canceled => |e| return e,
+ else => |e| return comp.link_diags.fail("flush write failed: {t}", .{e}),
+ };
+
+ if (coff.options.enable_link_snapshots)
+ coff.dumpStderr(tid) catch |err|
+ return comp.link_diags.fail("dumping link snapshot failed: {t}", .{err});
}
-pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
+/// Runs a single "resolution" task.
+/// These are tasks that need to modify the node structure in some way.
+/// They must run in a defined order with respect to linker tasks.
+fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
const comp = coff.base.comp;
task: {
+ while (coff.section_merge_pending_index < coff.section_merges.count()) {
+ defer coff.section_merge_pending_index += 1;
+ const sub_prog_node = coff.synth_prog_node.start(
+ coff.section_merges.keys()[coff.section_merge_pending_index].toSlice(coff),
+ 0,
+ );
+ defer sub_prog_node.end();
+ coff.flushSectionMerge(coff.section_merge_pending_index) catch |err| switch (err) {
+ //error.OutOfMemory => |e| return e,
+ else => |e| return comp.link_diags.fail(
+ "linker failed to merge section {s} into {s}: {t}",
+ .{
+ coff.section_merges.keys()[coff.section_merge_pending_index].toSlice(coff),
+ coff.section_merges.values()[coff.section_merge_pending_index].toSlice(coff),
+ e,
+ },
+ ),
+ };
+ break :task;
+ }
while (coff.pending_uavs.pop()) |pending_uav| {
const sub_prog_node = coff.idleProgNode(tid, coff.const_prog_node, .{ .uav = pending_uav.key });
defer sub_prog_node.end();
@@ -1779,22 +5973,52 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
};
break :task;
}
- if (coff.global_pending_index < coff.globals.count()) {
- const pt: Zcu.PerThread = .{ .zcu = comp.zcu.?, .tid = tid };
- const gmi: Node.GlobalMapIndex = @enumFromInt(coff.global_pending_index);
- coff.global_pending_index += 1;
+ if (coff.pending_input) |pending_iami| {
+ const name_slice = pending_iami.member(coff).name.toSlice(coff);
+ const sub_prog_node = coff.input_prog_node.start(
+ name_slice,
+ 0,
+ );
+ defer sub_prog_node.end();
+ coff.pending_input = null;
+ coff.flushInputMember(pending_iami) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ else => |e| return comp.link_diags.fail(
+ "linker failed to load archive member '{f}{f}': {t}",
+ .{
+ pending_iami.member(coff).iai.path(coff),
+ fmtMemberNameString(name_slice),
+ e,
+ },
+ ),
+ };
+ break :task;
+ }
+ if (coff.exports_complete and coff.global_pending_index < coff.globals.count()) {
+ const gmi: Node.GlobalMapIndex = .wrap(coff.global_pending_index);
const sub_prog_node = coff.synth_prog_node.start(
- gmi.globalName(coff).name.toSlice(coff),
+ gmi.name(coff).toSlice(coff),
0,
);
defer sub_prog_node.end();
- coff.flushGlobal(pt, gmi) catch |err| switch (err) {
+ if (coff.flushGlobal(gmi) catch |err| switch (err) {
else => |e| return e,
error.MappedFileIo => return comp.link_diags.fail(
"linker failed to lower constant: {t}",
.{coff.mf.io_err.?},
),
- };
+ }) coff.global_pending_index += 1;
+ break :task;
+ }
+ if (coff.exports_complete and coff.pending_special_symbol != .none) {
+ coff.pending_special_symbol = coff.flushSpecialSymbol(coff.pending_special_symbol) catch |err|
+ switch (err) {
+ error.OutOfMemory => |e| return e,
+ else => |e| return comp.link_diags.fail(
+ "linker failed to flush special symbols: {t}",
+ .{e},
+ ),
+ };
break :task;
}
var lazy_it = coff.lazy.iterator();
@@ -1824,6 +6048,73 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
};
break :task;
};
+ if (coff.symbol_table.pending_symbol_index < coff.symbol_table.symbols.count()) {
+ defer coff.symbol_table.pending_symbol_index += 1;
+ const si = coff.symbol_table.symbols.keys()[coff.symbol_table.pending_symbol_index];
+ const sym = si.get(coff);
+ const sub_prog_node = coff.idleProgNode(
+ tid,
+ coff.symbol_prog_node,
+ if (sym.ni != .none)
+ coff.getNode(sym.ni)
+ else
+ .{ .import_thunk = sym.gmi },
+ );
+ defer sub_prog_node.end();
+ coff.flushSymbolTableEntry(
+ coff.symbol_table.pending_symbol_index,
+ .{ .zcu = comp.zcu.?, .tid = tid },
+ ) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ else => |e| return comp.link_diags.fail(
+ "linker failed to flush symbol table entry: {t}",
+ .{e},
+ ),
+ };
+ break :task;
+ }
+ }
+
+ if (coff.section_merge_pending_index < coff.section_merges.count()) return true;
+ if (coff.pending_uavs.count() > 0) return true;
+ if (coff.pending_input != null) return true;
+ if (coff.exports_complete and coff.globals.count() > coff.global_pending_index) return true;
+ assert(!coff.exports_complete or coff.inputs_complete);
+ if (coff.exports_complete and coff.pending_special_symbol != .none) return true;
+ for (&coff.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true;
+ if (coff.symbol_table.pending_symbol_index < coff.symbol_table.symbols.count()) return true;
+ return false;
+}
+
+pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
+ // Idle tasks should not modify create / modify nodes, otherwise the output is not reproducible.
+ coff.mf.nodes_lock.lock();
+ defer coff.mf.nodes_lock.unlock();
+
+ const comp = coff.base.comp;
+ task: {
+ // TODO: Idle task for flushing obj into lib
+ if (coff.input_section_pending_index < coff.input_sections.items.len) {
+ const isi: Node.InputSection.Index = @enumFromInt(coff.input_section_pending_index);
+ coff.input_section_pending_index += 1;
+ const sub_prog_node = coff.idleProgNode(tid, coff.input_prog_node, coff.getNode(isi.symbol(coff).node(coff)));
+ defer sub_prog_node.end();
+ coff.flushInputSection(isi) catch |err| switch (err) {
+ else => |e| {
+ const ioi = isi.input(coff);
+ return comp.link_diags.fail(
+ "linker failed to read input section '{s}' from \"{f}{f}\": {t}",
+ .{
+ isi.symbol(coff).get(coff).section_number.name(coff).toSlice(coff),
+ ioi.path(coff).fmtEscapeString(),
+ fmtMemberNameString(ioi.memberName(coff)),
+ e,
+ },
+ );
+ },
+ };
+ break :task;
+ }
while (coff.mf.updates.pop()) |ni| {
const clean_moved = ni.cleanMoved(&coff.mf);
const clean_resized = ni.cleanResized(&coff.mf);
@@ -1836,11 +6127,33 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
break :task;
} else coff.mf.update_prog_node.completeOne();
}
+ while (coff.pending_members.pop()) |pending_mi| {
+ const sub_prog_node = coff.idleProgNode(
+ tid,
+ coff.symbol_prog_node,
+ coff.getNode(pending_mi.key.get(coff).content_ni),
+ );
+ defer sub_prog_node.end();
+ try coff.flushMember(pending_mi.key);
+ break :task;
+ }
+ if (coff.exports_complete and coff.export_table.pending_sort) {
+ defer coff.export_table.pending_sort = false;
+ const sub_prog_node = coff.idleProgNode(
+ tid,
+ coff.synth_prog_node,
+ coff.getNode(coff.export_table.ni),
+ );
+ defer sub_prog_node.end();
+
+ coff.flushExportsSort();
+ break :task;
+ }
}
- if (coff.pending_uavs.count() > 0) return true;
- if (coff.globals.count() > coff.global_pending_index) return true;
- for (&coff.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true;
+ if (coff.input_sections.items.len > coff.input_section_pending_index) return true;
if (coff.mf.updates.items.len > 0) return true;
+ if (coff.pending_members.count() > 0) return true;
+ if (coff.exports_complete and coff.export_table.pending_sort) return true;
return false;
}
@@ -1855,7 +6168,15 @@ fn idleProgNode(
else => |tag| @tagName(tag),
.image_section => |si| std.mem.sliceTo(&si.get(coff).section_number.header(coff).name, 0),
inline .pseudo_section, .object_section => |smi| smi.name(coff).toSlice(coff),
- .global => |gmi| gmi.globalName(coff).name.toSlice(coff),
+ .input_section => |isi| {
+ const ioi = isi.input(coff);
+ break :name std.fmt.bufPrint(&name, "{f}{f} {s}", .{
+ ioi.path(coff).fmtEscapeString(),
+ fmtMemberNameString(ioi.memberName(coff)),
+ coff.getNode(isi.symbol(coff).node(coff).parent(&coff.mf)).object_section.name(coff).toSlice(coff),
+ }) catch &name;
+ },
+ .import_thunk => |gmi| gmi.name(coff).toSlice(coff),
.nav => |nmi| {
const ip = &coff.base.comp.zcu.?.intern_pool;
break :name ip.getNav(nmi.navIndex(coff)).fqn.toSlice(ip);
@@ -1866,6 +6187,7 @@ fn idleProgNode(
.tid = tid,
}),
}) catch &name,
+ .archive_member => |mi| &mi.get(coff).headerPtr(coff).name,
}, 0);
}
@@ -1886,9 +6208,10 @@ fn flushUav(
const sec_si = (try coff.objectSectionMapIndex(
.@".rdata",
coff.mf.flags.block_size,
- .{ .read = true },
+ .{ .read = true, .initialized = true },
)).symbol(coff);
try coff.nodes.ensureUnusedCapacity(gpa, 1);
+ if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1);
const sym = si.get(coff);
const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{
.alignment = uav_align.toStdMem(),
@@ -1907,6 +6230,9 @@ fn flushUav(
const sym = si.get(coff);
assert(sym.loc_relocs == .none);
sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
+ if (!isImage(coff) and sym.target_relocs != .none)
+ try coff.pendingSymbolTableEntry(si);
+
break :ni sym.ni;
};
@@ -1923,173 +6249,561 @@ fn flushUav(
error.WriteFailed => return nw.err.?,
else => |e| return e,
};
- si.get(coff).size = @intCast(nw.interface.end);
- si.applyLocationRelocs(coff);
+ si.get(coff).extra.size = @intCast(nw.interface.end);
+ try si.applyLocationRelocs(coff);
}
-fn flushGlobal(coff: *Coff, pt: Zcu.PerThread, gmi: Node.GlobalMapIndex) !void {
- const zcu = pt.zcu;
- const comp = zcu.comp;
- const gpa = zcu.gpa;
- const gn = gmi.globalName(coff);
- if (gn.lib_name.toSlice(coff)) |lib_name| {
- const name = gn.name.toSlice(coff);
- try coff.nodes.ensureUnusedCapacity(gpa, 4);
- try coff.symbol_table.ensureUnusedCapacity(gpa, 1);
+fn aliasGlobal(coff: *Coff, gmi: Node.GlobalMapIndex, alias_si: Symbol.Index) !void {
+ const si = gmi.symbol(coff);
+ const sym = si.get(coff);
+ const alias_sym = alias_si.get(coff);
+ assert(sym.section_number == .UNDEFINED);
+ assert(sym.loc_relocs == .none);
- const target_endian = coff.targetEndian();
- const magic = coff.targetLoad(&coff.optionalHeaderStandardPtr().magic);
- const addr_size: u64, const addr_align: std.mem.Alignment = switch (magic) {
- _ => unreachable,
- .PE32 => .{ 4, .@"4" },
- .@"PE32+" => .{ 8, .@"8" },
- };
+ log.debug("aliasGlobal({s}, {?s}) {d}->{d} ({?s})", .{
+ gmi.name(coff).toSlice(coff),
+ gmi.libName(coff).toSlice(coff),
+ si,
+ alias_si,
+ if (alias_sym.gmi != .none) alias_sym.gmi.name(coff).toSlice(coff) else null,
+ });
- const gop = try coff.import_table.entries.getOrPutAdapted(
- gpa,
- lib_name,
- ImportTable.Adapter{ .coff = coff },
- );
- const import_hint_name_align: std.mem.Alignment = .@"2";
- if (!gop.found_existing) {
- errdefer _ = coff.import_table.entries.pop();
- try coff.import_table.ni.resize(
- &coff.mf,
- gpa,
- @sizeOf(std.coff.ImportDirectoryEntry) * (gop.index + 2),
+ var ri = sym.target_relocs;
+ while (ri != .none) {
+ const reloc = ri.get(coff);
+ assert(reloc.target == si);
+ reloc.target = alias_si;
+ if (reloc.next == .none) {
+ reloc.next = alias_sym.target_relocs;
+ if (alias_sym.target_relocs != .none)
+ alias_sym.target_relocs.get(coff).prev = ri;
+ break;
+ }
+ ri = reloc.next;
+ }
+
+ const prev_target_relocs = alias_sym.target_relocs;
+ if (sym.target_relocs != .none)
+ alias_sym.target_relocs = sym.target_relocs;
+ sym.target_relocs = .none;
+ sym.gmi = alias_sym.gmi;
+ coff.globals.values()[gmi.unwrap().?].si = alias_si;
+ // Only apply the new relocs
+ try alias_si.applyTargetRelocs(coff, prev_target_relocs);
+}
+
+fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
+ const comp = coff.base.comp;
+ const gpa = comp.gpa;
+ const name = gmi.name(coff);
+ const si = gmi.symbol(coff);
+
+ log.debug(
+ "flushGlobal({s}, {?s}) = n{d} {d}@{d}",
+ .{
+ name.toSlice(coff),
+ gmi.libName(coff).toSlice(coff),
+ si.get(coff).ni,
+ si,
+ si.get(coff).section_number,
+ },
+ );
+
+ if (!coff.isImage()) {
+ try coff.pendingSymbolTableEntry(si);
+ if (coff.isArchive() and si.get(coff).ni != .none)
+ try coff.ensureMemberSymbol(
+ coff.getNode(Node.known.zcu_member).archive_member,
+ name,
);
- const import_hint_name_table_len =
- import_hint_name_align.forward(lib_name.len + ".dll".len + 1);
- const idata_section_ni = coff.import_table.ni.parent(&coff.mf);
- const import_lookup_table_ni = try coff.mf.addLastChildNode(gpa, idata_section_ni, .{
- .size = addr_size * 2,
- .alignment = addr_align,
- .moved = true,
- });
- const import_address_table_ni = try coff.mf.addLastChildNode(gpa, idata_section_ni, .{
- .size = addr_size * 2,
- .alignment = addr_align,
- .moved = true,
- });
- const import_address_table_si = coff.addSymbolAssumeCapacity();
- {
- const import_address_table_sym = import_address_table_si.get(coff);
- import_address_table_sym.ni = import_address_table_ni;
- assert(import_address_table_sym.loc_relocs == .none);
- import_address_table_sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
- import_address_table_sym.section_number =
- coff.getNode(idata_section_ni).object_section.symbol(coff).get(coff).section_number;
+
+ return true;
+ }
+
+ if (si.get(coff).ni != .none)
+ return true;
+
+ const Import = struct {
+ lib_name: String,
+ name: String.Optional,
+ ordinal_hint: u16,
+ kind: enum {
+ iat_ptr,
+ thunk,
+ },
+ };
+
+ const import: Import = import: {
+ const sym = si.get(coff);
+ const name_slice = name.toSlice(coff);
+ const imp_match = std.mem.startsWith(u8, name_slice, imp_prefix);
+
+ // Globals may have the __imp_ prefix already if they are undef externals from another input.
+ assert(sym.flags.dll_storage_class != .dllexport);
+ const search_name, const is_imp = if (imp_match or sym.flags.dll_storage_class != .dllimport)
+ .{ name, imp_match }
+ else name: {
+ try coff.ensureUnusedStringCapacity(imp_prefix.len + name_slice.len);
+ const imp_name = try std.fmt.allocPrint(gpa, imp_prefix ++ "{s}", .{name_slice});
+ defer gpa.free(imp_name);
+ break :name .{ coff.getOrPutStringAssumeCapacity(imp_name), true };
+ };
+
+ const opt_alt_search_name = coff.alternate_names.get(search_name);
+ const search_libs = switch (sym.flags.value_tag) {
+ .weak_alias_si, .weak_alias_name => switch (sym.flags.weak_external_strat) {
+ .none => unreachable,
+ .no_library => false,
+ .library,
+ .alias,
+ => true,
+ .anti_dependency => return comp.link_diags.fail(
+ // TODO: Figure out what the purpose of this is
+ "TODO support anti_dependency weak external: {s}",
+ .{name.toSlice(coff)},
+ ),
+ },
+ else => true,
+ };
+
+ const opt_indices_lists: []const ?InputArchive.SearchList = if (search_libs) &.{
+ coff.input_archive_symbol_indices.get(search_name),
+ if (opt_alt_search_name) |alt| coff.input_archive_symbol_indices.get(alt) else null,
+ } else &.{};
+
+ for (opt_indices_lists) |opt_indices_list| {
+ const indices_list = opt_indices_list orelse continue;
+ var iter: InputArchive.Member.Symbol.Index = indices_list.first;
+ while (true) {
+ const archive_sym = &coff.input_archive_symbols.items[@intFromEnum(iter)];
+ const member = &coff.input_archive_members.items[@intFromEnum(archive_sym.iami)];
+ member: switch (member.content) {
+ .object => if (!member.flags.is_loaded) {
+ if (gmi.libName(coff).unwrap()) |lib_name|
+ if (!std.ascii.eqlIgnoreCase(
+ lib_name.toSlice(coff),
+ member.iai.path(coff).stem(),
+ )) break :member;
+
+ // Try loading the input member and then retry.
+ // This could still be a member containing imports
+ // that use the older non-IMPORT_HEADER method.
+ coff.pending_input = archive_sym.iami;
+ return false;
+ },
+ .import => |import| {
+ if (gmi.libName(coff).unwrap()) |lib_name|
+ if (!std.ascii.eqlIgnoreCase(
+ import.lib_name.toSlice(coff),
+ lib_name.toSlice(coff),
+ )) break :member;
+
+ const imp_name: String.Optional = name: switch (import.name_type) {
+ .NAME,
+ .NAME_NOPREFIX,
+ .NAME_UNDECORATE,
+ => |tag| {
+ const symbol_name: []const u8 = import.symbol_name.toSlice(coff);
+ const end_match = std.mem.endsWith(u8, name_slice, symbol_name);
+ const len_delta = name_slice.len -% symbol_name.len;
+ if (!end_match or
+ (!imp_match and len_delta != 0) or
+ (imp_match and len_delta != imp_prefix.len))
+ return comp.link_diags.fail(
+ "global '{s}' has mismatched symbol name in import header: '{s}'",
+ .{
+ name.toSlice(coff),
+ import.symbol_name.toSlice(coff),
+ },
+ );
+
+ const imp_name = if (tag == .NAME) import.symbol_name else undecorated: {
+ var imp_name = std.mem.trimStart(u8, symbol_name, "?@_");
+ if (tag == .NAME_UNDECORATE)
+ imp_name = std.mem.sliceTo(imp_name, '@');
+
+ try coff.ensureUnusedStringCapacity(imp_name.len);
+ break :undecorated coff.getOrPutStringAssumeCapacity(imp_name);
+ };
+
+ break :name imp_name.toOptional();
+ },
+ .ORDINAL => break :name .none,
+ else => |t| return comp.link_diags.fail("TODO handle name_type {t}", .{t}),
+ };
+
+ break :import .{
+ .lib_name = import.lib_name,
+ .name = imp_name,
+ .ordinal_hint = import.import_ordinal_hint,
+ .kind = if (import.type == .CODE and !is_imp) .thunk else .iat_ptr,
+ };
+ },
+ }
+
+ if (archive_sym.next == iter) break;
+ iter = archive_sym.next;
}
- const import_hint_name_table_ni = try coff.mf.addLastChildNode(gpa, idata_section_ni, .{
- .size = import_hint_name_table_len,
- .alignment = import_hint_name_align,
- .moved = true,
- });
- gop.value_ptr.* = .{
- .import_lookup_table_ni = import_lookup_table_ni,
- .import_address_table_si = import_address_table_si,
- .import_hint_name_table_ni = import_hint_name_table_ni,
- .len = 0,
- .hint_name_len = @intCast(import_hint_name_table_len),
+ }
+
+ switch (sym.flags.value_tag) {
+ .weak_alias_si => {
+ try coff.aliasGlobal(gmi, sym.value.weak_alias_si);
+ return true;
+ },
+ .weak_alias_name => {
+ // Convert an unresolved weak external that itself refers to an undef external
+ // into a (possibly new) global, so it can be resolved separately.
+ const alias_gop = try coff.getOrPutGlobalSymbol(.{
+ .name = sym.value.weak_alias_name.toSlice(coff),
+ });
+ try coff.aliasGlobal(gmi, alias_gop.value_ptr.si);
+ return true;
+ },
+ else => {},
+ }
+
+ // If there was an object that had the alternate name, we've attempted to load it
+ if (opt_alt_search_name) |alt_search_name| {
+ if (coff.globals.get(alt_search_name)) |alias_global| {
+ try coff.aliasGlobal(gmi, alias_global.si);
+ return true;
+ }
+ }
+
+ // Allow importing symbols with no implib entry, if a lib_name was specified.
+ // This is necessary for certain ntdll symbols, such as LdrRegisterDllNotification,
+ // which are not in the implib.
+ if (sym.flags.type != .unknown) {
+ if (gmi.libName(coff).unwrap()) |lib_name| break :import .{
+ .lib_name = lib_name,
+ .name = name.toOptional(),
+ .ordinal_hint = 0,
+ .kind = if (sym.flags.type == .code) .thunk else .iat_ptr,
};
- const import_hint_name_slice = import_hint_name_table_ni.slice(&coff.mf);
- @memcpy(import_hint_name_slice[0..lib_name.len], lib_name);
- @memcpy(import_hint_name_slice[lib_name.len..][0..".dll".len], ".dll");
- @memset(import_hint_name_slice[lib_name.len + ".dll".len ..], 0);
- coff.nodes.appendAssumeCapacity(.{ .import_lookup_table = @enumFromInt(gop.index) });
- coff.nodes.appendAssumeCapacity(.{ .import_address_table = @enumFromInt(gop.index) });
- coff.nodes.appendAssumeCapacity(.{ .import_hint_name_table = @enumFromInt(gop.index) });
+ }
+
+ return true;
+ };
+
+ try coff.nodes.ensureUnusedCapacity(gpa, 4);
+ try coff.symbols.ensureUnusedCapacity(gpa, 2);
- const import_directory_entries = coff.importDirectoryTableSlice()[gop.index..][0..2];
- import_directory_entries.* = .{ .{
- .import_lookup_table_rva = coff.computeNodeRva(import_lookup_table_ni),
- .time_date_stamp = 0,
- .forwarder_chain = 0,
- .name_rva = coff.computeNodeRva(import_hint_name_table_ni),
- .import_address_table_rva = coff.computeNodeRva(import_address_table_ni),
- }, .{
- .import_lookup_table_rva = 0,
- .time_date_stamp = 0,
- .forwarder_chain = 0,
- .name_rva = 0,
- .import_address_table_rva = 0,
- } };
- if (target_endian != native_endian)
- std.mem.byteSwapAllFields([2]std.coff.ImportDirectoryEntry, import_directory_entries);
+ const target_endian = coff.targetEndian();
+ const addr_info = coff.targetAddrInfo();
+ const lib_name = import.lib_name.toSlice(coff);
+ const gop = try coff.import_table.entries.getOrPutAdapted(
+ gpa,
+ lib_name,
+ ImportTable.Adapter{ .coff = coff },
+ );
+ const import_hint_name_align: std.mem.Alignment = .@"2";
+ if (!gop.found_existing) {
+ errdefer _ = coff.import_table.entries.pop();
+ try coff.import_table.ni.resize(
+ &coff.mf,
+ gpa,
+ @sizeOf(std.coff.ImportDirectoryEntry) * (gop.index + 2),
+ );
+ const import_hint_name_table_len =
+ import_hint_name_align.forward(lib_name.len + ".dll".len + 1);
+ const idata_section_ni = coff.import_table.ni.parent(&coff.mf);
+ const import_lookup_table_ni = try coff.mf.addLastChildNode(gpa, idata_section_ni, .{
+ .size = addr_info.size * 2,
+ .alignment = addr_info.alignment,
+ .moved = true,
+ });
+ const import_address_table_ni = try coff.mf.addLastChildNode(gpa, idata_section_ni, .{
+ .size = addr_info.size * 2,
+ .alignment = addr_info.alignment,
+ .moved = true,
+ });
+ const import_address_table_si = coff.addSymbolAssumeCapacity();
+ {
+ const import_address_table_sym = import_address_table_si.get(coff);
+ import_address_table_sym.ni = import_address_table_ni;
+ assert(import_address_table_sym.loc_relocs == .none);
+ import_address_table_sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
+ import_address_table_sym.section_number =
+ coff.getNode(idata_section_ni).object_section.symbol(coff).get(coff).section_number;
}
+ const import_hint_name_table_ni = try coff.mf.addLastChildNode(gpa, idata_section_ni, .{
+ .size = import_hint_name_table_len,
+ .alignment = import_hint_name_align,
+ .moved = true,
+ });
+ gop.value_ptr.* = .{
+ .import_lookup_table_ni = import_lookup_table_ni,
+ .import_address_table_si = import_address_table_si,
+ .import_hint_name_table_ni = import_hint_name_table_ni,
+ .import_address_table_symbols = .empty,
+ .len = 0,
+ .hint_name_len = @intCast(import_hint_name_table_len),
+ };
+ const import_hint_name_slice = import_hint_name_table_ni.slice(&coff.mf);
+ @memcpy(import_hint_name_slice[0..lib_name.len], lib_name);
+ @memcpy(import_hint_name_slice[lib_name.len..][0..".dll".len], ".dll");
+ @memset(import_hint_name_slice[lib_name.len + ".dll".len ..], 0);
+ coff.nodes.appendAssumeCapacity(.{ .import_lookup_table = @enumFromInt(gop.index) });
+ coff.nodes.appendAssumeCapacity(.{ .import_address_table = @enumFromInt(gop.index) });
+ coff.nodes.appendAssumeCapacity(.{ .import_hint_name_table = @enumFromInt(gop.index) });
+
+ const import_directory_entries = coff.importDirectoryTableSlice()[gop.index..][0..2];
+ import_directory_entries.* = .{ .{
+ .import_lookup_table_rva = coff.computeNodeRva(import_lookup_table_ni),
+ .time_date_stamp = 0,
+ .forwarder_chain = 0,
+ .name_rva = coff.computeNodeRva(import_hint_name_table_ni),
+ .import_address_table_rva = coff.computeNodeRva(import_address_table_ni),
+ }, .{
+ .import_lookup_table_rva = 0,
+ .time_date_stamp = 0,
+ .forwarder_chain = 0,
+ .name_rva = 0,
+ .import_address_table_rva = 0,
+ } };
+ if (target_endian != native_endian)
+ std.mem.byteSwapAllFields([2]std.coff.ImportDirectoryEntry, import_directory_entries);
+ }
+
+ log.debug(
+ "flushGlobalImport({s}, {?s}, {d}, {s})",
+ .{ name.toSlice(coff), import.name.toSlice(coff), import.ordinal_hint, lib_name },
+ );
+
+ const iat_symbol_gop = try coff.import_table.iat_symbol_indices.getOrPut(gpa, .{
+ .iti = @enumFromInt(gop.index),
+ .name = import.name,
+ .ordinal_hint = import.ordinal_hint,
+ });
+ if (!iat_symbol_gop.found_existing) {
const import_symbol_index = gop.value_ptr.len;
+ iat_symbol_gop.value_ptr.* = import_symbol_index;
+
gop.value_ptr.len = import_symbol_index + 1;
- const new_symbol_table_size = addr_size * (import_symbol_index + 2);
- const import_hint_name_index = gop.value_ptr.hint_name_len;
- gop.value_ptr.hint_name_len = @intCast(
- import_hint_name_align.forward(import_hint_name_index + 2 + name.len + 1),
- );
+ const new_symbol_table_size = addr_info.size * (import_symbol_index + 2);
+
try gop.value_ptr.import_lookup_table_ni.resize(&coff.mf, gpa, new_symbol_table_size);
const import_address_table_ni = gop.value_ptr.import_address_table_si.node(coff);
try import_address_table_ni.resize(&coff.mf, gpa, new_symbol_table_size);
- try gop.value_ptr.import_hint_name_table_ni.resize(&coff.mf, gpa, gop.value_ptr.hint_name_len);
+
+ const opt_imp_name = import.name.toSlice(coff);
+ const opt_import_hint_name_index = if (opt_imp_name) |imp_name| blk: {
+ const import_hint_name_index = gop.value_ptr.hint_name_len;
+ gop.value_ptr.hint_name_len = @intCast(
+ import_hint_name_align.forward(import_hint_name_index + 2 + imp_name.len + 1),
+ );
+ try gop.value_ptr.import_hint_name_table_ni.resize(&coff.mf, gpa, gop.value_ptr.hint_name_len);
+ break :blk import_hint_name_index;
+ } else null;
+
+ const import_hint_name_rva = if (opt_import_hint_name_index) |import_hint_name_index| blk: {
+ const import_hint_name_slice = gop.value_ptr.import_hint_name_table_ni.slice(&coff.mf);
+ const ordinal_hint: *u16 = @ptrCast(@alignCast(import_hint_name_slice[import_hint_name_index..][0..2]));
+ ordinal_hint.* = std.mem.nativeTo(u16, import.ordinal_hint, target_endian);
+ @memcpy(import_hint_name_slice[import_hint_name_index + 2 ..][0..opt_imp_name.?.len], opt_imp_name.?);
+ @memset(import_hint_name_slice[import_hint_name_index + 2 + opt_imp_name.?.len ..], 0);
+ break :blk coff.computeNodeRva(gop.value_ptr.import_hint_name_table_ni) + import_hint_name_index;
+ } else 0;
+
const import_lookup_slice = gop.value_ptr.import_lookup_table_ni.slice(&coff.mf);
const import_address_slice = import_address_table_ni.slice(&coff.mf);
- const import_hint_name_slice = gop.value_ptr.import_hint_name_table_ni.slice(&coff.mf);
- @memset(import_hint_name_slice[import_hint_name_index..][0..2], 0);
- @memcpy(import_hint_name_slice[import_hint_name_index + 2 ..][0..name.len], name);
- @memset(import_hint_name_slice[import_hint_name_index + 2 + name.len ..], 0);
- const import_hint_name_rva =
- coff.computeNodeRva(gop.value_ptr.import_hint_name_table_ni) + import_hint_name_index;
- switch (magic) {
+ switch (addr_info.magic) {
_ => unreachable,
inline .PE32, .@"PE32+" => |ct_magic| {
- const Addr = switch (ct_magic) {
- _ => comptime unreachable,
- .PE32 => u32,
- .@"PE32+" => u64,
- };
- const import_lookup_table: []Addr = @ptrCast(@alignCast(import_lookup_slice));
- const import_address_table: []Addr = @ptrCast(@alignCast(import_address_slice));
- const import_hint_name_rvas: [2]Addr = .{
- std.mem.nativeTo(Addr, @intCast(import_hint_name_rva), target_endian),
- std.mem.nativeTo(Addr, 0, target_endian),
+ const Entry = std.coff.ImportLookupTableEntry(ct_magic);
+ const import_lookup_table: []Entry = @ptrCast(@alignCast(import_lookup_slice));
+ const import_address_table: []Entry = @ptrCast(@alignCast(import_address_slice));
+ var import_hint_name_rvas: [2]Entry = .{
+ .{
+ .payload = if (import.name == .none)
+ .{ .ordinal = .{ .ordinal = import.ordinal_hint } }
+ else
+ .{ .hint_name_rva = @intCast(import_hint_name_rva) },
+ .is_ordinal = import.name == .none,
+ },
+ @bitCast(@as(@typeInfo(Entry).@"struct".backing_integer.?, 0)),
};
+ if (native_endian != target_endian)
+ for (&import_hint_name_rvas) |*v| std.mem.byteSwapAllFields(Entry, v);
+
import_lookup_table[import_symbol_index..][0..2].* = import_hint_name_rvas;
import_address_table[import_symbol_index..][0..2].* = import_hint_name_rvas;
},
}
- const si = gmi.symbol(coff);
- const sym = si.get(coff);
- sym.section_number = Symbol.Index.text.get(coff).section_number;
- assert(sym.loc_relocs == .none);
- sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
- switch (coff.targetLoad(&coff.headerPtr().machine)) {
- else => |tag| @panic(@tagName(tag)),
- .AMD64 => {
- const init = [_]u8{ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 };
- const target = &comp.root_mod.resolved_target.result;
- const ni = try coff.mf.addLastChildNode(gpa, Symbol.Index.text.node(coff), .{
- .alignment = switch (comp.root_mod.optimize_mode) {
- .Debug,
- .ReleaseSafe,
- .ReleaseFast,
- => target_util.defaultFunctionAlignment(target),
- .ReleaseSmall => target_util.minFunctionAlignment(target),
- }.toStdMem(),
- .size = init.len,
- });
- @memcpy(ni.slice(&coff.mf)[0..init.len], &init);
- sym.ni = ni;
- sym.size = init.len;
+ }
+
+ const sym = si.get(coff);
+ assert(sym.loc_relocs == .none);
+ const iat_offset: u32 = @intCast(addr_info.size * iat_symbol_gop.value_ptr.*);
+ switch (import.kind) {
+ .iat_ptr => {
+ const iat_sym = gop.value_ptr.import_address_table_si.get(coff);
+ sym.section_number = iat_sym.section_number;
+ sym.ni = iat_sym.ni;
+ sym.setValue(.{ .node_offset = iat_offset });
+ (try gop.value_ptr.import_address_table_symbols.addOne(gpa)).* = si;
+ },
+ .thunk => {
+ sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
+
+ const target = &comp.root_mod.resolved_target.result;
+ const alignment = switch (comp.root_mod.optimize_mode) {
+ .Debug,
+ .ReleaseSafe,
+ .ReleaseFast,
+ => target_util.defaultFunctionAlignment(target),
+ .ReleaseSmall => target_util.minFunctionAlignment(target),
+ }.toStdMem();
+ const parent_si = (try coff.pseudoSectionMapIndex(
+ .@".thunks",
+ alignment,
+ .{ .execute = true, .read = true },
+ )).symbol(coff);
+
+ const parent_sym = parent_si.get(coff);
+ sym.section_number = parent_sym.section_number;
+
+ switch (coff.targetLoad(&coff.headerPtr().machine)) {
+ else => |tag| @panic(@tagName(tag)),
+ .AMD64 => {
+ const init = [_]u8{ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 };
+ const ni = try coff.mf.addLastChildNode(gpa, parent_sym.ni, .{
+ .alignment = alignment,
+ .size = init.len,
+ });
+ @memcpy(ni.slice(&coff.mf)[0..init.len], &init);
+ sym.ni = ni;
+ sym.extra.size = init.len;
+ try coff.addReloc(
+ si,
+ init.len - 4,
+ gop.value_ptr.import_address_table_si,
+ .{ .known = iat_offset },
+ .{ .AMD64 = .REL32 },
+ );
+ },
+ }
+ coff.nodes.appendAssumeCapacity(.{ .import_thunk = gmi });
+ },
+ }
+
+ try si.flushMoved(coff);
+ return true;
+}
+
+fn flushSpecialSymbol(coff: *Coff, pending: SpecialSymbol) !SpecialSymbol {
+ const comp = coff.base.comp;
+
+ if (!coff.isImage()) return .none;
+ const gpa = comp.gpa;
+ const machine = coff.targetLoad(&coff.headerPtr().machine);
+ const target = &comp.root_mod.resolved_target.result;
+
+ return next: switch (pending) {
+ .entry => {
+ // TODO: Use explicitly specified entry if set, add err if not found
+ const entries: []const struct { ?[]const u8, []const u8 } = if (coff.isExe())
+ if (comp.config.link_libc) switch (coff.optionalHeaderField(.subsystem)) {
+ .WINDOWS_CUI => &.{
+ .{ "main", "mainCRTStartup" },
+ .{ "wmain", "wmainCRTStartup" },
+ },
+ .WINDOWS_GUI => &.{
+ .{ "WinMain", "WinMainCRTStartup" },
+ .{ "wWinMain", "wWinMainCRTStartup" },
+ },
+ else => unreachable,
+ } else &.{
+ .{ "wWinMainCRTStartup", "wWinMainCRTStartup" },
+ }
+ else
+ &.{.{ null, if (target.abi.isGnu()) "DllMainCRTStartup" else "_DllMainCRTStartup" }};
+
+ const entry_si = for (entries) |entry| {
+ if (entry[0]) |required_name|
+ if (coff.getDefinedGlobal(required_name) == .null) continue;
+
+ break try coff.globalSymbol(.{ .name = entry[1], .type = .code });
+ } else .null;
+
+ if (entry_si != .null) {
+ log.debug(
+ "entry({s}, {d})",
+ .{ entry_si.get(coff).gmi.name(coff).toSlice(coff), entry_si },
+ );
+
+ try coff.symbols.ensureUnusedCapacity(gpa, 1);
+ const optional_hdr_si = coff.addSymbolAssumeCapacity();
+ const optional_hdr_sym = optional_hdr_si.get(coff);
+ optional_hdr_sym.ni = Node.known.optional_header;
+ assert(optional_hdr_sym.loc_relocs == .none);
+ optional_hdr_sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
+
+ const optional_hdr = coff.optionalHeaderStandardPtr();
+ optional_hdr.address_of_entry_point = std.mem.nativeTo(
+ u32,
+ entry_si.get(coff).rva,
+ coff.targetEndian(),
+ );
+
try coff.addReloc(
- si,
- init.len - 4,
- gop.value_ptr.import_address_table_si,
- @intCast(addr_size * import_symbol_index),
- .{ .AMD64 = .REL32 },
+ optional_hdr_si,
+ @intFromPtr(&optional_hdr.address_of_entry_point) - @intFromPtr(optional_hdr),
+ entry_si,
+ .{ .known = 0 },
+ switch (machine) {
+ else => |tag| @panic(@tagName(tag)),
+ .AMD64 => .{ .AMD64 = .ADDR32NB },
+ .I386 => .{ .I386 = .DIR32NB },
+ },
);
- },
- }
- coff.nodes.appendAssumeCapacity(.{ .global = gmi });
- sym.rva = coff.computeNodeRva(sym.ni);
- si.applyLocationRelocs(coff);
- }
+ }
+
+ // Referencing the startup functions may trigger loading the object containing them,
+ // we need to wait until that is done before looking for further symbols.
+ break :next .tls;
+ },
+ .tls => {
+ if (coff.getDefinedGlobal("_tls_used").unwrap()) |tls_used_si| {
+ log.debug("tlsDir({d})", .{tls_used_si});
+
+ const tls_directory = coff.dataDirectoryPtr(.TLS);
+ tls_directory.* = .{
+ .virtual_address = tls_used_si.get(coff).rva,
+ .size = switch (coff.targetLoad(&coff.optionalHeaderStandardPtr().magic)) {
+ _ => unreachable,
+ .PE32 => 24,
+ .@"PE32+" => 40,
+ },
+ };
+ if (coff.targetEndian() != native_endian)
+ std.mem.byteSwapAllFields(std.coff.ImageDataDirectory, tls_directory);
+
+ try coff.symbols.ensureUnusedCapacity(gpa, 1);
+ const data_dir_si = coff.addSymbolAssumeCapacity();
+ const data_dir_sym = data_dir_si.get(coff);
+ data_dir_sym.ni = Node.known.data_directories;
+ assert(data_dir_sym.loc_relocs == .none);
+ data_dir_sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
+
+ try coff.addReloc(
+ data_dir_si,
+ @intFromPtr(&tls_directory.virtual_address) - @intFromPtr(coff.dataDirectorySlice().ptr),
+ tls_used_si,
+ .{ .known = 0 },
+ switch (machine) {
+ else => |tag| @panic(@tagName(tag)),
+ .AMD64 => .{ .AMD64 = .ADDR32NB },
+ .I386 => .{ .I386 = .DIR32NB },
+ },
+ );
+ }
+
+ break :next .none;
+ },
+ .none => unreachable,
+ };
}
fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
@@ -2119,6 +6833,9 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
}
assert(sym.loc_relocs == .none);
sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
+ if (!isImage(coff) and sym.target_relocs != .none)
+ try coff.pendingSymbolTableEntry(si);
+
break :ni sym.ni;
};
@@ -2138,42 +6855,107 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
error.WriteFailed => return nw.err.?,
else => |e| return e,
};
- si.get(coff).size = @intCast(nw.interface.end);
- si.applyLocationRelocs(coff);
+ si.get(coff).extra.size = @intCast(nw.interface.end);
+ try si.applyLocationRelocs(coff);
}
fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {
+ log.debug("flushMoved({s}, n{d})", .{ @tagName(coff.getNode(ni)), ni });
switch (coff.getNode(ni)) {
.file,
.header,
.signature,
+ => unreachable,
.coff_header,
.optional_header,
.data_directories,
.section_table,
- => unreachable,
- .image_section => |si| return coff.targetStore(
- &si.get(coff).section_number.header(coff).pointer_to_raw_data,
- @intCast(ni.fileLocation(&coff.mf, false).offset),
- ),
- .import_directory_table => coff.targetStore(
- &coff.dataDirectoryPtr(.IMPORT).virtual_address,
- coff.computeNodeRva(ni),
- ),
+ .placeholder,
+ => assert(!coff.isImage()),
+ .symbol_table,
+ .string_table,
+ => |_, tag| {
+ if (tag == .symbol_table)
+ coff.targetStore(
+ &coff.headerPtr().pointer_to_symbol_table,
+ @intCast(ni.location(&coff.mf).resolve(&coff.mf)[0]),
+ );
+
+ if (!coff.symbol_table.pending_shrink) {
+ const symbol_table_loc, const symbol_table_size = coff.symbol_table.ni.location(&coff.mf).resolve(&coff.mf);
+ const string_table_offset, _ = coff.symbol_table.strings_ni.location(&coff.mf).resolve(&coff.mf);
+ coff.symbol_table.pending_shrink = string_table_offset - (symbol_table_loc + symbol_table_size) > 0;
+ }
+ },
+ .relocation_table => |sn| {
+ coff.targetStore(
+ &sn.header(coff).pointer_to_relocations,
+ @intCast(ni.location(&coff.mf).resolve(&coff.mf)[0]),
+ );
+ },
+ .relocation_table_entry => {},
+ .archive_member_header => |mi| {
+ const member = mi.get(coff);
+ switch (member.kind) {
+ .first_linker, .second_linker, .longnames => {},
+ else => coff.targetStore(
+ &coff.secondLinkerMemberOffsetsSlice()[@intFromEnum(mi) - Member.Index.known_count],
+ @intCast(ni.fileLocation(&coff.mf, false).offset),
+ ),
+ }
+
+ if (member.kind == .coff)
+ try coff.pending_members.put(coff.base.comp.gpa, mi, {});
+ },
+ .archive_member,
+ => {},
+ .image_section => |si| {
+ const sym = si.get(coff);
+ const flags = coff.targetLoad(&sym.section_number.header(coff).flags);
+ if (!flags.CNT_UNINITIALIZED_DATA) {
+ const file_offset = if (isArchive(coff))
+ sym.ni.location(&coff.mf).resolve(&coff.mf)[0]
+ else
+ ni.fileLocation(&coff.mf, false).offset;
+
+ return coff.targetStore(
+ &sym.section_number.header(coff).pointer_to_raw_data,
+ @intCast(file_offset),
+ );
+ }
+ },
+ .input_section => |isi| {
+ try isi.symbol(coff).flushMoved(coff);
+ for (coff.input_symbols.items[@intFromEnum(isi.firstSymbol(coff))..]) |input_symbol| {
+ if (input_symbol.si.get(coff).ni != ni) break;
+ try input_symbol.si.flushMoved(coff);
+ }
+ },
+ .import_directory_table => {
+ _, const size = ni.location(&coff.mf).resolve(&coff.mf);
+ if (size > 0)
+ coff.targetStore(
+ &coff.dataDirectoryPtr(.IMPORT).virtual_address,
+ coff.computeNodeRva(ni),
+ );
+ },
.import_lookup_table => |import_index| coff.targetStore(
&coff.importDirectoryEntryPtr(import_index).import_lookup_table_rva,
coff.computeNodeRva(ni),
),
.import_address_table => |import_index| {
- const import_address_table_si = import_index.get(coff).import_address_table_si;
- import_address_table_si.flushMoved(coff);
+ const entry = import_index.get(coff);
+ const import_address_table_si = entry.import_address_table_si;
+ try import_address_table_si.flushMoved(coff);
coff.targetStore(
&coff.importDirectoryEntryPtr(import_index).import_address_table_rva,
import_address_table_si.get(coff).rva,
);
+
+ for (entry.import_address_table_symbols.items) |iat_ptr_si|
+ try iat_ptr_si.flushMoved(coff);
},
.import_hint_name_table => |import_index| {
- const target_endian = coff.targetEndian();
const magic = coff.targetLoad(&coff.optionalHeaderStandardPtr().magic);
const import_hint_name_rva = coff.computeNodeRva(ni);
coff.targetStore(
@@ -2186,78 +6968,173 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {
import_entry.import_address_table_si.node(coff).slice(&coff.mf);
const import_hint_name_slice = ni.slice(&coff.mf);
const import_hint_name_align = ni.alignment(&coff.mf);
+
var import_hint_name_index: u32 = 0;
for (0..import_entry.len) |import_symbol_index| {
- import_hint_name_index = @intCast(import_hint_name_align.forward(
- std.mem.indexOfScalarPos(
- u8,
- import_hint_name_slice,
- import_hint_name_index,
- 0,
- ).? + 1,
- ));
switch (magic) {
_ => unreachable,
inline .PE32, .@"PE32+" => |ct_magic| {
- const Addr = switch (ct_magic) {
- _ => comptime unreachable,
- .PE32 => u32,
- .@"PE32+" => u64,
- };
- const import_lookup_table: []Addr = @ptrCast(@alignCast(import_lookup_slice));
- const import_address_table: []Addr = @ptrCast(@alignCast(import_address_slice));
- const rva = std.mem.nativeTo(
- Addr,
- import_hint_name_rva + import_hint_name_index,
- target_endian,
- );
- import_lookup_table[import_symbol_index] = rva;
- import_address_table[import_symbol_index] = rva;
+ const Entry = std.coff.ImportLookupTableEntry(ct_magic);
+ const import_lookup_table: []Entry = @ptrCast(@alignCast(import_lookup_slice));
+ const import_address_table: []Entry = @ptrCast(@alignCast(import_address_slice));
+
+ var entry = coff.targetLoad(&import_lookup_table[import_symbol_index]);
+ if (entry.is_ordinal)
+ continue;
+
+ import_hint_name_index = @intCast(import_hint_name_align.forward(
+ std.mem.indexOfScalarPos(
+ u8,
+ import_hint_name_slice,
+ import_hint_name_index,
+ 0,
+ ).? + 1,
+ ));
+
+ entry.payload.hint_name_rva = @intCast(import_hint_name_rva + import_hint_name_index);
+ import_hint_name_index += 2;
+
+ coff.targetStore(&import_lookup_table[import_symbol_index], entry);
+ coff.targetStore(&import_address_table[import_symbol_index], entry);
},
}
- import_hint_name_index += 2;
+ }
+ },
+ .export_directory_table => {
+ const rva = coff.computeNodeRva(ni);
+ coff.targetStore(&coff.dataDirectoryPtr(.EXPORT).virtual_address, rva);
+ coff.targetStore(&coff.exportDirectoryTable().name_rva, rva + @sizeOf(std.coff.ExportDirectoryTable));
+ },
+ .export_address_table => {
+ try coff.export_table.export_address_table_si.flushMoved(coff);
+
+ // These relocs are applied directly here instead of via the above flushMoved call as
+ // they are non-contiguous, and not tracked under export_address_table_si.
+ for (coff.export_table.entries.values()) |entry|
+ try entry.export_address_table_ri.get(coff).apply(coff);
+
+ coff.targetStore(
+ &coff.exportDirectoryTable().export_address_table_rva,
+ coff.computeNodeRva(ni),
+ );
+ },
+ .export_name_pointer_table => coff.targetStore(
+ &coff.exportDirectoryTable().name_pointer_table_rva,
+ coff.computeNodeRva(ni),
+ ),
+ .export_ordinal_table => coff.targetStore(
+ &coff.exportDirectoryTable().ordinal_table_rva,
+ coff.computeNodeRva(ni),
+ ),
+ .export_name_table => {
+ const name_table_rva = coff.computeNodeRva(coff.export_table.name_table_ni);
+ for (
+ coff.exportNamePointerTableSlice(),
+ coff.exportOrdinalTableSlice(),
+ ) |*np, target_ord| {
+ const ord: ExportTable.Ordinal = @enumFromInt(coff.targetLoad(&target_ord.unbiased_ordinal));
+ const entry = ord.get(coff);
+ coff.targetStore(
+ &np.name_rva,
+ @intCast(name_table_rva + entry.name_index),
+ );
}
},
inline .pseudo_section,
.object_section,
- .global,
+ .import_thunk,
.nav,
.uav,
.lazy_code,
.lazy_const_data,
- => |mi| mi.symbol(coff).flushMoved(coff),
+ => |mi| try mi.symbol(coff).flushMoved(coff),
+ .builtin => |si| try si.flushMoved(coff),
}
try ni.childrenMoved(coff.base.comp.gpa, &coff.mf);
}
fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {
- _, const size = ni.location(&coff.mf).resolve(&coff.mf);
+ const offset, const size = ni.location(&coff.mf).resolve(&coff.mf);
+ log.debug("flushResized({s}, n{d}, 0x{x})", .{ @tagName(coff.getNode(ni)), ni, size });
+
switch (coff.getNode(ni)) {
- .file => {},
+ .file => {
+ if (coff.isArchive() and coff.members.items.len > 0) {
+ const last_member = coff.members.items[coff.members.items.len - 1];
+ // See .archive_member branch for reasoning
+ assert(Node.known.file.reverseChildren(&coff.mf).ni == last_member.content_ni);
+ try coff.flushResized(last_member.content_ni);
+ }
+ },
.header => {
- switch (coff.optionalHeaderPtr()) {
- inline else => |optional_header| coff.targetStore(
- &optional_header.size_of_headers,
- @intCast(size),
- ),
+ if (coff.isImage()) {
+ switch (coff.optionalHeaderPtr()) {
+ inline else => |optional_header| coff.targetStore(
+ &optional_header.size_of_headers,
+ @intCast(size),
+ ),
+ }
+
+ if (size > coff.section_table.values()[0].si.get(coff).rva) try coff.virtualSlide(
+ 0,
+ std.mem.alignForward(
+ u32,
+ @intCast(size * 4),
+ coff.optionalHeaderField(.section_alignment),
+ ),
+ );
}
- if (size > coff.image_section_table.items[0].get(coff).rva) try coff.virtualSlide(
- 0,
- std.mem.alignForward(
- u32,
- @intCast(size * 4),
- coff.optionalHeaderField(.section_alignment),
- ),
- );
},
- .signature, .coff_header, .optional_header, .data_directories => unreachable,
+ .signature,
+ .archive_member_header,
+ => unreachable,
+ .archive_member => |mi| {
+ const content_ni = mi.get(coff).content_ni;
+ const next_ni = content_ni.next(&coff.mf);
+ const content_offset, _ = content_ni.location(&coff.mf).resolve(&coff.mf);
+ const next_offset = switch (next_ni) {
+ .none => offset: {
+ assert(content_ni.parent(&coff.mf) == Node.known.file);
+ // This must take into account the final file size. If there are trailing
+ // bytes, they will be expected to contain another valid member header
+ break :offset coff.mf.memory_map.memory.len;
+ },
+ else => offset: {
+ assert(coff.getNode(next_ni) == .archive_member_header);
+ break :offset next_ni.location(&coff.mf).resolve(&coff.mf)[0];
+ },
+ };
+
+ // Not inserting IMAGE_ARCHIVE_PAD `\n` byte here, because we are expanding to full size
+ Member.storeHeaderDecimalStr(&mi.get(coff).headerPtr(coff).size, next_offset - content_offset);
+ },
+ .coff_header,
+ .optional_header,
+ .data_directories,
+ => unreachable,
.section_table => {},
+ .symbol_table => {
+ assert(!coff.isImage());
+ if (!coff.symbol_table.pending_shrink) {
+ const string_table_offset, _ = coff.symbol_table.strings_ni.location(&coff.mf).resolve(&coff.mf);
+ coff.symbol_table.pending_shrink =
+ size > coff.targetLoad(&coff.headerPtr().number_of_symbols) * std.coff.Symbol.sizeOf() or
+ string_table_offset - (offset + size) > 0;
+ }
+ },
+ .string_table => {
+ assert(!coff.isImage());
+ coff.targetStore(coff.symbolTableStringLenPtr(), @intCast(size));
+ },
+ .relocation_table,
+ .relocation_table_entry,
+ => assert(!coff.isImage()),
.image_section => |si| {
const sym = si.get(coff);
const section_index = sym.section_number.toIndex();
const section = &coff.sectionTableSlice()[section_index];
coff.targetStore(§ion.size_of_raw_data, @intCast(size));
- if (size > coff.targetLoad(§ion.virtual_size)) {
+ if (coff.isImage() and size > coff.targetLoad(§ion.virtual_size)) {
const virtual_size = std.mem.alignForward(
u32,
@intCast(size * 4),
@@ -2266,29 +7143,221 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {
coff.targetStore(§ion.virtual_size, virtual_size);
try coff.virtualSlide(section_index + 1, sym.rva + virtual_size);
}
+
+ if (!coff.isImage()) {
+ if (coff.symbolTableSectionAuxEntryPtr(si.sti(coff))) |aux_ptr|
+ coff.targetStore(&aux_ptr.length, @intCast(size));
+ }
},
- .import_directory_table => coff.targetStore(
- &coff.dataDirectoryPtr(.IMPORT).size,
- @intCast(size),
- ),
- .import_lookup_table, .import_address_table, .import_hint_name_table => {},
+ .input_section => {},
+ .import_directory_table => {
+ const prev_size = coff.targetLoad(&coff.dataDirectoryPtr(.IMPORT).size);
+ coff.targetStore(
+ &coff.dataDirectoryPtr(.IMPORT).size,
+ @intCast(size),
+ );
+ if (prev_size == 0) try coff.flushMoved(ni);
+ },
+ .import_lookup_table,
+ .import_address_table,
+ .import_hint_name_table,
+ => {},
+ .export_directory_table => unreachable,
+ .export_address_table,
+ .export_name_pointer_table,
+ .export_ordinal_table,
+ .export_name_table,
+ => {},
inline .pseudo_section,
.object_section,
- => |smi| smi.symbol(coff).get(coff).size = @intCast(size),
- .global, .nav, .uav, .lazy_code, .lazy_const_data => {},
+ => |smi, tag| {
+ if (tag == .pseudo_section and smi.name(coff) == .@".edata") {
+ coff.targetStore(
+ &coff.dataDirectoryPtr(.EXPORT).size,
+ @intCast(size),
+ );
+ }
+
+ var sym = smi.symbol(coff).get(coff);
+ while (sym.flags.extra_tag == .next_alias_si)
+ sym = sym.extra.next_alias_si.get(coff);
+
+ sym.extra.size = @intCast(size);
+ },
+ .import_thunk,
+ .nav,
+ .uav,
+ .lazy_code,
+ .lazy_const_data,
+ .builtin,
+ => {},
+ .placeholder,
+ => unreachable,
}
}
+
+fn flushMember(coff: *Coff, mi: Member.Index) !void {
+ const member = mi.get(coff);
+ switch (member.kind) {
+ .first_linker,
+ .longnames,
+ .import,
+ => unreachable,
+ .second_linker => {
+ const Context = struct {
+ coff: *Coff,
+ indices: []u16,
+ strings: []String,
+
+ pub fn lessThan(ctx: @This(), lhs: usize, rhs: usize) bool {
+ return std.mem.lessThan(
+ u8,
+ ctx.strings[lhs].toSlice(ctx.coff),
+ ctx.strings[rhs].toSlice(ctx.coff),
+ );
+ }
+
+ pub fn swap(ctx: @This(), lhs: usize, rhs: usize) void {
+ std.mem.swap(u16, &ctx.indices[lhs], &ctx.indices[rhs]);
+ std.mem.swap(String, &ctx.strings[lhs], &ctx.strings[rhs]);
+ }
+ };
+
+ // TODO: Does this sort need to also sort by linker input order (if names equal)?
+ std.sort.pdqContext(0, coff.lib_string_table.items.len, Context{
+ .coff = coff,
+ .indices = coff.secondLinkerMemberIndicesSlice(),
+ .strings = coff.lib_string_table.items,
+ });
+
+ var offset: usize = 0;
+ var string_table = coff.secondLinkerMemberStringsSlice();
+ for (coff.lib_string_table.items) |string| {
+ const str = string.toSlice(coff);
+ @memcpy(string_table[offset..][0..str.len], str);
+ string_table[offset + str.len] = 0;
+ offset += str.len + 1;
+ }
+ },
+ .coff => {
+ const file_offset: u32 = @intCast(member.header_ni.fileLocation(&coff.mf, false).offset);
+ const first_linker_offsets = coff.firstLinkerMemberOffsetsSlice();
+ for (member.first_linker_indices.values()) |mfli|
+ first_linker_offsets[@intFromEnum(mfli)] = std.mem.nativeTo(u32, file_offset, .big);
+ },
+ }
+}
+
+fn flushExportsSort(coff: *Coff) void {
+ const Context = struct {
+ coff: *Coff,
+ np: []std.coff.ExportNamePointerTableEntry,
+ ord: []std.coff.ExportOrdinalTableEntry,
+ entries: []ExportTable.Entry,
+ nt: []const u8,
+
+ pub fn lessThan(ctx: *const @This(), lhs: usize, rhs: usize) bool {
+ const lhs_entry = &ctx.entries[ctx.coff.targetLoad(&ctx.ord[lhs].unbiased_ordinal)];
+ const rhs_entry = &ctx.entries[ctx.coff.targetLoad(&ctx.ord[rhs].unbiased_ordinal)];
+ return std.mem.lessThan(
+ u8,
+ ctx.nt[lhs_entry.name_index..][0..lhs_entry.name_len],
+ ctx.nt[rhs_entry.name_index..][0..rhs_entry.name_len],
+ );
+ }
+
+ pub fn swap(ctx: @This(), lhs: usize, rhs: usize) void {
+ std.mem.swap(std.coff.ExportNamePointerTableEntry, &ctx.np[lhs], &ctx.np[rhs]);
+ std.mem.swap(std.coff.ExportOrdinalTableEntry, &ctx.ord[lhs], &ctx.ord[rhs]);
+ }
+ };
+
+ std.sort.pdqContext(0, coff.export_table.entries.count(), &Context{
+ .coff = coff,
+ .np = coff.exportNamePointerTableSlice(),
+ .ord = coff.exportOrdinalTableSlice(),
+ .entries = coff.export_table.entries.values(),
+ .nt = coff.export_table.name_table_ni.slice(&coff.mf),
+ });
+}
+
+fn flushSectionMerges(coff: *Coff) !void {
+ while (coff.section_merge_pending_index < coff.section_merges.count()) : (coff.section_merge_pending_index += 1)
+ try coff.flushSectionMerge(coff.section_merge_pending_index);
+}
+
+fn flushSectionMerge(coff: *Coff, index: u32) !void {
+ assert(coff.isImage());
+ const from = coff.section_merges.keys()[index];
+ const to = coff.section_merges.values()[index];
+ assert(from != to);
+
+ log.debug("flushSectionMerge({s}->{s})", .{ from.toSlice(coff), to.toSlice(coff) });
+
+ const opt_to_sec = coff.section_table.getPtr(to);
+ if (coff.section_table.getPtr(from)) |from_sec| {
+ const from_sym = from_sec.si.get(coff);
+ if (opt_to_sec) |to_sec| {
+ const to_sym = to_sec.si.get(coff);
+
+ // TODO: Create a pseudo-section named `from` in `to`, copy `from_sec` ni into that pseudo section
+ // TODO: Update .section_number for all contained syms
+ // TODO: Remove `from_sec` from section table (set size = 0 and can do it in flushResized?).
+ // This is non-trivial as we can't leave holes in the section table.
+ // TODO: Merge section flags
+ _ = to_sym;
+ return coff.base.comp.link_diags.fail("TODO implement section to section merge", .{});
+ } else if (coff.pseudo_section_table.get(to)) |to_ps_si| {
+ const to_sym = to_ps_si.get(coff);
+ if (from_sym.section_number == to_sym.section_number)
+ return;
+
+ // TODO: Same as above, except place `from` into a node in `to_psmi`'s parent
+ return coff.base.comp.link_diags.fail("TODO implement section to pseudosection merge", .{});
+ }
+
+ // If `to` doesn't exist, /MERGE is defined as renaming `from` to `to`.
+ // No other path will create image-level sections, so we can safely rename this now
+ const from_name = &from_sec.si.get(coff).section_number.header(coff).name;
+ const to_slice = to.toSlice(coff);
+ @memcpy(from_name[0..to_slice.len], to_slice);
+ @memset(from_name[to_slice.len..], 0);
+ } else if (coff.pseudo_section_table.getIndex(from)) |from_index| {
+ const from_psmi: Node.PseudoSectionMapIndex = @enumFromInt(from_index);
+ const from_sym = from_psmi.symbol(coff).get(coff);
+ if (opt_to_sec) |to_sec| {
+ const to_sym = to_sec.si.get(coff);
+ if (from_sym.section_number == to_sym.section_number)
+ return;
+
+ // TODO: Move from_psmi's node into to_sec
+ // TODO: Update .section_number for all contained syms
+ // TODO: Merge section flags
+ return coff.base.comp.link_diags.fail("TODO implement pseudosection to section merge", .{});
+ } else if (coff.pseudo_section_table.get(to)) |to_ps_si| {
+ const to_sym = to_ps_si.get(coff);
+ if (from_sym.section_number == to_sym.section_number)
+ return;
+
+ // TODO: Same as above, but move from_psmi's node after to_psmi's node in its parent
+ return coff.base.comp.link_diags.fail("TODO implement pseudosection to pseudosection merge", .{});
+ }
+
+ // Renaming pseudo-sections have no effect on the output, so this is a no-op.
+ }
+}
+
fn virtualSlide(coff: *Coff, start_section_index: usize, start_rva: u32) !void {
var rva = start_rva;
for (
- coff.image_section_table.items[start_section_index..],
+ coff.section_table.values()[start_section_index..],
coff.sectionTableSlice()[start_section_index..],
- ) |section_si, *section| {
- const section_sym = section_si.get(coff);
+ ) |*section, *header| {
+ const section_sym = section.si.get(coff);
section_sym.rva = rva;
- coff.targetStore(§ion.virtual_address, rva);
+ coff.targetStore(&header.virtual_address, rva);
try section_sym.ni.childrenMoved(coff.base.comp.gpa, &coff.mf);
- rva += coff.targetLoad(§ion.virtual_size);
+ rva += coff.targetLoad(&header.virtual_size);
}
switch (coff.optionalHeaderPtr()) {
inline else => |optional_header| coff.targetStore(
@@ -2303,19 +7372,27 @@ pub fn updateExports(
pt: Zcu.PerThread,
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
+) link.Error!void {
+ const diags = &coff.base.comp.link_diags;
+ return coff.updateExportsInner(pt, exported, export_indices) catch |err| switch (err) {
+ error.MappedFileIo => return diags.fail(
+ "failed to write output file: {t}",
+ .{coff.mf.io_err.?},
+ ),
+ else => |e| return e,
+ };
+}
+fn updateExportsInner(
+ coff: *Coff,
+ pt: Zcu.PerThread,
+ exported: Zcu.Exported,
+ export_indices: []const Zcu.Export.Index,
) !void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
- switch (exported) {
- .nav => |nav| log.debug("updateExports({f})", .{ip.getNav(nav).fqn.fmt(ip)}),
- .uav => |uav| log.debug("updateExports(@as({f}, {f}))", .{
- Type.fromInterned(ip.typeOf(uav)).fmt(pt),
- Value.fromInterned(uav).fmtValue(pt),
- }),
- }
- try coff.symbol_table.ensureUnusedCapacity(gpa, export_indices.len);
+ try coff.symbols.ensureUnusedCapacity(gpa, export_indices.len);
const exported_si: Symbol.Index = switch (exported) {
.nav => |nav| try coff.navSymbol(zcu, nav),
.uav => |uav| @enumFromInt(@intFromEnum(try coff.lowerUav(
@@ -2324,62 +7401,299 @@ pub fn updateExports(
Type.fromInterned(ip.typeOf(uav)).abiAlignment(zcu),
))),
};
+ switch (exported) {
+ .nav => |nav| log.debug("updateExports({f}) = {d}", .{ ip.getNav(nav).fqn.fmt(ip), exported_si }),
+ .uav => |uav| log.debug("updateExports(@as({f}, {f})) = {d}", .{
+ Type.fromInterned(ip.typeOf(uav)).fmt(pt),
+ Value.fromInterned(uav).fmtValue(pt),
+ exported_si,
+ }),
+ }
+ while (try coff.resolve(pt.tid)) {}
while (try coff.idle(pt.tid)) {}
+
+ const machine = coff.targetLoad(&coff.headerPtr().machine);
const exported_ni = exported_si.node(coff);
const exported_sym = exported_si.get(coff);
+ var prev_alias_si = exported_si;
+
for (export_indices) |export_index| {
const @"export" = export_index.ptr(zcu);
- const export_si = try coff.globalSymbol(@"export".opts.name.toSlice(ip), null);
+ const name = @"export".opts.name.toSlice(ip);
+
+ // TODO: add an errMsg if this conflicts with an existing symbol
+ const export_si = try coff.globalSymbol(.{ .name = name });
const export_sym = export_si.get(coff);
export_sym.ni = exported_ni;
export_sym.rva = exported_sym.rva;
- export_sym.size = exported_sym.size;
export_sym.section_number = exported_sym.section_number;
- export_si.applyTargetRelocs(coff);
- if (@"export".opts.name.eqlSlice("wWinMainCRTStartup", ip)) {
- coff.optionalHeaderStandardPtr().address_of_entry_point = exported_sym.rva;
- } else if (@"export".opts.name.eqlSlice("_tls_used", ip)) {
- const tls_directory = coff.dataDirectoryPtr(.TLS);
- tls_directory.* = .{ .virtual_address = exported_sym.rva, .size = exported_sym.size };
- if (coff.targetEndian() != native_endian)
- std.mem.byteSwapAllFields(std.coff.ImageDataDirectory, tls_directory);
+ if (@"export".opts.linkage == .weak and !coff.isImage()) {
+ // exported_si needs to be ahead of export_si in the symbol table,
+ // so that its sti is known when creating the weak external aux entry
+ try coff.pendingSymbolTableEntry(exported_si);
+ export_sym.flags.weak_external_strat = .alias;
+ export_sym.setValue(.{ .weak_alias_si = exported_si });
+ }
+ defer export_si.applyTargetRelocs(coff, .none) catch unreachable;
+
+ // The last symbol in the alias list holds the size
+ const prev_alias_sym = prev_alias_si.get(coff);
+ switch (prev_alias_sym.flags.extra_tag) {
+ .size => export_sym.setExtra(.{ .size = prev_alias_sym.extra.size }),
+ // This export should have been deleted
+ .next_alias_si => assert(prev_alias_sym.extra.next_alias_si == export_si),
+ else => unreachable,
+ }
+
+ prev_alias_sym.setExtra(.{ .next_alias_si = export_si });
+ prev_alias_si = export_si;
+
+ if (!coff.isImage()) continue;
+
+ const entries_ctx = ExportTable.Adapter{ .coff = coff };
+ const gop = try coff.export_table.entries.getOrPutAdapted(
+ gpa,
+ name,
+ entries_ctx,
+ );
+
+ if (!gop.found_existing) {
+ errdefer _ = coff.export_table.entries.pop();
+
+ const export_count = coff.export_table.entries.count();
+ if (export_count > std.math.maxInt(@FieldType(std.coff.ExportDirectoryTable, "number_of_entries")))
+ return coff.base.comp.link_diags.fail("exceeded maximum number of exports", .{});
+
+ const name_index: u32 = @intCast(coff.export_table.name_table_ni.location(&coff.mf).resolve(&coff.mf)[1]);
+ const new_name_table_size = name_index + name.len + 1;
+ if (new_name_table_size > std.math.maxInt(@FieldType(ExportTable.Entry, "name_index")))
+ return coff.base.comp.link_diags.fail("exports name table limit reached", .{});
+
+ try coff.export_table.name_table_ni.resize(&coff.mf, gpa, new_name_table_size);
+
+ const name_table_slice = coff.export_table.name_table_ni.slice(&coff.mf);
+ @memcpy(name_table_slice[name_index..][0 .. name.len + 1], name[0 .. name.len + 1]);
+
+ // If the new name sorts after the current tail of the sorted list, we don't need to re-sort
+ {
+ const ordinal_table_slice = coff.exportOrdinalTableSlice();
+ if (ordinal_table_slice.len > 0 and !coff.export_table.pending_sort) {
+ const tail_index: ExportTable.Ordinal =
+ @enumFromInt(ordinal_table_slice[ordinal_table_slice.len - 1].unbiased_ordinal);
+ const tail_entry = tail_index.get(coff);
+ const tail_name = name_table_slice[tail_entry.name_index..][0..tail_entry.name_len];
+ coff.export_table.pending_sort = std.mem.lessThan(u8, name, tail_name);
+ }
+ }
+
+ const edt = coff.exportDirectoryTable();
+ coff.targetStore(&edt.number_of_names, @intCast(export_count));
+ edt.number_of_entries = edt.number_of_names;
+
+ // TODO: These should all be resized ahead of time to fit all exports
+ // after https://github.com/ziglang/zig/issues/23616
+ try coff.export_table.export_address_table_si.node(coff).resize(
+ &coff.mf,
+ gpa,
+ export_count * @sizeOf(std.coff.ExportAddressTableEntry),
+ );
+
+ try coff.export_table.name_pointer_table_ni.resize(
+ &coff.mf,
+ gpa,
+ export_count * @sizeOf(std.coff.ExportNamePointerTableEntry),
+ );
+
+ try coff.export_table.ordinal_table_ni.resize(
+ &coff.mf,
+ gpa,
+ export_count * @sizeOf(std.coff.ExportOrdinalTableEntry),
+ );
+
+ coff.targetStore(
+ &coff.exportNamePointerTableSlice()[gop.index].name_rva,
+ @intCast(coff.computeNodeRva(coff.export_table.name_table_ni) + name_index),
+ );
+ coff.targetStore(
+ &coff.exportOrdinalTableSlice()[gop.index].unbiased_ordinal,
+ @intCast(gop.index),
+ );
+
+ gop.value_ptr.* = .{
+ .si = export_si,
+ .name_index = @intCast(name_index),
+ .name_len = @intCast(name.len),
+ .export_address_table_ri = @enumFromInt(coff.relocs.items.len),
+ };
+
+ try coff.addReloc(
+ coff.export_table.export_address_table_si,
+ @intCast(@sizeOf(std.coff.ExportAddressTableEntry) * gop.index),
+ export_si,
+ .{ .known = 0 },
+ switch (machine) {
+ else => |tag| @panic(@tagName(tag)),
+ .AMD64 => .{ .AMD64 = .ADDR32NB },
+ .I386 => .{ .I386 = .DIR32NB },
+ },
+ );
+ } else {
+ gop.value_ptr.si = export_si;
+ const reloc = gop.value_ptr.*.export_address_table_ri.get(coff);
+ reloc.target = export_si;
}
}
}
-pub fn deleteExport(coff: *Coff, exported: Zcu.Exported, name: InternPool.NullTerminatedString) void {
- _ = coff;
- _ = exported;
- _ = name;
+pub fn deleteExport(
+ coff: *Coff,
+ exported: Zcu.Exported,
+ name: InternPool.NullTerminatedString,
+) void {
+ const zcu = coff.base.comp.zcu.?;
+ const ip = &zcu.intern_pool;
+
+ const exported_si: Symbol.Index = switch (exported) {
+ .nav => |nav| coff.navs.get(nav).?,
+ .uav => |uav| coff.uavs.get(uav).?,
+ };
+
+ const name_slice = name.toSlice(ip);
+ log.debug("deleteExport({s}, {d})", .{ name_slice, exported_si });
+
+ // TODO: Delete from first / second linker member table
+ // TODO: Delete from symbol table inside section
}
-pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) Io.Cancelable!void {
+fn dumpStderr(coff: *Coff, tid: Zcu.PerThread.Id) !void {
const comp = coff.base.comp;
const io = comp.io;
var buffer: [512]u8 = undefined;
const stderr = try io.lockStderr(&buffer, null);
defer io.unlockStderr();
const w = &stderr.file_writer.interface;
- coff.printNode(tid, w, .root, 0) catch |err| switch (err) {
- error.WriteFailed => return stderr.err.?,
- };
+ _ = try coff.dump(w, tid);
}
-pub fn printNode(
+pub fn dump(coff: *Coff, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpResult {
+ if (coff.options.enable_link_snapshots) {
+ try coff.printNode(tid, w, .root, 0);
+ try w.writeAll("Section table:\n");
+ for (coff.section_table.keys(), coff.section_table.values()) |name, sec|
+ try coff.printSection(w, name, sec.si);
+ try w.writeAll("Symbol table:\n");
+ for (1..coff.symbols.items.len) |si|
+ try coff.printSymbol(w, tid, @enumFromInt(si));
+
+ return .enabled;
+ }
+ return .disabled;
+}
+
+fn printSection(coff: *Coff, w: *Io.Writer, name: String, si: Symbol.Index) !void {
+ const sym = si.get(coff);
+ try w.print("{d:0>6}@{d:0>2} {x:08} n{d:0>8} | {s}\n", .{
+ si,
+ sym.section_number,
+ if (sym.flags.extra_tag == .size) sym.extra.size else 0,
+ sym.ni,
+ name.toSlice(coff),
+ });
+}
+
+fn printSymbol(
coff: *Coff,
+ w: *Io.Writer,
tid: Zcu.PerThread.Id,
+ si: Symbol.Index,
+) !void {
+ const sym = si.get(coff);
+ const node = coff.getNode(sym.ni);
+ try w.print("{d:0>6}@{d:0>2} {x:08} {s} {s} {s} n{d:0>8}+{x:08}:{t: <26} | {x:08} ", .{
+ si,
+ sym.section_number,
+ if (sym.flags.extra_tag == .size)
+ @as(u64, sym.extra.size)
+ else if (sym.ni != .none)
+ sym.ni.location(&coff.mf).resolve(&coff.mf)[1]
+ else
+ 0,
+ switch (sym.flags.value_tag) {
+ .none => "xx",
+ .weak_alias_name => "an",
+ .weak_alias_si => "as",
+ .node_offset => "no",
+ },
+ switch (sym.flags.extra_tag) {
+ .size => "sz",
+ .isli => "li",
+ .next_alias_si => "na",
+ },
+ switch (sym.flags.type) {
+ .unknown => "u",
+ .code => "c",
+ .data => "d",
+ },
+ sym.ni,
+ if (sym.flags.value_tag == .node_offset) sym.value.node_offset else 0,
+ node,
+ sym.rva,
+ });
+
+ if (sym.gmi != .none) {
+ try w.print("G {f}\n", .{fmtGlobalName(coff, sym.gmi)});
+ } else {
+ try w.writeAll("| ");
+ try coff.printNodeName(w, tid, node);
+ if (sym.flags.extra_tag == .isli)
+ try w.print(" | {s}", .{sym.extra.isli.name(coff).toSlice(coff)});
+ try w.writeByte('\n');
+ }
+}
+
+const FmtGlobalName = struct { coff: *Coff, gmi: Node.GlobalMapIndex };
+
+fn fmtGlobalName(coff: *Coff, gmi: Node.GlobalMapIndex) std.fmt.Alt(FmtGlobalName, globalNameEscape) {
+ return .{ .data = .{ .coff = coff, .gmi = gmi } };
+}
+
+fn globalNameEscape(data: FmtGlobalName, w: *std.Io.Writer) std.Io.Writer.Error!void {
+ if (data.gmi == .none) return;
+ try w.writeAll(data.gmi.name(data.coff).toSlice(data.coff));
+ if (data.gmi.libName(data.coff).unwrap()) |lib_name|
+ try w.print("({s})", .{lib_name.toSlice(data.coff)});
+}
+
+fn printNodeName(
+ coff: *Coff,
w: *std.Io.Writer,
- ni: MappedFile.Node.Index,
- indent: usize,
+ tid: Zcu.PerThread.Id,
+ node: Node,
) !void {
- const node = coff.getNode(ni);
- try w.splatByteAll(' ', indent);
- try w.writeAll(@tagName(node));
switch (node) {
else => {},
.image_section => |si| try w.print("({s})", .{
std.mem.sliceTo(&si.get(coff).section_number.header(coff).name, 0),
}),
+ .input_section => |isi| {
+ const ioi = isi.input(coff);
+ const is = isi.inputSection(coff);
+ try w.print("({f}{f}, {s}", .{
+ ioi.path(coff).fmtEscapeString(),
+ fmtMemberNameString(ioi.memberName(coff)),
+ coff.getNode(is.si.node(coff).parent(&coff.mf)).object_section.name(coff).toSlice(coff),
+ });
+ if (is.comdat_si != .null) {
+ const comdat_sym = is.comdat_si.get(coff);
+ const comdat_name = if (comdat_sym.gmi != .none)
+ comdat_sym.gmi.name(coff).toSlice(coff)
+ else
+ coff.input_symbols.items[@intFromEnum(comdat_sym.extra.isli)].name.toSlice(coff);
+
+ try w.print("={s}", .{comdat_name});
+ }
+ try w.writeAll(")");
+ },
.import_lookup_table,
.import_address_table,
.import_hint_name_table,
@@ -2389,18 +7703,18 @@ pub fn printNode(
inline .pseudo_section, .object_section => |smi| try w.print("({s})", .{
smi.name(coff).toSlice(coff),
}),
- .global => |gmi| {
- const gn = gmi.globalName(coff);
+ .import_thunk,
+ => |gmi| {
try w.writeByte('(');
- if (gn.lib_name.toSlice(coff)) |lib_name| try w.print("{s}.dll, ", .{lib_name});
- try w.print("{s})", .{gn.name.toSlice(coff)});
+ if (gmi.libName(coff).toSlice(coff)) |lib_name| try w.print("{s}.dll, ", .{lib_name});
+ try w.print("{s})", .{gmi.name(coff).toSlice(coff)});
},
.nav => |nmi| {
const zcu = coff.base.comp.zcu.?;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nmi.navIndex(coff));
try w.print("({f}, {f})", .{
- Type.fromInterned(nav.typeOf(ip)).fmt(.{ .zcu = zcu, .tid = tid }),
+ Type.fromInterned(ip.typeOf(nav.resolved.?.value)).fmt(.{ .zcu = zcu, .tid = tid }),
nav.fqn.fmt(ip),
});
},
@@ -2418,7 +7732,28 @@ pub fn printNode(
.tid = tid,
}),
}),
+ .builtin => |si| {
+ const sym = si.get(coff);
+ if (sym.gmi != .none) {
+ try w.writeByte('(');
+ if (sym.gmi.libName(coff).toSlice(coff)) |lib_name| try w.print("{s}.dll, ", .{lib_name});
+ try w.print("{s})", .{sym.gmi.name(coff).toSlice(coff)});
+ }
+ },
}
+}
+
+pub fn printNode(
+ coff: *Coff,
+ tid: Zcu.PerThread.Id,
+ w: *Io.Writer,
+ ni: MappedFile.Node.Index,
+ indent: usize,
+) !void {
+ const node = coff.getNode(ni);
+ try w.splatByteAll(' ', indent);
+ try w.writeAll(@tagName(node));
+ try coff.printNodeName(w, tid, node);
{
const mf_node = &coff.mf.nodes.items[@intFromEnum(ni)];
const off, const size = mf_node.location().resolve(&coff.mf);
@@ -2446,7 +7781,7 @@ pub fn printNode(
const line_len = 0x10;
var line_it = std.mem.window(
u8,
- coff.mf.contents[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)],
+ coff.mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)],
line_len,
line_len,
);
diff --git a/src/link/ConstPool.zig b/src/link/ConstPool.zig
index 1282ad67c4b5fc49bac914bfeede2da46301ee91..3ff2d9a540e1d47d2da7e5e3d9b441ff70effa6b 100644
--- a/src/link/ConstPool.zig
+++ b/src/link/ConstPool.zig
@@ -15,10 +15,10 @@
/// * ensure that any `get` call is eventually followed by a `flushPending` call
const ConstPool = @This();
-values: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
+values: std.array_hash_map.Auto(InternPool.Index, void),
pending: std.ArrayList(Index),
-complete_containers: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
-container_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, ContainerDepEntry.Index),
+complete_containers: std.array_hash_map.Auto(InternPool.Index, void),
+container_deps: std.array_hash_map.Auto(InternPool.Index, ContainerDepEntry.Index),
container_dep_entries: std.ArrayList(ContainerDepEntry),
pub const empty: ConstPool = .{
@@ -196,6 +196,7 @@ fn checkType(pool: *const ConstPool, ty: Type, zcu: *const Zcu) bool {
.null,
.error_set,
.@"opaque",
+ .spirv,
.frame,
.@"anyframe",
.enum_literal,
@@ -241,6 +242,7 @@ fn registerTypeDeps(pool: *ConstPool, root: Index, ty: Type, zcu: *const Zcu) Al
.null,
.error_set,
.@"opaque",
+ .spirv,
.frame,
.@"anyframe",
.enum_literal,
diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig
index 0142b0a91969f2f9632a77d9b57cb4ff44a3a09e..96fb3d10c9191de8a2acaf7acaf799f5b9832fc5 100644
--- a/src/link/Dwarf.zig
+++ b/src/link/Dwarf.zig
@@ -27,11 +27,11 @@ address_size: AddressSize,
const_pool: link.ConstPool,
-mods: std.AutoArrayHashMapUnmanaged(*Module, ModInfo),
+mods: std.array_hash_map.Auto(*Module, ModInfo),
/// Indices are `link.ConstPool.Index`.
values: std.ArrayList(struct { Unit.Index, Entry.Index }),
-navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Entry.Index),
-decls: std.AutoArrayHashMapUnmanaged(InternPool.TrackedInst.Index, Entry.Index),
+navs: std.array_hash_map.Auto(InternPool.Nav.Index, Entry.Index),
+decls: std.array_hash_map.Auto(InternPool.TrackedInst.Index, Entry.Index),
debug_abbrev: DebugAbbrev,
debug_aranges: DebugAranges,
@@ -69,8 +69,8 @@ pub const AddressSize = enum(u8) {
const ModInfo = struct {
root_dir_path: Entry.Index,
- dirs: std.AutoArrayHashMapUnmanaged(Unit.Index, void),
- files: std.AutoArrayHashMapUnmanaged(Zcu.File.Index, void),
+ dirs: std.array_hash_map.Auto(Unit.Index, void),
+ files: std.array_hash_map.Auto(Zcu.File.Index, void),
fn deinit(mod_info: *ModInfo, gpa: Allocator) void {
mod_info.dirs.deinit(gpa);
@@ -236,7 +236,7 @@ const DebugRngLists = struct {
const StringSection = struct {
contents: std.ArrayList(u8),
- map: std.AutoArrayHashMapUnmanaged(void, void),
+ map: std.array_hash_map.Auto(void, void),
section: Section,
const unit: Unit.Index = @enumFromInt(0);
@@ -3047,6 +3047,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
.func_type,
.error_set_type,
.inferred_error_set_type,
+ .spirv_type,
=> .alias,
.struct_type => tag: {
@@ -3533,6 +3534,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
switch (value_ip_key) {
.func => unreachable, // handled above
.@"extern" => unreachable, // handled above
+ .spirv_type => unreachable,
.int_type => |int_type| {
try wip_nav.abbrevCode(.numeric_type);
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index 4c50caf8f2b6d363a37c3f6189b0975b8bdd1451..d64d429bb0bc7d03f3e152615cbf81434e67515e 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -2,7 +2,7 @@ pub const Atom = @import("Elf/Atom.zig");
base: link.File,
zig_object: ?*ZigObject,
-rpath_table: std.StringArrayHashMapUnmanaged(void),
+rpath_table: std.array_hash_map.String(void),
image_base: u64,
z_nodelete: bool,
z_notext: bool,
@@ -30,7 +30,7 @@ file_handles: std.ArrayList(File.Handle) = .empty,
zig_object_index: ?File.Index = null,
linker_defined_index: ?File.Index = null,
objects: std.ArrayList(File.Index) = .empty,
-shared_objects: std.StringArrayHashMapUnmanaged(File.Index) = .empty,
+shared_objects: std.array_hash_map.String(File.Index) = .empty,
/// List of all output sections and their associated metadata.
sections: std.MultiArrayList(Section) = .{},
@@ -249,7 +249,7 @@ pub fn createEmpty(
const is_dyn_lib = output_mode == .Lib and link_mode == .dynamic;
const default_sym_version: elf.Versym = if (is_dyn_lib or comp.config.rdynamic) .GLOBAL else .LOCAL;
- var rpath_table: std.StringArrayHashMapUnmanaged(void) = .empty;
+ var rpath_table: std.array_hash_map.String(void) = .empty;
try rpath_table.entries.resize(arena, options.rpath_list.len);
@memcpy(rpath_table.entries.items(.key), options.rpath_list);
try rpath_table.reIndex(arena);
@@ -1112,7 +1112,7 @@ fn parseDso(
io: Io,
diags: *Diags,
dso: link.Input.Dso,
- shared_objects: *std.StringArrayHashMapUnmanaged(File.Index),
+ shared_objects: *std.array_hash_map.String(File.Index),
files: *std.MultiArrayList(File.Entry),
target: *const std.Target,
) !void {
@@ -4153,7 +4153,7 @@ pub const Ref = struct {
pub const SymbolResolver = struct {
keys: std.ArrayList(Key) = .empty,
values: std.ArrayList(Ref) = .empty,
- table: std.AutoArrayHashMapUnmanaged(void, void) = .empty,
+ table: std.array_hash_map.Auto(void, void) = .empty,
const Result = struct {
found_existing: bool,
diff --git a/src/link/Elf/AtomList.zig b/src/link/Elf/AtomList.zig
index 9350f1a276b16382a297a471ae8214b1bcc1be29..245c00bf6ee359e452826363c428144d45371202 100644
--- a/src/link/Elf/AtomList.zig
+++ b/src/link/Elf/AtomList.zig
@@ -3,7 +3,7 @@ size: u64 = 0,
alignment: Atom.Alignment = .@"1",
output_section_index: u32 = 0,
// atoms: std.ArrayList(Elf.Ref) = .empty,
-atoms: std.AutoArrayHashMapUnmanaged(Elf.Ref, void) = .empty,
+atoms: std.array_hash_map.Auto(Elf.Ref, void) = .empty,
dirty: bool = true,
diff --git a/src/link/Elf/Thunk.zig b/src/link/Elf/Thunk.zig
index 1700bb8276dd4e534629e6ff30eaa9220ada8a5d..69af9707bc9e8d41c2b81952c32b5cc981ccfdbd 100644
--- a/src/link/Elf/Thunk.zig
+++ b/src/link/Elf/Thunk.zig
@@ -1,6 +1,6 @@
value: i64 = 0,
output_section_index: u32 = 0,
-symbols: std.AutoArrayHashMapUnmanaged(Elf.Ref, void) = .empty,
+symbols: std.array_hash_map.Auto(Elf.Ref, void) = .empty,
output_symtab_ctx: Elf.SymtabCtx = .{},
pub fn deinit(thunk: *Thunk, allocator: Allocator) void {
diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig
index d57a77a3ab4759d283c465b2850f7a713726c4d4..3f4a85ece7a40dbed094b587df82cc0e1293cbd6 100644
--- a/src/link/Elf/ZigObject.zig
+++ b/src/link/Elf/ZigObject.zig
@@ -267,8 +267,9 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
// Handle any lazy symbols that were emitted by incremental compilation.
if (self.lazy_syms.getPtr(.anyerror_type)) |metadata| {
- const pt: Zcu.PerThread = .activate(elf_file.base.comp.zcu.?, tid);
- defer pt.deactivate();
+ const active = elf_file.base.comp.zcu.?.activate(tid);
+ defer active.deactivate();
+ const pt = active.pt;
// Most lazy symbols can be updated on first use, but
// anyerror needs to wait for everything to be flushed.
@@ -291,20 +292,22 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
}
if (build_options.enable_logging) {
- const pt: Zcu.PerThread = .activate(elf_file.base.comp.zcu.?, tid);
- defer pt.deactivate();
+ const active = elf_file.base.comp.zcu.?.activate(tid);
+ defer active.deactivate();
for (self.navs.keys(), self.navs.values()) |nav_index, meta| {
- checkNavAllocated(pt, nav_index, meta);
+ checkNavAllocated(active.pt, nav_index, meta);
}
for (self.uavs.keys(), self.uavs.values()) |uav_index, meta| {
- checkUavAllocated(pt, uav_index, meta);
+ checkUavAllocated(active.pt, uav_index, meta);
}
}
if (self.dwarf) |*dwarf| {
- const pt: Zcu.PerThread = .activate(elf_file.base.comp.zcu.?, tid);
- defer pt.deactivate();
- try dwarf.flush(pt);
+ {
+ const active = elf_file.base.comp.zcu.?.activate(tid);
+ defer active.deactivate();
+ try dwarf.flush(active.pt);
+ }
const gpa = elf_file.base.comp.gpa;
const cpu_arch = elf_file.getTarget().cpu.arch;
@@ -2405,10 +2408,10 @@ const TlsVariable = struct {
};
const AtomList = std.ArrayList(Atom.Index);
-const NavTable = std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvMetadata);
-const UavTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, AvMetadata);
-const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymbolMetadata);
-const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, void);
+const NavTable = std.array_hash_map.Auto(InternPool.Nav.Index, AvMetadata);
+const UavTable = std.array_hash_map.Auto(InternPool.Index, AvMetadata);
+const LazySymbolTable = std.array_hash_map.Auto(InternPool.Index, LazySymbolMetadata);
+const TlsTable = std.array_hash_map.Auto(Atom.Index, void);
const x86_64 = struct {
fn writeTrampolineCode(source_addr: i64, target_addr: i64, buf: *[max_trampoline_len]u8) ![]u8 {
diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig
index b16e726d21213f6ba5ccd2c6aa6c22c4690ef914..372e32ed297687542379d5419b41165b32ef7133 100644
--- a/src/link/Elf2.zig
+++ b/src/link/Elf2.zig
@@ -112,7 +112,7 @@ plt_first_symbol_reloc: SymbolReloc.Index,
/// The `.dynamic` section contains zero or more symbol relocations starting at this index.
dynamic_first_symbol_reloc: SymbolReloc.Index,
-needed: std.AutoArrayHashMapUnmanaged(String(.dynstr), void),
+needed: std.array_hash_map.Auto(String(.dynstr), void),
inputs: std.ArrayList(struct {
path: std.Build.Cache.Path,
member: ?[]const u8,
@@ -120,21 +120,21 @@ inputs: std.ArrayList(struct {
}),
input_sections: std.ArrayList(InputSection),
input_section_pending_index: u32,
-navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, struct {
+navs: std.array_hash_map.Auto(InternPool.Nav.Index, struct {
lsi: Symbol.LocalIndex,
/// The start index of the contiguous sequence of symbol relocations in this NAV.
first_symbol_reloc: SymbolReloc.Index,
/// The start index of the contiguous sequence of GOT relocations in this NAV.
first_got_reloc: GotReloc.Index,
}),
-uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, struct {
+uavs: std.array_hash_map.Auto(InternPool.Index, struct {
lsi: Symbol.LocalIndex,
/// The start index of the contiguous sequence of symbol relocations in this UAV.
first_symbol_reloc: SymbolReloc.Index,
// No `first_got_reloc` field because a UAV never contains GOT relocations.
}),
lazy: std.EnumArray(link.File.LazySymbol.Kind, struct {
- map: std.AutoArrayHashMapUnmanaged(InternPool.Index, struct {
+ map: std.array_hash_map.Auto(InternPool.Index, struct {
lsi: Symbol.LocalIndex,
/// The start index of the contiguous sequence of symbol relocations in this lazy code/data.
first_symbol_reloc: SymbolReloc.Index,
@@ -749,6 +749,14 @@ const GotReloc = struct {
offset32,
rel64,
rel32,
+
+ rel32_hi20,
+ rel64_lo20,
+ rel64_hi12,
+ abs32_lo12,
+ abs32_hi20,
+ abs64_lo20,
+ abs64_hi12,
};
const Index = enum(u32) {
@@ -817,6 +825,41 @@ const GotReloc = struct {
@intCast(@as(i64, @bitCast(got_vaddr +% got_offset +% addend -% dest_vaddr))),
target_endian,
),
+ .rel32_hi20 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ const target_value = got_vaddr +% got_offset +% addend;
+ link.loongarch.writeJ20(dest_slice[0..4], link.loongarch.toPcalaHi20(target_value, dest_vaddr));
+ },
+ .rel64_lo20 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ const target_value = got_vaddr +% got_offset +% addend;
+ link.loongarch.writeJ20(dest_slice[0..4], link.loongarch.toPcala64Lo20(target_value, dest_vaddr));
+ },
+ .rel64_hi12 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ const target_value = got_vaddr +% got_offset +% addend;
+ link.loongarch.writeK12(dest_slice[0..4], link.loongarch.toPcala64Hi12(target_value, dest_vaddr));
+ },
+ .abs32_lo12 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ const target_value = got_vaddr +% got_offset +% addend;
+ link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value));
+ },
+ .abs32_hi20 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ const target_value = got_vaddr +% got_offset +% addend;
+ link.loongarch.writeJ20(dest_slice[0..4], @truncate(target_value >> 12));
+ },
+ .abs64_lo20 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ const target_value = got_vaddr +% got_offset +% addend;
+ link.loongarch.writeJ20(dest_slice[0..4], @truncate(target_value >> 32));
+ },
+ .abs64_hi12 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ const target_value = got_vaddr +% got_offset +% addend;
+ link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value >> 52));
+ },
}
}
};
@@ -824,6 +867,7 @@ const GotReloc = struct {
pub const MachineRelocType = union {
X86_64: std.elf.R_X86_64,
AARCH64: std.elf.R_AARCH64,
+ LOONGARCH: std.elf.R_LARCH,
RISCV: std.elf.R_RISCV,
PPC64: std.elf.R_PPC64,
@@ -831,6 +875,7 @@ pub const MachineRelocType = union {
return switch (elf.ehdrField(.machine)) {
else => unreachable,
.AARCH64 => .{ .AARCH64 = .NONE },
+ .LOONGARCH => .{ .LOONGARCH = .NONE },
.PPC64 => .{ .PPC64 = .NONE },
.RISCV => .{ .RISCV = .NONE },
.X86_64 => .{ .X86_64 = .NONE },
@@ -840,6 +885,7 @@ pub const MachineRelocType = union {
return switch (elf.ehdrField(.machine)) {
else => unreachable,
.AARCH64 => .{ .AARCH64 = .COPY },
+ .LOONGARCH => .{ .LOONGARCH = .COPY },
.PPC64 => .{ .PPC64 = .COPY },
.RISCV => .{ .RISCV = .COPY },
.X86_64 => .{ .X86_64 = .COPY },
@@ -849,24 +895,28 @@ pub const MachineRelocType = union {
return switch (elf.ehdrField(.machine)) {
else => unreachable,
.X86_64 => .{ .X86_64 = .JUMP_SLOT },
+ .LOONGARCH => .{ .LOONGARCH = .JUMP_SLOT },
};
}
pub fn globDat(elf: *Elf) MachineRelocType {
return switch (elf.ehdrField(.machine)) {
else => unreachable,
.X86_64 => .{ .X86_64 = .GLOB_DAT },
+ .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .@"64" else .@"32" },
};
}
pub fn dtpOffAddr(elf: *Elf) MachineRelocType {
return switch (elf.ehdrField(.machine)) {
else => unreachable,
.X86_64 => .{ .X86_64 = .DTPOFF64 },
+ .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_DTPREL64 else .TLS_DTPREL32 },
};
}
pub fn absAddr(elf: *Elf) MachineRelocType {
return switch (elf.ehdrField(.machine)) {
else => unreachable,
.AARCH64 => .{ .AARCH64 = .ABS64 },
+ .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .@"64" else .@"32" },
.PPC64 => .{ .PPC64 = .ADDR64 },
.RISCV => .{ .RISCV = .@"64" },
.X86_64 => .{ .X86_64 = .@"64" },
@@ -883,6 +933,7 @@ pub const MachineRelocType = union {
return switch (elf.ehdrField(.machine)) {
else => unreachable,
inline .AARCH64,
+ .LOONGARCH,
.PPC64,
.RISCV,
.X86_64,
@@ -893,6 +944,7 @@ pub const MachineRelocType = union {
return switch (elf.ehdrField(.machine)) {
else => unreachable,
inline .AARCH64,
+ .LOONGARCH,
.PPC64,
.RISCV,
.X86_64,
@@ -984,9 +1036,23 @@ const SymbolReloc = struct {
size64,
size32,
+ abs32_lo12,
+ rel32_hi20,
+ rel64_lo20,
+ rel64_hi12,
+ branch_rel18,
+ branch_rel23,
+ branch_rel28,
+ call_rel38,
+ tpoff32_lo12,
+ tpoff32_hi20,
+ tpoff64_lo20,
+ tpoff64_hi12,
+
fn dependsOnTlsSize(t: SymbolReloc.Type) bool {
return switch (t) {
.tpoff32, .tpoff64 => true,
+ .tpoff32_lo12, .tpoff32_hi20, .tpoff64_lo20, .tpoff64_hi12 => true,
else => false,
};
}
@@ -1145,6 +1211,67 @@ const SymbolReloc = struct {
target_endian,
);
},
+ .abs32_lo12 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value));
+ },
+ .rel32_hi20 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ link.loongarch.writeJ20(dest_slice[0..4], link.loongarch.toPcalaHi20(target_value, dest_vaddr));
+ },
+ .rel64_lo20 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ link.loongarch.writeJ20(dest_slice[0..4], link.loongarch.toPcala64Lo20(target_value, dest_vaddr));
+ },
+ .rel64_hi12 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ link.loongarch.writeK12(dest_slice[0..4], link.loongarch.toPcala64Hi12(target_value, dest_vaddr));
+ },
+ // TODO: handle bad alignment and overflow gracefully
+ .branch_rel18 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ const target_rel: i64 = @bitCast(target_value -% dest_vaddr);
+ const slot_target: i16 = @intCast(@shrExact(target_rel, 2));
+ link.loongarch.writeK16(dest_slice[0..4], @bitCast(slot_target));
+ },
+ .branch_rel23 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ const target_rel: i64 = @bitCast(target_value -% dest_vaddr);
+ const slot_target: i21 = @intCast(@shrExact(target_rel, 2));
+ link.loongarch.writeD5K16(dest_slice[0..4], @bitCast(slot_target));
+ },
+ .branch_rel28 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ const target_rel: i64 = @bitCast(target_value -% dest_vaddr);
+ const slot_target: i26 = @intCast(@shrExact(target_rel, 2));
+ link.loongarch.writeD10K16(dest_slice[0..4], @bitCast(slot_target));
+ },
+ .call_rel38 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ const target_rel: i64 = @bitCast(target_value -% dest_vaddr);
+ // We use i64 instead of i36 here because the allowed range is
+ // [PC - 128 GiB - 0x20000, PC + 128GiB - 0x20000 - 4].
+ // The intCast in writeJ20 will do the final check.
+ const slot_target: i64 = @intCast(@shrExact(target_rel, 2));
+ link.loongarch.writeJ20(dest_slice[0..4], @bitCast(@as(i20, @intCast((slot_target +% 0x8000) >> 16))));
+ link.loongarch.writeK16(dest_slice[4..8], @bitCast(@as(i16, @truncate(slot_target))));
+ },
+ .tpoff32_lo12 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value));
+ },
+ .tpoff32_hi20 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ link.loongarch.writeJ20(dest_slice[0..4], @truncate(target_value >> 12));
+ },
+ .tpoff64_lo20 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ link.loongarch.writeJ20(dest_slice[0..4], @truncate(target_value >> 32));
+ },
+ .tpoff64_hi12 => {
+ assert(elf.ehdrField(.machine) == .LOONGARCH);
+ link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value >> 52));
+ },
}
}
@@ -1259,6 +1386,18 @@ fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void {
const plt_sec_need_size: usize = 16 * need_plt_capacity;
try elf.ensureNodeSize(elf.shndx.plt_sec.get(elf).ni, plt_sec_need_size);
},
+ .LOONGARCH => {
+ // Ensure the `.plt` section's node is big enough
+ const plt_need_size: usize = 32 + 16 * need_plt_capacity;
+ try elf.ensureNodeSize(elf.shndx.plt.get(elf).ni, plt_need_size);
+
+ // Ensure the `.got.plt` section's node is big enough
+ const got_plt_need_size: usize = switch (elf.identClass()) {
+ .NONE, _ => unreachable,
+ inline else => |class| @sizeOf(class.ElfN().Addr) * (2 + need_plt_capacity),
+ };
+ try elf.ensureNodeSize(elf.shndx.got_plt.get(elf).ni, got_plt_need_size);
+ },
}
}
/// Given an index into the PLT, returns whether that PLT entry is dead, meaning it may be reused at
@@ -1874,12 +2013,18 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void
.addend = 0,
}));
+ const reserved_got_plt_entries: u32 = switch (elf.ehdrField(.machine)) {
+ else => |machine| @panic(@tagName(machine)),
+ .X86_64 => 3,
+ .LOONGARCH => 2,
+ };
+
// Now that we know the index, we can set the relocation's offset.
const got_plt_addr = switch (elf.shdrPtr(elf.shndx.got_plt)) {
inline else => |shdr, class| got_plt_addr: {
const ent_size = @sizeOf(class.ElfN().Addr);
assert(elf.targetLoad(&shdr.entsize) == ent_size);
- const offset = ent_size * @as(u64, 3 + plt_index);
+ const offset = ent_size * @as(u64, reserved_got_plt_entries + plt_index);
assert(offset <= elf.targetLoad(&shdr.size));
break :got_plt_addr elf.targetLoad(&shdr.addr) + offset;
},
@@ -1961,6 +2106,55 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void
},
}
},
+ .LOONGARCH => {
+ // add a .PLT entry, writing the template
+ const plt_ni = elf.shndx.plt.get(elf).ni;
+ const plt_addr, const plt_slice = plt_entry: switch (elf.shdrPtr(elf.shndx.plt)) {
+ inline else => |shdr| {
+ const old_size = 16 * (1 + plt_index);
+ assert(elf.targetLoad(&shdr.size) == old_size);
+ elf.targetStore(&shdr.size, old_size + 16);
+ const plt_slice = plt_ni.slice(&elf.mf)[old_size..][0..16];
+ @memcpy(plt_slice, source: switch (elf.identClass()) {
+ .NONE, _ => unreachable,
+ inline .@"32", .@"64" => |elf_class| {
+ const ld_byte = if (elf_class == .@"64") 0xc0 else 0x80;
+ break :source &[16]u8{
+ 0x1a, 0x00, 0x00, 0x0f, // pcalau12i $t3, %pc_hi20(func@.got.plt)
+ 0x28, ld_byte, 0x01, 0xef, // ld.w/d $t3, $t3, %lo12(func@.got.plt)
+ 0x4c, 0x00, 0x01, 0xed, // jirl $t1, $t3, 0
+ 0x00, 0x2a, 0x00, 0x00, // break
+ };
+ },
+ });
+ break :plt_entry .{ elf.targetLoad(&shdr.addr) + old_size, plt_slice };
+ },
+ };
+
+ // add a .GOT.PLT entry, writing the address of the corresponding .PLT entry
+ const got_plt_ni = elf.shndx.got_plt.get(elf).ni;
+ switch (elf.shdrPtr(elf.shndx.got_plt)) {
+ inline else => |shdr, class| {
+ const ent_size = @sizeOf(class.ElfN().Addr);
+ const old_size = ent_size * (2 + plt_index);
+ assert(elf.targetLoad(&shdr.size) == old_size);
+ elf.targetStore(&shdr.size, old_size + ent_size);
+ std.mem.writeInt(
+ class.ElfN().Addr,
+ got_plt_ni.slice(&elf.mf)[old_size..][0..ent_size],
+ @intCast(plt_addr),
+ target_endian,
+ );
+ assert(got_plt_addr == (elf.targetLoad(&shdr.addr) + old_size));
+ },
+ }
+
+ // relocate the PLT entry to point to the .GOT.PLT entry
+ const got_plt_abs: u64 = @as(u64, got_plt_addr);
+ // TODO: handle overflow gracefully
+ link.loongarch.writeJ20(plt_slice[0..4], link.loongarch.toPcalaHi20(got_plt_abs, plt_addr));
+ link.loongarch.writeK12(plt_slice[4..8], @truncate(got_plt_abs));
+ },
}
}
@@ -2715,6 +2909,12 @@ fn initHeaders(
const relro_phndx = phnum;
phnum += 1;
+ const init_plt_size: std.elf.Xword, const plt_align: std.mem.Alignment, const plt_sec =
+ switch (machine) {
+ else => @panic(@tagName(machine)),
+ .X86_64 => .{ 16, .@"16", true },
+ .LOONGARCH => .{ 32, .@"4", false },
+ };
const expected_nodes_len = expected_nodes_len: switch (@"type") {
.NONE, .CORE, _ => unreachable,
.REL => {
@@ -2722,9 +2922,10 @@ fn initHeaders(
defer phnum = 0;
break :expected_nodes_len 5 + phnum;
},
- .EXEC, .DYN => break :expected_nodes_len 10 +
+ .EXEC, .DYN => break :expected_nodes_len 9 +
phnum * 2 - 1 + // each phdr also has a matching shdr, except for the PT_PHDR phdr
- @as(usize, 4) * @intFromBool(have_dynamic_section), // .dynstr, .dynsym, .rela.dyn, .rela.plt
+ @as(usize, 4) * @intFromBool(have_dynamic_section) + // .dynstr, .dynsym, .rela.dyn, .rela.plt
+ @intFromBool(plt_sec),
};
try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len);
try elf.shdrs.ensureTotalCapacity(gpa, shnum);
@@ -2757,7 +2958,24 @@ fn initHeaders(
ehdr.entry = 0;
ehdr.phoff = 0;
ehdr.shoff = 0;
- ehdr.flags = 0;
+ ehdr.flags = switch (machine) {
+ .X86_64 => 0,
+ .LOONGARCH => e_flags: {
+ const target_cpu = &elf.base.comp.getTarget().cpu;
+ const e_flags: std.elf.loongarch.EFlags = .{
+ .base_abi_modifier = if (target_cpu.has(.loongarch, .d))
+ .d
+ else if (target_cpu.has(.loongarch, .f))
+ .f
+ else
+ .s,
+ .abi_extension = .base,
+ .abi_version = 1,
+ };
+ break :e_flags @bitCast(e_flags);
+ },
+ else => @panic(@tagName(machine)),
+ };
ehdr.ehsize = @sizeOf(ElfN.Ehdr);
ehdr.phentsize = @sizeOf(ElfN.Phdr);
ehdr.phnum = @min(phnum, std.elf.PN_XNUM);
@@ -3051,6 +3269,7 @@ fn initHeaders(
.size = switch (machine) {
else => @panic(@tagName(machine)),
.X86_64 => 3 * 8,
+ .LOONGARCH => if (elf.identClass() == .@"64") 8 else 4,
},
.flags = .{ .WRITE = true, .ALLOC = true },
.addralign = addr_align,
@@ -3066,21 +3285,17 @@ fn initHeaders(
else => @panic(@tagName(machine)),
.@"386" => 3 * 4,
.X86_64 => 3 * 8,
+ .LOONGARCH => if (elf.identClass() == .@"64") 2 * 8 else 2 * 4,
},
.addralign = addr_align,
.entsize = @intCast(addr_align.toByteUnits()),
},
);
- const plt_size: std.elf.Xword, const plt_align: std.mem.Alignment, const plt_sec =
- switch (machine) {
- else => @panic(@tagName(machine)),
- .X86_64 => .{ 16, .@"16", true },
- };
elf.shndx.plt = try elf.addSection(elf.ni.text, .{
.name = ".plt",
.type = .PROGBITS,
.flags = .{ .ALLOC = true, .EXECINSTR = true },
- .size = plt_size,
+ .size = init_plt_size,
.addralign = plt_align,
.node_align = elf.mf.flags.block_size,
});
@@ -3218,6 +3433,38 @@ fn initHeaders(
.{ .X86_64 = .PC32 },
);
},
+ .LOONGARCH => {
+ const plt_ni = elf.shndx.plt.get(elf).ni;
+ const got_plt_sym: Symbol.Id = .local(elf.shndx.got_plt.get(elf).lsi);
+ @memcpy(plt_ni.slice(&elf.mf)[0..32], switch (class) {
+ .NONE, _ => unreachable,
+ .@"32" => &[32]u8{
+ 0x1a, 0x00, 0x00, 0x0e, // pcalau12i $t2, %pc_hi20(.got.plt)
+ 0x00, 0x11, 0x3d, 0xad, // sub.w $t1, $t1, $t3
+ 0x28, 0x80, 0x01, 0xcf, // ld.w $t3, $t2, %lo12(.got.plt) # _dl_runtime_resolve
+ 0x02, 0xbf, 0x51, 0xad, // addi.w $t1, $t1, -44 # .plt entry
+ 0x02, 0x80, 0x01, 0xcc, // addi.w $t0, $t2, %lo12(.got.plt) # &.got.plt
+ 0x00, 0x44, 0x89, 0xad, // srli.w $t1, $t1, 2 # .plt entry offset
+ 0x28, 0x80, 0x11, 0x8c, // ld.w $t0, $t0, 4 # link map
+ 0x4c, 0x00, 0x01, 0xe0, // jr $t3
+ },
+ .@"64" => &[32]u8{
+ 0x1a, 0x00, 0x00, 0x0e, // pcalau12i $t2, %pc_hi20(.got.plt)
+ 0x00, 0x11, 0xbd, 0xad, // sub.d $t1, $t1, $t3
+ 0x28, 0xc0, 0x01, 0xcf, // ld.d $t3, $t2, %lo12(.got.plt) # _dl_runtime_resolve
+ 0x02, 0xff, 0x51, 0xad, // addi.d $t1, $t1, -44 # .plt entry
+ 0x02, 0xc0, 0x01, 0xcc, // addi.d $t0, $t2, %lo12(.got.plt) # &.got.plt
+ 0x00, 0x45, 0x05, 0xad, // srli.d $t1, $t1, 1 # .plt entry offset
+ 0x28, 0xc0, 0x21, 0x8c, // ld.d $t0, $t0, 8 # link map
+ 0x4c, 0x00, 0x01, 0xe0, // jr $t3
+ },
+ });
+ elf.plt_first_symbol_reloc = @enumFromInt(elf.symbol_relocs.items.len);
+ try elf.ensureUnusedRelocCapacity(plt_ni, 3);
+ try elf.addRelocAssumeCapacity(plt_ni, 0, got_plt_sym, 0, .{ .LOONGARCH = .PCALA_HI20 });
+ try elf.addRelocAssumeCapacity(plt_ni, 8, got_plt_sym, 0, .{ .LOONGARCH = .PCALA_LO12 });
+ try elf.addRelocAssumeCapacity(plt_ni, 16, got_plt_sym, 0, .{ .LOONGARCH = .PCALA_LO12 });
+ },
}
}
if (comp.config.any_non_single_threaded) {
@@ -3242,6 +3489,13 @@ fn initHeaders(
elf.got.putAssumeCapacityNoClobber(.{ .reserved = 1 }, .none);
elf.got.putAssumeCapacityNoClobber(.{ .reserved = 2 }, .none);
},
+ .LOONGARCH => {
+ try elf.got.ensureUnusedCapacity(gpa, 1);
+ elf.got.putAssumeCapacityNoClobber(switch (have_dynamic_section) {
+ true => .{ .symbol = .local(elf.shndx.dynamic.get(elf).lsi) },
+ false => .{ .reserved = 0 },
+ }, .none);
+ },
}
switch (elf.shdrPtr(elf.shndx.got)) {
inline else => |shdr, ct_class| {
@@ -3254,7 +3508,7 @@ fn initHeaders(
// `FINI_ARRAY`/`PREINIT_ARRAY` sections are instead created by `createInitFiniArraySection`
// when needed (it seems to be legal to leave those undefined if the section doesn't exist).
- try elf.ensureUnusedSymbolCapacity(4, .maybe_global);
+ try elf.ensureUnusedSymbolCapacity(10, .maybe_global);
// Despite the name, `__dso_handle` is necessary even in static binaries.
_ = elf.addGlobalSymbolAssumeCapacity(.{
.node = Section.Index.text.get(elf).ni,
@@ -3262,7 +3516,7 @@ fn initHeaders(
.value = Section.Index.text.vaddr(elf),
.size = 0,
.type = .NOTYPE,
- .bind = .strong,
+ .bind = .weak,
.visibility = .HIDDEN,
.shndx = .text,
}) catch |err| switch (err) {
@@ -3292,6 +3546,78 @@ fn initHeaders(
}) catch |err| switch (err) {
error.MultipleDefinitions => unreachable, // no inputs are processed yet
};
+ _ = elf.addGlobalSymbolAssumeCapacity(.{
+ .node = .none,
+ .name = try .string(elf, "__init_array_start"),
+ .value = 0,
+ .size = 0,
+ .type = .NOTYPE,
+ .bind = .strong,
+ .visibility = .HIDDEN,
+ .shndx = .ABS,
+ }) catch |err| switch (err) {
+ error.MultipleDefinitions => unreachable, // no inputs are processed yet
+ };
+ _ = elf.addGlobalSymbolAssumeCapacity(.{
+ .node = .none,
+ .name = try .string(elf, "__init_array_end"),
+ .value = 0,
+ .size = 0,
+ .type = .NOTYPE,
+ .bind = .strong,
+ .visibility = .HIDDEN,
+ .shndx = .ABS,
+ }) catch |err| switch (err) {
+ error.MultipleDefinitions => unreachable, // no inputs are processed yet
+ };
+ _ = elf.addGlobalSymbolAssumeCapacity(.{
+ .node = .none,
+ .name = try .string(elf, "__fini_array_start"),
+ .value = 0,
+ .size = 0,
+ .type = .NOTYPE,
+ .bind = .strong,
+ .visibility = .HIDDEN,
+ .shndx = .ABS,
+ }) catch |err| switch (err) {
+ error.MultipleDefinitions => unreachable, // no inputs are processed yet
+ };
+ _ = elf.addGlobalSymbolAssumeCapacity(.{
+ .node = .none,
+ .name = try .string(elf, "__fini_array_end"),
+ .value = 0,
+ .size = 0,
+ .type = .NOTYPE,
+ .bind = .strong,
+ .visibility = .HIDDEN,
+ .shndx = .ABS,
+ }) catch |err| switch (err) {
+ error.MultipleDefinitions => unreachable, // no inputs are processed yet
+ };
+ _ = elf.addGlobalSymbolAssumeCapacity(.{
+ .node = .none,
+ .name = try .string(elf, "__preinit_array_start"),
+ .value = 0,
+ .size = 0,
+ .type = .NOTYPE,
+ .bind = .strong,
+ .visibility = .HIDDEN,
+ .shndx = .ABS,
+ }) catch |err| switch (err) {
+ error.MultipleDefinitions => unreachable, // no inputs are processed yet
+ };
+ _ = elf.addGlobalSymbolAssumeCapacity(.{
+ .node = .none,
+ .name = try .string(elf, "__preinit_array_end"),
+ .value = 0,
+ .size = 0,
+ .type = .NOTYPE,
+ .bind = .strong,
+ .visibility = .HIDDEN,
+ .shndx = .ABS,
+ }) catch |err| switch (err) {
+ error.MultipleDefinitions => unreachable, // no inputs are processed yet
+ };
if (have_dynamic_section) {
_ = elf.addGlobalSymbolAssumeCapacity(.{
.node = elf.shndx.dynamic.get(elf).ni,
@@ -3713,7 +4039,7 @@ fn mapInputSection(elf: *Elf, opts: struct {
const new_alignment: std.mem.Alignment = .fromByteUnits(
std.math.ceilPowerOfTwoAssert(usize, @intCast(opts.addralign)),
);
- try existing_shndx.get(elf).ni.realign(&elf.mf, gpa, new_alignment);
+ try existing_shndx.get(elf).ni.realign(&elf.mf, gpa, new_alignment, .{ .set_alignment = true });
}
// ...and update the shdr as needed.
switch (elf.shdrPtr(existing_shndx)) {
@@ -3876,7 +4202,7 @@ fn uavMapIndex(
} else {
const node = uav_gop.value_ptr.lsi.index().ptr(elf).node;
if (resolved_align.toStdMem().order(node.alignment(&elf.mf)).compare(.gt)) {
- try node.realign(&elf.mf, gpa, resolved_align.toStdMem());
+ try node.realign(&elf.mf, gpa, resolved_align.toStdMem(), .{ .set_alignment = true });
}
}
return umi;
@@ -4605,7 +4931,7 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadPars
// We have a copy relocation for this global, but the amount of space we
// reserved for it could be too small or underaligned!
try copied_global.node.resize(&elf.mf, gpa, gop.value_ptr.size);
- try copied_global.node.realign(&elf.mf, gpa, gop.value_ptr.alignment);
+ try copied_global.node.realign(&elf.mf, gpa, gop.value_ptr.alignment, .{ .set_alignment = true });
const global_ptr = elf.globalByName(name).?;
switch (elf.symPtr(global_ptr.symtab_index)) {
inline else => |sym_ptr| elf.targetStore(&sym_ptr.size, @intCast(gop.value_ptr.size)),
@@ -4759,36 +5085,24 @@ fn createInitFiniArraySection(
});
elf.section_by_name.putAssumeCapacityNoClobber(shndx.name(elf), {});
try elf.ensureUnusedSymbolCapacity(2, .maybe_global);
- _ = elf.addGlobalSymbolAssumeCapacity(.{
+ // These symbols definitely already have strong definitions, because we added them alongside the
+ // other linker-defined symbols, all the way back in `initHeaders`.
+ const start_sym_name = try elf.string(.strtab, "__" ++ name ++ "_start");
+ const end_sym_name = try elf.string(.strtab, "__" ++ name ++ "_end");
+ elf.setGlobalSymbolValue(start_sym_name, elf.globals.strong_def.getPtr(start_sym_name).?, .{
.node = shndx.get(elf).ni,
- .name = try .string(elf, "__" ++ name ++ "_start"),
.value = shndx.vaddr(elf),
.size = 0,
.type = .NOTYPE,
- .bind = .strong,
- .visibility = .HIDDEN,
.shndx = shndx.*,
- }) catch |err| switch (err) {
- error.MultipleDefinitions => return elf.base.comp.link_diags.fail(
- "multiple definitions of '{s}'",
- .{"__" ++ name ++ "_start"},
- ),
- };
- _ = elf.addGlobalSymbolAssumeCapacity(.{
+ });
+ elf.setGlobalSymbolValue(end_sym_name, elf.globals.strong_def.getPtr(end_sym_name).?, .{
.node = shndx.get(elf).ni,
- .name = try .string(elf, "__" ++ name ++ "_end"),
.value = shndx.vaddr(elf),
.size = 0,
.type = .NOTYPE,
- .bind = .strong,
- .visibility = .HIDDEN,
.shndx = shndx.*,
- }) catch |err| switch (err) {
- error.MultipleDefinitions => return elf.base.comp.link_diags.fail(
- "multiple definitions of '{s}'",
- .{"__" ++ name ++ "_end"},
- ),
- };
+ });
}
fn updateInitFiniArraySectionSize(
elf: *Elf,
@@ -5315,6 +5629,52 @@ fn addRelocAssumeCapacity(
.TLSLD => elf.addGotRelocAssumeCapacity(node, offset, .tlsld0, addend, .rel32),
.GOTTPOFF => elf.addGotRelocAssumeCapacity(node, offset, .{ .tpoff = target }, addend, .rel32),
},
+ .LOONGARCH => switch (@"type".LOONGARCH) {
+ else => std.debug.panic("TODO: unsupported input relocation, {t}", .{@"type".LOONGARCH}),
+ _,
+ .NONE,
+ .COPY,
+ .JUMP_SLOT,
+ .RELATIVE,
+ .IRELATIVE,
+ => std.debug.panic("TODO: error for illegal or unsupported input relocation, {t}", .{@"type".LOONGARCH}),
+
+ .RELAX => {}, // TODO: relaxation is not yet implemented
+
+ // Relocations targeting a symbol
+ .@"64" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs64),
+ .@"32" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs32),
+ .@"64_PCREL" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel64),
+ .@"32_PCREL" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel32),
+
+ .PCALA_LO12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs32_lo12),
+ .PCALA_HI20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel32_hi20),
+ .PCALA64_HI12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel64_hi12),
+ .PCALA64_LO20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel64_lo20),
+
+ .B16 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .branch_rel18),
+ .B21 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .branch_rel23),
+ .B26 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .branch_rel28),
+ .CALL36 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .call_rel38),
+
+ // Relocations targeting a TLS symbol
+ .TLS_LE_LO12, .TLS_LE_LO12_R => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .tpoff32_lo12),
+ .TLS_LE_HI20, .TLS_LE_HI20_R => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .tpoff32_hi20),
+ .TLS_LE64_LO20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .tpoff64_lo20),
+ .TLS_LE64_HI12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .tpoff64_hi12),
+ .TLS_LE_ADD_R => {}, // TODO: relaxation is not yet implemented
+
+ // Relocations targeting a GOT entry
+ .GOT_PC_LO12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .abs32_lo12),
+ .GOT_PC_HI20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .rel32_hi20),
+ .GOT64_PC_LO20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .rel64_lo20),
+ .GOT64_PC_HI12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .rel64_hi12),
+
+ .GOT_LO12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .abs32_lo12),
+ .GOT_HI20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .abs32_hi20),
+ .GOT64_LO20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .abs64_lo20),
+ .GOT64_HI12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .abs64_hi12),
+ },
},
}
}
@@ -5352,7 +5712,47 @@ fn addSymbolRelocAssumeCapacity(
.tpoff32 => .TPOFF32,
.size64 => .SIZE64,
.size32 => .SIZE32,
+ .abs32_lo12,
+ .rel32_hi20,
+ .rel64_lo20,
+ .rel64_hi12,
+ .branch_rel18,
+ .branch_rel23,
+ .branch_rel28,
+ .call_rel38,
+ .tpoff32_lo12,
+ .tpoff32_hi20,
+ .tpoff64_lo20,
+ .tpoff64_hi12,
+ => unreachable,
} },
+ .LOONGARCH => .{
+ .LOONGARCH = switch (@"type") {
+ .write_rela => unreachable,
+ .abs64 => .@"64",
+ .abs32 => .@"32",
+ .abs32s, .size64, .size32 => unreachable,
+ .rel64 => .@"64_PCREL",
+ .rel32 => .@"32_PCREL",
+ .pltrel64, .pltrel32 => break :r .none,
+ .dtpoff64 => .TLS_DTPREL64,
+ .dtpoff32 => .TLS_DTPREL32,
+ .tpoff64 => .TLS_TPREL64,
+ .tpoff32 => .TLS_TPREL32,
+ .abs32_lo12 => .PCALA_LO12,
+ .rel32_hi20 => .PCALA_HI20,
+ .rel64_lo20 => .PCALA64_LO20,
+ .rel64_hi12 => .PCALA64_HI12,
+ .branch_rel18 => .B16,
+ .branch_rel23 => .B21,
+ .branch_rel28 => .B26,
+ .call_rel38 => .CALL36,
+ .tpoff32_lo12 => .TLS_LE_LO12,
+ .tpoff32_hi20 => .TLS_LE_HI20,
+ .tpoff64_lo20 => .TLS_LE64_LO20,
+ .tpoff64_hi12 => .TLS_LE64_HI12,
+ },
+ },
};
// TODO: even if the symbol is locally defined, preemption/interposition is a
// possibility, which this condition does not currently consider!
@@ -5523,6 +5923,7 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void {
.type = switch (elf.ehdrField(.machine)) {
else => |machine| @panic(@tagName(machine)),
.X86_64 => .{ .X86_64 = .TPOFF64 },
+ .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_TPREL64 else .TLS_TPREL32 },
},
.dynsym_index = switch (sym_id.unwrap()) {
.global => |name| elf.globalByName(name).?.dynsym_index,
@@ -5579,7 +5980,11 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void {
.UNDEF => .{ .unsigned = 1 }, // TLS module ID for exexcutable
else => .{
.reloc = .{
- .type = .{ .X86_64 = .DTPMOD64 },
+ .type = switch (elf.ehdrField(.machine)) {
+ else => |machine| @panic(@tagName(machine)),
+ .X86_64 => .{ .X86_64 = .DTPMOD64 },
+ .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 },
+ },
.dynsym_index = switch (sym.unwrap()) {
.local => 0,
.global => |name| dsi: {
@@ -5611,7 +6016,11 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void {
.tlsld0 => switch (elf.shndx.dynamic) {
.UNDEF => .{ .unsigned = 1 }, // TLS module ID for exexcutable
else => .{ .reloc = .{
- .type = .{ .X86_64 = .DTPMOD64 },
+ .type = switch (elf.ehdrField(.machine)) {
+ else => |machine| @panic(@tagName(machine)),
+ .X86_64 => .{ .X86_64 = .DTPMOD64 },
+ .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 },
+ },
.dynsym_index = 0,
} },
},
@@ -6558,6 +6967,55 @@ fn flushMovedPltSection(elf: *Elf, which: enum { plt, plt_sec, got_plt }, old_ad
},
}
},
+ .LOONGARCH => {
+ switch (which) {
+ .plt => {
+ // We also need to update all of the references from `.plt` to `.got.plt`.
+ // However, if there's also a flush pending for `.got.plt`, don't bother doing
+ // this now, because we'll do it when `.got.plt` is flushed anyway.
+ if (elf.shndx.got_plt.get(elf).ni.hasMoved(&elf.mf)) {
+ return;
+ }
+ // Exit this `switch` to update those references.
+ },
+ .plt_sec => unreachable,
+ .got_plt => {
+ // Update the offsets of the relocation entries in `.rela.plt`.
+ const rela_plt_shndx = elf.shndx.rela_plt;
+ for (0..elf.plt.count()) |plt_index| {
+ if (elf.pltEntryIsDead(plt_index)) continue;
+ rela_plt_shndx.relaAdjustOffset(elf, @enumFromInt(plt_index), old_addr, addr);
+ }
+ // We also need to update all of the references from `.plt` to `.got.plt`.
+ // However, if there's also a flush pending for `.plt`, don't bother doing
+ // this now, because we'll do it when `.plt` is flushed anyway.
+ if (elf.shndx.plt.get(elf).ni.hasMoved(&elf.mf)) {
+ return;
+ }
+ // Exit this `switch` to update those references.
+ },
+ }
+ // We are updating the references from `.plt` to `.got.plt`.
+ const got_plt_addr = elf.shndx.got_plt.vaddr(elf);
+ const plt_addr = elf.shndx.plt.vaddr(elf);
+ const plt_slice = elf.shndx.plt.get(elf).ni.slice(&elf.mf);
+ switch (elf.identClass()) {
+ .NONE, _ => unreachable,
+ inline else => |class| {
+ const Addr = class.ElfN().Addr;
+ for (0..elf.plt.count()) |plt_index| {
+ const plt_offset = 16 * plt_index;
+ const got_plt_offset = @sizeOf(Addr) * (2 + plt_index);
+ const target_slice = plt_slice[plt_offset..];
+
+ const got_plt_abs: u64 = got_plt_addr + got_plt_offset;
+ // TODO: handle overflow gracefully
+ link.loongarch.writeJ20(target_slice[0..4], link.loongarch.toPcalaHi20(got_plt_abs, plt_addr + plt_offset));
+ link.loongarch.writeK12(target_slice[4..8], @truncate(got_plt_abs));
+ }
+ },
+ }
+ },
}
}
@@ -6651,16 +7109,12 @@ pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerm
_ = name;
}
-pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) Io.Cancelable!void {
- const comp = elf.base.comp;
- const io = comp.io;
- var buffer: [512]u8 = undefined;
- const stderr = try io.lockStderr(&buffer, null);
- defer io.lockStderr();
- const w = &stderr.file_writer.interface;
- elf.printNode(tid, w, .root, 0) catch |err| switch (err) {
- error.WriteFailed => return stderr.err.?,
- };
+pub fn dump(elf: *Elf, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpResult {
+ if (elf.options.enable_link_snapshots) {
+ try elf.printNode(tid, w, .root, 0);
+ return .enabled;
+ }
+ return .disabled;
}
pub fn printNode(
@@ -6704,13 +7158,13 @@ pub fn printNode(
elf.getNode(isi.node(elf).parent(&elf.mf)).section.name(elf).slice(elf),
});
},
- .copied_global => |name| try w.print("(copy:{s})", .{name}),
+ .copied_global => |name| try w.print("(copy:{s})", .{name.slice(elf)}),
.nav => |nmi| {
const zcu = elf.base.comp.zcu.?;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nmi.navIndex(elf));
try w.print("({f}, {f})", .{
- Type.fromInterned(nav.typeOf(ip)).fmt(.{ .zcu = zcu, .tid = tid }),
+ Type.fromInterned(ip.typeOf(nav.resolved.?.value)).fmt(.{ .zcu = zcu, .tid = tid }),
nav.fqn.fmt(ip),
});
},
diff --git a/src/link/Lld.zig b/src/link/Lld.zig
index 3f20d15ebd7e8c9890b2fab69d57dc5779715579..c4c4e0fb3d721cc134473db4b348ee65a048d08e 100644
--- a/src/link/Lld.zig
+++ b/src/link/Lld.zig
@@ -304,23 +304,25 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void {
// insight as to what's going on here you can read that function body which is more
// well-commented.
- const link_inputs = comp.link_inputs;
-
var object_files: std.ArrayList([*:0]const u8) = .empty;
- try object_files.ensureUnusedCapacity(arena, link_inputs.len);
- for (link_inputs) |input| {
- object_files.appendAssumeCapacity(try input.path().?.toStringZ(arena));
- }
+ try object_files.ensureUnusedCapacity(arena, comp.link_inputs.len);
+ for (comp.link_inputs) |input| switch (input) {
+ .res, .dso, .dso_exact => {}, // shared libraries should not be included in static archives
+ .object, .archive => {
+ const path = try input.path().?.toStringZ(arena);
+ object_files.appendAssumeCapacity(path);
+ },
+ };
- try object_files.ensureUnusedCapacity(arena, comp.c_object_table.count() +
- comp.win32_resource_table.count() + 2);
+ try object_files.ensureUnusedCapacity(arena, comp.c_objects.items.len +
+ comp.win32_resources.items.len + 2);
- for (comp.c_object_table.keys()) |key| {
- object_files.appendAssumeCapacity(try key.status.success.object_path.toStringZ(arena));
+ for (comp.c_objects.items) |c_object| {
+ object_files.appendAssumeCapacity(try c_object.status.success.object_path.toStringZ(arena));
}
- for (comp.win32_resource_table.keys()) |key| {
- object_files.appendAssumeCapacity(try arena.dupeSentinel(u8, key.status.success.res_path, 0));
+ for (comp.win32_resources.items) |win32_resource| {
+ object_files.appendAssumeCapacity(try arena.dupeSentinel(u8, win32_resource.status.success.res_path, 0));
}
if (zcu_obj_path) |p| object_files.appendAssumeCapacity(try p.toStringZ(arena));
if (compiler_rt_path) |p| object_files.appendAssumeCapacity(try p.toStringZ(arena));
@@ -395,8 +397,8 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
const the_object_path = blk: {
if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
- if (comp.c_object_table.count() != 0)
- break :blk comp.c_object_table.keys()[0].status.success.object_path;
+ if (comp.c_objects.items.len != 0)
+ break :blk comp.c_objects.items[0].status.success.object_path;
if (zcu_obj_path) |p|
break :blk p;
@@ -546,12 +548,12 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
},
};
- for (comp.c_object_table.keys()) |key| {
- try argv.append(try key.status.success.object_path.toString(arena));
+ for (comp.c_objects.items) |c_object| {
+ try argv.append(try c_object.status.success.object_path.toString(arena));
}
- for (comp.win32_resource_table.keys()) |key| {
- try argv.append(key.status.success.res_path);
+ for (comp.win32_resources.items) |win32_resource| {
+ try argv.append(win32_resource.status.success.res_path);
}
if (zcu_obj_path) |p| {
@@ -805,8 +807,8 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
const the_object_path = blk: {
if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
- if (comp.c_object_table.count() != 0)
- break :blk comp.c_object_table.keys()[0].status.success.object_path;
+ if (comp.c_objects.items.len != 0)
+ break :blk comp.c_objects.items[0].status.success.object_path;
if (zcu_obj_path) |p|
break :blk p;
@@ -1099,8 +1101,8 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
whole_archive = false;
}
- for (comp.c_object_table.keys()) |key| {
- try argv.append(try key.status.success.object_path.toString(arena));
+ for (comp.c_objects.items) |c_object| {
+ try argv.append(try c_object.status.success.object_path.toString(arena));
}
if (zcu_obj_path) |p| {
@@ -1295,21 +1297,21 @@ fn getLDMOption(target: *const std.Target) ?[]const u8 {
},
.mips64 => switch (target.os.tag) {
.freebsd => switch (target.abi) {
- .gnuabin32, .muslabin32 => "elf32btsmipn32_fbsd",
+ .gnuabin32, .muslabin32, .abin32 => "elf32btsmipn32_fbsd",
else => "elf64btsmip_fbsd",
},
else => switch (target.abi) {
- .gnuabin32, .muslabin32 => "elf32btsmipn32",
+ .gnuabin32, .muslabin32, .abin32 => "elf32btsmipn32",
else => "elf64btsmip",
},
},
.mips64el => switch (target.os.tag) {
.freebsd => switch (target.abi) {
- .gnuabin32, .muslabin32 => "elf32ltsmipn32_fbsd",
+ .gnuabin32, .muslabin32, .abin32 => "elf32ltsmipn32_fbsd",
else => "elf64ltsmip_fbsd",
},
else => switch (target.abi) {
- .gnuabin32, .muslabin32 => "elf32ltsmipn32",
+ .gnuabin32, .muslabin32, .abin32 => "elf32ltsmipn32",
else => "elf64ltsmip",
},
},
@@ -1336,7 +1338,7 @@ fn getLDMOption(target: *const std.Target) ?[]const u8 {
else => "elf_i386",
},
.x86_64 => switch (target.abi) {
- .gnux32, .muslx32 => "elf32_x86_64",
+ .gnux32, .muslx32, .x32 => "elf32_x86_64",
else => "elf_x86_64",
},
else => null,
@@ -1381,8 +1383,8 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void {
const the_object_path = blk: {
if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
- if (comp.c_object_table.count() != 0)
- break :blk comp.c_object_table.keys()[0].status.success.object_path;
+ if (comp.c_objects.items.len != 0)
+ break :blk comp.c_objects.items[0].status.success.object_path;
if (zcu_obj_path) |p|
break :blk p;
@@ -1566,8 +1568,8 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void {
whole_archive = false;
}
- for (comp.c_object_table.keys()) |key| {
- try argv.append(try key.status.success.object_path.toString(arena));
+ for (comp.c_objects.items) |c_object| {
+ try argv.append(try c_object.status.success.object_path.toString(arena));
}
if (zcu_obj_path) |p| {
try argv.append(try p.toString(arena));
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 8783781a4ced69514353f2696587a9f9a1516b23..125db2983f2fa8a550b218d2d4be6d41153c1c8b 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -28,9 +28,9 @@ sections: std.MultiArrayList(Section) = .{},
resolver: SymbolResolver = .{},
/// This table will be populated after `scanRelocs` has run.
/// Key is symbol index.
-undefs: std.AutoArrayHashMapUnmanaged(SymbolResolver.Index, UndefRefs) = .empty,
+undefs: std.array_hash_map.Auto(SymbolResolver.Index, UndefRefs) = .empty,
undefs_mutex: std.Io.Mutex = .init,
-dupes: std.AutoArrayHashMapUnmanaged(SymbolResolver.Index, std.ArrayList(File.Index)) = .empty,
+dupes: std.array_hash_map.Auto(SymbolResolver.Index, std.ArrayList(File.Index)) = .empty,
dupes_mutex: std.Io.Mutex = .init,
dyld_info_cmd: macho.dyld_info_command = .{},
@@ -377,9 +377,9 @@ pub fn flush(
// This is a set of object files emitted by clang in a single `build-exe` invocation.
// For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up
// in this set.
- try positionals.ensureUnusedCapacity(comp.c_object_table.keys().len);
- for (comp.c_object_table.keys()) |key| {
- positionals.appendAssumeCapacity(try link.openObjectInput(io, diags, key.status.success.object_path));
+ try positionals.ensureUnusedCapacity(comp.c_objects.items.len);
+ for (comp.c_objects.items) |c_object| {
+ positionals.appendAssumeCapacity(try link.openObjectInput(io, diags, c_object.status.success.object_path));
}
if (zcu_obj_path) |path| try positionals.append(try link.openObjectInput(io, diags, path));
@@ -657,8 +657,8 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
.dso_exact => |dso_exact| try argv.appendSlice(&.{ "-l", dso_exact.name }),
};
- for (comp.c_object_table.keys()) |key| {
- try argv.append(try key.status.success.object_path.toString(arena));
+ for (comp.c_objects.items) |c_object| {
+ try argv.append(try c_object.status.success.object_path.toString(arena));
}
if (zcu_obj_path) |p| {
@@ -749,8 +749,8 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
.dso_exact => |dso_exact| try argv.appendSlice(&.{ "-l", dso_exact.name }),
};
- for (comp.c_object_table.keys()) |key| {
- try argv.append(try key.status.success.object_path.toString(arena));
+ for (comp.c_objects.items) |c_object| {
+ try argv.append(try c_object.status.success.object_path.toString(arena));
}
if (zcu_obj_path) |p| {
@@ -4102,7 +4102,7 @@ const Section = struct {
};
pub const LiteralPool = struct {
- table: std.AutoArrayHashMapUnmanaged(void, void) = .empty,
+ table: std.array_hash_map.Auto(void, void) = .empty,
keys: std.ArrayList(Key) = .empty,
values: std.ArrayList(MachO.Ref) = .empty,
data: std.ArrayList(u8) = .empty,
@@ -4541,7 +4541,7 @@ pub const Ref = struct {
pub const SymbolResolver = struct {
keys: std.ArrayList(Key) = .empty,
values: std.ArrayList(Ref) = .empty,
- table: std.AutoArrayHashMapUnmanaged(void, void) = .empty,
+ table: std.array_hash_map.Auto(void, void) = .empty,
const Result = struct {
found_existing: bool,
diff --git a/src/link/MachO/Dylib.zig b/src/link/MachO/Dylib.zig
index d1f79b5ab73e7efd293858116a2031453d57c8de..3125cd538d01636f3c181c48282c354de53f388a 100644
--- a/src/link/MachO/Dylib.zig
+++ b/src/link/MachO/Dylib.zig
@@ -14,7 +14,7 @@ symbols: std.ArrayList(Symbol) = .empty,
symbols_extra: std.ArrayList(u32) = .empty,
globals: std.ArrayList(MachO.SymbolResolver.Index) = .empty,
dependents: std.ArrayList(Id) = .empty,
-rpaths: std.StringArrayHashMapUnmanaged(void) = .empty,
+rpaths: std.array_hash_map.String(void) = .empty,
umbrella: File.Index,
platform: ?MachO.Platform = null,
diff --git a/src/link/MachO/Thunk.zig b/src/link/MachO/Thunk.zig
index cdb9eb649af4a0aeb340d96cad81716cc66ecbde..d71cf29aea5c331a08028cf99eb78fd7a7f8f511 100644
--- a/src/link/MachO/Thunk.zig
+++ b/src/link/MachO/Thunk.zig
@@ -1,6 +1,6 @@
value: u64 = 0,
out_n_sect: u8 = 0,
-symbols: std.AutoArrayHashMapUnmanaged(MachO.Ref, void) = .empty,
+symbols: std.array_hash_map.Auto(MachO.Ref, void) = .empty,
output_symtab_ctx: MachO.SymtabCtx = .{},
pub fn deinit(thunk: *Thunk, allocator: Allocator) void {
diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig
index 5f2309dbfee59c24df7d3f6e90a3d8264913b1a4..fc2500867f7d90d619c91fd0b2ad48bc3c59f9d1 100644
--- a/src/link/MachO/ZigObject.zig
+++ b/src/link/MachO/ZigObject.zig
@@ -560,14 +560,14 @@ pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.E
// Handle any lazy symbols that were emitted by incremental compilation.
if (self.lazy_syms.getPtr(.anyerror_type)) |metadata| {
- const pt: Zcu.PerThread = .activate(macho_file.base.comp.zcu.?, tid);
- defer pt.deactivate();
+ const active = macho_file.base.comp.zcu.?.activate(tid);
+ defer active.deactivate();
// Most lazy symbols can be updated on first use, but
// anyerror needs to wait for everything to be flushed.
if (metadata.text_state != .unused) self.updateLazySymbol(
macho_file,
- pt,
+ active.pt,
.{ .kind = .code, .ty = .anyerror_type },
metadata.text_symbol_index,
) catch |err| switch (err) {
@@ -576,7 +576,7 @@ pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.E
};
if (metadata.const_state != .unused) self.updateLazySymbol(
macho_file,
- pt,
+ active.pt,
.{ .kind = .const_data, .ty = .anyerror_type },
metadata.const_symbol_index,
) catch |err| switch (err) {
@@ -590,9 +590,9 @@ pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.E
}
if (self.dwarf) |*dwarf| {
- const pt: Zcu.PerThread = .activate(macho_file.base.comp.zcu.?, tid);
- defer pt.deactivate();
- dwarf.flush(pt) catch |err| switch (err) {
+ const active = macho_file.base.comp.zcu.?.activate(tid);
+ defer active.deactivate();
+ dwarf.flush(active.pt) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
else => |e| return diags.fail("failed to flush dwarf module: {s}", .{@errorName(e)}),
};
@@ -1750,11 +1750,11 @@ const TlvInitializer = struct {
}
};
-const NavTable = std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvMetadata);
-const UavTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, AvMetadata);
-const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymbolMetadata);
+const NavTable = std.array_hash_map.Auto(InternPool.Nav.Index, AvMetadata);
+const UavTable = std.array_hash_map.Auto(InternPool.Index, AvMetadata);
+const LazySymbolTable = std.array_hash_map.Auto(InternPool.Index, LazySymbolMetadata);
const RelocationTable = std.ArrayList(std.ArrayList(Relocation));
-const TlvInitializerTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlvInitializer);
+const TlvInitializerTable = std.array_hash_map.Auto(Atom.Index, TlvInitializer);
const x86_64 = struct {
fn writeTrampolineCode(source_addr: u64, target_addr: u64, buf: *[max_trampoline_len]u8) ![]u8 {
diff --git a/src/link/MachO/relocatable.zig b/src/link/MachO/relocatable.zig
index be36cfc045b7bb4abe4ff8fde43b62b7299511e6..b864ee66ca42394529dd6c58556e5cb10801e413 100644
--- a/src/link/MachO/relocatable.zig
+++ b/src/link/MachO/relocatable.zig
@@ -9,8 +9,8 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat
try positionals.ensureUnusedCapacity(comp.link_inputs.len);
positionals.appendSliceAssumeCapacity(comp.link_inputs);
- for (comp.c_object_table.keys()) |key| {
- try positionals.append(try link.openObjectInput(io, diags, key.status.success.object_path));
+ for (comp.c_objects.items) |c_object| {
+ try positionals.append(try link.openObjectInput(io, diags, c_object.status.success.object_path));
}
if (module_obj_path) |path| try positionals.append(try link.openObjectInput(io, diags, path));
@@ -86,8 +86,8 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
try positionals.ensureUnusedCapacity(comp.link_inputs.len);
positionals.appendSliceAssumeCapacity(comp.link_inputs);
- for (comp.c_object_table.keys()) |key| {
- try positionals.append(try link.openObjectInput(io, diags, key.status.success.object_path));
+ for (comp.c_objects.items) |c_object| {
+ try positionals.append(try link.openObjectInput(io, diags, c_object.status.success.object_path));
}
if (module_obj_path) |path| try positionals.append(try link.openObjectInput(io, diags, path));
diff --git a/src/link/MappedFile.zig b/src/link/MappedFile.zig
index 9c317aff744d99f6570654851bb253670d35f8e8..74c1ce432999043d8fe5ad0331d8ba4128973abd 100644
--- a/src/link/MappedFile.zig
+++ b/src/link/MappedFile.zig
@@ -26,6 +26,9 @@ updates: std.ArrayList(Node.Index),
update_prog_node: std.Progress.Node,
writers: std.SinglyLinkedList,
io_err: ?IoError,
+/// If locked, modifying the node layout is not allowed.
+/// Modifying node content is always allowed.
+nodes_lock: std.debug.SafetyLock = .{},
pub const growth_factor = 4;
@@ -188,6 +191,10 @@ pub const Node = extern struct {
return ni.get(mf).parent;
}
+ pub fn next(ni: Node.Index, mf: *const MappedFile) Node.Index {
+ return ni.get(mf).next;
+ }
+
pub fn ChildIterator(comptime direction: enum { prev, next }) type {
return struct {
mf: *const MappedFile,
@@ -330,6 +337,7 @@ pub const Node = extern struct {
}
pub fn resize(ni: Node.Index, mf: *MappedFile, gpa: std.mem.Allocator, size: u64) Error!void {
+ defer if (std.debug.runtime_safety) mf.verify();
mf.resizeNode(gpa, ni, size) catch |err| switch (err) {
error.OutOfMemory,
error.Canceled,
@@ -346,16 +354,23 @@ pub const Node = extern struct {
}
}
+ pub const RealignNodeOptions = struct {
+ /// Shift the node backwards if possible
+ try_backwards: bool = true,
+ /// If `set, persists `new_alignment` as the node's alignment for future operations.
+ set_alignment: bool = true,
+ };
+
/// Moves and expands a node such that its offset and size are aligned to `new_alignment`.
- ///
/// Asserts that `ni` is not `Node.Index.root`.
pub fn realign(
ni: Node.Index,
mf: *MappedFile,
gpa: std.mem.Allocator,
new_alignment: std.mem.Alignment,
+ opts: RealignNodeOptions,
) Error!void {
- mf.realignNode(gpa, ni, new_alignment) catch |err| switch (err) {
+ mf.realignNode(gpa, ni, new_alignment, opts) catch |err| switch (err) {
error.OutOfMemory,
error.Canceled,
=> |e| return e,
@@ -371,6 +386,26 @@ pub const Node = extern struct {
}
}
+ /// Shrink a node to `size`, exactly.
+ /// Asserts that the new size can contain all the children.
+ /// If `shift_next` is set, then the following node is shifted backwards into
+ /// the free space as much as alignment allows.
+ /// Asserts that `size` is >= the end of the last child node.
+ pub fn shrink(
+ ni: Node.Index,
+ mf: *MappedFile,
+ gpa: std.mem.Allocator,
+ size: u64,
+ shift_next: bool,
+ ) Error!void {
+ try mf.shrinkNode(gpa, ni, size, shift_next);
+ var writers_it = mf.writers.first;
+ while (writers_it) |writer_node| : (writers_it = writer_node.next) {
+ const w: *Node.Writer = @fieldParentPtr("writer_node", writer_node);
+ w.interface.buffer = w.ni.slice(mf);
+ }
+ }
+
pub fn writer(ni: Node.Index, mf: *MappedFile, gpa: std.mem.Allocator, w: *Writer) void {
w.* = .{
.gpa = gpa,
@@ -530,7 +565,26 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
add_node: AddNodeOptions,
}) Error!Node.Index {
if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1);
+ mf.nodes_lock.assertUnlocked();
const offset = opts.add_node.alignment.forward(@intCast(opts.offset));
+ if (opts.parent != .none) {
+ const new_end = offset + opts.add_node.size;
+ switch (opts.next) {
+ .none => {
+ _, const parent_size = opts.parent.location(mf).resolve(mf);
+ if (new_end > parent_size)
+ try opts.parent.resize(mf, gpa, new_end);
+ },
+ else => |next_ni| {
+ const next_offset, _ = next_ni.location(mf).resolve(mf);
+ if (new_end > next_offset)
+ try next_ni.realign(mf, gpa, opts.add_node.alignment, .{
+ .try_backwards = false,
+ .set_alignment = false,
+ });
+ },
+ }
+ }
const location_tag: Node.Location.Tag, const location_payload: Node.Location.Payload = location: {
if (std.math.cast(u32, offset)) |small_offset| break :location .{ .small, .{
.small = .{ .offset = small_offset, .size = 0 },
@@ -572,14 +626,12 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
},
.location_payload = location_payload,
};
+
{
- defer {
- free_node.flags.moved = false;
- free_node.flags.resized = false;
- }
- _, const parent_size = opts.parent.location(mf).resolve(mf);
- if (offset > parent_size) try opts.parent.resize(mf, gpa, offset);
try free_ni.resize(mf, gpa, opts.add_node.size);
+ if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1);
+ free_node.flags.moved = false;
+ free_node.flags.resized = false;
}
if (opts.add_node.moved) free_ni.movedAssumeCapacity(mf);
if (opts.add_node.resized) free_ni.resizedAssumeCapacity(mf);
@@ -666,11 +718,63 @@ pub fn addNodeAfter(
});
}
-fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested_size: u64) (Allocator.Error || Io.Cancelable || IoError)!void {
+fn shrinkNode(
+ mf: *MappedFile,
+ gpa: std.mem.Allocator,
+ ni: Node.Index,
+ size: u64,
+ shift_next: bool,
+) !void {
+ mf.nodes_lock.assertUnlocked();
+ const node = ni.get(mf);
+ const old_offset, _ = node.location().resolve(mf);
+
+ // This would require unmapping first
+ assert(ni != Node.Index.root);
+ defer if (std.debug.runtime_safety) mf.verify();
+
+ if (node.last != .none) {
+ const last = node.last.get(mf);
+ const last_offset, const last_size = last.location().resolve(mf);
+ assert(last_offset + last_size > size);
+ }
+
+ try mf.large.ensureUnusedCapacity(gpa, 4);
+ try mf.updates.ensureUnusedCapacity(gpa, 2);
+
+ ni.setLocationAssumeCapacity(mf, old_offset, size);
+ if (!shift_next or node.next == .none) return;
+
+ const next = node.next.get(mf);
+ const old_next_offset, const next_size = next.location().resolve(mf);
+ const padding = old_next_offset - (old_offset + size);
+ const new_next_offset = next.flags.alignment.forward(@intCast(old_next_offset - padding));
+
+ if (next.flags.has_content and new_next_offset < old_next_offset) {
+ const old_file_offset = node.next.fileLocation(mf, false).offset;
+ const new_file_offset = (old_file_offset - old_next_offset) + new_next_offset;
+ @memmove(
+ mf.memory_map.memory[@intCast(new_file_offset)..][0..@intCast(next_size)],
+ mf.memory_map.memory[@intCast(old_file_offset)..][0..@intCast(next_size)],
+ );
+ @memset(mf.memory_map.memory[@intCast(new_file_offset + next_size)..@intCast(old_file_offset + next_size)], 0);
+ }
+
+ node.next.setLocationAssumeCapacity(mf, new_next_offset, next_size);
+}
+
+fn resizeNode(
+ mf: *MappedFile,
+ gpa: std.mem.Allocator,
+ ni: Node.Index,
+ requested_size: u64,
+) (Allocator.Error || Io.Cancelable || IoError)!void {
+ mf.nodes_lock.assertUnlocked();
const io = mf.io;
const node = ni.get(mf);
const old_offset, const old_size = node.location().resolve(mf);
const new_size = node.flags.alignment.forward(@intCast(requested_size));
+
// Resize the entire file
if (ni == Node.Index.root) {
try mf.ensureCapacityForSetLocation(gpa);
@@ -703,19 +807,26 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested
if (is_linux and !mf.flags.fallocate_insert_range_unsupported and
node.flags.alignment.order(mf.flags.block_size).compare(.gte))
insert_range: {
- mf.memory_map.write(io) catch |err| switch (err) {
- error.WouldBlock => return error.Unexpected, // file was not opened as non-blocking
- error.NotOpenForWriting => return error.Unexpected, // we definitely opened the file for writing
- else => |e| return e,
- };
- // Ask the filesystem driver to insert extents into the file without copying any data
- const last_offset, const last_size = parent.last.location(mf).resolve(mf);
- const last_end = last_offset + last_size;
- assert(last_end <= old_parent_size);
const range_file_offset = ni.fileLocation(mf, false).offset + old_size;
const range_size = node.flags.alignment.forward(
@intCast(requested_size +| requested_size / growth_factor),
) - old_size;
+
+ // If this node is being realigned, its current state might not
+ // meet the requirements for fallocate
+ if (!mf.flags.block_size.check(@intCast(range_file_offset)) or
+ !mf.flags.block_size.check(@intCast(range_size)))
+ break :insert_range;
+
+ mf.memory_map.write(io) catch |err| switch (err) {
+ error.WouldBlock => return error.Unexpected, // file was not opened as non-blocking
+ error.NotOpenForWriting => return error.Unexpected, // we definitely opened the file for writing
+ else => |e| return e,
+ };
+ // Ask the filesystem driver to insert extents into the file without copying any data
+ const last_offset, const last_size = parent.last.location(mf).resolve(mf);
+ const last_end = last_offset + last_size;
+ assert(last_end <= old_parent_size);
_, const file_size = Node.Index.root.location(mf).resolve(mf);
while (true) switch (linux.errno(switch (std.math.order(range_file_offset, file_size)) {
.lt => linux.fallocate(
@@ -814,6 +925,7 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested
var last_fixed_ni = ni;
var first_floating_ni = node.next;
var shift = new_size - old_size;
+ var max_shift_align: std.mem.Alignment = .@"1";
var direction: enum { forward, reverse } = .forward;
while (true) {
assert(last_fixed_ni != .none);
@@ -830,10 +942,12 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested
if (new_last_fixed_offset + last_fixed_size <= old_first_floating_offset)
break :make_space;
assert(direction == .forward);
+ max_shift_align = max_shift_align.max(first_floating.flags.alignment.max(last_fixed.flags.alignment));
if (first_floating.flags.fixed) {
- shift = first_floating.flags.alignment.forward(@intCast(
+ shift = max_shift_align.forward(@intCast(
@max(shift, first_floating_size),
));
+
// Not enough space, try the next node
last_fixed_ni = first_floating_ni;
first_floating_ni = first_floating.next;
@@ -842,7 +956,7 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested
// Move the found floating node to make space for preceding fixed nodes
const last = parent.last.get(mf);
const last_offset, const last_size = last.location().resolve(mf);
- const new_first_floating_offset = first_floating.flags.alignment.forward(
+ const new_first_floating_offset = max_shift_align.forward(
@intCast(@max(new_last_fixed_offset + last_fixed_size, last_offset + last_size)),
);
const new_parent_size = new_first_floating_offset + first_floating_size;
@@ -903,7 +1017,7 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested
last_fixed_ni.setLocationAssumeCapacity(
mf,
old_last_fixed_offset,
- last_fixed_size + shift,
+ new_size,
);
return;
}
@@ -929,8 +1043,10 @@ fn realignNode(
gpa: std.mem.Allocator,
ni: Node.Index,
new_alignment: std.mem.Alignment,
+ opts: Node.Index.RealignNodeOptions,
) (Allocator.Error || Io.Cancelable || IoError)!void {
assert(ni != Node.Index.root); // currently unsupported
+ mf.nodes_lock.assertUnlocked();
const node = ni.get(mf);
const old_offset, const size = node.location().resolve(mf);
@@ -939,7 +1055,12 @@ fn realignNode(
defer if (std.debug.runtime_safety) mf.verify();
+ const prev_alignment = node.flags.alignment;
node.flags.alignment = new_alignment;
+ defer {
+ // alignment needs to be temporarily set for the resizes below
+ if (!opts.set_alignment) node.flags.alignment = prev_alignment;
+ }
const new_size = node.flags.alignment.forward(@intCast(size));
if (new_alignment.check(@intCast(old_offset))) {
@@ -956,6 +1077,37 @@ fn realignNode(
},
};
+ if (opts.try_backwards) {
+ const backward_offset = new_alignment.backward(@intCast(old_offset));
+ const prev_end = if (node.prev == .none) 0 else prev: {
+ const prev_offset, const prev_size = node.prev.location(mf).resolve(mf);
+ break :prev prev_offset + prev_size;
+ };
+
+ if (backward_offset >= prev_end) {
+ try mf.ensureCapacityForSetLocation(gpa);
+
+ if (node.flags.has_content) {
+ const old_file_offset = ni.fileLocation(mf, false).offset;
+ const new_file_offset = (old_file_offset - old_offset) + backward_offset;
+ @memmove(
+ mf.memory_map.memory[@intCast(new_file_offset)..][0..@intCast(size)],
+ mf.memory_map.memory[@intCast(old_file_offset)..][0..@intCast(size)],
+ );
+ @memset(mf.memory_map.memory[@intCast(new_file_offset + size)..@intCast(old_file_offset + size)], 0);
+ }
+
+ if (backward_offset + new_size <= trailing_end) {
+ ni.setLocationAssumeCapacity(mf, backward_offset, new_size);
+ } else {
+ ni.setLocationAssumeCapacity(mf, backward_offset, size);
+ try mf.resizeNode(gpa, ni, new_size);
+ }
+
+ return;
+ }
+ }
+
const forward_offset = new_alignment.forward(@intCast(old_offset));
if (forward_offset + new_size <= trailing_end) {
// Shift into the free space if possible
@@ -1135,6 +1287,12 @@ fn ensureTotalCapacityPreciseInner(mf: *MappedFile, new_capacity: usize) (Alloca
error.OperationUnsupported => {},
else => |e| return e,
}
+
+ mf.memory_map.write(io) catch |err| switch (err) {
+ error.WouldBlock => return error.Unexpected, // file was not opened as non-blocking
+ error.NotOpenForWriting => return error.Unexpected, // we definitely opened the file for writing
+ else => |e| return e,
+ };
unmap(mf);
}
@@ -1156,11 +1314,12 @@ pub fn unmap(mf: *MappedFile) void {
}
pub fn flush(mf: *MappedFile) (Io.Cancelable || error{MappedFileIo})!void {
- mf.memory_map.write(mf.io) catch |err| switch (err) {
+ mf.flushInner() catch |err| switch (err) {
error.Canceled => |e| return e,
error.WouldBlock, // file was not opened as non-blocking
error.NotOpenForWriting, // we definitely opened the file for writing
+ error.ReadOnlyFileSystem,
=> {
mf.io_err = error.Unexpected;
return error.MappedFileIo;
@@ -1173,6 +1332,11 @@ pub fn flush(mf: *MappedFile) (Io.Cancelable || error{MappedFileIo})!void {
};
}
+fn flushInner(mf: *MappedFile) (Io.File.WritePositionalError || Io.File.SetTimestampsError)!void {
+ try mf.memory_map.write(mf.io);
+ if (is_windows) try mf.memory_map.file.setTimestampsNow(mf.io);
+}
+
fn verify(mf: *MappedFile) void {
const root = Node.Index.root.get(mf);
assert(root.parent == .none);
@@ -1207,3 +1371,184 @@ fn verifyNode(mf: *MappedFile, parent_ni: Node.Index) void {
ni = node.next;
}
}
+
+const testing = std.testing;
+fn testVerifyContent(mf: *@This(), ni: Node.Index, value: u8, init_len: usize) !void {
+ // Not using std.mem.allEqual, so we can get useful output
+ const slice = ni.slice(mf);
+ var buf: [256]u8 = undefined;
+ @memset(buf[0..init_len], value);
+ @memset(buf[init_len..], 0);
+ try testing.expectEqualSlices(u8, buf[0..slice.len], slice);
+}
+
+test {
+ const gpa = testing.allocator;
+
+ var tmp_dir = testing.tmpDir(.{});
+ defer tmp_dir.cleanup();
+
+ var file = try tmp_dir.dir.createFile(testing.io, "test.mf", .{ .read = true });
+ defer file.close(testing.io);
+
+ var mf = try init(file, gpa, testing.io);
+ defer mf.deinit(gpa);
+
+ const a = try mf.addFirstChildNode(gpa, .root, .{ .fixed = true, .alignment = .@"4" });
+ const c = try mf.addLastChildNode(gpa, .root, .{ .fixed = true, .alignment = .@"4" });
+ const b = try mf.addNodeAfter(gpa, a, .{ .fixed = true, .alignment = .@"16" });
+ const d = try mf.addNodeAfter(gpa, b, .{ .alignment = .@"4" });
+
+ const a_init_size = 8;
+ const b_init_size = 16;
+ const c_init_size = 24;
+ const d_init_size = 28;
+
+ // Resize without content
+ {
+ // Verify size is aligned forward
+ try d.resize(&mf, gpa, d_init_size - 1);
+ try a.resize(&mf, gpa, a_init_size - 2);
+ try c.resize(&mf, gpa, c_init_size);
+ try b.resize(&mf, gpa, b_init_size);
+ mf.verify();
+
+ const a_loc, const a_size = a.location(&mf).resolve(&mf);
+ const b_loc, const b_size = b.location(&mf).resolve(&mf);
+ const c_loc, const c_size = c.location(&mf).resolve(&mf);
+ _, const d_size = d.location(&mf).resolve(&mf);
+ try testing.expect(a_size >= a_init_size);
+ try testing.expect(b_size >= b_init_size);
+ try testing.expect(c_size >= c_init_size);
+ try testing.expect(d_size >= d_init_size);
+ try testing.expect(b_loc >= a_loc + a_size);
+ try testing.expect(c_loc >= b_loc + b_size);
+ }
+
+ const a_exp_size = 24;
+ const b_exp_size = 28;
+ const c_exp_size = 48;
+ const d_exp_size = 32;
+
+ // Resize with content
+ {
+ @memset(a.slice(&mf)[0..a_init_size], 0xaa);
+ @memset(b.slice(&mf)[0..b_init_size], 0xbb);
+ @memset(c.slice(&mf)[0..c_init_size], 0xcc);
+ @memset(d.slice(&mf)[0..d_init_size], 0xdd);
+
+ try a.resize(&mf, gpa, a_exp_size);
+ try b.resize(&mf, gpa, b_exp_size);
+ try c.resize(&mf, gpa, c_exp_size);
+ try d.resize(&mf, gpa, d_exp_size);
+ mf.verify();
+
+ const a_loc, const a_size = a.location(&mf).resolve(&mf);
+ const b_loc, const b_size = b.location(&mf).resolve(&mf);
+ const c_loc, const c_size = c.location(&mf).resolve(&mf);
+ _, const d_size = d.location(&mf).resolve(&mf);
+ try testing.expect(a_size >= a_exp_size);
+ try testing.expect(b_size >= b_exp_size);
+ try testing.expect(c_size >= c_exp_size);
+ try testing.expect(d_size >= d_exp_size);
+ try testing.expect(b_loc >= a_loc + a_size);
+ try testing.expect(c_loc >= b_loc + b_size);
+
+ try testVerifyContent(&mf, a, 0xaa, a_init_size);
+ try testVerifyContent(&mf, b, 0xbb, b_init_size);
+ try testVerifyContent(&mf, c, 0xcc, c_init_size);
+ try testVerifyContent(&mf, d, 0xdd, d_init_size);
+ }
+
+ const child_init: []const struct { std.mem.Alignment, usize } = &.{
+ .{ .@"16", 16 },
+ .{ .@"1", 1 },
+ .{ .@"1", 19 },
+ .{ .@"1", 3 },
+ .{ .@"8", 30 },
+ .{ .@"2", 5 },
+ .{ .@"1", 60 },
+ .{ .@"2", 2 },
+ .{ .@"16", 32 },
+ };
+
+ var children: [child_init.len]Node.Index = undefined;
+
+ // Differently-aligned fixed sibling nodes
+ {
+ for (children[0 .. children.len - 1], child_init[0 .. children.len - 1], 0..) |*ni, opts, i| {
+ ni.* = try mf.addLastChildNode(gpa, b, .{
+ .alignment = opts.@"0",
+ .size = opts.@"1",
+ .fixed = true,
+ });
+
+ @memset(ni.slice(&mf)[0..opts.@"1"], @intCast(i + 1));
+ }
+ // Shift differently-aligned nodes by inserting a node
+ children[children.len - 1] = try mf.addNodeAfter(gpa, children[3], .{
+ .alignment = child_init[children.len - 1].@"0",
+ .size = child_init[children.len - 1].@"1",
+ .fixed = true,
+ });
+ @memset(children[children.len - 1].slice(&mf), @intCast(children.len));
+
+ mf.verify();
+ for (children, child_init, 0..) |ni, opts, i| {
+ try testVerifyContent(&mf, ni, @intCast(i + 1), opts.@"1");
+ }
+ }
+
+ // Shifting child nodes forward due via resize of parent.prev
+ {
+ try testing.expect(a.location(&mf).resolve(&mf)[1] < 64);
+ try a.resize(&mf, gpa, 64);
+
+ try testVerifyContent(&mf, a, 0xaa, a_init_size);
+ try testVerifyContent(&mf, c, 0xcc, c_init_size);
+ try testVerifyContent(&mf, d, 0xdd, d_init_size);
+ for (children, child_init, 0..) |ni, opts, i| {
+ try testVerifyContent(&mf, ni, @intCast(i + 1), opts.@"1");
+ }
+ }
+
+ // Re-align last node into trailing free space within parent
+ {
+ try b.resize(&mf, gpa, b.location(&mf).resolve(&mf)[1] + 64);
+
+ const last = children[children.len - 2];
+ try last.realign(&mf, gpa, .@"4", true);
+ mf.verify();
+
+ for (children, child_init, 0..) |ni, opts, i|
+ try testVerifyContent(&mf, ni, @intCast(i + 1), opts.@"1");
+ try testVerifyContent(&mf, c, 0xcc, c_init_size);
+ }
+
+ // Re-align, shifting sibling nodes
+ {
+ try children[1].realign(&mf, gpa, .@"8", true);
+ mf.verify();
+
+ for (children, child_init, 0..) |ni, opts, i|
+ try testVerifyContent(&mf, ni, @intCast(i + 1), opts.@"1");
+ try testVerifyContent(&mf, c, 0xcc, c_init_size);
+ }
+
+ // Shrink and shift start of trailing node into free space
+ {
+ try mf.shrinkNode(gpa, a, 16, true);
+ mf.verify();
+
+ const a_loc, const a_size = a.location(&mf).resolve(&mf);
+ const b_loc, _ = b.location(&mf).resolve(&mf);
+ try testing.expectEqual(b_loc, a_loc + a_size);
+
+ try testVerifyContent(&mf, a, 0xaa, a_init_size);
+ try testVerifyContent(&mf, c, 0xcc, c_init_size);
+ try testVerifyContent(&mf, d, 0xdd, d_init_size);
+ for (children, child_init, 0..) |ni, opts, i| {
+ try testVerifyContent(&mf, ni, @intCast(i + 1), opts.@"1");
+ }
+ }
+}
diff --git a/src/link/Queue.zig b/src/link/Queue.zig
index 9e05b0b99ef870fb90f800d091124269c0f39ca0..2057245f012e32d25bd3005ec8f466430230d9bd 100644
--- a/src/link/Queue.zig
+++ b/src/link/Queue.zig
@@ -101,8 +101,6 @@ pub fn enqueueZcu(
) Io.Cancelable!void {
const io = comp.io;
- assert(tid == .main);
-
if (q.future != null) {
if (q.zcu_queue.putOne(io, task)) |_| {
return;
diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig
index 5095e2e8c51e2d0f3dbc5bb89ce5856a36eaf4b6..e6cdabd133e641406bfd0ef96328e9fe8e07469a 100644
--- a/src/link/SpirV.zig
+++ b/src/link/SpirV.zig
@@ -3,28 +3,43 @@ const Allocator = std.mem.Allocator;
const Path = std.Build.Cache.Path;
const assert = std.debug.assert;
const log = std.log.scoped(.link);
-
+const zig_version = @import("builtin").zig_version;
const Zcu = @import("../Zcu.zig");
const InternPool = @import("../InternPool.zig");
const Compilation = @import("../Compilation.zig");
const link = @import("../link.zig");
const Air = @import("../Air.zig");
const Type = @import("../Type.zig");
+const codegen = @import("../codegen.zig");
const CodeGen = @import("../codegen/spirv/CodeGen.zig");
-const Module = @import("../codegen/spirv/Module.zig");
-const trace = @import("../tracy.zig").trace;
const BinaryModule = @import("SpirV/BinaryModule.zig");
const lower_invocation_globals = @import("SpirV/lower_invocation_globals.zig");
-
+const dedup_types = @import("SpirV/dedup_types.zig");
+const prune_unused = @import("SpirV/prune_unused.zig");
const spec = @import("../codegen/spirv/spec.zig");
+const Section = @import("../codegen/spirv/Section.zig");
const Id = spec.Id;
const Word = spec.Word;
+const Mir = @import("../codegen/spirv/Mir.zig");
const Linker = @This();
base: link.File,
-module: Module,
-cg: CodeGen,
+fragments: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Mir) = .empty,
+pending_navs: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,
+entry_points: std.ArrayListUnmanaged(EntryPointDecl) = .empty,
+external_objects: std.ArrayListUnmanaged(ExternalObject) = .empty,
+
+const EntryPointDecl = struct {
+ nav: InternPool.Nav.Index,
+ name: []const u8,
+ cc: std.builtin.CallingConvention,
+};
+
+const ExternalObject = struct {
+ instructions: []const Word,
+ id_bound: u32,
+};
pub fn createEmpty(
arena: Allocator,
@@ -32,7 +47,6 @@ pub fn createEmpty(
emit: Path,
options: link.File.OpenOptions,
) !*Linker {
- const gpa = comp.gpa;
const io = comp.io;
const target = &comp.root_mod.resolved_target.result;
@@ -61,21 +75,6 @@ pub fn createEmpty(
.file = null,
.build_id = options.build_id,
},
- .module = .{
- .gpa = gpa,
- .arena = arena,
- .zcu = comp.zcu.?,
- },
- .cg = .{
- // These fields are populated in generate()
- .pt = undefined,
- .air = undefined,
- .liveness = undefined,
- .owner_nav = undefined,
- .module = undefined,
- .control_flow = .{ .structured = .{} },
- .base_line = undefined,
- },
};
errdefer linker.deinit();
@@ -97,70 +96,124 @@ pub fn open(
}
pub fn deinit(linker: *Linker) void {
- linker.cg.deinit();
- linker.module.deinit();
+ const gpa = linker.base.comp.gpa;
+ for (linker.fragments.values()) |*mir| {
+ mir.deinit(gpa);
+ }
+ linker.fragments.deinit(gpa);
+ linker.pending_navs.deinit(gpa);
+ linker.entry_points.deinit(gpa);
+ for (linker.external_objects.items) |obj| {
+ gpa.free(obj.instructions);
+ }
+ linker.external_objects.deinit(gpa);
}
-fn generate(
- linker: *Linker,
- pt: Zcu.PerThread,
- nav_index: InternPool.Nav.Index,
- air: Air,
- liveness: Air.Liveness,
- do_codegen: bool,
-) !void {
- const zcu = pt.zcu;
- const gpa = zcu.gpa;
- const structured_cfg = zcu.navFileScope(nav_index).mod.?.structured_cfg;
-
- linker.cg.control_flow.deinit(gpa);
- linker.cg.args.clearRetainingCapacity();
- linker.cg.inst_results.clearRetainingCapacity();
- linker.cg.id_scratch.clearRetainingCapacity();
- linker.cg.prologue.reset();
- linker.cg.body.reset();
-
- linker.cg = .{
- .pt = pt,
- .air = air,
- .liveness = liveness,
- .owner_nav = nav_index,
- .module = &linker.module,
- .control_flow = switch (structured_cfg) {
- true => .{ .structured = .{} },
- false => .{ .unstructured = .{} },
+pub fn loadInput(linker: *Linker, input: link.Input) !void {
+ switch (input) {
+ .object => |obj| {
+ const comp = linker.base.comp;
+ const gpa = comp.gpa;
+ const io = comp.io;
+ const diags = &comp.link_diags;
+
+ const stat = obj.file.stat(io) catch |err|
+ return diags.fail("failed to stat SPIR-V object '{f}': {t}", .{ obj.path, err });
+ const file_size = std.math.cast(usize, stat.size) orelse
+ return diags.fail("SPIR-V object '{f}' is too large", .{obj.path});
+ if (file_size < 5 * @sizeOf(Word))
+ return diags.fail("SPIR-V object '{f}' is too small to contain a valid header", .{obj.path});
+ if (file_size % @sizeOf(Word) != 0)
+ return diags.fail("SPIR-V object '{f}' size is not a multiple of the word size", .{obj.path});
+
+ const word_count = file_size / @sizeOf(Word);
+ const all_words = try gpa.alloc(Word, word_count);
+ defer gpa.free(all_words);
+
+ const bytes = std.mem.sliceAsBytes(all_words);
+ const n_read = obj.file.readPositionalAll(io, bytes, 0) catch |err|
+ return diags.fail("failed to read SPIR-V object '{f}': {t}", .{ obj.path, err });
+ if (n_read != bytes.len)
+ return diags.fail("SPIR-V object '{f}': incomplete read", .{obj.path});
+
+ const needs_swap = all_words[0] == @byteSwap(spec.magic_number);
+ if (needs_swap) {
+ for (all_words) |*w| w.* = @byteSwap(w.*);
+ }
+
+ if (all_words[0] != spec.magic_number)
+ return diags.fail("SPIR-V object '{f}': invalid magic number", .{obj.path});
+
+ const id_bound = all_words[3];
+ const instructions = try gpa.dupe(Word, all_words[5..]);
+ errdefer gpa.free(instructions);
+
+ // OpCapability instructions appear at the top of the module
+ // so we can stop scanning as soon as we hit anything else.
+ var it: BinaryModule.Instruction.Iterator = .init(instructions, 0);
+ const has_linkage = while (it.next()) |inst| switch (inst.opcode) {
+ .OpCapability => {
+ const cap: spec.Capability = @enumFromInt(inst.operands[0]);
+ if (cap == .linkage) break true;
+ },
+ else => break false,
+ } else false;
+ if (!has_linkage) {
+ return diags.fail("SPIR-V object '{f}' is missing the Linkage capability and cannot be linked", .{obj.path});
+ }
+
+ try linker.external_objects.append(gpa, .{
+ .instructions = instructions,
+ .id_bound = id_bound,
+ });
+ },
+ else => {
+ const diags = &linker.base.comp.link_diags;
+ return diags.fail("unsupported link input for SPIR-V target", .{});
},
- .base_line = zcu.navSrcLine(nav_index),
-
- .args = linker.cg.args,
- .inst_results = linker.cg.inst_results,
- .id_scratch = linker.cg.id_scratch,
- .prologue = linker.cg.prologue,
- .body = linker.cg.body,
- };
-
- linker.cg.genNav(do_codegen) catch |err| switch (err) {
- error.AlreadyReported => return,
- else => |e| return e,
- };
+ }
}
pub fn updateFunc(
linker: *Linker,
pt: Zcu.PerThread,
func_index: InternPool.Index,
- air: *const Air,
- liveness: *const ?Air.Liveness,
+ mir: *codegen.AnyMir,
) !void {
+ const gpa = linker.base.comp.gpa;
const nav = pt.zcu.funcInfo(func_index).owner_nav;
- // TODO: Separate types for generating decls and functions?
- try linker.generate(pt, nav, air.*, liveness.*.?, true);
+
+ if (linker.fragments.getPtr(nav)) |existing| {
+ existing.deinit(gpa);
+ }
+
+ try linker.fragments.put(gpa, nav, mir.spirv);
+ mir.spirv = .{
+ .extended_instruction_set = &.{},
+ .globals = &.{},
+ .functions = &.{},
+ .annotations = &.{},
+ .debug_names = &.{},
+ .debug_strings = &.{},
+ .execution_modes = &.{},
+ .id_bound = 0,
+ .owner_nav = mir.spirv.owner_nav,
+ .kind = mir.spirv.kind,
+ .decl_result_id = .none,
+ .nav_refs = &.{},
+ .uav_refs = &.{},
+ .decl_deps = &.{},
+ .internal_globals = &.{},
+ .entry_points = &.{},
+ };
}
pub fn updateNav(linker: *Linker, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.Error!void {
const ip = &pt.zcu.intern_pool;
- log.debug("lowering nav {f}({d})", .{ ip.getNav(nav).fqn.fmt(ip), nav });
- try linker.generate(pt, nav, undefined, undefined, false);
+ log.debug("deferring nav {f}({d}) to flush", .{ ip.getNav(nav).fqn.fmt(ip), nav });
+
+ const gpa = linker.base.comp.gpa;
+ linker.pending_navs.append(gpa, nav) catch return error.OutOfMemory;
}
pub fn updateExports(
@@ -171,6 +224,7 @@ pub fn updateExports(
) !void {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
+ const gpa = linker.base.comp.gpa;
const nav_index = switch (exported) {
.nav => |nav| nav,
.uav => |uav| {
@@ -179,40 +233,17 @@ pub fn updateExports(
},
};
const nav_ty = ip.getNav(nav_index).resolved.?.type;
- const target = zcu.getTarget();
if (ip.isFunctionType(nav_ty)) {
- const spv_decl_index = try linker.module.resolveNav(ip, nav_index);
const cc = Type.fromInterned(nav_ty).fnCallingConvention(zcu);
- const exec_model: spec.ExecutionModel = switch (target.os.tag) {
- .vulkan, .opengl => switch (cc) {
- .spirv_vertex => .vertex,
- .spirv_fragment => .fragment,
- .spirv_kernel => .gl_compute,
- // TODO: We should integrate with the Linkage capability and export this function
- .spirv_device => return,
- else => unreachable,
- },
- .opencl => switch (cc) {
- .spirv_kernel => .kernel,
- // TODO: We should integrate with the Linkage capability and export this function
- .spirv_device => return,
- else => unreachable,
- },
- else => unreachable,
- };
-
for (export_indices) |export_idx| {
const exp = export_idx.ptr(zcu);
- try linker.module.declareEntryPoint(
- spv_decl_index,
- exp.opts.name.toSlice(ip),
- exec_model,
- null,
- );
+ try linker.entry_points.append(gpa, .{
+ .nav = nav_index,
+ .name = exp.opts.name.toSlice(ip),
+ .cc = cc,
+ });
}
}
-
- // TODO: Export regular functions, variables, etc using Linkage attributes.
}
pub fn flush(
@@ -221,14 +252,6 @@ pub fn flush(
tid: Zcu.PerThread.Id,
prog_node: std.Progress.Node,
) link.Error!void {
- // The goal is to never use this because it's only needed if we need to
- // write to InternPool, but flush is too late to be writing to the
- // InternPool.
- _ = tid;
-
- const tracy = trace(@src());
- defer tracy.end();
-
const sub_prog_node = prog_node.start("Flush Module", 0);
defer sub_prog_node.end();
@@ -237,19 +260,519 @@ pub fn flush(
const gpa = comp.gpa;
const io = comp.io;
- // We need to export the list of error names somewhere so that we can pretty-print them in the
- // executor. This is not really an important thing though, so we can just dump it in any old
- // nonsemantic instruction. For now, just put it in OpSourceExtension with a special name.
- var error_info: std.Io.Writer.Allocating = .init(linker.module.gpa);
+ if (comp.zcu) |zcu| {
+ const active = zcu.activate(tid);
+ defer active.deactivate();
+ const pt = active.pt;
+ for (linker.pending_navs.items) |nav| {
+ if (linker.fragments.contains(nav)) continue;
+
+ const mir = CodeGen.generateNav(pt, nav) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.AlreadyReported => continue,
+ error.Canceled => return error.Canceled,
+ };
+
+ linker.fragments.put(gpa, nav, mir) catch return error.OutOfMemory;
+ }
+ linker.pending_navs.clearRetainingCapacity();
+ }
+
+ const merged = mergeFragments(linker, gpa, arena) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ };
+
+ var binary = linkModule(arena, merged.words, merged.id_bound, sub_prog_node) catch |err| switch (err) {
+ error.OutOfMemory => |e| return e,
+ else => |other| {
+ return diags.fail("error while linking: {s}", .{@errorName(other)});
+ },
+ };
+ defer binary.deinit(arena);
+
+ const header = [_]Word{
+ spec.magic_number,
+ merged.version.toWord(),
+ merged.generator_id,
+ binary.id_bound,
+ 0,
+ };
+
+ var file_writer = linker.base.file.?.writer(io, &.{});
+ file_writer.interface.writeSliceEndian(Word, &header, .little) catch |err| switch (err) {
+ error.WriteFailed => return diags.fail("failed to write: {t}", .{file_writer.err.?}),
+ };
+ file_writer.interface.writeSliceEndian(Word, binary.instructions, .little) catch |err| switch (err) {
+ error.WriteFailed => return diags.fail("failed to write: {t}", .{file_writer.err.?}),
+ };
+ file_writer.end() catch |err| switch (err) {
+ error.WriteFailed => return diags.fail("failed to write: {t}", .{file_writer.err.?}),
+ else => |e| return diags.fail("failed to write: {t}", .{e}),
+ };
+}
+
+fn linkModule(arena: Allocator, words: []const Word, id_bound: u32, progress: std.Progress.Node) !BinaryModule {
+ var parser = try BinaryModule.Parser.init(arena);
+ defer parser.deinit();
+ var binary = try parser.initFromWords(words, id_bound);
+ try prune_unused.run(&parser, &binary);
+ try dedup_types.run(&parser, &binary);
+ try lower_invocation_globals.run(&parser, &binary, progress);
+ return binary;
+}
+
+fn mergeFragments(linker: *Linker, gpa: Allocator, arena: Allocator) error{OutOfMemory}!MergedModule {
+ const comp = linker.base.comp;
+ const target = &comp.root_mod.resolved_target.result;
+ const maybe_ip: ?*InternPool = if (comp.zcu) |zcu| &zcu.intern_pool else null;
+ const is_obj = comp.config.output_mode == .Obj;
+
+ var next_id: Word = 1;
+
+ var nav_final_ids: std.AutoHashMapUnmanaged(InternPool.Nav.Index, Id) = .empty;
+ defer nav_final_ids.deinit(gpa);
+
+ var uav_final_ids: std.AutoHashMapUnmanaged(struct { InternPool.Index, spec.StorageClass }, Id) = .empty;
+ defer uav_final_ids.deinit(gpa);
+
+ var frag_infos: std.ArrayList(FragmentInfo) = .empty;
+ defer frag_infos.deinit(gpa);
+ try frag_infos.ensureTotalCapacity(gpa, @intCast(linker.fragments.count()));
+
+ for (linker.fragments.keys(), linker.fragments.values()) |nav, *mir| {
+ const id_offset = next_id - 1;
+ frag_infos.appendAssumeCapacity(.{ .id_offset = id_offset });
+ if (mir.decl_result_id != .none) {
+ try nav_final_ids.put(gpa, nav, @enumFromInt(@intFromEnum(mir.decl_result_id) + id_offset));
+ }
+ next_id += mir.id_bound - 1;
+ }
+
+ for (linker.fragments.values(), frag_infos.items) |*mir, frag_info| {
+ for (mir.nav_refs) |ref| {
+ if (!nav_final_ids.contains(ref.nav)) {
+ try nav_final_ids.put(gpa, ref.nav, @enumFromInt(@intFromEnum(ref.local_id) + frag_info.id_offset));
+ }
+ }
+ for (mir.uav_refs) |ref| {
+ const key = .{ ref.val, ref.storage_class };
+ if (!uav_final_ids.contains(key)) {
+ try uav_final_ids.put(gpa, key, @enumFromInt(@intFromEnum(ref.local_id) + frag_info.id_offset));
+ }
+ }
+ }
+
+ // Resolve Zig extern navs against external objects.
+ var ext_id_offsets: std.ArrayListUnmanaged(Word) = .empty;
+ defer ext_id_offsets.deinit(gpa);
+ try ext_id_offsets.ensureTotalCapacity(gpa, linker.external_objects.items.len);
+
+ var unresolved_extern_count: u32 = 0;
+ var resolved_ids: std.AutoArrayHashMapUnmanaged(Id, void) = .empty;
+ defer resolved_ids.deinit(gpa);
+
+ if (maybe_ip) |ip| {
+ var extern_name_map: std.StringArrayHashMapUnmanaged(InternPool.Nav.Index) = .empty;
+ defer extern_name_map.deinit(gpa);
+
+ var nav_it = nav_final_ids.iterator();
+ while (nav_it.next()) |entry| {
+ const nav = ip.getNav(entry.key_ptr.*);
+ if (!nav.resolved.?.is_extern_decl) continue;
+ const name = if (nav.getExtern(ip)) |e| e.name.toSlice(ip) else nav.fqn.toSlice(ip);
+ try extern_name_map.put(gpa, name, entry.key_ptr.*);
+ }
+
+ for (linker.external_objects.items) |ext_obj| {
+ const id_offset = next_id - 1;
+ ext_id_offsets.appendAssumeCapacity(id_offset);
+
+ var it: BinaryModule.Instruction.Iterator = .init(ext_obj.instructions, 0);
+ while (it.next()) |inst| {
+ const ld = LinkageDecoration.parse(inst) orelse continue;
+ if (ld.linkage_type != .@"export") continue;
+ const remapped_id: Id = @enumFromInt(@intFromEnum(ld.target_id) + id_offset);
+
+ if (extern_name_map.get(ld.name)) |nav_index| {
+ log.debug("extern resolve: '{s}' -> ext_fn_id={d}", .{ ld.name, @intFromEnum(remapped_id) });
+ nav_final_ids.getPtr(nav_index).?.* = remapped_id;
+ _ = extern_name_map.swapRemove(ld.name);
+ try resolved_ids.put(gpa, remapped_id, {});
+ }
+ }
+ next_id += ext_obj.id_bound - 1;
+ }
+
+ unresolved_extern_count = @intCast(extern_name_map.count());
+ } else {
+ for (linker.external_objects.items) |ext_obj| {
+ ext_id_offsets.appendAssumeCapacity(next_id - 1);
+ next_id += ext_obj.id_bound - 1;
+ }
+ }
+
+ var parser = BinaryModule.Parser.init(gpa) catch return error.OutOfMemory;
+ defer parser.deinit();
+ var sections: Sections = .{};
+ defer sections.deinit(gpa);
+
+ try mergeZigFragments(linker, gpa, &parser, §ions, frag_infos.items, &nav_final_ids, &uav_final_ids, &resolved_ids, maybe_ip);
+
+ var has_linkage = false;
+ try appendExternalObjects(linker, gpa, &parser, ext_id_offsets.items, §ions, &has_linkage, linker.fragments.count() == 0, is_obj, &resolved_ids);
+
+ if (is_obj) {
+ for (linker.entry_points.items) |ep| {
+ if (ep.cc != .spirv_device) continue;
+ const final_id = nav_final_ids.get(ep.nav) orelse continue;
+ try sections.annotations.emit(gpa, .OpDecorate, .{
+ .target = final_id,
+ .decoration = .{ .linkage_attributes = .{ .name = ep.name, .linkage_type = .@"export" } },
+ });
+ has_linkage = true;
+ }
+ if (unresolved_extern_count > 0) has_linkage = true;
+ }
+
+ var capabilities_section = Section{};
+ defer capabilities_section.deinit(gpa);
+ var extensions_section = Section{};
+ defer extensions_section.deinit(gpa);
+ var memory_model_section = Section{};
+ defer memory_model_section.deinit(gpa);
+
+ try emitPreamble(
+ gpa,
+ target,
+ has_linkage,
+ &capabilities_section,
+ &extensions_section,
+ &memory_model_section,
+ );
+ try emitEntryPoints(
+ linker,
+ gpa,
+ target,
+ §ions.entry_points,
+ §ions.execution_modes,
+ &nav_final_ids,
+ &uav_final_ids,
+ &frag_infos,
+ );
+
+ const zig_packed_version = (zig_version.major << 12) | (zig_version.minor << 7) | zig_version.patch;
+ if (maybe_ip) |ip| {
+ try emitSourceInfo(gpa, ip, zig_packed_version, §ions.debug_strings);
+ }
+
+ const version: spec.Version = .{
+ .major = 1,
+ .minor = blk: {
+ if (target.cpu.has(.spirv, .v1_6)) break :blk 6;
+ if (target.cpu.has(.spirv, .v1_5)) break :blk 5;
+ if (target.cpu.has(.spirv, .v1_4)) break :blk 4;
+ if (target.cpu.has(.spirv, .v1_3)) break :blk 3;
+ if (target.cpu.has(.spirv, .v1_2)) break :blk 2;
+ if (target.cpu.has(.spirv, .v1_1)) break :blk 1;
+ break :blk 0;
+ },
+ };
+
+ const buffers = &[_][]const Word{
+ capabilities_section.toWords(),
+ extensions_section.toWords(),
+ sections.ext_inst.toWords(),
+ memory_model_section.toWords(),
+ sections.entry_points.toWords(),
+ sections.execution_modes.toWords(),
+ sections.debug_strings.toWords(),
+ sections.debug_names.toWords(),
+ sections.annotations.toWords(),
+ sections.globals.toWords(),
+ sections.functions.toWords(),
+ };
+
+ var total_size: usize = 0;
+ for (buffers) |buffer| total_size += buffer.len;
+ const result = try arena.alloc(Word, total_size);
+
+ var offset: usize = 0;
+ for (buffers) |buffer| {
+ @memcpy(result[offset..][0..buffer.len], buffer);
+ offset += buffer.len;
+ }
+
+ return .{
+ .words = result,
+ .id_bound = next_id,
+ .version = version,
+ .generator_id = (spec.zig_generator_id << 16) | zig_packed_version,
+ };
+}
+
+fn mergeZigFragments(
+ linker: *Linker,
+ gpa: Allocator,
+ parser: *BinaryModule.Parser,
+ sections: *Sections,
+ frag_infos: []const FragmentInfo,
+ nav_final_ids: *const std.AutoHashMapUnmanaged(InternPool.Nav.Index, Id),
+ uav_final_ids: *const std.AutoHashMapUnmanaged(struct { InternPool.Index, spec.StorageClass }, Id),
+ resolved_ids: *const std.AutoArrayHashMapUnmanaged(Id, void),
+ maybe_ip: ?*InternPool,
+) error{OutOfMemory}!void {
+ for (linker.fragments.values(), frag_infos) |*mir, frag_info| {
+ var id_remap: std.AutoHashMapUnmanaged(Id, Id) = .empty;
+ defer id_remap.deinit(gpa);
+
+ var resolved_local_ids: std.AutoArrayHashMapUnmanaged(Id, void) = .empty;
+ defer resolved_local_ids.deinit(gpa);
+
+ for (mir.nav_refs) |ref| {
+ if (nav_final_ids.get(ref.nav)) |final_id| {
+ try id_remap.put(gpa, ref.local_id, final_id);
+ if (maybe_ip) |ip| {
+ const nav = ip.getNav(ref.nav);
+ if (nav.resolved.?.is_extern_decl and resolved_ids.contains(final_id)) {
+ try resolved_local_ids.put(gpa, ref.local_id, {});
+ }
+ }
+ }
+ }
+ for (mir.uav_refs) |ref| {
+ if (uav_final_ids.get(.{ ref.val, ref.storage_class })) |final_id| {
+ try id_remap.put(gpa, ref.local_id, final_id);
+ }
+ }
+
+ try remapAndAppend(gpa, §ions.ext_inst, mir.extended_instruction_set, frag_info.id_offset, &id_remap, parser);
+ try remapAndAppend(gpa, §ions.globals, mir.globals, frag_info.id_offset, &id_remap, parser);
+
+ try remapFilteredInsts(gpa, §ions.functions, mir.functions, frag_info.id_offset, &id_remap, parser, &resolved_local_ids, .skip_functions);
+ try remapFilteredInsts(gpa, §ions.annotations, mir.annotations, frag_info.id_offset, &id_remap, parser, &resolved_local_ids, .skip_linkage);
+ try remapFilteredInsts(gpa, §ions.debug_names, mir.debug_names, frag_info.id_offset, &id_remap, parser, &resolved_local_ids, .skip_names);
+ try remapAndAppend(gpa, §ions.debug_strings, mir.debug_strings, frag_info.id_offset, &id_remap, parser);
+ try remapAndAppend(gpa, §ions.execution_modes, mir.execution_modes, frag_info.id_offset, &id_remap, parser);
+
+ for (mir.entry_points) |ep| {
+ try linker.entry_points.append(gpa, .{ .nav = mir.owner_nav, .name = ep.name, .cc = ep.cc });
+ }
+ }
+}
+
+const FilterMode = enum { skip_functions, skip_linkage, skip_names };
+
+fn remapFilteredInsts(
+ gpa: Allocator,
+ dest: *Section,
+ words: []const Word,
+ id_offset: Word,
+ id_remap: *const std.AutoHashMapUnmanaged(Id, Id),
+ parser: *BinaryModule.Parser,
+ skip_ids: *const std.AutoArrayHashMapUnmanaged(Id, void),
+ mode: FilterMode,
+) error{OutOfMemory}!void {
+ if (words.len == 0) return;
+ var it: BinaryModule.Instruction.Iterator = .init(words, 0);
+ var skip_function = false;
+ while (it.next()) |inst| {
+ switch (mode) {
+ .skip_functions => {
+ if (inst.opcode == .OpFunction) {
+ skip_function = skip_ids.contains(@enumFromInt(inst.operands[1]));
+ }
+ if (skip_function) {
+ if (inst.opcode == .OpFunctionEnd) skip_function = false;
+ continue;
+ }
+ },
+ .skip_linkage => {
+ if (LinkageDecoration.parse(inst)) |ld| {
+ if (skip_ids.contains(ld.target_id)) continue;
+ }
+ },
+ .skip_names => {
+ if (inst.opcode == .OpName and inst.operands.len >= 1) {
+ if (skip_ids.contains(@enumFromInt(inst.operands[0]))) continue;
+ }
+ },
+ }
+ try remapAndAppendInst(gpa, dest, words, inst, id_offset, id_remap, parser);
+ }
+}
+
+fn emitPreamble(
+ gpa: Allocator,
+ target: *const std.Target,
+ has_linkage: bool,
+ capabilities: *Section,
+ extensions: *Section,
+ memory_model: *Section,
+) !void {
+ var caps: std.EnumSet(spec.Capability) = .empty;
+ var exts: std.StringHashMapUnmanaged(void) = .empty;
+ defer exts.deinit(gpa);
+
+ switch (target.os.tag) {
+ .opengl, .vulkan => caps.insert(.shader),
+ .opencl, .amdhsa => {
+ caps.insert(.kernel);
+ caps.insert(.addresses);
+ },
+ else => unreachable,
+ }
+ if (target.os.tag == .vulkan and target.cpu.arch == .spirv64) {
+ caps.insert(.physical_storage_buffer_addresses);
+ try exts.put(gpa, "SPV_KHR_physical_storage_buffer", {});
+ }
+ if (has_linkage) caps.insert(.linkage);
+
+ inline for (@typeInfo(spec.Capability).@"enum".field_names) |cap_name| {
+ if (target.cpu.has(.spirv, @field(std.Target.spirv.Feature, cap_name)))
+ caps.insert(@field(spec.Capability, cap_name));
+ }
+ inline for (@typeInfo(spec.Extension).@"enum".field_names) |ext_name| {
+ switch (@field(spec.Extension, ext_name)) {
+ .v1_0, .v1_1, .v1_2, .v1_3, .v1_4, .v1_5, .v1_6 => {},
+ else => if (target.cpu.has(.spirv, @field(std.Target.spirv.Feature, ext_name)))
+ try exts.put(gpa, ext_name, {}),
+ }
+ }
+
+ var cit = caps.iterator();
+ while (cit.next()) |cap| try capabilities.emit(gpa, .OpCapability, .{ .capability = cap });
+ var eit = exts.iterator();
+ while (eit.next()) |e| try extensions.emit(gpa, .OpExtension, .{ .name = e.key_ptr.* });
+
+ const addressing_model: spec.AddressingModel = switch (target.os.tag) {
+ .opengl => .logical,
+ .vulkan => switch (target.cpu.arch) {
+ .spirv32 => .logical,
+ .spirv64 => .physical_storage_buffer64,
+ else => unreachable,
+ },
+ .opencl => switch (target.cpu.arch) {
+ .spirv32 => .physical32,
+ .spirv64 => .physical64,
+ else => unreachable,
+ },
+ .amdhsa => .physical64,
+ else => unreachable,
+ };
+ try memory_model.emit(gpa, .OpMemoryModel, .{
+ .addressing_model = addressing_model,
+ .memory_model = switch (target.os.tag) {
+ .opencl => .open_cl,
+ .vulkan, .opengl => .glsl450,
+ .amdhsa => unreachable, // TODO
+ else => unreachable,
+ },
+ });
+}
+
+fn emitEntryPoints(
+ linker: *Linker,
+ gpa: Allocator,
+ target: *const std.Target,
+ entry_points_section: *Section,
+ execution_modes_section: *Section,
+ nav_final_ids: *const std.AutoHashMapUnmanaged(InternPool.Nav.Index, Id),
+ uav_final_ids: *const std.AutoHashMapUnmanaged(struct { InternPool.Index, spec.StorageClass }, Id),
+ frag_infos: *const std.ArrayList(FragmentInfo),
+) error{OutOfMemory}!void {
+ for (linker.entry_points.items) |ep| {
+ const final_id = nav_final_ids.get(ep.nav) orelse continue;
+
+ var interface: std.ArrayList(Id) = .empty;
+ defer interface.deinit(gpa);
+ var visited: std.AutoHashMapUnmanaged(InternPool.Nav.Index, void) = .empty;
+ defer visited.deinit(gpa);
+ try collectEntryPointInterface(linker, ep.nav, &interface, &visited, nav_final_ids, uav_final_ids, frag_infos, gpa);
+
+ const exec_model: spec.ExecutionModel = switch (target.os.tag) {
+ .vulkan, .opengl => switch (ep.cc) {
+ .spirv_vertex => .vertex,
+ .spirv_fragment => .fragment,
+ .spirv_kernel => .gl_compute,
+ .spirv_task => .task_ext,
+ .spirv_mesh => .mesh_ext,
+ .spirv_device => continue,
+ else => unreachable,
+ },
+ .opencl => switch (ep.cc) {
+ .spirv_kernel => .kernel,
+ .spirv_device => continue,
+ else => unreachable,
+ },
+ else => unreachable,
+ };
+
+ try entry_points_section.emit(gpa, .OpEntryPoint, .{
+ .execution_model = exec_model,
+ .entry_point = final_id,
+ .name = ep.name,
+ .interface = interface.items,
+ });
+
+ switch (ep.cc) {
+ .spirv_kernel, .spirv_task => |kernel| {
+ try execution_modes_section.emit(gpa, .OpExecutionMode, .{
+ .entry_point = final_id,
+ .mode = .{ .local_size = .{ .x_size = kernel.x, .y_size = kernel.y, .z_size = kernel.z } },
+ });
+ },
+ .spirv_fragment => |fragment| {
+ try execution_modes_section.emit(gpa, .OpExecutionMode, .{
+ .entry_point = final_id,
+ .mode = if (target.os.tag == .vulkan) .origin_upper_left else .origin_lower_left,
+ });
+ if (fragment.pixel_centered_integer) {
+ try execution_modes_section.emit(gpa, .OpExecutionMode, .{
+ .entry_point = final_id,
+ .mode = .pixel_center_integer,
+ });
+ }
+ const exec_mode: ?spec.ExecutionMode.Extended = switch (fragment.depth_assumption) {
+ .none => null,
+ .greater => .depth_greater,
+ .less => .depth_less,
+ .unchanged => .depth_unchanged,
+ };
+ if (exec_mode) |mode| {
+ try execution_modes_section.emit(gpa, .OpExecutionMode, .{
+ .entry_point = final_id,
+ .mode = mode,
+ });
+ }
+ },
+ .spirv_mesh => |mesh| {
+ try execution_modes_section.emit(gpa, .OpExecutionMode, .{
+ .entry_point = final_id,
+ .mode = .{ .output_vertices = .{ .vertex_count = mesh.max_vertices } },
+ });
+ try execution_modes_section.emit(gpa, .OpExecutionMode, .{
+ .entry_point = final_id,
+ .mode = .{ .output_primitives_ext = .{ .primitive_count = mesh.max_primitives } },
+ });
+ try execution_modes_section.emit(gpa, .OpExecutionMode, .{
+ .entry_point = final_id,
+ .mode = switch (mesh.stage_output) {
+ .output_points => .output_points,
+ .output_lines => .output_lines_ext,
+ .output_triangles => .output_triangles_ext,
+ },
+ });
+ },
+ else => {},
+ }
+ }
+}
+
+fn emitSourceInfo(gpa: Allocator, ip: *InternPool, version: u32, debug_strings: *Section) error{OutOfMemory}!void {
+ var error_info: std.Io.Writer.Allocating = .init(gpa);
defer error_info.deinit();
-
error_info.writer.writeAll("zig_errors:") catch return error.OutOfMemory;
- const ip = &linker.base.comp.zcu.?.intern_pool;
for (ip.global_error_set.getNamesFromMainThread()) |name| {
- // Errors can contain pretty much any character - to encode them in a string we must escape
- // them somehow. Easiest here is to use some established scheme, one which also preseves the
- // name if it contains no strange characters is nice for debugging. URI encoding fits the bill.
- // We're using : as separator, which is a reserved character.
error_info.writer.writeByte(':') catch return error.OutOfMemory;
std.Uri.Component.percentEncode(
&error_info.writer,
@@ -264,27 +787,423 @@ pub fn flush(
}.isValidChar,
) catch return error.OutOfMemory;
}
- try linker.module.sections.debug_strings.emit(gpa, .OpSourceExtension, .{
- .extension = error_info.written(),
- });
+ try debug_strings.emit(gpa, .OpSourceExtension, .{ .extension = error_info.written() });
+ try debug_strings.emit(gpa, .OpSource, .{ .source_language = .zig, .version = version, .file = null, .source = null });
+}
- const module = try linker.module.finalize(arena);
- errdefer arena.free(module);
+const MergedModule = struct {
+ words: []const Word,
+ id_bound: Word,
+ version: spec.Version,
+ generator_id: u32,
+};
- const linked_module = linkModule(arena, module, sub_prog_node) catch |err| switch (err) {
- error.OutOfMemory => |e| return e,
- else => |other| return diags.fail("error while linking: {s}", .{@errorName(other)}),
+const FragmentInfo = struct {
+ id_offset: Word,
+};
+
+const LinkageDecoration = struct {
+ target_id: Id,
+ name: []const u8,
+ linkage_type: spec.LinkageType,
+
+ fn parse(inst: BinaryModule.Instruction) ?LinkageDecoration {
+ if (inst.opcode != .OpDecorate) return null;
+ if (inst.operands.len < 3) return null;
+ if (inst.operands[1] != @intFromEnum(spec.Decoration.linkage_attributes)) return null;
+ return .{
+ .target_id = @enumFromInt(inst.operands[0]),
+ .name = std.mem.sliceTo(std.mem.sliceAsBytes(inst.operands[2 .. inst.operands.len - 1]), 0),
+ .linkage_type = @enumFromInt(inst.operands[inst.operands.len - 1]),
+ };
+ }
+};
+
+const Sections = struct {
+ ext_inst: Section = .{},
+ globals: Section = .{},
+ functions: Section = .{},
+ annotations: Section = .{},
+ debug_names: Section = .{},
+ debug_strings: Section = .{},
+ entry_points: Section = .{},
+ execution_modes: Section = .{},
+
+ fn deinit(self: *Sections, gpa: Allocator) void {
+ self.ext_inst.deinit(gpa);
+ self.globals.deinit(gpa);
+ self.functions.deinit(gpa);
+ self.annotations.deinit(gpa);
+ self.debug_names.deinit(gpa);
+ self.debug_strings.deinit(gpa);
+ self.entry_points.deinit(gpa);
+ self.execution_modes.deinit(gpa);
+ }
+
+ const SectionClass = enum { ext_inst, debug_name, debug_string, annotation, global };
+
+ fn classifyPreambleInst(opcode: spec.Opcode) SectionClass {
+ return switch (opcode) {
+ .OpExtInstImport => .ext_inst,
+ .OpName, .OpMemberName => .debug_name,
+ .OpString => .debug_string,
+ .OpDecorate,
+ .OpMemberDecorate,
+ .OpGroupDecorate,
+ .OpGroupMemberDecorate,
+ .OpDecorationGroup,
+ .OpDecorateId,
+ .OpDecorateString,
+ .OpMemberDecorateString,
+ => .annotation,
+ else => .global,
+ };
+ }
+
+ fn getSection(self: *Sections, class: SectionClass) *Section {
+ return switch (class) {
+ .ext_inst => &self.ext_inst,
+ .debug_name => &self.debug_names,
+ .debug_string => &self.debug_strings,
+ .annotation => &self.annotations,
+ .global => &self.globals,
+ };
+ }
+};
+
+fn appendExternalObjects(
+ linker: *Linker,
+ gpa: Allocator,
+ parser: *BinaryModule.Parser,
+ ext_id_offsets: []const Word,
+ sections: *Sections,
+ has_linkage: *bool,
+ keep_entry_points: bool,
+ is_obj: bool,
+ resolved_ids: *const std.AutoArrayHashMapUnmanaged(Id, void),
+) error{OutOfMemory}!void {
+ var export_map: std.StringArrayHashMapUnmanaged(Id) = .empty;
+ defer export_map.deinit(gpa);
+
+ for (linker.external_objects.items, ext_id_offsets) |ext_obj, id_offset| {
+ var it: BinaryModule.Instruction.Iterator = .init(ext_obj.instructions, 0);
+ while (it.next()) |inst| {
+ const ld = LinkageDecoration.parse(inst) orelse continue;
+ if (ld.linkage_type != .@"export") continue;
+ try export_map.put(gpa, ld.name, @enumFromInt(@intFromEnum(ld.target_id) + id_offset));
+ }
+ }
+
+ var per_obj_remaps = try gpa.alloc(std.AutoHashMapUnmanaged(Id, Id), linker.external_objects.items.len);
+ defer {
+ for (per_obj_remaps) |*m| m.deinit(gpa);
+ gpa.free(per_obj_remaps);
+ }
+ for (per_obj_remaps) |*m| m.* = .empty;
+
+ var resolved_linkage_ids: std.AutoArrayHashMapUnmanaged(Id, void) = .empty;
+ defer resolved_linkage_ids.deinit(gpa);
+
+ for (resolved_ids.keys()) |id| {
+ try resolved_linkage_ids.put(gpa, id, {});
+ }
+
+ for (linker.external_objects.items, ext_id_offsets, 0..) |ext_obj, id_offset, obj_idx| {
+ var it: BinaryModule.Instruction.Iterator = .init(ext_obj.instructions, 0);
+ while (it.next()) |inst| {
+ const ld = LinkageDecoration.parse(inst) orelse continue;
+ if (ld.linkage_type != .import) continue;
+ const remapped_import: Id = @enumFromInt(@intFromEnum(ld.target_id) + id_offset);
+
+ if (export_map.get(ld.name)) |export_id| {
+ try per_obj_remaps[obj_idx].put(gpa, ld.target_id, export_id);
+ try resolved_linkage_ids.put(gpa, remapped_import, {});
+ try resolved_linkage_ids.put(gpa, export_id, {});
+ log.debug("cross-object resolve: '{s}' import={d} -> export={d}", .{
+ ld.name, @intFromEnum(remapped_import), @intFromEnum(export_id),
+ });
+ } else {
+ has_linkage.* = true;
+ }
+ }
+ }
+
+ for (linker.external_objects.items, ext_id_offsets, 0..) |ext_obj, id_offset, obj_idx| {
+ var binary = parser.initFromWords(ext_obj.instructions, ext_obj.id_bound) catch
+ return error.OutOfMemory;
+ defer binary.deinit(gpa);
+
+ const id_remap = &per_obj_remaps[obj_idx];
+
+ var preamble_it: BinaryModule.Instruction.Iterator = .init(ext_obj.instructions, 0);
+ while (preamble_it.next()) |inst| {
+ if (inst.offset >= binary.functions_start) break;
+
+ switch (inst.opcode) {
+ .OpCapability,
+ .OpExtension,
+ .OpMemoryModel,
+ .OpSource,
+ .OpSourceExtension,
+ .OpSourceContinued,
+ => continue,
+ .OpEntryPoint => {
+ if (keep_entry_points)
+ try remapAndAppendInst(gpa, §ions.entry_points, ext_obj.instructions, inst, id_offset, id_remap, parser);
+ continue;
+ },
+ .OpExecutionMode, .OpExecutionModeId => {
+ if (keep_entry_points)
+ try remapAndAppendInst(gpa, §ions.execution_modes, ext_obj.instructions, inst, id_offset, id_remap, parser);
+ continue;
+ },
+ else => {},
+ }
+
+ if (LinkageDecoration.parse(inst)) |ld| {
+ const remapped: Id = @enumFromInt(@intFromEnum(ld.target_id) + id_offset);
+ if (resolved_linkage_ids.contains(remapped)) {
+ if (ld.linkage_type == .@"export" and is_obj) {
+ has_linkage.* = true;
+ } else {
+ continue;
+ }
+ }
+ }
+
+ if (inst.opcode == .OpName and inst.operands.len >= 1) {
+ if (id_remap.contains(@enumFromInt(inst.operands[0]))) continue;
+ }
+
+ const dest = sections.getSection(Sections.classifyPreambleInst(inst.opcode));
+ try remapAndAppendInst(gpa, dest, ext_obj.instructions, inst, id_offset, id_remap, parser);
+ }
+
+ var fn_it: BinaryModule.Instruction.Iterator = .init(ext_obj.instructions, binary.functions_start);
+ var skip_function = false;
+ while (fn_it.next()) |inst| {
+ if (inst.opcode == .OpFunction) {
+ skip_function = id_remap.contains(@enumFromInt(inst.operands[1]));
+ }
+ if (!skip_function) {
+ try remapAndAppendInst(gpa, §ions.functions, ext_obj.instructions, inst, id_offset, id_remap, parser);
+ }
+ if (inst.opcode == .OpFunctionEnd) {
+ skip_function = false;
+ }
+ }
+ }
+}
+
+fn collectEntryPointInterface(
+ linker: *Linker,
+ nav: InternPool.Nav.Index,
+ interface: *std.ArrayList(Id),
+ visited: *std.AutoHashMapUnmanaged(InternPool.Nav.Index, void),
+ nav_final_ids: *const std.AutoHashMapUnmanaged(InternPool.Nav.Index, Id),
+ uav_final_ids: *const std.AutoHashMapUnmanaged(struct { InternPool.Index, spec.StorageClass }, Id),
+ frag_infos: *const std.ArrayList(FragmentInfo),
+ gpa: Allocator,
+) error{OutOfMemory}!void {
+ const visited_gop = try visited.getOrPut(gpa, nav);
+ if (visited_gop.found_existing) return;
+
+ const frag_index = linker.fragments.getIndex(nav) orelse return;
+ const mir = &linker.fragments.values()[frag_index];
+ const id_offset = frag_infos.items[frag_index].id_offset;
+
+ if (mir.kind == .global) {
+ if (nav_final_ids.get(nav)) |final_id| {
+ try interface.append(gpa, final_id);
+ }
+ }
+
+ for (mir.uav_refs) |ref| {
+ if (ref.kind == .global) {
+ if (uav_final_ids.get(.{ ref.val, ref.storage_class })) |final_id| {
+ try interface.append(gpa, final_id);
+ }
+ }
+ }
+
+ for (mir.internal_globals) |local_id| {
+ const global_id: Id = @enumFromInt(@intFromEnum(local_id) + id_offset);
+ try interface.append(gpa, global_id);
+ }
+
+ for (mir.decl_deps) |dep| {
+ try collectEntryPointInterface(linker, dep.nav, interface, visited, nav_final_ids, uav_final_ids, frag_infos, gpa);
+ }
+}
+
+fn remapAndAppend(
+ gpa: Allocator,
+ dest: *Section,
+ words: []const Word,
+ id_offset: Word,
+ id_remap: *const std.AutoHashMapUnmanaged(Id, Id),
+ parser: *BinaryModule.Parser,
+) error{OutOfMemory}!void {
+ if (words.len == 0) return;
+
+ try dest.instructions.ensureUnusedCapacity(gpa, words.len);
+
+ var it: BinaryModule.Instruction.Iterator = .init(words, 0);
+ while (it.next()) |inst| {
+ try remapAndAppendInst(gpa, dest, words, inst, id_offset, id_remap, parser);
+ }
+}
+
+fn remapAndAppendInst(
+ gpa: Allocator,
+ dest: *Section,
+ words: []const Word,
+ inst: BinaryModule.Instruction,
+ id_offset: Word,
+ id_remap: *const std.AutoHashMapUnmanaged(Id, Id),
+ parser: *BinaryModule.Parser,
+) error{OutOfMemory}!void {
+ const inst_words = words[inst.offset..][0..((words[inst.offset] >> 16))];
+ try dest.instructions.ensureUnusedCapacity(gpa, inst_words.len);
+ const dest_start = dest.instructions.items.len;
+ dest.instructions.appendSliceAssumeCapacity(inst_words);
+ const inst_slice = dest.instructions.items[dest_start..][0..inst_words.len];
+
+ const inst_spec = parser.getInstSpec(inst.opcode) orelse return;
+ var offset: usize = 0;
+ for (inst_spec.operands) |operand| {
+ const cat = operand.kind.category();
+ switch (operand.quantifier) {
+ .required, .optional => {
+ if (offset >= inst.operands.len) break;
+ offset += remapOperand(operand.kind, cat, inst, inst_slice, offset, id_offset, id_remap);
+ },
+ .variadic => {
+ while (offset < inst.operands.len) {
+ offset += remapOperand(operand.kind, cat, inst, inst_slice, offset, id_offset, id_remap);
+ }
+ },
+ }
+ }
+}
+
+fn remapOperand(
+ kind: spec.OperandKind,
+ cat: spec.OperandCategory,
+ inst: BinaryModule.Instruction,
+ inst_slice: []Word,
+ offset: usize,
+ id_offset: Word,
+ id_remap: *const std.AutoHashMapUnmanaged(Id, Id),
+) usize {
+ switch (cat) {
+ .id => {
+ remapSingleId(&inst_slice[1 + offset], id_offset, id_remap);
+ return 1;
+ },
+ .literal => return operandLiteralWordCount(kind, inst, offset),
+ .composite => {
+ remapCompositeOperand(kind, inst_slice, offset, id_offset, id_remap);
+ return 2;
+ },
+ .bit_enum => {
+ const mask = inst_slice[1 + offset];
+ var consumed: usize = 1;
+ for (kind.enumerants()) |e| {
+ if ((mask & e.value) == 0) continue;
+ for (e.parameters) |param_kind| {
+ if (offset + consumed >= inst.operands.len) return consumed;
+ consumed += remapOperand(
+ param_kind,
+ param_kind.category(),
+ inst,
+ inst_slice,
+ offset + consumed,
+ id_offset,
+ id_remap,
+ );
+ }
+ }
+ return consumed;
+ },
+ .value_enum => {
+ const value = inst_slice[1 + offset];
+ var consumed: usize = 1;
+ for (kind.enumerants()) |e| {
+ if (e.value != value) continue;
+ for (e.parameters) |param_kind| {
+ if (offset + consumed >= inst.operands.len) return consumed;
+ consumed += remapOperand(
+ param_kind,
+ param_kind.category(),
+ inst,
+ inst_slice,
+ offset + consumed,
+ id_offset,
+ id_remap,
+ );
+ }
+ break;
+ }
+ return consumed;
+ },
+ }
+}
+
+fn remapCompositeOperand(
+ kind: spec.OperandKind,
+ inst_slice: []Word,
+ offset: usize,
+ id_offset: Word,
+ id_remap: *const std.AutoHashMapUnmanaged(Id, Id),
+) void {
+ switch (kind) {
+ .pair_literal_integer_id_ref => {
+ remapSingleId(&inst_slice[1 + offset + 1], id_offset, id_remap);
+ },
+ .pair_id_ref_literal_integer => {
+ remapSingleId(&inst_slice[1 + offset], id_offset, id_remap);
+ },
+ .pair_id_ref_id_ref => {
+ remapSingleId(&inst_slice[1 + offset], id_offset, id_remap);
+ remapSingleId(&inst_slice[1 + offset + 1], id_offset, id_remap);
+ },
+ else => {},
+ }
+}
+
+fn operandLiteralWordCount(kind: spec.OperandKind, inst: BinaryModule.Instruction, offset: usize) usize {
+ return switch (kind) {
+ .literal_integer, .literal_float => 1,
+ .literal_string => blk: {
+ var count: usize = 0;
+ var off = offset;
+ while (off < inst.operands.len) {
+ const word = inst.operands[off];
+ count += 1;
+ off += 1;
+ if (word & 0xFF000000 == 0 or
+ word & 0x00FF0000 == 0 or
+ word & 0x0000FF00 == 0 or
+ word & 0x000000FF == 0)
+ {
+ break;
+ }
+ }
+ break :blk count;
+ },
+ .literal_context_dependent_number => inst.operands.len - offset,
+ .literal_ext_inst_integer => 1,
+ else => 1,
};
-
- // TODO endianness bug. use file writer and call writeSliceEndian instead
- linker.base.file.?.writeStreamingAll(io, @ptrCast(linked_module)) catch |err|
- return diags.fail("failed to write: {t}", .{err});
}
-fn linkModule(arena: Allocator, module: []Word, progress: std.Progress.Node) ![]Word {
- var parser = try BinaryModule.Parser.init(arena);
- defer parser.deinit();
- var binary = try parser.parse(module);
- try lower_invocation_globals.run(&parser, &binary, progress);
- return binary.finalize(arena);
+fn remapSingleId(word: *Word, id_offset: Word, id_remap: *const std.AutoHashMapUnmanaged(Id, Id)) void {
+ const id: Id = @enumFromInt(word.*);
+ if (id == .none) return;
+ if (id_remap.get(id)) |final_id| {
+ word.* = @intFromEnum(final_id);
+ } else {
+ word.* = @intFromEnum(id) + id_offset;
+ }
}
diff --git a/src/link/SpirV/BinaryModule.zig b/src/link/SpirV/BinaryModule.zig
index e639994f33b7df39e90814768983803cbb898d17..55604fc194d6e70df9fbd54eb417b6e55426eea5 100644
--- a/src/link/SpirV/BinaryModule.zig
+++ b/src/link/SpirV/BinaryModule.zig
@@ -11,278 +11,161 @@ const ResultId = spec.Id;
const BinaryModule = @This();
-pub const header_words = 5;
-
-/// The module SPIR-V version.
-version: spec.Version,
-
-/// The generator magic number.
-generator_magic: u32,
-
/// The result-id bound of this SPIR-V module.
id_bound: u32,
-/// The instructions of this module. This does not contain the header.
+/// The instructions of this module (no header).
instructions: []const Word,
/// Maps OpExtInstImport result-ids to their InstructionSet.
ext_inst_map: std.AutoHashMapUnmanaged(ResultId, InstructionSet),
-/// This map contains the width of arithmetic types (OpTypeInt and
-/// OpTypeFloat). We need this information to correctly parse the operands
-/// of Op(Spec)Constant and OpSwitch.
+/// Width of arithmetic types (OpTypeInt/OpTypeFloat). Needed to correctly
+/// parse operands of Op(Spec)Constant and OpSwitch.
arith_type_width: std.AutoHashMapUnmanaged(ResultId, u16),
-/// The starting offsets of some sections
-sections: struct {
- functions: usize,
-},
+functions_start: usize,
-pub fn deinit(self: *BinaryModule, a: Allocator) void {
- self.ext_inst_map.deinit(a);
- self.arith_type_width.deinit(a);
- self.* = undefined;
+pub fn deinit(bm: *BinaryModule, gpa: Allocator) void {
+ bm.ext_inst_map.deinit(gpa);
+ bm.arith_type_width.deinit(gpa);
+ bm.* = undefined;
}
-pub fn iterateInstructions(self: BinaryModule) Instruction.Iterator {
- return Instruction.Iterator.init(self.instructions, 0);
+pub fn iterateInstructions(bm: BinaryModule) Instruction.Iterator {
+ return Instruction.Iterator.init(bm.instructions, 0);
}
-pub fn iterateInstructionsFrom(self: BinaryModule, offset: usize) Instruction.Iterator {
- return Instruction.Iterator.init(self.instructions, offset);
+pub fn iterateInstructionsFrom(bm: BinaryModule, offset: usize) Instruction.Iterator {
+ return Instruction.Iterator.init(bm.instructions, offset);
}
-pub fn instructionAt(self: BinaryModule, offset: usize) Instruction {
- var it = self.iterateInstructionsFrom(offset);
- return it.next().?;
-}
-
-pub fn finalize(self: BinaryModule, a: Allocator) ![]Word {
- const result = try a.alloc(Word, 5 + self.instructions.len);
- errdefer a.free(result);
-
- result[0] = spec.magic_number;
- result[1] = @bitCast(self.version);
- result[2] = @bitCast(self.generator_magic);
- result[3] = self.id_bound;
- result[4] = 0; // Schema
-
- @memcpy(result[5..], self.instructions);
- return result;
-}
-
-/// Errors that can be raised when the module is not correct.
-/// Note that the parser doesn't validate SPIR-V modules by a
-/// long shot. It only yields errors that critically prevent
-/// further analysis of the module.
-pub const ParseError = error{
- /// Raised when the module doesn't start with the SPIR-V magic.
- /// This usually means that the module isn't actually SPIR-V.
- InvalidMagic,
- /// Raised when the module has an invalid "physical" format:
- /// For example when the header is incomplete, or an instruction
- /// has an illegal format.
- InvalidPhysicalFormat,
- /// OpExtInstImport was used with an unknown extension string.
- InvalidExtInstImport,
- /// The module had an instruction with an invalid (unknown) opcode.
- InvalidOpcode,
- /// An instruction's operands did not conform to the SPIR-V specification
- /// for that instruction.
- InvalidOperands,
- /// A result-id was declared more than once.
- DuplicateId,
- /// Some ID did not resolve.
- InvalidId,
- /// This opcode or instruction is not supported yet.
- UnsupportedOperation,
- /// Parser ran out of memory.
- OutOfMemory,
-};
-
pub const Instruction = struct {
pub const Iterator = struct {
words: []const Word,
- index: usize = 0,
offset: usize = 0,
pub fn init(words: []const Word, start_offset: usize) Iterator {
return .{ .words = words, .offset = start_offset };
}
- pub fn next(self: *Iterator) ?Instruction {
- if (self.offset >= self.words.len) return null;
+ pub fn next(it: *Iterator) ?Instruction {
+ if (it.offset >= it.words.len) return null;
- const instruction_len = self.words[self.offset] >> 16;
- defer self.offset += instruction_len;
- defer self.index += 1;
+ const instruction_len = it.words[it.offset] >> 16;
+ defer it.offset += instruction_len;
assert(instruction_len != 0);
- assert(self.offset < self.words.len);
+ assert(it.offset < it.words.len);
return Instruction{
- .opcode = @enumFromInt(self.words[self.offset] & 0xFFFF),
- .index = self.index,
- .offset = self.offset,
- .operands = self.words[self.offset..][1..instruction_len],
+ .opcode = @enumFromInt(it.words[it.offset] & 0xFFFF),
+ .offset = it.offset,
+ .operands = it.words[it.offset..][1..instruction_len],
};
}
};
- /// The opcode for this instruction.
opcode: Opcode,
- /// The instruction's index.
- index: usize,
- /// The instruction's word offset in the module.
offset: usize,
- /// The raw (unparsed) operands for this instruction.
operands: []const Word,
};
-/// This parser contains information (acceleration tables)
-/// that can be persisted across different modules. This is
-/// used to initialize the module, and is also used when
-/// further analyzing it.
pub const Parser = struct {
- /// The allocator used to allocate this parser's structures,
- /// and also the structures of any parsed module.
- a: Allocator,
-
- /// Maps (instruction set, opcode) => instruction index (for instruction set)
+ gpa: Allocator,
opcode_table: std.AutoHashMapUnmanaged(u32, u16) = .empty,
- pub fn init(a: Allocator) !Parser {
- var self = Parser{
- .a = a,
- };
- errdefer self.deinit();
+ pub fn init(gpa: Allocator) !Parser {
+ var parser = Parser{ .gpa = gpa };
+ errdefer parser.deinit();
inline for (std.meta.tags(InstructionSet)) |set| {
const instructions = set.instructions();
- try self.opcode_table.ensureUnusedCapacity(a, @intCast(instructions.len));
+ try parser.opcode_table.ensureUnusedCapacity(gpa, @intCast(instructions.len));
for (instructions, 0..) |inst, i| {
- // Note: Some instructions may alias another. In this case we don't really care
- // which one is first: they all (should) have the same operands anyway. Just pick
- // the first, which is usually the core, KHR or EXT variant.
- const entry = self.opcode_table.getOrPutAssumeCapacity(mapSetAndOpcode(set, @intCast(inst.opcode)));
+ const entry = parser.opcode_table.getOrPutAssumeCapacity(mapSetAndOpcode(set, @intCast(inst.opcode)));
if (!entry.found_existing) {
entry.value_ptr.* = @intCast(i);
}
}
}
- return self;
+ return parser;
}
- pub fn deinit(self: *Parser) void {
- self.opcode_table.deinit(self.a);
+ pub fn deinit(parser: *Parser) void {
+ parser.opcode_table.deinit(parser.gpa);
}
fn mapSetAndOpcode(set: InstructionSet, opcode: u16) u32 {
return (@as(u32, @intFromEnum(set)) << 16) | opcode;
}
- pub fn getInstSpec(self: Parser, opcode: Opcode) ?spec.Instruction {
- const index = self.opcode_table.get(mapSetAndOpcode(.core, @intFromEnum(opcode))) orelse return null;
+ pub fn getInstSpec(parser: Parser, opcode: Opcode) ?spec.Instruction {
+ const index = parser.opcode_table.get(mapSetAndOpcode(.core, @intFromEnum(opcode))) orelse return null;
return InstructionSet.core.instructions()[index];
}
- pub fn parse(self: *Parser, module: []const u32) ParseError!BinaryModule {
- if (module[0] != spec.magic_number) {
- return error.InvalidMagic;
- } else if (module.len < header_words) {
- log.err("module only has {}/{} header words", .{ module.len, header_words });
- return error.InvalidPhysicalFormat;
- }
-
+ /// Build a BinaryModule from raw instruction words (no header).
+ /// Scans for ext_inst_map, arith_type_width, and the functions section offset.
+ pub fn initFromWords(parser: *Parser, words: []const Word, id_bound: u32) !BinaryModule {
var binary = BinaryModule{
- .version = @bitCast(module[1]),
- .generator_magic = @bitCast(module[2]),
- .id_bound = module[3],
- .instructions = module[header_words..],
+ .id_bound = id_bound,
+ .instructions = words,
.ext_inst_map = .{},
.arith_type_width = .{},
- .sections = undefined,
+ .functions_start = undefined,
};
var maybe_function_section: ?usize = null;
+ var it = binary.iterateInstructions();
+ while (it.next()) |inst| {
+ const inst_spec = parser.getInstSpec(inst.opcode) orelse continue;
+ const operands = inst.operands;
- // First pass through the module to verify basic structure and
- // to gather some initial stuff for more detailed analysis.
- // We want to check some stuff that Instruction.Iterator is no good for,
- // so just iterate manually.
- var offset: usize = 0;
- while (offset < binary.instructions.len) {
- const len = binary.instructions[offset] >> 16;
- if (len == 0 or len + offset > binary.instructions.len) {
- log.err("invalid instruction format: len={}, end={}, module len={}", .{ len, len + offset, binary.instructions.len });
- return error.InvalidPhysicalFormat;
- }
- defer offset += len;
-
- // We can't really efficiently use non-exhaustive enums here, because we would
- // need to manually write out all valid cases. Since we have this map anyway, just
- // use that.
- const opcode: Opcode = @enumFromInt(@as(u16, @truncate(binary.instructions[offset])));
- const inst_spec = self.getInstSpec(opcode) orelse {
- log.err("invalid opcode for core set: {}", .{@intFromEnum(opcode)});
- return error.InvalidOpcode;
- };
-
- const operands = binary.instructions[offset..][1..len];
- switch (opcode) {
+ switch (inst.opcode) {
.OpExtInstImport => {
const set_name = std.mem.sliceTo(std.mem.sliceAsBytes(operands[1..]), 0);
- const set = std.meta.stringToEnum(InstructionSet, set_name) orelse {
- log.err("invalid instruction set '{s}'", .{set_name});
- return error.InvalidExtInstImport;
- };
- if (set == .core) return error.InvalidExtInstImport;
- try binary.ext_inst_map.put(self.a, @enumFromInt(operands[0]), set);
+ const set = std.meta.stringToEnum(InstructionSet, set_name) orelse continue;
+ if (set == .core) continue;
+ try binary.ext_inst_map.put(parser.gpa, @enumFromInt(operands[0]), set);
},
.OpTypeInt, .OpTypeFloat => {
- const entry = try binary.arith_type_width.getOrPut(self.a, @enumFromInt(operands[0]));
- if (entry.found_existing) return error.DuplicateId;
- entry.value_ptr.* = std.math.cast(u16, operands[1]) orelse return error.InvalidOperands;
+ try binary.arith_type_width.put(parser.gpa, @enumFromInt(operands[0]), @intCast(operands[1]));
},
.OpFunction => if (maybe_function_section == null) {
- maybe_function_section = offset;
+ maybe_function_section = inst.offset;
},
else => {},
}
- // OpSwitch takes a value as argument, not an OpType... hence we need to populate arith_type_width
- // with ALL operations that return an int or float.
+ // propagate arith type widths through instructions that return int/float
const spec_operands = inst_spec.operands;
if (spec_operands.len >= 2 and
spec_operands[0].kind == .id_result_type and
spec_operands[1].kind == .id_result)
{
- if (operands.len < 2) return error.InvalidOperands;
- if (binary.arith_type_width.get(@enumFromInt(operands[0]))) |width| {
- const entry = try binary.arith_type_width.getOrPut(self.a, @enumFromInt(operands[1]));
- if (entry.found_existing) return error.DuplicateId;
- entry.value_ptr.* = width;
+ if (operands.len >= 2) {
+ if (binary.arith_type_width.get(@enumFromInt(operands[0]))) |width| {
+ try binary.arith_type_width.put(parser.gpa, @enumFromInt(operands[1]), width);
+ }
}
}
}
- binary.sections = .{
- .functions = maybe_function_section orelse binary.instructions.len,
- };
+ binary.functions_start = maybe_function_section orelse binary.instructions.len;
return binary;
}
/// Parse offsets in the instruction that contain result-ids.
/// Returned offsets are relative to inst.operands.
- /// Returns in an arraylist to armortize allocations.
pub fn parseInstructionResultIds(
- self: *Parser,
+ parser: *Parser,
binary: BinaryModule,
inst: Instruction,
- offsets: *std.array_list.Managed(u16),
+ offsets: *std.ArrayList(u16),
) !void {
- const index = self.opcode_table.get(mapSetAndOpcode(.core, @intFromEnum(inst.opcode))).?;
+ const index = parser.opcode_table.get(mapSetAndOpcode(.core, @intFromEnum(inst.opcode))).?;
const operands = InstructionSet.core.instructions()[index].operands;
var offset: usize = 0;
@@ -290,37 +173,37 @@ pub const Parser = struct {
.OpSpecConstantOp => {
assert(operands[0].kind == .id_result_type);
assert(operands[1].kind == .id_result);
- offset = try self.parseOperandsResultIds(binary, inst, operands[0..2], offset, offsets);
+ offset = try parser.parseOperandsResultIds(binary, inst, operands[0..2], offset, offsets);
if (offset >= inst.operands.len) return error.InvalidPhysicalFormat;
const spec_opcode = std.math.cast(u16, inst.operands[offset]) orelse return error.InvalidPhysicalFormat;
- const spec_index = self.opcode_table.get(mapSetAndOpcode(.core, spec_opcode)) orelse
+ const spec_index = parser.opcode_table.get(mapSetAndOpcode(.core, spec_opcode)) orelse
return error.InvalidPhysicalFormat;
const spec_operands = InstructionSet.core.instructions()[spec_index].operands;
assert(spec_operands[0].kind == .id_result_type);
assert(spec_operands[1].kind == .id_result);
- offset = try self.parseOperandsResultIds(binary, inst, spec_operands[2..], offset + 1, offsets);
+ offset = try parser.parseOperandsResultIds(binary, inst, spec_operands[2..], offset + 1, offsets);
},
.OpExtInst => {
assert(operands[0].kind == .id_result_type);
assert(operands[1].kind == .id_result);
- offset = try self.parseOperandsResultIds(binary, inst, operands[0..2], offset, offsets);
+ offset = try parser.parseOperandsResultIds(binary, inst, operands[0..2], offset, offsets);
if (offset + 1 >= inst.operands.len) return error.InvalidPhysicalFormat;
const set_id: ResultId = @enumFromInt(inst.operands[offset]);
- try offsets.append(@intCast(offset));
+ try offsets.append(parser.gpa, @intCast(offset));
const set = binary.ext_inst_map.get(set_id) orelse {
log.err("invalid instruction set {}", .{@intFromEnum(set_id)});
return error.InvalidId;
};
const ext_opcode = std.math.cast(u16, inst.operands[offset + 1]) orelse return error.InvalidPhysicalFormat;
- const ext_index = self.opcode_table.get(mapSetAndOpcode(set, ext_opcode)) orelse
+ const ext_index = parser.opcode_table.get(mapSetAndOpcode(set, ext_opcode)) orelse
return error.InvalidPhysicalFormat;
const ext_operands = set.instructions()[ext_index].operands;
- offset = try self.parseOperandsResultIds(binary, inst, ext_operands, offset + 2, offsets);
+ offset = try parser.parseOperandsResultIds(binary, inst, ext_operands, offset + 2, offsets);
},
else => {
- offset = try self.parseOperandsResultIds(binary, inst, operands, offset, offsets);
+ offset = try parser.parseOperandsResultIds(binary, inst, operands, offset, offsets);
},
}
@@ -328,50 +211,50 @@ pub const Parser = struct {
}
fn parseOperandsResultIds(
- self: *Parser,
+ parser: *Parser,
binary: BinaryModule,
inst: Instruction,
operands: []const spec.Operand,
start_offset: usize,
- offsets: *std.array_list.Managed(u16),
+ offsets: *std.ArrayList(u16),
) !usize {
var offset = start_offset;
for (operands) |operand| {
- offset = try self.parseOperandResultIds(binary, inst, operand, offset, offsets);
+ offset = try parser.parseOperandResultIds(binary, inst, operand, offset, offsets);
}
return offset;
}
fn parseOperandResultIds(
- self: *Parser,
+ parser: *Parser,
binary: BinaryModule,
inst: Instruction,
operand: spec.Operand,
start_offset: usize,
- offsets: *std.array_list.Managed(u16),
+ offsets: *std.ArrayList(u16),
) !usize {
var offset = start_offset;
switch (operand.quantifier) {
.variadic => while (offset < inst.operands.len) {
- offset = try self.parseOperandKindResultIds(binary, inst, operand.kind, offset, offsets);
+ offset = try parser.parseOperandKindResultIds(binary, inst, operand.kind, offset, offsets);
},
.optional => if (offset < inst.operands.len) {
- offset = try self.parseOperandKindResultIds(binary, inst, operand.kind, offset, offsets);
+ offset = try parser.parseOperandKindResultIds(binary, inst, operand.kind, offset, offsets);
},
.required => {
- offset = try self.parseOperandKindResultIds(binary, inst, operand.kind, offset, offsets);
+ offset = try parser.parseOperandKindResultIds(binary, inst, operand.kind, offset, offsets);
},
}
return offset;
}
fn parseOperandKindResultIds(
- self: *Parser,
+ parser: *Parser,
binary: BinaryModule,
inst: Instruction,
kind: spec.OperandKind,
start_offset: usize,
- offsets: *std.array_list.Managed(u16),
+ offsets: *std.ArrayList(u16),
) !usize {
var offset = start_offset;
if (offset >= inst.operands.len) return error.InvalidPhysicalFormat;
@@ -383,7 +266,7 @@ pub const Parser = struct {
for (kind.enumerants()) |enumerant| {
if ((mask & enumerant.value) != 0) {
for (enumerant.parameters) |param_kind| {
- offset = try self.parseOperandKindResultIds(binary, inst, param_kind, offset, offsets);
+ offset = try parser.parseOperandKindResultIds(binary, inst, param_kind, offset, offsets);
}
}
}
@@ -394,14 +277,14 @@ pub const Parser = struct {
for (kind.enumerants()) |enumerant| {
if (value == enumerant.value) {
for (enumerant.parameters) |param_kind| {
- offset = try self.parseOperandKindResultIds(binary, inst, param_kind, offset, offsets);
+ offset = try parser.parseOperandKindResultIds(binary, inst, param_kind, offset, offsets);
}
break;
}
}
},
.id => {
- try offsets.append(@intCast(offset));
+ try offsets.append(parser.gpa, @intCast(offset));
offset += 1;
},
else => switch (kind) {
@@ -433,7 +316,7 @@ pub const Parser = struct {
},
.literal_ext_inst_integer => unreachable,
.literal_spec_constant_op_integer => unreachable,
- .pair_literal_integer_id_ref => { // Switch case
+ .pair_literal_integer_id_ref => {
assert(inst.opcode == .OpSwitch);
const bit_width = binary.arith_type_width.get(@enumFromInt(inst.operands[0])) orelse {
log.err("invalid OpSwitch type {}", .{inst.operands[0]});
@@ -444,16 +327,16 @@ pub const Parser = struct {
33...64 => 2,
else => unreachable,
};
- try offsets.append(@intCast(offset));
+ try offsets.append(parser.gpa, @intCast(offset));
offset += 1;
},
.pair_id_ref_literal_integer => {
- try offsets.append(@intCast(offset));
+ try offsets.append(parser.gpa, @intCast(offset));
offset += 2;
},
.pair_id_ref_id_ref => {
- try offsets.append(@intCast(offset));
- try offsets.append(@intCast(offset + 1));
+ try offsets.append(parser.gpa, @intCast(offset));
+ try offsets.append(parser.gpa, @intCast(offset + 1));
offset += 2;
},
else => unreachable,
diff --git a/src/link/SpirV/dedup_types.zig b/src/link/SpirV/dedup_types.zig
new file mode 100644
index 0000000000000000000000000000000000000000..338258e17ef40eff1d9557163395689a33cb22db
--- /dev/null
+++ b/src/link/SpirV/dedup_types.zig
@@ -0,0 +1,244 @@
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const BinaryModule = @import("BinaryModule.zig");
+
+const spec = @import("../../codegen/spirv/spec.zig");
+const Word = spec.Word;
+const Id = spec.Id;
+const Opcode = spec.Opcode;
+const Instruction = BinaryModule.Instruction;
+
+/// Deduplicate types and constants in a SPIR-V binary module.
+///
+/// The SPIR-V spec requires that non-aggregate types be unique.
+/// When merging fragments from parallel codegen, duplicate type definitions
+/// may exist. This pass identifies structurally identical types/constants,
+/// keeps one canonical instance, and remaps all references to duplicates.
+pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {
+ const gpa = parser.gpa;
+
+ const Decoration = struct { offset: usize, len: usize };
+ var decorations_by_id: std.array_hash_map.Auto(Id, std.ArrayList(Decoration)) = .empty;
+ defer {
+ for (decorations_by_id.values()) |*list| list.deinit(gpa);
+ decorations_by_id.deinit(gpa);
+ }
+
+ var it = binary.iterateInstructions();
+ while (it.next()) |inst| {
+ if (inst.offset >= binary.functions_start) break;
+ switch (inst.opcode) {
+ .OpName, .OpMemberName => continue,
+ else => switch (inst.opcode.class()) {
+ .annotation => {},
+ else => continue,
+ },
+ }
+ if (inst.operands.len == 0) continue;
+ const target_id: Id = @enumFromInt(inst.operands[0]);
+
+ const gop = try decorations_by_id.getOrPut(gpa, target_id);
+ if (!gop.found_existing) gop.value_ptr.* = .empty;
+ try gop.value_ptr.append(gpa, .{
+ .offset = inst.offset,
+ .len = 1 + inst.operands.len,
+ });
+ }
+
+ var canonical_map: std.array_hash_map.Custom(TypeKey, Id, TypeKey.HashContext, true) = .empty;
+ defer {
+ for (canonical_map.keys()) |key| gpa.free(key.words);
+ canonical_map.deinit(gpa);
+ }
+
+ var id_remap: std.AutoHashMapUnmanaged(Id, Id) = .empty;
+ defer id_remap.deinit(gpa);
+
+ var id_offsets: std.ArrayList(u16) = .empty;
+ defer id_offsets.deinit(gpa);
+
+ var key_words: std.ArrayList(Word) = .empty;
+ defer key_words.deinit(gpa);
+
+ var dec_hashes: std.ArrayList(u64) = .empty;
+ defer dec_hashes.deinit(gpa);
+
+ // first pass: build canonical map, identify duplicates
+ it = binary.iterateInstructions();
+ while (it.next()) |inst| {
+ if (inst.offset >= binary.functions_start) break;
+ if (!canDeduplicate(inst.opcode)) continue;
+
+ const result_id_index: usize = switch (inst.opcode.class()) {
+ .type_declaration, .extension => 0,
+ .constant_creation => 1,
+ else => continue,
+ };
+ if (result_id_index >= inst.operands.len) continue;
+ const result_id: Id = @enumFromInt(inst.operands[result_id_index]);
+
+ key_words.items.len = 0;
+ try key_words.append(gpa, @intFromEnum(inst.opcode));
+
+ id_offsets.items.len = 0;
+ parser.parseInstructionResultIds(binary.*, inst, &id_offsets) catch continue;
+
+ for (inst.operands, 0..) |word, i| {
+ if (i == result_id_index) continue;
+ if (std.mem.indexOfScalar(u16, id_offsets.items, @intCast(i)) != null) {
+ const canonical = id_remap.get(@enumFromInt(word)) orelse @as(Id, @enumFromInt(word));
+ try key_words.append(gpa, @intFromEnum(canonical));
+ } else {
+ try key_words.append(gpa, word);
+ }
+ }
+
+ if (decorations_by_id.getPtr(result_id)) |dec_list| {
+ dec_hashes.items.len = 0;
+ for (dec_list.items) |dec| {
+ const dec_words = binary.instructions[dec.offset..][0..dec.len];
+ var hasher = std.hash.Wyhash.init(0);
+ hasher.update(std.mem.asBytes(&dec_words[0]));
+ for (dec_words[2..]) |w| {
+ const w_val = if (id_remap.get(@enumFromInt(w))) |c| @intFromEnum(c) else w;
+ hasher.update(std.mem.asBytes(&w_val));
+ }
+ try dec_hashes.append(gpa, hasher.final());
+ }
+ std.mem.sort(u64, dec_hashes.items, {}, std.sort.asc(u64));
+ var prev: u64 = 0;
+ for (dec_hashes.items) |h| {
+ if (h == prev) continue;
+ prev = h;
+ try key_words.append(gpa, @truncate(h));
+ try key_words.append(gpa, @truncate(h >> 32));
+ }
+ }
+
+ const key = TypeKey{ .words = try gpa.dupe(Word, key_words.items) };
+ const gop = try canonical_map.getOrPut(gpa, key);
+ if (gop.found_existing) {
+ try id_remap.put(gpa, result_id, gop.value_ptr.*);
+ gpa.free(key.words);
+ } else {
+ gop.value_ptr.* = result_id;
+ }
+ }
+
+ if (id_remap.count() == 0) return;
+
+ // second pass: rewrite id references, remove duplicates and redundant annotations
+ var new_words: std.ArrayList(Word) = .empty;
+ defer new_words.deinit(gpa);
+ try new_words.ensureTotalCapacity(gpa, binary.instructions.len);
+
+ var emitted_annotations: std.AutoHashMapUnmanaged(u64, void) = .empty;
+ defer emitted_annotations.deinit(gpa);
+
+ var new_functions_offset: ?usize = null;
+ var max_id: Word = 0;
+
+ it = binary.iterateInstructions();
+ while (it.next()) |inst| {
+ if (new_functions_offset == null and inst.offset >= binary.functions_start) {
+ new_functions_offset = new_words.items.len;
+ }
+
+ if (canDeduplicate(inst.opcode)) {
+ const result_id_index: usize = switch (inst.opcode.class()) {
+ .type_declaration, .extension => 0,
+ .constant_creation => 1,
+ else => unreachable,
+ };
+ if (result_id_index < inst.operands.len) {
+ const result_id: Id = @enumFromInt(inst.operands[result_id_index]);
+ if (id_remap.contains(result_id)) continue;
+ }
+ }
+
+ switch (inst.opcode.class()) {
+ .annotation, .debug => {
+ if (inst.operands.len > 0) {
+ const target: Id = @enumFromInt(inst.operands[0]);
+ if (id_remap.contains(target)) continue;
+ }
+ },
+ else => {},
+ }
+
+ const inst_start = new_words.items.len;
+ new_words.appendAssumeCapacity(binary.instructions[inst.offset]);
+ new_words.appendSliceAssumeCapacity(inst.operands);
+ const inst_slice = new_words.items[inst_start + 1 ..];
+
+ id_offsets.items.len = 0;
+ parser.parseInstructionResultIds(binary.*, inst, &id_offsets) catch continue;
+
+ const inst_spec = parser.getInstSpec(inst.opcode);
+ const maybe_result_id_index: ?usize = if (inst_spec) |ispec| blk: {
+ break :blk for (0..@min(2, ispec.operands.len)) |i| {
+ if (ispec.operands[i].kind == .id_result) break @intCast(i);
+ } else null;
+ } else null;
+
+ for (inst_slice, 0..) |*word, i| {
+ if (std.mem.indexOfScalar(u16, id_offsets.items, @intCast(i)) == null) continue;
+ max_id = @max(max_id, word.*);
+ if (maybe_result_id_index != null and i == maybe_result_id_index.?) continue;
+
+ if (id_remap.get(@enumFromInt(word.*))) |canonical| {
+ word.* = @intFromEnum(canonical);
+ max_id = @max(max_id, word.*);
+ }
+ }
+
+ switch (inst.opcode.class()) {
+ .annotation, .debug => {
+ const ann_words = new_words.items[inst_start..];
+ const ann_hash = std.hash.Wyhash.hash(0, std.mem.sliceAsBytes(ann_words));
+ const gop = try emitted_annotations.getOrPut(gpa, ann_hash);
+ if (gop.found_existing) {
+ new_words.items.len = inst_start;
+ continue;
+ }
+ },
+ else => {},
+ }
+ }
+
+ var remap_it = id_remap.iterator();
+ while (remap_it.next()) |entry| {
+ _ = binary.ext_inst_map.remove(entry.key_ptr.*);
+ _ = binary.arith_type_width.remove(entry.key_ptr.*);
+ }
+
+ binary.instructions = try gpa.dupe(Word, new_words.items);
+ binary.functions_start = new_functions_offset orelse new_words.items.len;
+ binary.id_bound = max_id + 1;
+}
+
+fn canDeduplicate(opcode: Opcode) bool {
+ return switch (opcode) {
+ .OpTypeForwardPointer => false,
+ .OpGroupDecorate, .OpGroupMemberDecorate => false,
+ else => switch (opcode.class()) {
+ .type_declaration, .constant_creation => true,
+ .extension => opcode == .OpExtInstImport,
+ else => false,
+ },
+ };
+}
+
+const TypeKey = struct {
+ words: []const Word,
+
+ const HashContext = struct {
+ pub fn hash(_: @This(), key: TypeKey) u32 {
+ return @truncate(std.hash.Wyhash.hash(0, std.mem.sliceAsBytes(key.words)));
+ }
+
+ pub fn eql(_: @This(), a: TypeKey, b: TypeKey, _: usize) bool {
+ return std.mem.eql(Word, a.words, b.words);
+ }
+ };
+};
diff --git a/src/link/SpirV/lower_invocation_globals.zig b/src/link/SpirV/lower_invocation_globals.zig
index e2db1b33e5ca64c772082db596ceae64592c3bb9..7cc9604d049908c09fa63599ac2d0b61359331ef 100644
--- a/src/link/SpirV/lower_invocation_globals.zig
+++ b/src/link/SpirV/lower_invocation_globals.zig
@@ -23,14 +23,14 @@ const ModuleInfo = struct {
/// The set of (result-id's of) invocation globals that are accessed
/// in this function, or after resolution, that are accessed in this
/// function or any of it's callees.
- invocation_globals: std.AutoArrayHashMapUnmanaged(ResultId, void),
+ invocation_globals: std.array_hash_map.Auto(ResultId, void),
};
/// Information about a particular invocation global
const InvocationGlobal = struct {
/// The list of invocation globals that this invocation global
/// depends on.
- dependencies: std.AutoArrayHashMapUnmanaged(ResultId, void),
+ dependencies: std.array_hash_map.Auto(ResultId, void),
/// The invocation global's type
ty: ResultId,
/// Initializer function. May be `none`.
@@ -39,13 +39,18 @@ const ModuleInfo = struct {
};
/// Maps function result-id -> Fn information structure.
- functions: std.AutoArrayHashMapUnmanaged(ResultId, Fn),
+ functions: std.array_hash_map.Auto(ResultId, Fn),
/// Set of OpFunction result-ids in this module.
- entry_points: std.AutoArrayHashMapUnmanaged(ResultId, void),
+ entry_points: std.array_hash_map.Auto(ResultId, void),
/// For each function, a list of function result-ids that it calls.
callee_store: []const ResultId,
/// Maps each invocation global result-id to a type-id.
- invocation_globals: std.AutoArrayHashMapUnmanaged(ResultId, InvocationGlobal),
+ invocation_globals: std.array_hash_map.Auto(ResultId, InvocationGlobal),
+ /// Subset of `invocation_globals` reachable from any entry point.
+ live_invocation_globals: std.array_hash_map.Auto(ResultId, void),
+ /// Initializer functions of unreachable invocation globals. Their
+ /// OpFunction...OpFunctionEnd ranges are skipped during rewriteFunctions.
+ dead_initializers: std.array_hash_map.Auto(ResultId, void),
/// Fetch the list of callees per function. Guaranteed to contain only unique IDs.
fn callees(self: ModuleInfo, fn_id: ResultId) []const ResultId {
@@ -66,7 +71,7 @@ const ModuleInfo = struct {
arena: Allocator,
parser: *BinaryModule.Parser,
binary: BinaryModule,
- ) BinaryModule.ParseError!ModuleInfo {
+ ) !ModuleInfo {
var entry_points: std.array_hash_map.Auto(ResultId, void) = .empty;
var functions: std.array_hash_map.Auto(ResultId, Fn) = .empty;
var fn_types = std.AutoHashMap(ResultId, struct {
@@ -74,9 +79,9 @@ const ModuleInfo = struct {
param_types: []const ResultId,
}).init(arena);
var calls: std.array_hash_map.Auto(ResultId, void) = .empty;
- var callee_store = std.array_list.Managed(ResultId).init(arena);
+ var callee_store: std.ArrayList(ResultId) = .empty;
var function_invocation_globals: std.array_hash_map.Auto(ResultId, void) = .empty;
- var result_id_offsets = std.array_list.Managed(u16).init(arena);
+ var result_id_offsets: std.ArrayList(u16) = .empty;
var invocation_globals: std.array_hash_map.Auto(ResultId, InvocationGlobal) = .empty;
var maybe_current_function: ?ResultId = null;
@@ -159,7 +164,7 @@ const ModuleInfo = struct {
}
const first_callee = callee_store.items.len;
- try callee_store.appendSlice(calls.keys());
+ try callee_store.appendSlice(arena, calls.keys());
const fn_type = fn_types.get(fn_ty_id) orelse {
log.err("Function {f} has invalid OpFunction type", .{current_function});
@@ -196,6 +201,8 @@ const ModuleInfo = struct {
.entry_points = entry_points,
.callee_store = callee_store.items,
.invocation_globals = invocation_globals,
+ .live_invocation_globals = .empty,
+ .dead_initializers = .empty,
};
}
@@ -203,6 +210,25 @@ const ModuleInfo = struct {
fn resolve(self: *ModuleInfo, arena: Allocator) !void {
try self.resolveInvocationGlobalUsage(arena);
try self.resolveInvocationGlobalDependencies(arena);
+ try self.resolveLiveSet(arena);
+ }
+
+ fn resolveLiveSet(self: *ModuleInfo, arena: Allocator) !void {
+ for (self.entry_points.keys()) |ep_id| {
+ const ep_info = self.functions.get(ep_id) orelse continue;
+ for (ep_info.invocation_globals.keys()) |g| {
+ try self.live_invocation_globals.put(arena, g, {});
+ const g_info = self.invocation_globals.get(g).?;
+ for (g_info.dependencies.keys()) |dep| {
+ try self.live_invocation_globals.put(arena, dep, {});
+ }
+ }
+ }
+ for (self.invocation_globals.keys(), self.invocation_globals.values()) |g, info| {
+ if (info.initializer == .none) continue;
+ if (self.live_invocation_globals.contains(g)) continue;
+ try self.dead_initializers.put(arena, info.initializer, {});
+ }
}
/// For each function, extend the list of `invocation_globals` with the
@@ -340,11 +366,13 @@ const ModuleBuilder = struct {
/// The first ID of the new entry points. Entry points are allocated from
/// here according to their index in `info.entry_points`.
entry_point_new_id_base: u32,
+ /// OpName operands saved for invocation globals to re-emit.
+ global_names: std.array_hash_map.Auto(ResultId, []const Word) = .empty,
/// A set of all function types in the new program. SPIR-V mandates that these are unique,
/// and until a general type deduplication pass is programmed, we just handle it here via this.
- function_types: std.ArrayHashMapUnmanaged(FunctionType, ResultId, FunctionType.Context, true) = .empty,
+ function_types: std.array_hash_map.Custom(FunctionType, ResultId, FunctionType.Context, true) = .empty,
/// Maps functions to new information required for creating the module
- function_new_info: std.AutoArrayHashMapUnmanaged(ResultId, FunctionNewInfo) = .empty,
+ function_new_info: std.array_hash_map.Auto(ResultId, FunctionNewInfo) = .empty,
/// Offset of the functions section in the new binary.
new_functions_section: ?usize,
@@ -369,22 +397,50 @@ const ModuleBuilder = struct {
return @enumFromInt(self.id_bound);
}
- fn finalize(self: *ModuleBuilder, a: Allocator, binary: *BinaryModule) !void {
+ fn finalize(self: *ModuleBuilder, arena: Allocator, binary: *BinaryModule) !void {
binary.id_bound = self.id_bound;
- binary.instructions = try a.dupe(Word, self.section.instructions.items);
+ binary.instructions = try arena.dupe(Word, self.section.instructions.items);
// Nothing is removed in this pass so we don't need to change any of the maps,
// just make sure the section is updated.
- binary.sections.functions = self.new_functions_section orelse binary.instructions.len;
+ binary.functions_start = self.new_functions_section orelse binary.instructions.len;
+ }
+
+ fn emitGlobalNames(self: *ModuleBuilder, info: ModuleInfo) !void {
+ for (info.functions.keys(), info.functions.values()) |func, fn_info| {
+ if (info.dead_initializers.contains(func)) continue;
+ const new_info = self.function_new_info.get(func) orelse continue;
+ for (fn_info.invocation_globals.keys(), 0..) |global, i| {
+ if (!info.live_invocation_globals.contains(global)) continue;
+ const name_words = self.global_names.get(global) orelse continue;
+ const id = new_info.invocationGlobalId(i);
+ try self.section.emitRaw(self.arena, .OpName, 1 + name_words.len);
+ self.section.writeOperand(ResultId, id);
+ self.section.writeWords(name_words);
+ }
+ }
}
/// Process everything from `binary` up to the first function and emit it into the builder.
fn processPreamble(self: *ModuleBuilder, binary: BinaryModule, info: ModuleInfo) !void {
+ var emitted_global_names = false;
var it = binary.iterateInstructions();
while (it.next()) |inst| {
+ if (!emitted_global_names) switch (inst.opcode.class()) {
+ .annotation, .type_declaration, .constant_creation => {
+ try self.emitGlobalNames(info);
+ emitted_global_names = true;
+ },
+ else => {},
+ };
+
switch (inst.opcode) {
.OpName => {
const id: ResultId = @enumFromInt(inst.operands[0]);
- if (info.invocation_globals.contains(id)) continue;
+ if (info.invocation_globals.contains(id)) {
+ try self.global_names.put(self.arena, id, inst.operands[1..]);
+ continue;
+ }
+ if (info.dead_initializers.contains(id)) continue;
},
.OpExtInstImport => {
const set_id: ResultId = @enumFromInt(inst.operands[0]);
@@ -401,29 +457,34 @@ const ModuleBuilder = struct {
},
.OpEntryPoint => {
const original_id: ResultId = @enumFromInt(inst.operands[1]);
- const new_id_index = info.entry_points.getIndex(original_id).?;
- const new_id: ResultId = @enumFromInt(self.entry_point_new_id_base + new_id_index);
- try self.section.emitRaw(self.arena, .OpEntryPoint, inst.operands.len);
- self.section.writeWord(inst.operands[0]);
- self.section.writeOperand(ResultId, new_id);
- self.section.writeWords(inst.operands[2..]);
+ const fn_info = info.functions.get(original_id).?;
+ if (fn_info.invocation_globals.count() > 0) {
+ const new_id_index = info.entry_points.getIndex(original_id).?;
+ const new_id: ResultId = @enumFromInt(self.entry_point_new_id_base + new_id_index);
+ try self.section.emitRaw(self.arena, .OpEntryPoint, inst.operands.len);
+ self.section.writeWord(inst.operands[0]);
+ self.section.writeOperand(ResultId, new_id);
+ self.section.writeWords(inst.operands[2..]);
+ } else {
+ try self.section.emitRawInstruction(self.arena, inst.opcode, inst.operands);
+ }
continue;
},
.OpExecutionMode, .OpExecutionModeId => {
const original_id: ResultId = @enumFromInt(inst.operands[0]);
- const new_id_index = info.entry_points.getIndex(original_id).?;
- const new_id: ResultId = @enumFromInt(self.entry_point_new_id_base + new_id_index);
- try self.section.emitRaw(self.arena, inst.opcode, inst.operands.len);
- self.section.writeOperand(ResultId, new_id);
- self.section.writeWords(inst.operands[1..]);
+ const fn_info = info.functions.get(original_id).?;
+ if (fn_info.invocation_globals.count() > 0) {
+ const new_id_index = info.entry_points.getIndex(original_id).?;
+ const new_id: ResultId = @enumFromInt(self.entry_point_new_id_base + new_id_index);
+ try self.section.emitRaw(self.arena, inst.opcode, inst.operands.len);
+ self.section.writeOperand(ResultId, new_id);
+ self.section.writeWords(inst.operands[1..]);
+ } else {
+ try self.section.emitRawInstruction(self.arena, inst.opcode, inst.operands);
+ }
continue;
},
.OpTypeFunction => {
- // Re-emitted in `emitFunctionTypes()`. We can do this because
- // OpTypeFunction's may not currently be used anywhere that is not
- // directly with an OpFunction. For now we ignore Intels function
- // pointers extension, that is not a problem with a generalized
- // pass anyway.
continue;
},
.OpFunction => break,
@@ -432,6 +493,10 @@ const ModuleBuilder = struct {
try self.section.emitRawInstruction(self.arena, inst.opcode, inst.operands);
}
+
+ if (!emitted_global_names) {
+ try self.emitGlobalNames(info);
+ }
}
/// Derive new information required for further emitting this module,
@@ -498,18 +563,23 @@ const ModuleBuilder = struct {
binary: BinaryModule,
info: ModuleInfo,
) !void {
- var result_id_offsets = std.array_list.Managed(u16).init(self.arena);
- var operands = std.array_list.Managed(u32).init(self.arena);
+ var result_id_offsets: std.ArrayList(u16) = .empty;
+ var operands: std.ArrayList(u32) = .empty;
var maybe_current_function: ?ResultId = null;
- var it = binary.iterateInstructionsFrom(binary.sections.functions);
+ var skip_until_end: bool = false;
+ var it = binary.iterateInstructionsFrom(binary.functions_start);
self.new_functions_section = self.section.instructions.items.len;
while (it.next()) |inst| {
+ if (skip_until_end) {
+ if (inst.opcode == .OpFunctionEnd) skip_until_end = false;
+ continue;
+ }
result_id_offsets.items.len = 0;
try parser.parseInstructionResultIds(binary, inst, &result_id_offsets);
operands.items.len = 0;
- try operands.appendSlice(inst.operands);
+ try operands.appendSlice(self.arena, inst.operands);
// Replace the result-ids with the global's new result-id if required.
for (result_id_offsets.items) |off| {
@@ -527,6 +597,10 @@ const ModuleBuilder = struct {
.OpFunction => {
// Re-declare the function with the new parameters.
const func: ResultId = @enumFromInt(operands.items[1]);
+ if (info.dead_initializers.contains(func)) {
+ skip_until_end = true;
+ continue;
+ }
const fn_info = info.functions.get(func).?;
const new_info = self.function_new_info.get(func).?;
@@ -588,6 +662,7 @@ const ModuleBuilder = struct {
for (info.entry_points.keys(), 0..) |func, entry_point_index| {
const fn_info = info.functions.get(func).?;
+ if (fn_info.invocation_globals.count() == 0) continue;
const ep_id: ResultId = @enumFromInt(self.entry_point_new_id_base + @as(u32, @intCast(entry_point_index)));
const fn_type = self.function_types.get(.{
.return_type = fn_info.return_type,
@@ -705,14 +780,14 @@ pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule, progress: std.Pr
const sub_node = progress.start("Lower invocation globals", 6);
defer sub_node.end();
- var arena = std.heap.ArenaAllocator.init(parser.a);
- defer arena.deinit();
- const a = arena.allocator();
+ var arena_state = std.heap.ArenaAllocator.init(parser.gpa);
+ defer arena_state.deinit();
+ const arena = arena_state.allocator();
- var info = try ModuleInfo.parse(a, parser, binary.*);
- try info.resolve(a);
+ var info = try ModuleInfo.parse(arena, parser, binary.*);
+ try info.resolve(arena);
- var builder = try ModuleBuilder.init(a, binary.*, info);
+ var builder = try ModuleBuilder.init(arena, binary.*, info);
sub_node.completeOne();
try builder.deriveNewFnInfo(info);
sub_node.completeOne();
@@ -724,5 +799,5 @@ pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule, progress: std.Pr
sub_node.completeOne();
try builder.emitNewEntryPoints(info);
sub_node.completeOne();
- try builder.finalize(parser.a, binary);
+ try builder.finalize(parser.gpa, binary);
}
diff --git a/src/link/SpirV/prune_unused.zig b/src/link/SpirV/prune_unused.zig
new file mode 100644
index 0000000000000000000000000000000000000000..356da14952784938ade741ba08e5ed52fd859df3
--- /dev/null
+++ b/src/link/SpirV/prune_unused.zig
@@ -0,0 +1,257 @@
+const std = @import("std");
+const BinaryModule = @import("BinaryModule.zig");
+const spec = @import("../../codegen/spirv/spec.zig");
+const Opcode = spec.Opcode;
+const ResultId = spec.Id;
+const Word = spec.Word;
+
+pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {
+ const gpa = parser.gpa;
+
+ // map result-id → index in id_offsets for preamble instructions and function headers
+ var id_to_index: std.AutoHashMapUnmanaged(ResultId, u32) = .empty;
+ defer id_to_index.deinit(gpa);
+
+ // for each indexed instruction, its offset in the binary
+ var code_offsets: std.ArrayList(usize) = .empty;
+ defer code_offsets.deinit(gpa);
+
+ var it = binary.iterateInstructions();
+ while (it.next()) |inst| {
+ const inst_spec = parser.getInstSpec(inst.opcode) orelse continue;
+ const result_id = getResultId(inst, inst_spec) orelse continue;
+
+ // only index preamble instructions and function headers
+ if (inst.offset < binary.functions_start or inst.opcode == .OpFunction) {
+ const index: u32 = @intCast(code_offsets.items.len);
+ try id_to_index.put(gpa, result_id, index);
+ try code_offsets.append(gpa, inst.offset);
+ }
+ }
+
+ var alive: std.bit_set.Dynamic = try .initEmpty(gpa, code_offsets.items.len);
+ defer alive.deinit(gpa);
+
+ var id_offset_buf: std.ArrayList(u16) = .empty;
+ defer id_offset_buf.deinit(gpa);
+
+ // Mark non-prunable preamble instructions alive
+ // OpExtInst in the preamble is metadata (e.g. Zig error info) that references
+ // functions. skip it here so it doesn't root dead functions alive.
+ // These instructions are handled as prunable during the rewrite phase.
+ it = binary.iterateInstructions();
+ while (it.next()) |inst| {
+ if (inst.offset >= binary.functions_start) break;
+ if (canPrune(inst.opcode) or inst.opcode == .OpExtInst) continue;
+ try markAlive(
+ parser,
+ binary.*,
+ inst,
+ &alive,
+ &id_to_index,
+ &code_offsets,
+ &id_offset_buf,
+ );
+ }
+
+ // mark functions with LinkageAttributes Export alive
+ it = binary.iterateInstructions();
+ while (it.next()) |inst| {
+ if (inst.offset >= binary.functions_start) break;
+ if (inst.opcode == .OpDecorate and inst.operands.len >= 2 and
+ inst.operands[1] == @intFromEnum(spec.Decoration.linkage_attributes))
+ {
+ // Last word after the string is the linkage type; Export = 0.
+ if (inst.operands[inst.operands.len - 1] == @intFromEnum(spec.LinkageType.@"export")) {
+ const target: ResultId = @enumFromInt(inst.operands[0]);
+ if (id_to_index.get(target)) |index| {
+ alive.set(index);
+ }
+ }
+ }
+ }
+
+ // mark alive functions' contents alive
+ it = binary.iterateInstructionsFrom(binary.functions_start);
+ while (it.next()) |inst| {
+ if (inst.opcode == .OpFunction) {
+ const inst_spec = parser.getInstSpec(inst.opcode) orelse continue;
+ const result_id = getResultId(inst, inst_spec) orelse continue;
+ const index = id_to_index.get(result_id) orelse continue;
+ if (!alive.isSet(index)) {
+ // skip dead function
+ while (it.next()) |inner| {
+ if (inner.opcode == .OpFunctionEnd) break;
+ }
+ continue;
+ }
+
+ // mark the function's type operands alive
+ try markAlive(parser, binary.*, inst, &alive, &id_to_index, &code_offsets, &id_offset_buf);
+ continue;
+ }
+
+ // mark operands of alive function contents
+ try markAlive(parser, binary.*, inst, &alive, &id_to_index, &code_offsets, &id_offset_buf);
+ }
+
+ // rewrite
+ var new_words: std.ArrayList(Word) = .empty;
+ defer new_words.deinit(gpa);
+ try new_words.ensureTotalCapacity(gpa, binary.instructions.len);
+
+ var new_functions_start: ?usize = null;
+
+ it = binary.iterateInstructions();
+ while (it.next()) |inst| {
+ if (inst.offset >= binary.functions_start and inst.opcode == .OpFunction) {
+ const inst_spec = parser.getInstSpec(inst.opcode) orelse continue;
+ const result_id = getResultId(inst, inst_spec) orelse continue;
+ const index = id_to_index.get(result_id) orelse continue;
+ if (!alive.isSet(index)) {
+ while (it.next()) |inner| {
+ if (inner.opcode == .OpFunctionEnd) break;
+ }
+ continue;
+ }
+ }
+
+ const is_prunable = canPrune(inst.opcode) or
+ (inst.opcode == .OpExtInst and inst.offset < binary.functions_start);
+ if (is_prunable) {
+ const inst_spec = parser.getInstSpec(inst.opcode) orelse {
+ appendInst(&new_words, binary, inst, &new_functions_start);
+ continue;
+ };
+
+ if (getResultId(inst, inst_spec)) |result_id| {
+ const index = id_to_index.get(result_id) orelse {
+ appendInst(&new_words, binary, inst, &new_functions_start);
+ continue;
+ };
+ if (!alive.isSet(index)) continue;
+ } else {
+ // annotation-style: emit only if the target id is alive
+ if (inst.operands.len > 0) {
+ const target: ResultId = @enumFromInt(inst.operands[0]);
+ if (id_to_index.get(target)) |idx| {
+ if (!alive.isSet(idx)) continue;
+ } else continue;
+ }
+ }
+ }
+
+ appendInst(&new_words, binary, inst, &new_functions_start);
+ }
+
+ {
+ var to_remove: std.ArrayList(ResultId) = .empty;
+ defer to_remove.deinit(gpa);
+
+ var ext_it = binary.ext_inst_map.iterator();
+ while (ext_it.next()) |entry| {
+ if (id_to_index.get(entry.key_ptr.*)) |index| {
+ if (!alive.isSet(index)) try to_remove.append(gpa, entry.key_ptr.*);
+ }
+ }
+ for (to_remove.items) |id| _ = binary.ext_inst_map.remove(id);
+
+ to_remove.items.len = 0;
+ var arith_it = binary.arith_type_width.iterator();
+ while (arith_it.next()) |entry| {
+ if (id_to_index.get(entry.key_ptr.*)) |index| {
+ if (!alive.isSet(index)) try to_remove.append(gpa, entry.key_ptr.*);
+ }
+ }
+ for (to_remove.items) |id| _ = binary.arith_type_width.remove(id);
+ }
+
+ binary.instructions = try gpa.dupe(Word, new_words.items);
+ binary.functions_start = new_functions_start orelse new_words.items.len;
+}
+
+fn appendInst(
+ new_words: *std.ArrayList(Word),
+ binary: *const BinaryModule,
+ inst: BinaryModule.Instruction,
+ new_functions_start: *?usize,
+) void {
+ if (new_functions_start.* == null and inst.offset >= binary.functions_start) {
+ new_functions_start.* = new_words.items.len;
+ }
+ const len = @as(usize, binary.instructions[inst.offset] >> 16);
+ new_words.appendSliceAssumeCapacity(binary.instructions[inst.offset..][0..len]);
+}
+
+fn markAlive(
+ parser: *BinaryModule.Parser,
+ binary: BinaryModule,
+ inst: BinaryModule.Instruction,
+ alive: *std.DynamicBitSetUnmanaged,
+ id_to_index: *const std.AutoHashMapUnmanaged(ResultId, u32),
+ code_offsets: *const std.ArrayList(usize),
+ id_offset_buf: *std.ArrayList(u16),
+) !void {
+ const start = id_offset_buf.items.len;
+ try parser.parseInstructionResultIds(binary, inst, id_offset_buf);
+ const end = id_offset_buf.items.len;
+
+ var i = start;
+ while (i < end) : (i += 1) {
+ const off = id_offset_buf.items[i];
+ const id: ResultId = @enumFromInt(inst.operands[off]);
+ const index = id_to_index.get(id) orelse continue;
+ if (alive.isSet(index)) continue;
+ alive.set(index);
+
+ const offset = code_offsets.items[index];
+ const ref_inst = BinaryModule.Instruction{
+ .opcode = @enumFromInt(binary.instructions[offset] & 0xFFFF),
+ .offset = offset,
+ .operands = blk: {
+ const l = binary.instructions[offset] >> 16;
+ break :blk binary.instructions[offset..][1..l];
+ },
+ };
+
+ if (ref_inst.opcode == .OpFunction) {
+ var fn_it = binary.iterateInstructionsFrom(ref_inst.offset);
+ _ = fn_it.next();
+ while (fn_it.next()) |fn_inst| {
+ if (fn_inst.opcode == .OpFunctionEnd) break;
+ try markAlive(parser, binary, fn_inst, alive, id_to_index, code_offsets, id_offset_buf);
+ }
+ try markAlive(parser, binary, ref_inst, alive, id_to_index, code_offsets, id_offset_buf);
+ } else {
+ try markAlive(parser, binary, ref_inst, alive, id_to_index, code_offsets, id_offset_buf);
+ }
+ }
+}
+
+fn getResultId(inst: BinaryModule.Instruction, inst_spec: spec.Instruction) ?ResultId {
+ for (0..@min(2, inst_spec.operands.len)) |i| {
+ if (inst_spec.operands[i].kind == .id_result) {
+ if (i < inst.operands.len) return @enumFromInt(inst.operands[i]);
+ }
+ }
+ return null;
+}
+
+fn canPrune(op: Opcode) bool {
+ return switch (op.class()) {
+ .type_declaration,
+ .constant_creation,
+ .annotation,
+ => true,
+ else => switch (op) {
+ .OpFunction,
+ .OpUndef,
+ .OpString,
+ .OpName,
+ .OpMemberName,
+ .OpVariable,
+ => true,
+ else => false,
+ },
+ };
+}
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
index 88502d8329e81c37e3dd3a7f8c48b7cd7bfd29a9..fd18419bab38858a538154f459cb683e2a345d2c 100644
--- a/src/link/Wasm.zig
+++ b/src/link/Wasm.zig
@@ -80,27 +80,27 @@ name: []const u8,
/// List of relocatable files to be linked into the final binary.
objects: std.ArrayList(Object) = .empty,
-func_types: std.AutoArrayHashMapUnmanaged(FunctionType, void) = .empty,
+func_types: std.array_hash_map.Auto(FunctionType, void) = .empty,
/// Provides a mapping of both imports and provided functions to symbol name.
/// Local functions may be unnamed.
/// Key is symbol name, however the `FunctionImport` may have an name override for the import name.
-object_function_imports: std.AutoArrayHashMapUnmanaged(String, FunctionImport) = .empty,
+object_function_imports: std.array_hash_map.Auto(String, FunctionImport) = .empty,
/// All functions for all objects.
object_functions: std.ArrayList(ObjectFunction) = .empty,
/// Provides a mapping of both imports and provided globals to symbol name.
/// Local globals may be unnamed.
-object_global_imports: std.AutoArrayHashMapUnmanaged(String, GlobalImport) = .empty,
+object_global_imports: std.array_hash_map.Auto(String, GlobalImport) = .empty,
/// All globals for all objects.
object_globals: std.ArrayList(ObjectGlobal) = .empty,
/// All table imports for all objects.
-object_table_imports: std.AutoArrayHashMapUnmanaged(String, TableImport) = .empty,
+object_table_imports: std.array_hash_map.Auto(String, TableImport) = .empty,
/// All parsed table sections for all objects.
object_tables: std.ArrayList(Table) = .empty,
/// All memory imports for all objects.
-object_memory_imports: std.AutoArrayHashMapUnmanaged(String, MemoryImport) = .empty,
+object_memory_imports: std.array_hash_map.Auto(String, MemoryImport) = .empty,
/// All parsed memory sections for all objects.
object_memories: std.ArrayList(ObjectMemory) = .empty,
@@ -119,15 +119,15 @@ object_data_segments: std.ArrayList(ObjectDataSegment) = .empty,
/// Each segment has many data symbols, which correspond logically to global
/// constants.
object_datas: std.ArrayList(ObjectData) = .empty,
-object_data_imports: std.AutoArrayHashMapUnmanaged(String, ObjectDataImport) = .empty,
+object_data_imports: std.array_hash_map.Auto(String, ObjectDataImport) = .empty,
/// Non-synthetic section that can essentially be mem-cpy'd into place after performing relocations.
-object_custom_segments: std.AutoArrayHashMapUnmanaged(ObjectSectionIndex, CustomSegment) = .empty,
+object_custom_segments: std.array_hash_map.Auto(ObjectSectionIndex, CustomSegment) = .empty,
/// All comdat information for all objects.
object_comdats: std.ArrayList(Comdat) = .empty,
/// A table that maps the relocations to be performed where the key represents
/// the section (across all objects) that the slice of relocations applies to.
-object_relocations_table: std.AutoArrayHashMapUnmanaged(ObjectSectionIndex, ObjectRelocation.Slice) = .empty,
+object_relocations_table: std.array_hash_map.Auto(ObjectSectionIndex, ObjectRelocation.Slice) = .empty,
/// Incremented across all objects in order to enable calculation of `ObjectSectionIndex` values.
object_total_sections: u32 = 0,
/// All comdat symbols from all objects concatenated.
@@ -150,7 +150,7 @@ nav_fixups: std.ArrayList(NavFixup) = .empty,
func_table_fixups: std.ArrayList(FuncTableFixup) = .empty,
/// Symbols to be emitted into an object file. Remains empty when not emitting
/// an object file.
-symbol_table: std.AutoArrayHashMapUnmanaged(String, void) = .empty,
+symbol_table: std.array_hash_map.Auto(String, void) = .empty,
/// When importing objects from the host environment, a name must be supplied.
/// LLVM uses "env" by default when none is given.
@@ -174,24 +174,24 @@ preloaded_strings: PreloadedStrings,
/// This field is used when emitting an object; `navs_exe` used otherwise.
/// Does not include externs since that data lives elsewhere.
-navs_obj: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, ZcuDataObj) = .empty,
+navs_obj: std.array_hash_map.Auto(InternPool.Nav.Index, ZcuDataObj) = .empty,
/// This field is unused when emitting an object; `navs_obj` used otherwise.
/// Does not include externs since that data lives elsewhere.
-navs_exe: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, ZcuDataExe) = .empty,
+navs_exe: std.array_hash_map.Auto(InternPool.Nav.Index, ZcuDataExe) = .empty,
/// Tracks all InternPool values referenced by codegen. Needed for outputting
/// the data segment. This one does not track ref count because object files
/// require using max LEB encoding for these references anyway.
-uavs_obj: std.AutoArrayHashMapUnmanaged(InternPool.Index, ZcuDataObj) = .empty,
+uavs_obj: std.array_hash_map.Auto(InternPool.Index, ZcuDataObj) = .empty,
/// Tracks ref count to optimize LEB encodings for UAV references.
-uavs_exe: std.AutoArrayHashMapUnmanaged(InternPool.Index, ZcuDataExe) = .empty,
+uavs_exe: std.array_hash_map.Auto(InternPool.Index, ZcuDataExe) = .empty,
/// Sparse table of uavs that need to be emitted with greater alignment than
/// the default for the type.
-overaligned_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .empty,
+overaligned_uavs: std.array_hash_map.Auto(InternPool.Index, Alignment) = .empty,
/// When the key is an enum type, this represents a `@tagName` function.
-zcu_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ZcuFunc) = .empty,
-nav_exports: std.AutoArrayHashMapUnmanaged(NavExport, Zcu.Export.Index) = .empty,
-uav_exports: std.AutoArrayHashMapUnmanaged(UavExport, Zcu.Export.Index) = .empty,
-imports: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty,
+zcu_funcs: std.array_hash_map.Auto(InternPool.Index, ZcuFunc) = .empty,
+nav_exports: std.array_hash_map.Auto(NavExport, Zcu.Export.Index) = .empty,
+uav_exports: std.array_hash_map.Auto(UavExport, Zcu.Export.Index) = .empty,
+imports: std.array_hash_map.Auto(InternPool.Nav.Index, void) = .empty,
dwarf: ?Dwarf = null,
@@ -200,19 +200,19 @@ flush_buffer: Flush = .{},
/// Empty until `prelink`. There it is populated based on object files.
/// Next, it is copied into `Flush.missing_exports` just before `flush`
/// and that data is used during `flush`.
-missing_exports: std.AutoArrayHashMapUnmanaged(String, void) = .empty,
+missing_exports: std.array_hash_map.Auto(String, void) = .empty,
entry_resolution: FunctionImport.Resolution = .unresolved,
/// Empty when outputting an object.
-function_exports: std.AutoArrayHashMapUnmanaged(String, FunctionIndex) = .empty,
-hidden_function_exports: std.AutoArrayHashMapUnmanaged(String, FunctionIndex) = .empty,
+function_exports: std.array_hash_map.Auto(String, FunctionIndex) = .empty,
+hidden_function_exports: std.array_hash_map.Auto(String, FunctionIndex) = .empty,
global_exports: std.ArrayList(GlobalExport) = .empty,
/// Tracks the value at the end of prelink.
global_exports_len: u32 = 0,
/// Ordered list of non-import functions that will appear in the final binary.
/// Empty until prelink.
-functions: std.AutoArrayHashMapUnmanaged(FunctionImport.Resolution, void) = .empty,
+functions: std.array_hash_map.Auto(FunctionImport.Resolution, void) = .empty,
/// Tracks the value at the end of prelink, at which point `functions`
/// contains only object file functions, and nothing from the Zcu yet.
functions_end_prelink: u32 = 0,
@@ -230,7 +230,7 @@ data_imports_len_prelink: u32 = 0,
/// `flush` gets a copy of this table, and then Zcu exports are applied to
/// remove elements from the table, and the remainder are either undefined
/// symbol errors, or import section entries depending on the output mode.
-function_imports: std.AutoArrayHashMapUnmanaged(String, FunctionImportId) = .empty,
+function_imports: std.array_hash_map.Auto(String, FunctionImportId) = .empty,
/// At the end of prelink, this is populated with data symbols needed by
/// objects.
@@ -243,29 +243,29 @@ function_imports: std.AutoArrayHashMapUnmanaged(String, FunctionImportId) = .emp
/// `flush` gets a copy of this table, and then Zcu exports are applied to
/// remove elements from the table, and the remainder are either undefined
/// symbol errors, or symbol table entries depending on the output mode.
-data_imports: std.AutoArrayHashMapUnmanaged(String, DataImportId) = .empty,
+data_imports: std.array_hash_map.Auto(String, DataImportId) = .empty,
/// Set of data symbols that will appear in the final binary. Used to populate
/// `Flush.data_segments` before sorting.
-data_segments: std.AutoArrayHashMapUnmanaged(DataSegmentId, void) = .empty,
+data_segments: std.array_hash_map.Auto(DataSegmentId, void) = .empty,
/// Ordered list of non-import globals that will appear in the final binary.
/// Empty until prelink.
-globals: std.AutoArrayHashMapUnmanaged(GlobalImport.Resolution, void) = .empty,
+globals: std.array_hash_map.Auto(GlobalImport.Resolution, void) = .empty,
/// Tracks the value at the end of prelink, at which point `globals`
/// contains only object file globals, and nothing from the Zcu yet.
globals_end_prelink: u32 = 0,
-global_imports: std.AutoArrayHashMapUnmanaged(String, GlobalImportId) = .empty,
+global_imports: std.array_hash_map.Auto(String, GlobalImportId) = .empty,
/// Ordered list of non-import tables that will appear in the final binary.
/// Empty until prelink.
-tables: std.AutoArrayHashMapUnmanaged(TableImport.Resolution, void) = .empty,
-table_imports: std.AutoArrayHashMapUnmanaged(String, TableImport.Index) = .empty,
+tables: std.array_hash_map.Auto(TableImport.Resolution, void) = .empty,
+table_imports: std.array_hash_map.Auto(String, TableImport.Index) = .empty,
/// All functions that have had their address taken and therefore might be
/// called via a `call_indirect` function.
-zcu_indirect_function_set: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty,
-object_indirect_function_import_set: std.AutoArrayHashMapUnmanaged(String, void) = .empty,
-object_indirect_function_set: std.AutoArrayHashMapUnmanaged(ObjectFunctionIndex, void) = .empty,
+zcu_indirect_function_set: std.array_hash_map.Auto(InternPool.Nav.Index, void) = .empty,
+object_indirect_function_import_set: std.array_hash_map.Auto(String, void) = .empty,
+object_indirect_function_set: std.array_hash_map.Auto(ObjectFunctionIndex, void) = .empty,
error_name_table_ref_count: u32 = 0,
tag_name_table_ref_count: u32 = 0,
diff --git a/src/link/Wasm/Archive.zig b/src/link/Wasm/Archive.zig
index 9424eeabf41db56a8fab5fc55464bdeaba49d857..65a1ee313b8c6bc5e8710728cd877284c47b544f 100644
--- a/src/link/Wasm/Archive.zig
+++ b/src/link/Wasm/Archive.zig
@@ -12,7 +12,7 @@ toc: Toc,
/// Key points into `LazyArchive` `file_contents`.
/// Value is allocated with gpa.
-const Toc = std.StringArrayHashMapUnmanaged(std.ArrayList(u32));
+const Toc = std.array_hash_map.String(std.ArrayList(u32));
const ARMAG = std.elf.ARMAG;
const ARFMAG = std.elf.ARFMAG;
diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig
index 95bc18070facb84f8a5e5d5ab3286b2a6df8bc20..56b07cd158f0ab2b6fa79cc87daa15b76bbdb62f 100644
--- a/src/link/Wasm/Flush.zig
+++ b/src/link/Wasm/Flush.zig
@@ -24,22 +24,22 @@ const ArrayList = std.ArrayList;
/// Ordered list of data segments that will appear in the final binary.
/// When sorted, to-be-merged segments will be made adjacent.
/// Values are virtual address.
-data_segments: std.AutoArrayHashMapUnmanaged(Wasm.DataSegmentId, u32) = .empty,
+data_segments: std.array_hash_map.Auto(Wasm.DataSegmentId, u32) = .empty,
/// Each time a `data_segment` offset equals zero it indicates a new group, and
/// the next element in this array will contain the total merged segment size.
/// Value is the virtual memory address of the end of the segment.
data_segment_groups: ArrayList(DataSegmentGroup) = .empty,
binary_bytes: ArrayList(u8) = .empty,
-missing_exports: std.AutoArrayHashMapUnmanaged(String, void) = .empty,
-function_imports: std.AutoArrayHashMapUnmanaged(String, Wasm.FunctionImportId) = .empty,
-global_imports: std.AutoArrayHashMapUnmanaged(String, Wasm.GlobalImportId) = .empty,
-data_imports: std.AutoArrayHashMapUnmanaged(String, Wasm.DataImportId) = .empty,
+missing_exports: std.array_hash_map.Auto(String, void) = .empty,
+function_imports: std.array_hash_map.Auto(String, Wasm.FunctionImportId) = .empty,
+global_imports: std.array_hash_map.Auto(String, Wasm.GlobalImportId) = .empty,
+data_imports: std.array_hash_map.Auto(String, Wasm.DataImportId) = .empty,
-indirect_function_table: std.AutoArrayHashMapUnmanaged(Wasm.OutputFunctionIndex, void) = .empty,
+indirect_function_table: std.array_hash_map.Auto(Wasm.OutputFunctionIndex, void) = .empty,
/// A subset of the full interned function type list created only during flush.
-func_types: std.AutoArrayHashMapUnmanaged(Wasm.FunctionType.Index, void) = .empty,
+func_types: std.array_hash_map.Auto(Wasm.FunctionType.Index, void) = .empty,
/// For debug purposes only.
memory_layout_finished: bool = false,
diff --git a/src/link/loongarch.zig b/src/link/loongarch.zig
new file mode 100644
index 0000000000000000000000000000000000000000..be460a0c19e7f49094324c004bdd912b56474cea
--- /dev/null
+++ b/src/link/loongarch.zig
@@ -0,0 +1,55 @@
+const std = @import("std");
+const mem = std.mem;
+
+pub fn writeK12(code: *[4]u8, target_value: u12) void {
+ var inst = std.mem.readInt(u32, code, .little);
+ inst &= 0b11111111110000000000001111111111;
+ inst |= (@as(u32, target_value) << 10);
+ std.mem.writeInt(u32, code, inst, .little);
+}
+
+pub fn writeK16(code: *[4]u8, target_value: u16) void {
+ var inst = std.mem.readInt(u32, code, .little);
+ inst &= 0b11111100000000000000001111111111;
+ inst |= (@as(u32, target_value) << 10);
+ std.mem.writeInt(u32, code, inst, .little);
+}
+
+pub fn writeJ20(code: *[4]u8, target_value: u20) void {
+ var inst = std.mem.readInt(u32, code, .little);
+ inst &= 0b11111110000000000000000000011111;
+ inst |= (@as(u32, target_value) << 5);
+ std.mem.writeInt(u32, code, inst, .little);
+}
+
+pub fn writeD5K16(code: *[4]u8, target_value: u21) void {
+ var inst = std.mem.readInt(u32, code, .little);
+ inst &= 0b11111100000000000000001111100000;
+ inst |= @as(u32, target_value >> 16);
+ inst |= (@as(u32, target_value << 5) << 5);
+ std.mem.writeInt(u32, code, inst, .little);
+}
+
+pub fn writeD10K16(code: *[4]u8, target_value: u26) void {
+ var inst = std.mem.readInt(u32, code, .little);
+ inst &= 0b11111100000000000000000000000000;
+ inst |= @as(u32, target_value >> 16);
+ inst |= @as(u32, target_value << 10);
+ std.mem.writeInt(u32, code, inst, .little);
+}
+
+pub fn toPcalaHi20(target: u64, pc: u64) u20 {
+ return @truncate(((target +% 0x800) >> 12) -% (pc >> 12));
+}
+
+pub fn toPcala64Lo20(target: u64, pc: u64) u20 {
+ const fixup = if (target & 0x800 != 0) (@as(u64, 0x1000) -% @as(u64, 0x100000000)) else 0;
+ const hi32 = (((target +% 0x80000000 +% fixup) >> 12) -% ((pc -% 8) >> 12)) >> 20;
+ return @truncate(hi32);
+}
+
+pub fn toPcala64Hi12(target: u64, pc: u64) u12 {
+ const fixup = if (target & 0x800 != 0) (@as(u64, 0x1000) -% @as(u64, 0x100000000)) else 0;
+ const hi32 = (((target +% 0x80000000 +% fixup) >> 12) -% ((pc -% 12) >> 12)) >> 20;
+ return @truncate(hi32 >> 20);
+}
diff --git a/src/main.zig b/src/main.zig
index 142d5facb6dddffaa242d3e94081f2d549eb7a5c..4dd56dd3b0623c7836ce04604c9066b562a223a4 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -295,7 +295,7 @@ fn mainArgs(
// However it's possible Zig is installed as *that* C compiler as well, which is
// why we have this additional environment variable here to check.
- const inf_loop_env_key: EnvVar = .ZIG_IS_TRYING_TO_NOT_CALL_ITSELF;
+ const inf_loop_env_key: EnvVar = .ZIG_IS_AVOIDING_CALLING_ITSELF;
if (inf_loop_env_key.isSet(environ_map)) {
fatal("{s}", .{
"The compilation links against libc, but Zig is unable to provide a libc " ++
@@ -887,6 +887,7 @@ const CliModule = struct {
inherited: Package.Module.CreateOptions.Inherited,
target_arch_os_abi: ?[]const u8,
target_mcpu: ?[]const u8,
+ dynamic_linker: ?[]const u8,
deps: []const Dep,
resolved: ?*Package.Module,
@@ -943,6 +944,7 @@ fn buildOutputType(
var emit_implib_arg_provided = false;
var target_arch_os_abi: ?[]const u8 = null;
var target_mcpu: ?[]const u8 = null;
+ var dynamic_linker: ?[]const u8 = null;
var emit_h: Emit = .no;
var soname: SOName = undefined;
var want_compiler_rt: ?bool = null;
@@ -987,7 +989,7 @@ fn buildOutputType(
var test_no_exec = false;
var test_execve = false;
var entry: Compilation.CreateOptions.Entry = .default;
- var force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .empty;
+ var force_undefined_symbols: std.array_hash_map.String(void) = .empty;
var stack_size: ?u64 = null;
var image_base: ?u64 = null;
var link_eh_frame_hdr = false;
@@ -1024,7 +1026,7 @@ fn buildOutputType(
// These are before resolving sysroot.
var extra_cflags: std.ArrayList([]const u8) = .empty;
var extra_rcflags: std.ArrayList([]const u8) = .empty;
- var symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .empty;
+ var symbol_wrap_set: std.array_hash_map.String(void) = .empty;
var rc_includes: std.zig.RcIncludes = .any;
var manifest_file: ?[]const u8 = null;
var linker_export_symbol_names: std.ArrayList([]const u8) = .empty;
@@ -1059,7 +1061,6 @@ fn buildOutputType(
// Populated just before the call to `createModule`.
.dirs = undefined,
.object_format = null,
- .dynamic_linker = null,
.modules = .empty,
.opts = .{
.is_test = switch (arg_mode) {
@@ -1179,6 +1180,7 @@ fn buildOutputType(
&cc_argv,
&target_arch_os_abi,
&target_mcpu,
+ &dynamic_linker,
&deps,
&c_source_files_owner_index,
&rc_source_files_owner_index,
@@ -1397,9 +1399,9 @@ fn buildOutputType(
} else if (mem.cutPrefix(u8, arg, "-O")) |rest| {
mod_opts.optimize_mode = parseOptimizeMode(rest);
} else if (mem.eql(u8, arg, "--dynamic-linker")) {
- create_module.dynamic_linker = args_iter.nextOrFatal();
+ dynamic_linker = args_iter.nextOrFatal();
} else if (mem.eql(u8, arg, "--no-dynamic-linker")) {
- create_module.dynamic_linker = "";
+ dynamic_linker = "";
} else if (mem.eql(u8, arg, "--sysroot")) {
const next_arg = args_iter.nextOrFatal();
create_module.sysroot = next_arg;
@@ -1438,8 +1440,8 @@ fn buildOutputType(
dev.check(.stdio_listen);
listen = .stdio;
} else if (mem.eql(u8, arg, "--debug-link-snapshot")) {
- if (!build_options.enable_link_snapshots) {
- warn("Zig was compiled without linker snapshots enabled (-Dlink-snapshot). --debug-link-snapshot has no effect.", .{});
+ if (!build_options.enable_debug_extensions) {
+ warn("Zig was compiled without debug extensions. --debug-link-snapshot has no effect.", .{});
} else {
enable_link_snapshots = true;
}
@@ -1846,7 +1848,7 @@ fn buildOutputType(
const lang = if (rest.len == 0) args_iter.nextOrFatal() else rest;
if (mem.eql(u8, lang, "none")) {
file_ext = null;
- } else if (Compilation.LangToExt.get(lang)) |got_ext| {
+ } else if (Compilation.FileExt.from_lang.get(lang)) |got_ext| {
file_ext = got_ext;
} else {
fatal("language not recognized: {s}", .{lang});
@@ -1983,7 +1985,7 @@ fn buildOutputType(
const lang = mem.sliceTo(it.only_arg, 0);
if (mem.eql(u8, lang, "none")) {
file_ext = null;
- } else if (Compilation.LangToExt.get(lang)) |got_ext| {
+ } else if (Compilation.FileExt.from_lang.get(lang)) |got_ext| {
file_ext = got_ext;
} else {
fatal("language not recognized: {q}", .{lang});
@@ -2610,12 +2612,11 @@ fn buildOutputType(
mem.eql(u8, arg, "--dynamic-linker") or
mem.eql(u8, arg, "-dynamic-linker"))
{
- create_module.dynamic_linker = linker_args_it.nextOrFatal();
- } else if (mem.eql(u8, arg, "-I") or
- mem.eql(u8, arg, "--no-dynamic-linker") or
+ dynamic_linker = linker_args_it.nextOrFatal();
+ } else if (mem.eql(u8, arg, "--no-dynamic-linker") or
mem.eql(u8, arg, "-no-dynamic-linker"))
{
- create_module.dynamic_linker = "";
+ dynamic_linker = "";
} else if (mem.eql(u8, arg, "-E") or
mem.eql(u8, arg, "--export-dynamic") or
mem.eql(u8, arg, "-export-dynamic"))
@@ -3184,6 +3185,7 @@ fn buildOutputType(
.inherited = mod_opts,
.target_arch_os_abi = target_arch_os_abi,
.target_mcpu = target_mcpu,
+ .dynamic_linker = dynamic_linker,
.deps = try deps.toOwnedSlice(arena),
.resolved = null,
.c_source_files_start = c_source_files_owner_index,
@@ -3592,7 +3594,7 @@ fn buildOutputType(
defer file_system_inputs.deinit(gpa);
// Deduplicate rpath entries
- var rpath_dedup = std.StringArrayHashMapUnmanaged(void){};
+ var rpath_dedup = std.array_hash_map.String(void){};
for (create_module.rpath_list.items) |rpath| {
try rpath_dedup.put(arena, rpath, {});
}
@@ -3842,10 +3844,59 @@ fn buildOutputType(
if (test_exec_args.items.len == 0 and target.ofmt == .c and emit_bin_resolved != .no) {
// Default to using `zig run` to execute the produced .c code from `zig test`.
try test_exec_args.appendSlice(arena, &.{ self_exe_path, "run" });
- if (dirs.zig_lib.path) |p| {
- try test_exec_args.appendSlice(arena, &.{ "-I", p });
+ // Skip passing `-ofmt`, we want the default for the target, not `.c` anymore.
+
+ var prev_has_cflags = false;
+ var prev_has_rcflags = false;
+ if (dirs.zig_lib.path) |zig_lib_path| {
+ try test_exec_args.appendSlice(arena, &.{ "-cflags", "-I", zig_lib_path, "--" });
+ prev_has_cflags = true;
+ }
+ try test_exec_args.append(arena, null);
+ for (create_module.modules.keys(), create_module.modules.values()) |mod_name, mod| {
+ for (create_module.c_source_files.items[mod.c_source_files_start..mod.c_source_files_end]) |c_source_file| {
+ const cflags_len = c_source_file.extra_flags.len + c_source_file.cache_exempt_flags.len;
+ if (prev_has_cflags or cflags_len > 0) {
+ try test_exec_args.ensureUnusedCapacity(arena, 1 + cflags_len + 1);
+ test_exec_args.appendAssumeCapacity("-cflags");
+ for (c_source_file.extra_flags) |extra_flag| test_exec_args.appendAssumeCapacity(extra_flag);
+ for (c_source_file.cache_exempt_flags) |cache_exempt_flag| test_exec_args.appendAssumeCapacity(cache_exempt_flag);
+ test_exec_args.appendAssumeCapacity("--");
+ }
+ prev_has_cflags = cflags_len > 0;
+ if (c_source_file.ext) |ext| try test_exec_args.appendSlice(arena, &.{ "-x", ext.toLang() });
+ try test_exec_args.append(arena, c_source_file.src_path);
+ if (c_source_file.ext) |_| try test_exec_args.appendSlice(arena, &.{ "-x", "none" });
+ }
+ for (create_module.rc_source_files.items[mod.rc_source_files_start..mod.rc_source_files_end]) |rc_source_file| {
+ const rcflags_len = rc_source_file.extra_flags.len;
+ if (prev_has_rcflags or rcflags_len > 0) {
+ try test_exec_args.ensureUnusedCapacity(arena, 1 + rcflags_len + 1);
+ test_exec_args.appendAssumeCapacity("-rcflags");
+ for (rc_source_file.extra_flags) |extra_flag| test_exec_args.appendAssumeCapacity(extra_flag);
+ test_exec_args.appendAssumeCapacity("--");
+ }
+ prev_has_rcflags = rcflags_len > 0;
+ try test_exec_args.append(arena, rc_source_file.src_path);
+ }
+ if (mod.target_arch_os_abi) |triple| try test_exec_args.appendSlice(arena, &.{ "-target", triple });
+ if (mod.target_mcpu) |mcpu| try test_exec_args.appendSlice(arena, &.{ "-mcpu", mcpu });
+ if (mod.dynamic_linker) |dl| if (dl.len > 0)
+ try test_exec_args.appendSlice(arena, &.{ "--dynamic-linker", dl })
+ else
+ try test_exec_args.append(arena, "--no-dynamic-linker");
+ try test_exec_args.ensureUnusedCapacity(arena, mod.cc_argv.len);
+ for (mod.cc_argv) |cc_arg| test_exec_args.appendAssumeCapacity(cc_arg);
+ for (mod.deps) |dep| try test_exec_args.appendSlice(arena, &.{
+ "--dep",
+ if (std.mem.eql(u8, dep.key, dep.value)) dep.value else try std.fmt.allocPrint(arena, "{s}={s}", .{ dep.key, dep.value }),
+ });
+ try test_exec_args.append(arena, try std.fmt.allocPrint(arena, "-M{s}", .{mod_name}));
}
+ try test_exec_args.ensureUnusedCapacity(arena, comp.global_cc_argv.len);
+ for (comp.global_cc_argv) |global_cc_arg| test_exec_args.appendAssumeCapacity(global_cc_arg);
+ if (create_module.resolved_options.link_libcpp) try test_exec_args.append(arena, "-lc++");
if (create_module.resolved_options.link_libc) {
try test_exec_args.append(arena, "-lc");
} else if (target.os.tag == .windows) {
@@ -3855,21 +3906,10 @@ fn buildOutputType(
});
}
- const first_cli_mod = create_module.modules.values()[0];
- if (first_cli_mod.target_arch_os_abi) |triple| {
- try test_exec_args.appendSlice(arena, &.{ "-target", triple });
- }
- if (first_cli_mod.target_mcpu) |mcpu| {
- try test_exec_args.append(arena, try std.fmt.allocPrint(arena, "-mcpu={s}", .{mcpu}));
- }
- if (create_module.dynamic_linker) |dl| {
- if (dl.len > 0) {
- try test_exec_args.appendSlice(arena, &.{ "--dynamic-linker", dl });
- } else {
- try test_exec_args.append(arena, "--no-dynamic-linker");
- }
- }
- try test_exec_args.append(arena, null); // placeholder for the path of the emitted C source file
+ try test_exec_args.ensureUnusedCapacity(arena, 2 * log_scopes.items.len + @intFromBool(verbose_link) + @intFromBool(verbose_cc));
+ for (log_scopes.items) |log_scope| test_exec_args.appendSliceAssumeCapacity(&.{ "--debug-log", log_scope });
+ if (verbose_link) test_exec_args.appendAssumeCapacity("--verbose-link");
+ if (verbose_cc) test_exec_args.appendAssumeCapacity("--verbose-cc");
}
try runOrTest(
@@ -3896,9 +3936,8 @@ fn buildOutputType(
const CreateModule = struct {
dirs: Compilation.Directories,
- modules: std.StringArrayHashMapUnmanaged(CliModule),
+ modules: std.array_hash_map.String(CliModule),
opts: Compilation.Config.Options,
- dynamic_linker: ?[]const u8,
object_format: ?[]const u8,
/// undefined until createModule() for the root module is called.
resolved_options: Compilation.Config,
@@ -3908,7 +3947,7 @@ const CreateModule = struct {
/// link_libcpp, and then the libraries are filtered into
/// `unresolved_link_inputs` and `windows_libs`.
cli_link_inputs: std.ArrayList(link.UnresolvedInput),
- windows_libs: std.StringArrayHashMapUnmanaged(void),
+ windows_libs: std.array_hash_map.String(void),
/// The local variable `unresolved_link_inputs` is fed into library
/// resolution, mutating the input array, and producing this data as
/// output. Allocated with gpa.
@@ -3926,7 +3965,7 @@ const CreateModule = struct {
lib_dir_args: std.ArrayList([]const u8),
libc_installation: ?LibCInstallation,
want_native_include_dirs: bool,
- frameworks: std.StringArrayHashMapUnmanaged(Framework),
+ frameworks: std.array_hash_map.String(Framework),
native_system_include_paths: []const []const u8,
framework_dirs: std.ArrayList([]const u8),
rpath_list: std.ArrayList([]const u8),
@@ -3960,7 +3999,7 @@ fn createModule(
var target_parse_options: std.Target.Query.ParseOptions = .{
.arch_os_abi = cli_mod.target_arch_os_abi orelse "native",
.cpu_features = cli_mod.target_mcpu,
- .dynamic_linker = create_module.dynamic_linker,
+ .dynamic_linker = cli_mod.dynamic_linker,
.object_format = create_module.object_format,
};
@@ -4419,7 +4458,7 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void {
var file_name_bytes: std.ArrayList(u8) = .empty;
defer file_name_bytes.deinit(gpa);
- var files: std.AutoArrayHashMapUnmanaged(Zcu.File.Index, void) = .empty;
+ var files: std.array_hash_map.Auto(Zcu.File.Index, void) = .empty;
defer files.deinit(gpa);
var decl_data: std.ArrayList(u8) = .empty;
defer decl_data.deinit(gpa);
@@ -7844,6 +7883,7 @@ fn handleModArg(
cc_argv: *std.ArrayList([]const u8),
target_arch_os_abi: *?[]const u8,
target_mcpu: *?[]const u8,
+ dynamic_linker: *?[]const u8,
deps: *std.ArrayList(CliModule.Dep),
c_source_files_owner_index: *usize,
rc_source_files_owner_index: *usize,
@@ -7892,6 +7932,7 @@ fn handleModArg(
.inherited = mod_opts.*,
.target_arch_os_abi = target_arch_os_abi.*,
.target_mcpu = target_mcpu.*,
+ .dynamic_linker = dynamic_linker.*,
.deps = try deps.toOwnedSlice(arena),
.resolved = null,
.c_source_files_start = c_source_files_owner_index.*,
@@ -7903,6 +7944,7 @@ fn handleModArg(
mod_opts.* = .{};
target_arch_os_abi.* = null;
target_mcpu.* = null;
+ dynamic_linker.* = null;
c_source_files_owner_index.* = create_module.c_source_files.items.len;
rc_source_files_owner_index.* = create_module.rc_source_files.items.len;
}
diff --git a/src/print_value.zig b/src/print_value.zig
index be363a76b707723432ad01c7d8955d5d64459bbe..54d81d50d26abba08d8bde2d60820c8b652f02f9 100644
--- a/src/print_value.zig
+++ b/src/print_value.zig
@@ -60,6 +60,7 @@ pub fn print(
.union_type,
.opaque_type,
.enum_type,
+ .spirv_type,
.func_type,
.error_set_type,
.inferred_error_set_type,
diff --git a/src/print_zir.zig b/src/print_zir.zig
index 596c6d504091089638d35af7901f45091227ad9c..64703fbd60052209854fc733570fa008ec5b201e 100644
--- a/src/print_zir.zig
+++ b/src/print_zir.zig
@@ -204,6 +204,8 @@ const Writer = struct {
.ensure_result_used,
.ensure_result_non_error,
.ensure_err_union_payload_void,
+ .deref,
+ .ref_deref,
.ret_node,
.ret_load,
.resolve_inferred_alloc,
@@ -260,7 +262,6 @@ const Writer = struct {
.bit_reverse,
.@"resume",
.make_ptr_const,
- .validate_deref,
.validate_const,
.check_comptime_control_flow,
.opt_eu_base_ptr_init,
@@ -685,6 +686,16 @@ const Writer = struct {
defer self.parent_decl_node = prev_parent_decl_node;
try self.writeSrcNode(stream, .zero);
},
+ .reify_spirv_type => {
+ const extra = self.code.extraData(Zir.Inst.ReifySpirvType, extended.operand).data;
+ try stream.print("line({d}), ", .{extra.src_line});
+ try self.writeInstRef(stream, extra.operand);
+ try stream.writeAll(")) ");
+ const prev_parent_decl_node = self.parent_decl_node;
+ self.parent_decl_node = extra.node;
+ defer self.parent_decl_node = prev_parent_decl_node;
+ try self.writeSrcNode(stream, .zero);
+ },
.cmpxchg => try self.writeCmpxchg(stream, extended),
.ptr_cast_full => try self.writePtrCastFull(stream, extended),
diff --git a/src/target.zig b/src/target.zig
index 997dbb89453bf30bcbc5cb172000684c27d75ba6..200591c68ebae9abba03633ec3ece7fbc88906bf 100644
--- a/src/target.zig
+++ b/src/target.zig
@@ -164,7 +164,10 @@ pub fn hasValgrindSupport(target: *const std.Target, backend: std.lang.CompilerB
else => false,
},
.x86_64 => switch (target.os.tag) {
- .linux => target.abi != .gnux32 and target.abi != .muslx32,
+ .linux => switch (target.abi) {
+ .gnux32, .muslx32, .x32 => false,
+ else => true,
+ },
.freebsd, .illumos => true,
.windows => !ofmt_c_msvc,
else => false,
@@ -700,7 +703,7 @@ pub fn llvmMachineAbi(target: *const std.Target) ?[:0]const u8 {
},
.mips, .mipsel => "o32",
.mips64, .mips64el => switch (target.abi) {
- .gnuabin32, .muslabin32 => "n32",
+ .gnuabin32, .muslabin32, .abin32 => "n32",
else => "n64",
},
.powerpc64 => if (target.os.tag == .ps3) "elfv1" else "elfv2",
@@ -950,9 +953,6 @@ pub inline fn backendSupportsFeature(backend: std.lang.CompilerBackend, comptime
// threads because they would all just be locking the same mutex to
// protect Builder.
.stage2_llvm => false,
- // Same problem. Frontend needs to allow this backend to run in the
- // linker thread.
- .stage2_spirv => false,
// Please do not make any more exceptions. Backends must support
// being run in a separate thread from now on.
else => true,
diff --git a/stage1/zig.h b/stage1/zig.h
index f2faed0b376201db96a464f6c1394f2fc26f8aa8..34b56286a508b2707f4498f49612d9d625ee7c86 100644
--- a/stage1/zig.h
+++ b/stage1/zig.h
@@ -11,8 +11,6 @@
#elif defined(__GNUC__)
#define zig_gcc
#define zig_gnuc
-#elif defined(__IBMC__)
-#define zig_xlc
#elif defined(__TINYC__)
#define zig_tinyc
#elif defined(__slimcc__)
@@ -28,8 +26,18 @@
#define zig_arm
#elif defined(__arm__)
#define zig_arm
+#elif defined(__arc__)
+#define zig_arc
+#elif defined(__csky__)
+#define zig_csky
#elif defined(__hexagon__)
#define zig_hexagon
+#elif defined(__hppa__) && defined(_LP64)
+#define zig_hppa64
+#define zig_hppa
+#elif defined(__hppa__)
+#define zig_hppa32
+#define zig_hppa
#elif defined(__kvx__)
#define zig_kvx
#elif defined(__loongarch32)
@@ -42,6 +50,8 @@
#define zig_m68k
#elif defined(__m88k__)
#define zig_m88k
+#elif defined(__microblaze__)
+#define zig_microblaze
#elif defined(__mips64)
#define zig_mips64
#define zig_mips
@@ -64,6 +74,8 @@
#define zig_riscv
#elif defined(__s390x__)
#define zig_s390x
+#elif defined(__sh__)
+#define zig_sh
#elif defined(__sparc__) && defined(__arch64__)
#define zig_sparc64
#define zig_sparc
@@ -100,32 +112,30 @@
#define zig_big_endian 1
#endif
-#if defined(__MACH__)
+#if defined(__APPLE__)
#define zig_darwin
#elif defined(__DragonFly__)
#define zig_dragonfly
-#define zig_bsd
#elif defined(__EMSCRIPTEN__)
#define zig_emscripten
#elif defined(__FreeBSD__)
#define zig_freebsd
-#define zig_bsd
#elif defined(__Fuchsia__)
#define zig_fuchsia
#elif defined(__HAIKU__)
#define zig_haiku
#elif defined(__gnu_hurd__)
#define zig_hurd
+#elif defined(__illumos__)
+#define zig_illumos
#elif defined(__linux__)
#define zig_linux
#elif defined(__NetBSD__)
#define zig_netbsd
-#define zig_bsd
#elif defined(__OpenBSD__)
#define zig_openbsd
-#define zig_bsd
-#elif defined(__SVR4)
-#define zig_solaris
+#elif defined(__serenity__)
+#define zig_serenity
#elif defined(__wasi__)
#define zig_wasi
#elif defined(_WIN32)
@@ -404,14 +414,22 @@
#define zig_trap() __asm__ volatile("udf #0xfe")
#elif defined(zig_arm) || defined(zig_aarch64)
#define zig_trap() __asm__ volatile("udf #0xfdee")
+#elif defined(zig_arc)
+#define zig_trap() __asm__ volatile("unimp_s")
+#elif defined(zig_csky)
+#define zig_trap() __asm__ volatile(".word 0x3fff")
#elif defined(zig_hexagon)
#define zig_trap() __asm__ volatile("r27:26 = memd(#0xbadc0fee)")
+#elif defined(zig_hppa)
+#define zig_trap() __asm__ volatile("iitlbp %r0, (%sr0, %r0)")
#elif defined(zig_kvx) || defined(zig_loongarch) || defined(zig_powerpc)
#define zig_trap() __asm__ volatile(".word 0x0")
#elif defined(zig_m68k)
#define zig_trap() __asm__ volatile("illegal")
#elif defined(zig_m88k)
#define zig_trap() __asm__ volatile("tb0 0, %%r0, 511")
+#elif defined(zig_microblaze)
+#define zig_trap() __asm__ volatile("getd r0, r0")
#elif defined(zig_mips)
#define zig_trap() __asm__ volatile(".word 0x3d")
#elif defined(zig_or1k)
@@ -420,6 +438,8 @@
#define zig_trap() __asm__ volatile("unimp")
#elif defined(zig_s390x)
#define zig_trap() __asm__ volatile("j 0x2")
+#elif defined(zig_sh)
+#define zig_trap() __asm__ volatile(".word 0x0001")
#elif defined(zig_sparc)
#define zig_trap() __asm__ volatile("illtrap")
#elif defined(zig_x86_16)
@@ -446,16 +466,22 @@
#if defined(zig_alpha)
#define zig_breakpoint() __asm__ volatile("call_pal 0x000080")
-#elif defined(zig_arm)
+#elif defined(zig_arm) || defined(zig_csky)
#define zig_breakpoint() __asm__ volatile("bkpt #0x0")
#elif defined(zig_aarch64)
#define zig_breakpoint() __asm__ volatile("brk #0xf000")
+#elif defined(zig_arc)
+#define zig_breakpoint() __asm__ volatile("brk_s")
#elif defined(zig_hexagon)
#define zig_breakpoint() __asm__ volatile("brkpt")
+#elif defined(zig_hppa)
+#define zig_breakpoint() __asm__ volatile("break 0x04, 0x0008")
#elif defined(zig_kvx) || defined(zig_loongarch)
#define zig_breakpoint() __asm__ volatile("break 0x0")
#elif defined(zig_m88k)
#define zig_breakpoint() __asm__ volatile("illop1")
+#elif defined(zig_microblaze)
+#define zig_breakpoint() __asm__ volatile("brki r16, 0x0018")
#elif defined(zig_mips)
#define zig_breakpoint() __asm__ volatile("break")
#elif defined(zig_or1k)
@@ -466,6 +492,8 @@
#define zig_breakpoint() __asm__ volatile("ebreak")
#elif defined(zig_s390x)
#define zig_breakpoint() __asm__ volatile("j 0x6")
+#elif defined(zig_sh)
+#define zig_breakpoint() __asm__ volatile("trapa #0xc3")
#elif defined(zig_sparc)
#define zig_breakpoint() __asm__ volatile("ta 0x1")
#elif defined(zig_x86)
@@ -4529,9 +4557,12 @@ static inline void zig_msvc_atomic_store_i128(zig_i128 volatile* obj, zig_i128 a
#include
#endif
+static inline void* zig_e_zig_windows_teb(void) zig_mangled(zig_e_zig_windows_teb, "zig_windows_teb");
+static inline void* zig_e_zig_windows_peb(void) zig_mangled(zig_e_zig_windows_peb, "zig_windows_peb");
+
#if defined(zig_thumb)
-static inline void* zig_windows_teb(void) {
+static inline void* zig_e_zig_windows_teb(void) {
void* teb = 0;
#if defined(zig_msvc)
teb = (void*)_MoveFromCoprocessor(15, 0, 13, 0, 2);
@@ -4543,7 +4574,7 @@ static inline void* zig_windows_teb(void) {
#elif defined(zig_aarch64)
-static inline void* zig_windows_teb(void) {
+static inline void* zig_e_zig_windows_teb(void) {
void* teb = 0;
#if defined(zig_msvc)
teb = (void*)__readx18qword(0x0);
@@ -4555,7 +4586,7 @@ static inline void* zig_windows_teb(void) {
#elif defined(zig_x86_32)
-static inline void* zig_windows_teb(void) {
+static inline void* zig_e_zig_windows_teb(void) {
void* teb = 0;
#if defined(zig_msvc)
teb = (void*)__readfsdword(0x18);
@@ -4565,7 +4596,7 @@ static inline void* zig_windows_teb(void) {
return teb;
}
-static inline void* zig_windows_peb(void) {
+static inline void* zig_e_zig_windows_peb(void) {
void* peb = 0;
#if defined(zig_msvc)
peb = (void*)__readfsdword(0x30);
@@ -4577,7 +4608,7 @@ static inline void* zig_windows_peb(void) {
#elif defined(zig_x86_64)
-static inline void* zig_windows_teb(void) {
+static inline void* zig_e_zig_windows_teb(void) {
void* teb = 0;
#if defined(zig_msvc)
teb = (void*)__readgsqword(0x30);
@@ -4587,7 +4618,7 @@ static inline void* zig_windows_teb(void) {
return teb;
}
-static inline void* zig_windows_peb(void) {
+static inline void* zig_e_zig_windows_peb(void) {
void* peb = 0;
#if defined(zig_msvc)
peb = (void*)__readgsqword(0x60);
@@ -4601,7 +4632,9 @@ static inline void* zig_windows_peb(void) {
#if defined(zig_loongarch)
-static inline void zig_loongarch_cpucfg(uint32_t word, uint32_t* result) {
+static inline void zig_e_zig_loongarch_cpucfg(uint32_t word, uint32_t* result) zig_mangled(zig_e_zig_loongarch_cpucfg, "zig_loongarch_cpucfg");
+
+static inline void zig_e_zig_loongarch_cpucfg(uint32_t word, uint32_t* result) {
#if defined(zig_gnuc_asm)
__asm__("cpucfg %[result], %[word]" : [result] "=r" (result) : [word] "r" (word));
#else
@@ -4611,7 +4644,10 @@ static inline void zig_loongarch_cpucfg(uint32_t word, uint32_t* result) {
#elif defined(zig_x86) && !defined(zig_x86_16)
-static inline void zig_x86_cpuid(uint32_t leaf_id, uint32_t subid, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) {
+static inline void zig_e_zig_x86_cpuid(uint32_t leaf_id, uint32_t subid, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) zig_mangled(zig_e_zig_x86_cpuid, "zig_x86_cpuid");
+static inline uint32_t zig_e_zig_x86_get_xcr0(void) zig_mangled(zig_e_zig_x86_get_xcr0, "zig_x86_get_xcr0");
+
+static inline void zig_e_zig_x86_cpuid(uint32_t leaf_id, uint32_t subid, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) {
#if defined(zig_msvc)
int cpu_info[4];
__cpuidex(cpu_info, leaf_id, subid);
@@ -4629,7 +4665,7 @@ static inline void zig_x86_cpuid(uint32_t leaf_id, uint32_t subid, uint32_t* eax
#endif
}
-static inline uint32_t zig_x86_get_xcr0(void) {
+static inline uint32_t zig_e_zig_x86_get_xcr0(void) {
#if defined(zig_msvc)
return (uint32_t)_xgetbv(0);
#elif defined(zig_gnuc_asm)
diff --git a/stage1/zig1.wasm b/stage1/zig1.wasm
index 10afc539bc2588e4bc10cb6f074094a403f80e1d..1a985c43006c7abfd1e82ead3ac9b656a5b753ab 100644
Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ
diff --git a/test/behavior.zig b/test/behavior.zig
index c9c06e934230692c95d07b96d911fb09a80d3bdf..32be1951bcd7359632884683ca6b2108bd18a717 100644
--- a/test/behavior.zig
+++ b/test/behavior.zig
@@ -112,6 +112,10 @@ test {
_ = @import("behavior/wasm.zig");
}
+ if (builtin.zig_backend == .stage2_spirv) {
+ _ = @import("behavior/spirv.zig");
+ }
+
if (builtin.zig_backend != .stage2_spirv and builtin.os.tag != .wasi) {
_ = @import("behavior/asm.zig");
}
diff --git a/test/behavior/abs.zig b/test/behavior/abs.zig
index 55c7ebf6a7b0704fa88c83e7afec14584eb00d55..895f9bbf8d956e61bdf5455084cd4d58ebd2b1e9 100644
--- a/test/behavior/abs.zig
+++ b/test/behavior/abs.zig
@@ -7,7 +7,6 @@ test "@abs integers" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try comptime testAbsIntegers();
try testAbsIntegers();
@@ -145,7 +144,6 @@ test "@abs big int <= 128 bits" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
try comptime testAbsSignedBigInt();
diff --git a/test/behavior/align.zig b/test/behavior/align.zig
index 3de3dd090670331c27e4856e90246483546a2432..06c12eaea14622bbeaaa0aa85cede2fda9feb504 100644
--- a/test/behavior/align.zig
+++ b/test/behavior/align.zig
@@ -7,6 +7,8 @@ const assert = std.debug.assert;
var foo: u8 align(4) = 100;
test "global variable alignment" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
comptime assert(@typeInfo(@TypeOf(&foo)).pointer.attrs.@"align" == 4);
comptime assert(@TypeOf(&foo) == *align(4) u8);
{
@@ -16,6 +18,8 @@ test "global variable alignment" {
}
test "large abi alignment of global" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const S = struct {
var global: @This() = undefined;
x: u64 align(64),
@@ -51,6 +55,8 @@ test "slicing array of length 1 can not assume runtime index is always zero" {
}
test "implicitly-aligned pointer is coercible to equivalent explicitly-aligned pointer" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const A = *u32;
const B = *align(@alignOf(u32)) u32;
@@ -83,6 +89,8 @@ test "implicitly-aligned pointer is coercible to equivalent explicitly-aligned p
}
test "implicitly decreasing pointer alignment" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const a: u32 align(4) = 3;
const b: u32 align(8) = 4;
try expect(addUnaligned(&a, &b) == 7);
@@ -93,8 +101,6 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
}
test "@alignCast pointers" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
var x: u32 align(4) = 1;
expectsOnly1(&x);
try expect(x == 2);
@@ -125,6 +131,20 @@ test "alignment and size of structs with 128-bit fields" {
y: u8,
};
const expected = switch (builtin.cpu.arch) {
+ .s390x,
+ => .{
+ .a_align = 8,
+ .a_size = 16,
+
+ .b_align = 8,
+ .b_size = 24,
+
+ .u128_align = 8,
+ .u128_size = 16,
+ .u129_align = 8,
+ .u129_size = 24,
+ },
+
.amdgcn,
.arm,
.armeb,
@@ -137,7 +157,6 @@ test "alignment and size of structs with 128-bit fields" {
.powerpc,
.powerpcle,
.riscv32,
- .s390x,
=> .{
.a_align = 8,
.a_size = 16,
@@ -183,7 +202,7 @@ test "alignment and size of structs with 128-bit fields" {
else => return error.SkipZigTest,
};
- const min_struct_align = if (builtin.zig_backend == .stage2_c) 16 else 0;
+ const min_struct_align = if (builtin.zig_backend == .stage2_c) if (builtin.cpu.arch == .s390x) 8 else 16 else 0;
comptime {
assert(@alignOf(A) == @max(expected.a_align, min_struct_align));
assert(@sizeOf(A) == expected.a_size);
@@ -202,7 +221,6 @@ test "alignment and size of structs with 128-bit fields" {
test "implicitly decreasing slice alignment" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const a: u32 align(4) = 3;
const b: u32 align(8) = 4;
try expect(addUnalignedSlice(@as(*const [1]u32, &a)[0..], @as(*const [1]u32, &b)[0..]) == 7);
@@ -244,8 +262,6 @@ test "return error union with 128-bit integer" {
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
try expect(3 == try give());
}
fn give() anyerror!u128 {
@@ -257,7 +273,6 @@ test "page aligned array on stack" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
// Large alignment value to make it hard to accidentally pass.
var array align(0x1000) = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
var number1: u8 align(16) = 42;
@@ -616,3 +631,30 @@ test "function pointer align mask" {
const aligned: *align(16) const fn () callconv(.c) void = @alignCast(unaligned);
try expect(@intFromPtr(aligned) == int);
}
+
+test "align expression is implicitly comptime" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
+ const S = struct {
+ fn alignment() usize {
+ return 4;
+ }
+
+ var global: [3]u8 align(alignment()) = @splat(0);
+ fn check() !void {
+ try std.testing.expect(@intFromPtr(&global) % alignment() == 0);
+ var local: [3]u8 align(alignment()) = @splat(0);
+ try std.testing.expect(@intFromPtr(&local) % alignment() == 0);
+ var de: [3]u8 align(alignment()), var structure: [3]u8 align(alignment()) = .{ @splat(0), @splat(0) };
+ try std.testing.expect(@intFromPtr(&de) % alignment() == 0);
+ try std.testing.expect(@intFromPtr(&structure) % alignment() == 0);
+ var @"struct": struct { field: [3]u8 align(alignment()) } = .{ .field = @splat(0) };
+ try std.testing.expect(@intFromPtr(&@"struct".field) % alignment() == 0);
+ var @"union": union { field: [3]u8 align(alignment()) } = .{ .field = @splat(0) };
+ try std.testing.expect(@intFromPtr(&@"union".field) % alignment() == 0);
+ const ptr: *align(alignment()) [3]u8 = &global;
+ try std.testing.expect(@intFromPtr(ptr) % alignment() == 0);
+ }
+ };
+ try S.check();
+}
diff --git a/test/behavior/array.zig b/test/behavior/array.zig
index 04e014b5157ef2e15bfc3ae10ff10c4d5e2f9c32..f7e179034a9a2f16807a6682f8ee7f1f50ba97e8 100644
--- a/test/behavior/array.zig
+++ b/test/behavior/array.zig
@@ -7,6 +7,7 @@ const expect = testing.expect;
const expectEqual = testing.expectEqual;
test "array to slice" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const a: u32 align(4) = 3;
const b: u32 align(8) = 4;
const a_slice: []align(1) const u32 = @as(*const [1]u32, &a)[0..];
@@ -21,7 +22,6 @@ test "array to slice" {
test "arrays" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
-
var array: [5]u32 = undefined;
var i: u32 = 0;
@@ -49,7 +49,6 @@ test "runtime array concat with comptime slice" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
var a: [1]u8 = .{1};
const b = (comptime @as([]const u8, &.{0})) ++ &a;
const c = &a ++ (comptime @as([]const u8, &.{0}));
@@ -96,6 +95,24 @@ test "array concat with tuple" {
}
}
+test "array concat with undefined tuple" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
+ {
+ const array: [2]u64 = .{ 1, 2 };
+ var seq = array ++ @as(struct { u32, u16 }, undefined);
+ seq[2] = 3;
+ seq[3] = 4;
+ try std.testing.expectEqualSlices(u64, &.{ 1, 2, 3, 4 }, &seq);
+ }
+ {
+ const array: [2]u64 = undefined;
+ var seq = @as(struct { u32, u16 }, undefined) ++ array;
+ for (&seq, 1..) |*s, i| s.* = i;
+ try std.testing.expectEqualSlices(u64, &.{ 1, 2, 3, 4 }, &seq);
+ }
+}
+
test "array init with concat" {
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
@@ -259,6 +276,7 @@ fn doSomeMangling(array: *[4]u8) void {
test "implicit cast zero sized array ptr to slice" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
{
var b = "".*;
@@ -636,6 +654,8 @@ test "array of array agregate init" {
}
test "pointer to array has ptr field" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const arr: *const [5]u32 = &.{ 10, 20, 30, 40, 50 };
try std.testing.expect(arr.ptr == @as([*]const u32, arr));
try std.testing.expect(arr.ptr[0] == 10);
@@ -969,6 +989,7 @@ test "runtime index of array of zero-bit values" {
}
test "@splat array" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -1036,11 +1057,15 @@ test "@splat zero-length array" {
}
test "initialize slice with reference to empty array initializer" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const a: []const u8 = &.{};
comptime assert(a.len == 0);
}
test "initialize many-pointer with reference to empty array initializer" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const a: [*]const u8 = &.{};
_ = a; // nothing meaningful to test; points to zero bits
}
@@ -1052,6 +1077,7 @@ test "initialize sentinel-terminated slice with reference to empty array initial
}
test "initialize sentinel-terminated many-pointer with reference to empty array initializer" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const a: [*:0]const u8 = &.{};
comptime assert(a[0] == 0);
}
@@ -1124,3 +1150,30 @@ test "resist alias of explicit copy of array passed as arg" {
try expect(buf_b[0] == 1234);
}
+
+test "access element through reference" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
+ const S = struct {
+ fn doTheTest(x: u8) !void {
+ {
+ var val: [1]u8 = .{x};
+ const single_ptr: *[1]u8 = &val;
+ try expect(single_ptr.*[0] == x);
+ const elem_ptr = &single_ptr.*[0];
+ comptime assert(@TypeOf(elem_ptr) == *u8);
+ try expect(elem_ptr.* == x);
+ }
+ {
+ var val: [1]u8 = .{x};
+ const c_ptr: [*c][1]u8 = &val;
+ try expect(c_ptr.*[0] == x);
+ const elem_ptr = &c_ptr.*[0];
+ comptime assert(@TypeOf(elem_ptr) == *u8);
+ try expect(elem_ptr.* == x);
+ }
+ }
+ };
+ try comptime S.doTheTest(123);
+ try S.doTheTest(123);
+}
diff --git a/test/behavior/asm.zig b/test/behavior/asm.zig
index 8d7f3bcbca2566d2669a577a958a720d21d0d83b..ac2178044584884d536295a336765e21517c4e6f 100644
--- a/test/behavior/asm.zig
+++ b/test/behavior/asm.zig
@@ -82,7 +82,6 @@ test "sized integer/float in asm input" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
@@ -210,42 +209,6 @@ test "packed output types (x86_64)" {
}
}
-test "extern output types (x86_64)" {
- if (builtin.target.cpu.arch != .x86_64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
- if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31531
-
- const S = extern struct { x: u32 };
- {
- const s: S = asm volatile ("mov $123, %[ret]"
- : [ret] "=r" (-> S),
- );
- try expect(s.x == 123);
- }
- {
- var s: S = undefined;
- asm volatile ("mov $123, %[ret]"
- : [ret] "=r" (s),
- );
- try expect(s.x == 123);
- }
-
- const U = extern union { x: u32 };
- {
- const u: U = asm volatile ("mov $123, %[ret]"
- : [ret] "=r" (-> U),
- );
- try expect(u.x == 123);
- }
- {
- var u: U = undefined;
- asm volatile ("mov $123, %[ret]"
- : [ret] "=r" (u),
- );
- try expect(u.x == 123);
- }
-}
-
test "abi register aliases as clobbers (RISC-V)" {
if (!builtin.target.cpu.arch.isRISCV()) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
diff --git a/test/behavior/atomics.zig b/test/behavior/atomics.zig
index a8580904c5be15e8409eafaeac007ba38d00da75..e53a4c818fb7e1a911a6ecee4e171ba67b37cfe2 100644
--- a/test/behavior/atomics.zig
+++ b/test/behavior/atomics.zig
@@ -358,7 +358,6 @@ test "atomics with different types" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.target.cpu.arch.endian() == .big) return error.SkipZigTest; // #24282
try testAtomicsWithType(bool, true, false);
diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig
index 2c5e6ab9a9c65ca28d72d60b32c0f100e9a4824b..16fdfc8c15cbd9f5e9ad3cc11d72461092cf839c 100644
--- a/test/behavior/basic.zig
+++ b/test/behavior/basic.zig
@@ -24,7 +24,6 @@ fn testTruncate(x: u32) u8 {
}
test "truncate to non-power-of-two integers" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
try testTrunc(u32, u1, 0b10101, 0b1);
@@ -41,7 +40,6 @@ test "truncate to non-power-of-two integers" {
test "truncate to non-power-of-two integers from 128-bit" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testTrunc(u128, u1, 0xffffffff_ffffffff_ffffffff_01010101, 0x01);
try testTrunc(u128, u1, 0xffffffff_ffffffff_ffffffff_01010110, 0x00);
@@ -299,7 +297,6 @@ const global_b: *const i32 = &global_a;
const global_c: *const f32 = @as(*const f32, @ptrCast(global_b));
test "compile time global reinterpret" {
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const d = @as(*const i32, @ptrCast(global_c));
try expect(d.* == 1234);
}
@@ -376,7 +373,6 @@ fn fB() []const u8 {
test "call function pointer in struct" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
try expect(mem.eql(u8, f3(true), "a"));
try expect(mem.eql(u8, f3(false), "b"));
}
@@ -640,6 +636,7 @@ fn emptyFn() void {}
const addr1 = @as(*const u8, @ptrCast(&emptyFn));
test "comptime cast fn to ptr" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const addr2 = @as(*const u8, @ptrCast(&emptyFn));
comptime assert(addr1 == addr2);
}
@@ -918,6 +915,7 @@ test "labeled block with runtime branch forwards its result location type to bre
test "try in labeled block doesn't cast to wrong type" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
a: u32,
@@ -1142,7 +1140,7 @@ test "arrays and vectors with big integers" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_llvm and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23805
+ if (builtin.zig_backend == .stage2_llvm and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32 or builtin.abi == .abin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23805
inline for (.{ u65528, u65529, u65535 }) |Int| {
var a: [1]Int = undefined;
@@ -1214,8 +1212,6 @@ fn testUnsignedCmp(comptime T: type) !void {
}
test "integer compare <= 64 bits" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
inline for (.{ u8, u16, u32, u64, usize, u10, u20, u30, u60 }) |T| {
try testUnsignedCmp(T);
try comptime testUnsignedCmp(T);
@@ -1228,7 +1224,6 @@ test "integer compare <= 64 bits" {
test "integer compare <= 128 bits" {
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
inline for (.{ u65, u96, u127, u128 }) |T| {
try testUnsignedCmp(T);
@@ -1242,7 +1237,6 @@ test "integer compare <= 128 bits" {
test "integer compare > 128 bits" {
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
inline for (.{ u129, u255, u512, u800 }) |T| {
try testUnsignedCmp(T);
@@ -1278,6 +1272,7 @@ test "@Int returned from block" {
}
test "comptime variable initialized with addresses of literals" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
comptime var st = .{
.foo = &1,
.bar = &2,
@@ -1327,6 +1322,8 @@ test "proper value is returned from labeled block" {
}
test "const inferred array of slices" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const T = struct { v: bool };
const decls = [_][]const T{
@@ -1339,6 +1336,7 @@ test "const inferred array of slices" {
test "var inferred array of slices" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const T = struct { v: bool };
@@ -1437,3 +1435,14 @@ test "loading array from struct is not optimized away" {
var s = S{};
try s.doTheTest();
}
+
+test "local variable name begins with primitive integer type" {
+ const u032_ = 123;
+ comptime assert(u032_ == 123);
+
+ const u0_ = 456;
+ comptime assert(u0_ == 456);
+
+ const i0_ = 789;
+ comptime assert(i0_ == 789);
+}
diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig
index 28b45428d6b111a327561769781d5c045f49e17e..3b77d2c6023256829590cc98d9b8c217e6bbe660 100644
--- a/test/behavior/bitcast.zig
+++ b/test/behavior/bitcast.zig
@@ -23,8 +23,6 @@ test "@bitCast iX -> uX (8, 16, 128)" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const bit_values = [_]usize{ 8, 16, 128 };
inline for (bit_values) |bits| {
@@ -37,7 +35,6 @@ test "@bitCast iX -> uX exotic integers" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
const bit_values = [_]usize{ 1, 48, 27, 512, 493, 293, 125, 204, 112 };
@@ -77,55 +74,6 @@ fn conv_uN(comptime N: usize, x: @Int(.unsigned, N)) @Int(.signed, N) {
return @as(@Int(.signed, N), @bitCast(x));
}
-test "bitcast uX to bytes" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
-
- const bit_values = [_]usize{ 1, 48, 27, 512, 493, 293, 125, 204, 112 };
- inline for (bit_values) |bits| {
- try testBitCast(bits);
- try comptime testBitCast(bits);
- }
-}
-
-fn testBitCastuXToBytes(comptime N: usize) !void {
-
- // The location of padding bits in these layouts are technically not defined
- // by LLVM, but we currently allow exotic integers to be cast (at comptime)
- // to types that expose their padding bits anyway.
- //
- // This test at least makes sure those bits are matched by the runtime behavior
- // on the platforms we target. If the above behavior is restricted after all,
- // this test should be deleted.
-
- const T = @Int(.unsigned, N);
- for ([_]T{ 0, ~@as(T, 0) }) |init_value| {
- var x: T = init_value;
- const bytes = std.mem.asBytes(&x);
-
- const byte_count = (N + 7) / 8;
- switch (native_endian) {
- .little => {
- var byte_i = 0;
- while (byte_i < (byte_count - 1)) : (byte_i += 1) {
- try expect(bytes[byte_i] == 0xff);
- }
- try expect(((bytes[byte_i] ^ 0xff) << -%@as(u3, @truncate(N))) == 0);
- },
- .big => {
- var byte_i = byte_count - 1;
- while (byte_i > 0) : (byte_i -= 1) {
- try expect(bytes[byte_i] == 0xff);
- }
- try expect(((bytes[byte_i] ^ 0xff) << -%@as(u3, @truncate(N))) == 0);
- },
- }
- }
-}
-
test "nested bitcast" {
const S = struct {
fn moo(x: isize) !void {
@@ -162,6 +110,7 @@ test "@bitCast packed structs at runtime and comptime" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const Full = packed struct {
number: u16,
@@ -185,43 +134,11 @@ test "@bitCast packed structs at runtime and comptime" {
try comptime S.doTheTest();
}
-test "@bitCast extern structs at runtime and comptime" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
- const Full = extern struct {
- number: u16,
- };
- const TwoHalves = extern struct {
- half1: u8,
- half2: u8,
- };
- const S = struct {
- fn doTheTest() !void {
- var full = Full{ .number = 0x1234 };
- _ = &full;
- const two_halves: TwoHalves = @bitCast(full);
- switch (native_endian) {
- .big => {
- try expect(two_halves.half1 == 0x12);
- try expect(two_halves.half2 == 0x34);
- },
- .little => {
- try expect(two_halves.half1 == 0x34);
- try expect(two_halves.half2 == 0x12);
- },
- }
- }
- };
- try S.doTheTest();
- try comptime S.doTheTest();
-}
-
test "bitcast packed struct to integer and back" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const LevelUpMove = packed struct {
move_id: u9,
@@ -364,32 +281,12 @@ test "comptime @bitCast packed struct to int and back" {
}
}
-test "comptime bitcast with fields following f80" {
- if (true) {
- // https://github.com/ziglang/zig/issues/19387
- return error.SkipZigTest;
- }
-
- if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
-
- const FloatT = extern struct { f: f80, x: u128 align(16) };
- const x: FloatT = .{ .f = 0.5, .x = 123 };
- var x_as_uint: u256 = comptime @as(u256, @bitCast(x));
- _ = &x_as_uint;
-
- try expect(x.f == @as(FloatT, @bitCast(x_as_uint)).f);
- try expect(x.x == @as(FloatT, @bitCast(x_as_uint)).x);
-}
-
test "bitcast vector to integer and back" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.cpu.arch.endian() == .big and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
var vec: @Vector(16, bool) = @splat(true);
vec[1] = false;
@@ -525,73 +422,6 @@ test "@bitCast of packed struct of bools all false" {
try expect(@as(u8, @as(u4, @bitCast(p))) == 0);
}
-test "@bitCast of extern struct containing pointer" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
-
- const S = struct {
- const A = extern struct {
- ptr: *const u32,
- };
-
- const B = extern struct {
- ptr: *const i32,
- };
-
- fn doTheTest() !void {
- const x: u32 = 123;
- var a: A = undefined;
- a = .{ .ptr = &x };
- const b: B = @bitCast(a);
- try expect(b.ptr.* == 123);
- }
- };
-
- try S.doTheTest();
- try comptime S.doTheTest();
-}
-
-test "@bitCast of extern struct to float" {
- if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
-
- const S = struct {
- const S = extern struct {
- x: u16,
- y: u16,
- };
- fn doTheTest() !void {
- var s: S = .{ .x = 0, .y = 0 };
- _ = &s;
- const a: f32 = @bitCast(s);
- try expect(a == 0);
- }
- };
-
- try S.doTheTest();
- try comptime S.doTheTest();
-}
-
-test "@bitCast of float to extern struct" {
- if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
-
- const S = struct {
- const S = extern struct {
- x: u32,
- };
- fn doTheTest() !void {
- var a: f32 = -0.0;
- _ = &a;
- const s: S = @bitCast(a);
- try expect(s.x == 0x80000000);
- }
- };
-
- try S.doTheTest();
- try comptime S.doTheTest();
-}
-
test "@bitCast of packed struct with void field to integer" {
const S = packed struct(u8) {
v: void,
@@ -607,3 +437,158 @@ test "@bitCast of packed struct with void field to integer" {
try S.doTheTest(123);
try comptime S.doTheTest(123);
}
+
+test "@bitCast vector to array with different element size" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
+ const static = struct {
+ fn doTheTest(v: @Vector(4, u5)) !void {
+ const result: [5]u4 = @bitCast(v);
+ // See the definition of `v` in the test proper for these values.
+ try expect(result[0] == 0b0010);
+ try expect(result[1] == 0b1110);
+ try expect(result[2] == 0b0101);
+ try expect(result[3] == 0b0110);
+ try expect(result[4] == 0b0000);
+ }
+ };
+ // The strange digit groupings here are to indicate how this maps to `expected` above.
+ const v: @Vector(4, u5) = .{
+ 0b0_0010,
+ 0b01_111,
+ 0b110_01,
+ 0b0000_0,
+ };
+ try static.doTheTest(v);
+ try comptime static.doTheTest(v);
+}
+
+test "@bitCast packed struct to array of bits" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
+ const S = packed struct(u16) {
+ foo: u5,
+ bar: i7,
+ baz: u3,
+ qux: bool,
+ fn doTheTest(val: @This(), comptime Bits: type) !void {
+ const bits: Bits = @bitCast(val);
+
+ // foo
+ try expect(bits[0] == 1);
+ try expect(bits[1] == 0);
+ try expect(bits[2] == 0);
+ try expect(bits[3] == 1);
+ try expect(bits[4] == 0);
+ // bar
+ try expect(bits[5] == 0);
+ try expect(bits[6] == 1);
+ try expect(bits[7] == 1);
+ try expect(bits[8] == 1);
+ try expect(bits[9] == 1);
+ try expect(bits[10] == 1);
+ try expect(bits[11] == 1);
+ // baz
+ try expect(bits[12] == 0);
+ try expect(bits[13] == 1);
+ try expect(bits[14] == 0);
+ // qux
+ try expect(bits[15] == 1);
+ }
+ };
+
+ const val: S = .{
+ .foo = 0b01001,
+ .bar = -2,
+ .baz = 0b010,
+ .qux = true,
+ };
+
+ try val.doTheTest(@Vector(16, u1));
+ try val.doTheTest([16]u1);
+
+ try comptime val.doTheTest(@Vector(16, u1));
+ try comptime val.doTheTest([16]u1);
+}
+
+test "@bitCast nested arrays of vectors" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
+ const Src = [2][2]@Vector(4, u5);
+ const Dest = [5]@Vector(2, u8);
+
+ // The strange digit groupings here are to indicate how this maps to the output.
+ const src: Src = .{ .{
+ .{ 0b00011, 0b00_100, 0b11100, 0b0010_1 },
+ .{ 0b1_0110, 0b11011, 0b101_10, 0b10101 },
+ }, .{
+ .{ 0b10101, 0b00_001, 0b01011, 0b0001_0 },
+ .{ 0b0_0001, 0b01111, 0b111_10, 0b00001 },
+ } };
+
+ const expected: Dest = .{
+ .{ 0b10000011, 0b11110000 },
+ .{ 0b01100010, 0b10110111 },
+ .{ 0b10101101, 0b00110101 },
+ .{ 0b00101100, 0b00010001 },
+ .{ 0b10011110, 0b00001111 },
+ };
+
+ const static = struct {
+ fn doTheTest(src_arg: Src) !void {
+ const actual: Dest = @bitCast(src_arg);
+ for (actual, expected) |actual_vec, expected_vec| {
+ try expect(actual_vec[0] == expected_vec[0]);
+ try expect(actual_vec[1] == expected_vec[1]);
+ }
+ }
+ };
+
+ try static.doTheTest(src);
+ try comptime static.doTheTest(src);
+}
+
+test "@bitCast nested arrays of bool to scalar" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
+ const static = struct {
+ fn doTheTest(src: [4][4]bool) !void {
+ const result: u16 = @bitCast(src);
+ try expect(result == 0b1100_0101_1010_0011);
+ }
+ };
+ const src: [4][4]bool = .{
+ .{ true, true, false, false }, // 0b0011
+ .{ false, true, false, true }, // 0b1010
+ .{ true, false, true, false }, // 0b0101
+ .{ false, false, true, true }, // 0b1100
+ };
+ try static.doTheTest(src);
+ try comptime static.doTheTest(src);
+}
+
+test "@bitCast deeply nested arrays to scalar" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
+ const static = struct {
+ fn doTheTest(src: [2][1][3][5]u4) !void {
+ const signed: i120 = @bitCast(src);
+ try expect(signed < 0); // top nibble is 0x8 so sign bit is 1
+ const unsigned: u120 = @bitCast(src);
+ try expect(unsigned == 0x8873B_5BF6F_F4020_0E7AC_1EFED_40F51);
+ try expect(@as(i120, @bitCast(unsigned)) == signed);
+ try expect(@as(u120, @bitCast(signed)) == unsigned);
+ }
+ };
+ const src: [2][1][3][5]u4 = .{ .{.{
+ .{ 0x1, 0x5, 0xF, 0x0, 0x4 },
+ .{ 0xD, 0xE, 0xF, 0xE, 0x1 },
+ .{ 0xC, 0xA, 0x7, 0xE, 0x0 },
+ }}, .{.{
+ .{ 0x0, 0x2, 0x0, 0x4, 0xF },
+ .{ 0xF, 0x6, 0xF, 0xB, 0x5 },
+ .{ 0xB, 0x3, 0x7, 0x8, 0x8 },
+ }} };
+ try static.doTheTest(src);
+ try comptime static.doTheTest(src);
+}
diff --git a/test/behavior/bool.zig b/test/behavior/bool.zig
index 7944c0903eba58efb24377b22d773f347a3674c6..72c1dff3362afc5960160776841f04a8b22ef2f9 100644
--- a/test/behavior/bool.zig
+++ b/test/behavior/bool.zig
@@ -10,7 +10,6 @@ test "bool literals" {
test "cast bool to int" {
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const t = true;
const f = false;
diff --git a/test/behavior/call.zig b/test/behavior/call.zig
index e1152ad910695f425c8de60894d7ecc92fe9d0f9..4846d475af9548e24a518ff035a6288aa64c7352 100644
--- a/test/behavior/call.zig
+++ b/test/behavior/call.zig
@@ -408,6 +408,7 @@ test "recursive inline call with comptime known argument" {
test "inline while with @call" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
fn inc(a: *u32) void {
@@ -735,6 +736,7 @@ test "tail call function pointer" {
test "tail call with potentially extended types" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_llvm or builtin.zig_backend == .stage2_c) {
if (builtin.cpu.arch.isMIPS() or builtin.cpu.arch.isPowerPC() or builtin.cpu.arch.isWasm()) {
diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig
index 2e5871d9dd2ae26b8f9b1739ce84a847b5a9f535..41b53fdbbb0f17e9f27264eeaebcf4e376a68cfc 100644
--- a/test/behavior/cast.zig
+++ b/test/behavior/cast.zig
@@ -131,6 +131,7 @@ fn testIntFromFloat(comptime F: type, f: F, comptime I: type, i: I) !void {
}
test "@intFromFloat > 128 bits" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
@@ -156,6 +157,7 @@ fn testFloatFromInt(comptime I: type, i: I, comptime F: type, expected: F) !void
}
test "@floatFromInt > 128 bits" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
@@ -216,6 +218,8 @@ test "@floatFromInt(f80)" {
}
test "type coercion from int to float" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const check = struct {
// Check that an integer value can be coerced to a float type and
// then converted back to the original value without rounding issues.
@@ -277,8 +281,6 @@ test "type coercion from int to float" {
test "@intFromFloat" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
try testIntFromFloats();
try comptime testIntFromFloats();
}
@@ -342,7 +344,6 @@ fn expectTruncCast(comptime F: type, f: F, comptime I: type, i: I) !void {
test "implicitly cast indirect pointer to maybe-indirect pointer" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const S = struct {
const Self = @This();
x: u8,
@@ -505,7 +506,6 @@ test "array coercion to undefined at runtime" {
var array = [4]u8{ 3, 4, 5, 6 };
var undefined_val = [4]u8{ 0xAA, 0xAA, 0xAA, 0xAA };
-
try expect(std.mem.eql(u8, &array, &array));
array = undefined;
try expect(std.mem.eql(u8, &array, &undefined_val));
@@ -539,6 +539,8 @@ test "return u8 coercing into ?u32 return type" {
}
test "cast from ?[*]T to ??[*]T" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const a: ??[*]u8 = @as(?[*]u8, null);
try expect(a != null and a.? == null);
}
@@ -597,6 +599,7 @@ fn testPeerResolveArrayConstSlice(b: bool) !void {
}
test "implicitly cast from T to anyerror!?T" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -622,6 +625,7 @@ fn castToOptionalTypeError(z: i32) !void {
}
test "implicitly cast from [0]T to anyerror![]T" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
try testCastZeroArrayToErrSliceMut();
@@ -1420,6 +1424,7 @@ test "comptime float casts" {
}
test "pointer reinterpret const float to int" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
// The hex representation is 0x3fe3333333333303.
@@ -1613,6 +1618,7 @@ fn incrementVoidPtrValue(value: ?*anyopaque) void {
}
test "implicit cast *[0]T to E![]const u8" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
var x = @as(anyerror![]const u8, &[0]u8{});
@@ -1807,6 +1813,7 @@ test "cast compatible optional types" {
}
test "coerce undefined single-item pointer of array to error union of slice" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
const a = @as([*]u8, undefined)[0..0];
@@ -1817,6 +1824,7 @@ test "coerce undefined single-item pointer of array to error union of slice" {
}
test "pointer to empty struct literal to mutable slice" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
var x: []i32 = &.{};
@@ -1970,6 +1978,7 @@ test "peer type resolution forms error union" {
}
test "@constCast without a result location" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const x: i32 = 1234;
const y = @constCast(&x);
try expect(@TypeOf(y) == *i32);
@@ -1977,6 +1986,7 @@ test "@constCast without a result location" {
}
test "@constCast optional" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const x: u8 = 10;
const m: ?*const u8 = &x;
const p = @constCast(m);
@@ -2053,6 +2063,7 @@ test "peer type resolution: float and comptime-known fixed-width integer" {
}
test "peer type resolution: float and runtime-known fixed-width integer" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -2163,6 +2174,7 @@ test "peer type resolution: array and vector with same child type" {
}
test "peer type resolution: array with smaller child type and vector with larger child type" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -2343,6 +2355,7 @@ test "peer type resolution: array and tuple" {
}
test "peer type resolution: vector and tuple" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -2541,7 +2554,7 @@ test "peer type resolution: many compatible pointers" {
test "peer type resolution: tuples with comptime fields" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
+ // if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
const a = .{ 1, 2 };
const b = .{ @as(u32, 3), @as(i16, 4) };
@@ -2734,6 +2747,7 @@ test "cast builtins can wrap result in optional" {
}
test "cast builtins can wrap result in error union" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -2809,6 +2823,7 @@ test "cast builtins can wrap result in error union and optional" {
}
test "@floatCast on vector" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -2897,6 +2912,7 @@ test "@intFromPtr on vector" {
}
test "@floatFromInt on vector" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -2916,6 +2932,7 @@ test "@floatFromInt on vector" {
}
test "@intFromFloat on vector" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -2935,6 +2952,7 @@ test "@intFromFloat on vector" {
}
test "@intFromBool on vector" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -3061,6 +3079,7 @@ test "peer type resolution: slice of sentinel-terminated array" {
}
test "@intFromFloat boundary cases" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
const S = struct {
@@ -3092,6 +3111,7 @@ test "@intFromFloat boundary cases" {
}
test "@intFromFloat vector boundary cases" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
diff --git a/test/behavior/cast_int.zig b/test/behavior/cast_int.zig
index 841030a9e1a02fd23587b852bd73d2cdedfd5fdf..34adedf7267030379ee573cb519ce6dbe29c95e3 100644
--- a/test/behavior/cast_int.zig
+++ b/test/behavior/cast_int.zig
@@ -8,7 +8,6 @@ const minInt = std.math.minInt;
test "@intCast i32 to u7" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
var x: u128 = maxInt(u128);
@@ -144,7 +143,7 @@ fn testIntCast(comptime S: type, a: S, comptime D: type, expected: D) !void {
test "@intCast <= 64 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testIntCast(i32, minInt(i32), i64, minInt(i32));
try testIntCast(i32, maxInt(i32), i64, maxInt(i32));
try testIntCast(u32, maxInt(u32), u64, maxInt(u32));
@@ -170,6 +169,7 @@ test "@intCast <= 64 bits" {
test "@intCast > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testIntCast(u8, 123, u140, 123);
try testIntCast(u64, 1 << 63, u140, 1 << 63);
@@ -213,119 +213,3 @@ test "@intCast > 128 bits" {
try testIntCast(u64, maxInt(u64), i255, maxInt(u64));
try testIntCast(u128, maxInt(u128), i255, maxInt(u128));
}
-
-const Piece = packed struct {
- color: Color,
- type: Type,
-
- const Type = enum(u3) { KING, QUEEN, BISHOP, KNIGHT, ROOK, PAWN };
- const Color = enum(u1) { WHITE, BLACK };
-
- fn charToPiece(c: u8) !@This() {
- return .{
- .type = try charToPieceType(c),
- .color = if (std.ascii.isUpper(c)) Color.WHITE else Color.BLACK,
- };
- }
-
- fn charToPieceType(c: u8) !Type {
- return switch (std.ascii.toLower(c)) {
- 'p' => .PAWN,
- 'k' => .KING,
- 'q' => .QUEEN,
- 'b' => .BISHOP,
- 'n' => .KNIGHT,
- 'r' => .ROOK,
- else => error.UnexpectedCharError,
- };
- }
-};
-
-// Originally reported at https://github.com/ziglang/zig/issues/14200
-test "load non byte-sized optional value" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
-
- // note: this bug is triggered by the == operator, expectEqual will hide it
- const opt: ?Piece = try Piece.charToPiece('p');
- try expect(opt.?.type == .PAWN);
- try expect(opt.?.color == .BLACK);
-
- var p: Piece = undefined;
- @as(*u8, @ptrCast(&p)).* = 0b11111011;
- try expect(p.type == .PAWN);
- try expect(p.color == .BLACK);
-}
-
-test "load non byte-sized value in struct" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
- if (builtin.cpu.arch.endian() != .little) return error.SkipZigTest; // packed struct TODO
- if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
-
- // note: this bug is triggered by the == operator, expectEqual will hide it
- // using ptrCast not to depend on unitialised memory state
-
- var struct0: struct {
- p: Piece,
- int: u8,
- } = undefined;
- @as(*u8, @ptrCast(&struct0.p)).* = 0b11111011;
- try expect(struct0.p.type == .PAWN);
- try expect(struct0.p.color == .BLACK);
-
- var struct1: packed struct {
- p0: Piece,
- p1: Piece,
- pad: u1,
- p2: Piece,
- } = undefined;
- @as(*u8, @ptrCast(&struct1.p0)).* = 0b11111011;
- struct1.p1 = try Piece.charToPiece('p');
- struct1.p2 = try Piece.charToPiece('p');
- try expect(struct1.p0.type == .PAWN);
- try expect(struct1.p0.color == .BLACK);
- try expect(struct1.p1.type == .PAWN);
- try expect(struct1.p1.color == .BLACK);
- try expect(struct1.p2.type == .PAWN);
- try expect(struct1.p2.color == .BLACK);
-}
-
-test "load non byte-sized value in union" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
-
- // note: this bug is triggered by the == operator, expectEqual will hide it
- // using ptrCast not to depend on unitialised memory state
-
- var union0: packed union {
- p: packed struct(u8) {
- a: Piece,
- b: u4,
- },
- int: u8,
- } = .{ .int = 0 };
- union0.int = 0b11111011;
- try expect(union0.p.a.type == .PAWN);
- try expect(union0.p.a.color == .BLACK);
-
- var union1: union {
- p: packed struct(u8) {
- a: Piece,
- b: u4,
- },
- int: u8,
- } = .{ .p = .{ .a = .{ .color = .WHITE, .type = .KING }, .b = 0 } };
- @as(*u8, @ptrCast(&union1.p.a)).* = 0b11111011;
- try expect(union1.p.a.type == .PAWN);
- try expect(union1.p.a.color == .BLACK);
-
- var pieces: [3]Piece = undefined;
- @as(*u8, @ptrCast(&pieces[1])).* = 0b11111011;
- try expect(pieces[1].type == .PAWN);
- try expect(pieces[1].color == .BLACK);
-}
diff --git a/test/behavior/comptime_memory.zig b/test/behavior/comptime_memory.zig
index 769075aefff3c23691fa8474e16e62f1328d37a6..d11a7cb0165dca71e86447ec8a059257001d4cb4 100644
--- a/test/behavior/comptime_memory.zig
+++ b/test/behavior/comptime_memory.zig
@@ -516,7 +516,6 @@ fn fieldPtrTest() u32 {
}
test "pointer in aggregate field can mutate comptime state" {
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
try comptime std.testing.expect(fieldPtrTest() == 2);
}
@@ -553,6 +552,8 @@ test "comptime store of packed struct with void field into array" {
}
test "comptime store of reinterpreted zero-bit type" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const S = struct {
fn doTheTest(comptime T: type) void {
comptime var buf: T = undefined;
@@ -582,3 +583,21 @@ test "comptime store to extern struct reinterpreted as byte array" {
comptime std.debug.assert(val.x == 0);
}
+
+test "reinterpret sentinel-terminated array as packed struct" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
+ const S = packed struct(u16) { lo: u8, hi: u8 };
+ const data: [2:0]u8 = .{ 0x12, 0x34 };
+ const ptr: *align(1) const S = @ptrCast(&data);
+ switch (endian) {
+ .little => {
+ try testing.expect(ptr.lo == 0x12);
+ try testing.expect(ptr.hi == 0x34);
+ },
+ .big => {
+ try testing.expect(ptr.lo == 0x34);
+ try testing.expect(ptr.hi == 0x12);
+ },
+ }
+}
diff --git a/test/behavior/decl_literals.zig b/test/behavior/decl_literals.zig
index f96f46177179af58eee8e419648e5fdc7568a185..5d237778757f3c2f2a3faa160668f26debfee9f9 100644
--- a/test/behavior/decl_literals.zig
+++ b/test/behavior/decl_literals.zig
@@ -49,6 +49,8 @@ test "call decl literal with optional" {
}
test "call decl literal with pointer" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const S = struct {
x: u32,
fn init() *const @This() {
diff --git a/test/behavior/defer.zig b/test/behavior/defer.zig
index c90df21fbca81fc441837057b74f26e227c17f9c..1a999c32c01a30dfe4c0cf98cdca5642c8b83511 100644
--- a/test/behavior/defer.zig
+++ b/test/behavior/defer.zig
@@ -109,7 +109,6 @@ test "mixing normal and error defers" {
test "simple else prong doesn't emit an error for unreachable else prong" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const S = struct {
fn foo() error{Foo}!void {
return error.Foo;
diff --git a/test/behavior/duplicated_test_names.zig b/test/behavior/duplicated_test_names.zig
index e7ee93776cb23e8731255818a1a38f485c243860..b16a7787d84b7f22c57376fee8cae225ced9b87f 100644
--- a/test/behavior/duplicated_test_names.zig
+++ b/test/behavior/duplicated_test_names.zig
@@ -15,7 +15,6 @@ comptime {
test "thingy" {}
test thingy {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
if (thingy(1, 2) != 3) unreachable;
diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig
index 6557de08ca9dd687b2231436b3d48bf96e0dbbde..19a053e2c9192c63fd13929a39c73e1b9085f0bb 100644
--- a/test/behavior/enum.zig
+++ b/test/behavior/enum.zig
@@ -931,7 +931,6 @@ test "constant enum initialization with differing sizes" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
try test3_1(test3_foo);
try test3_2(test3_bar);
}
@@ -973,8 +972,8 @@ test "@tagName" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
@@ -1059,6 +1058,7 @@ test "tag name with signed enum values" {
test "tag name with large enum values" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const Kdf = enum(u128) {
aes_kdf = 0xea4f8ac1080d74bf60448a629af3d9c9,
@@ -1078,6 +1078,7 @@ test "tag name with large enum values" {
test "@tagName with exotic integer enum types" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
fn testEnumSigned(comptime T: type) !void {
@@ -1280,6 +1281,7 @@ test "tag name functions are unique" {
test "size of enum with only one tag which has explicit integer tag type" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const E = enum(u8) { nope = 10 };
const S0 = struct { e: E };
@@ -1313,6 +1315,26 @@ test "switch on an extern enum with negative value" {
}
}
+test "switch on an enum with small signed tag type" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
+ const E = enum(i3) {
+ y = -2,
+ z = -1,
+ a = 0,
+ b = 1,
+ c = 2,
+ };
+
+ var runtime: E = .c;
+ _ = &runtime;
+ const result: u8 = switch (runtime) {
+ .y, .z, .a, .b => 0,
+ .c => 1,
+ };
+ try expect(result == 1);
+}
+
test "Non-exhaustive enum with nonstandard int size behaves correctly" {
const E = enum(u15) { _ };
try expect(@sizeOf(E) == @sizeOf(u15));
diff --git a/test/behavior/error.zig b/test/behavior/error.zig
index 7a53776b36adecbaede5972f89e7ea19efed0375..725f52bfbee8ab78a3185caa5a20183b292944a3 100644
--- a/test/behavior/error.zig
+++ b/test/behavior/error.zig
@@ -145,6 +145,8 @@ test "implicit cast to optional to error union to return result loc" {
}
test "fn returning empty error set can be passed as fn returning any error" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
entry();
comptime entry();
}
@@ -155,7 +157,6 @@ test "fn returning empty error set can be passed as fn returning any error - poi
entryPtr();
comptime entryPtr();
}
-
fn entry() void {
foo2(bar2);
}
@@ -509,7 +510,6 @@ test "function pointer with return type that is error union with payload which i
const Foo = struct {
fun: *const fn (a: i32) (anyerror!*Foo),
};
-
const Err = error{UnspecifiedErr};
fn bar(a: i32) anyerror!*Foo {
@@ -526,6 +526,7 @@ test "function pointer with return type that is error union with payload which i
}
test "return result loc as peer result loc in inferred error set function" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -557,6 +558,7 @@ test "return result loc as peer result loc in inferred error set function" {
}
test "error payload type is correctly resolved" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -695,7 +697,6 @@ test "coerce error set to the current inferred error set" {
test "error union payload is properly aligned" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
const S = struct {
@@ -1111,6 +1112,7 @@ test "'if' ignores error via local while 'else' ignores error directly" {
}
test "@errorCast into own inferred error set" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const static = struct {
fn foo(b: bool) !void {
if (b) {
diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig
index f644c4261eb79460e5045ce81914a1dbaf3e227e..6b60920e8560c6dfa7cd4381d8b6ede61706cd7e 100644
--- a/test/behavior/eval.zig
+++ b/test/behavior/eval.zig
@@ -456,7 +456,6 @@ test "binary math operator in partially inlined function" {
test "comptime shl" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const a: u128 = 3;
const b: u7 = 63;
@@ -883,6 +882,8 @@ test "debug variable type resolved through indirect zero-bit types" {
}
test "const local with comptime init through array init" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const E1 = enum {
A,
pub fn a() void {}
@@ -1180,8 +1181,6 @@ test "lazy sizeof is resolved in division" {
}
test "lazy sizeof union tag size in compare" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const A = union(enum) {
a: void,
b: void,
@@ -1194,7 +1193,6 @@ test "lazy value is resolved as slice operand" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const A = struct { a: u32 };
var a: [512]u64 = undefined;
diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig
index 693656095332986f1062f0dd546acbe23c2bf8ff..2dbf47fff4d4632660d884e275b1da75420f3133 100644
--- a/test/behavior/floatop.zig
+++ b/test/behavior/floatop.zig
@@ -134,7 +134,6 @@ test "cmp f32" {
}
test "cmp f64" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
try testCmp(f64);
@@ -144,8 +143,8 @@ test "cmp f64" {
test "cmp f128" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testCmp(f128);
try comptime testCmp(f128);
@@ -1546,6 +1545,7 @@ fn testNeg(comptime T: type) !void {
test "negate f80" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
var f: f80 = 0.0;
const a: u80 = @bitCast(f);
diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig
index 52648140162843ecbceddf78165e201129bcc28c..7b22be363ca285bdbdcefa203086538292c05654 100644
--- a/test/behavior/fn.zig
+++ b/test/behavior/fn.zig
@@ -292,6 +292,7 @@ fn voidFun(a: i32, b: void, c: i32, d: void) !void {
test "call function with empty string" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
acceptsString("");
}
@@ -405,6 +406,7 @@ test "function with inferred error set but returning no error" {
test "import passed byref to function in return type" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
fn get() @import("std").ArrayList(i32) {
@@ -440,6 +442,7 @@ test "implicit cast function to function ptr" {
test "method call with optional and error union first param" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
x: i32 = 1234,
@@ -744,6 +747,8 @@ test "coerce generic function making generic parameter concrete" {
}
test "return undefined pointer from function, directly and by expired local" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const S = struct {
var global: i32 = 1;
diff --git a/test/behavior/for.zig b/test/behavior/for.zig
index 3923029312f5c41115dcd202246eb434897e33f9..f4b2ea923f0e7407030b4dc661de7ebf154bfaec 100644
--- a/test/behavior/for.zig
+++ b/test/behavior/for.zig
@@ -521,6 +521,8 @@ test "return from inline for" {
}
test "for loop 0 length range" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const map: []const u8 = &.{};
for (map, 0..map.len) |i, j| {
_ = i;
@@ -545,3 +547,20 @@ test "labeled break from else" {
try S.doTheTest(5);
try comptime S.doTheTest(5);
}
+
+test "value break from inline for" {
+ const S = struct {
+ fn doTheTest() !void {
+ const x = inline for (0..2) |_| {
+ if (true) {
+ var idx: u32 = 0;
+ idx += 1;
+ break idx;
+ }
+ };
+ try expect(x == 1);
+ }
+ };
+ try S.doTheTest();
+ try comptime S.doTheTest();
+}
diff --git a/test/behavior/generics.zig b/test/behavior/generics.zig
index 6f6c6d4707e29a2408c171f269ccba2bf46ca62a..1314925420c7b8a7c31c32fdaaa7e0fcac7bd9b0 100644
--- a/test/behavior/generics.zig
+++ b/test/behavior/generics.zig
@@ -486,8 +486,6 @@ test "union in struct captures argument" {
test "function argument tuple used as struct field" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const S = struct {
fn DeleagateWithContext(comptime Function: type) type {
const ArgArgs = std.meta.ArgsTuple(Function);
@@ -521,6 +519,7 @@ test "call generic function with from function called by the generic function" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const GET = struct {
key: []const u8,
diff --git a/test/behavior/globals.zig b/test/behavior/globals.zig
index 982ebc41f839ecbf7a28289be2fe38ab3c474acd..98ebedae41cf85ac2f7e6500e5d8cb380159a3d4 100644
--- a/test/behavior/globals.zig
+++ b/test/behavior/globals.zig
@@ -16,6 +16,7 @@ var vpos = @Vector(2, f32){ 0.0, 0.0 };
test "store to global vector" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try expect(vpos[1] == 0.0);
vpos = @Vector(2, f32){ 0.0, 1.0 };
@@ -42,6 +43,7 @@ test "slices pointing at the same address as global array." {
}
test "global loads can affect liveness" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
diff --git a/test/behavior/hasdecl.zig b/test/behavior/hasdecl.zig
index 220a4afd491947c9a3906f80402ec197a8aff01a..71f9200b276e8bb02fdf5f53a7eb33c5c436e7d1 100644
--- a/test/behavior/hasdecl.zig
+++ b/test/behavior/hasdecl.zig
@@ -13,7 +13,6 @@ const Bar = struct {
test "@hasDecl" {
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try expect(@hasDecl(Foo, "public_thing"));
try expect(!@hasDecl(Foo, "private_thing"));
@@ -26,7 +25,6 @@ test "@hasDecl" {
test "@hasDecl using a sliced string literal" {
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try expect(@hasDecl(@This(), "std") == true);
try expect(@hasDecl(@This(), "std"[0..0]) == false);
diff --git a/test/behavior/import.zig b/test/behavior/import.zig
index faa3a08141558864248a10bff2e5a60f7993fe42..7f1025a9156ef723d2733432f2e6511f3732c071 100644
--- a/test/behavior/import.zig
+++ b/test/behavior/import.zig
@@ -5,21 +5,18 @@ const expectEqual = std.testing.expectEqual;
const a_namespace = @import("import/a_namespace.zig");
test "call fn via namespace lookup" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
try expect(@as(i32, 1234) == a_namespace.foo());
}
test "importing the same thing gives the same import" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
try expect(@import("std") == @import("std"));
}
test "import empty file" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
_ = @import("import/empty.zig");
diff --git a/test/behavior/incomplete_struct_param_tld.zig b/test/behavior/incomplete_struct_param_tld.zig
index 4edf974daba261157c5ecc355ff7355ce2a5bfe3..0dc585820f7220d4458e55ca7b3caf39c1c12580 100644
--- a/test/behavior/incomplete_struct_param_tld.zig
+++ b/test/behavior/incomplete_struct_param_tld.zig
@@ -23,6 +23,7 @@ fn foo(a: A) i32 {
test "incomplete struct param top level declaration" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const a = A{
.b = B{
diff --git a/test/behavior/inline_switch.zig b/test/behavior/inline_switch.zig
index a1efe7ab022e1de44dc0e0e0411d915348523999..2e35307167d7ec9ec3764da6cf349315d4c0e72d 100644
--- a/test/behavior/inline_switch.zig
+++ b/test/behavior/inline_switch.zig
@@ -4,6 +4,7 @@ const builtin = @import("builtin");
test "inline scalar prongs" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
var x: usize = 0;
switch (x) {
@@ -18,6 +19,7 @@ test "inline scalar prongs" {
test "inline prong ranges" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
var x: usize = 0;
_ = &x;
@@ -32,7 +34,6 @@ test "inline prong ranges" {
const E = enum { a, b, c, d };
test "inline switch enums" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
-
var x: E = .a;
_ = &x;
switch (x) {
@@ -45,7 +46,7 @@ const U = union(E) { a: void, b: u2, c: u3, d: u4 };
test "inline switch unions" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
-
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
var x: U = .a;
_ = &x;
switch (x) {
@@ -70,7 +71,6 @@ test "inline switch unions" {
test "inline else bool" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
-
var a = true;
_ = &a;
switch (a) {
@@ -81,7 +81,7 @@ test "inline else bool" {
test "inline else error" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
-
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const Err = error{ a, b, c };
var a = Err.a;
_ = &a;
@@ -93,6 +93,7 @@ test "inline else error" {
test "inline else enum" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const E2 = enum(u8) { a = 2, b = 3, c = 4, d = 5 };
var a: E2 = .a;
@@ -123,6 +124,7 @@ test "inline else int with gaps" {
test "inline else int all values" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
var a: u2 = 0;
_ = &a;
@@ -138,6 +140,8 @@ test "inline else int all values" {
}
test "inline switch capture is set when switch operand is comptime known" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const U2 = union(enum) {
a: u32,
};
diff --git a/test/behavior/int128.zig b/test/behavior/int128.zig
index eddf74097b78dc4d1a63521eee5bbc35e5833bb2..9687e3171497df8fb41e9c7fd3277829e81069e2 100644
--- a/test/behavior/int128.zig
+++ b/test/behavior/int128.zig
@@ -7,7 +7,6 @@ const builtin = @import("builtin");
test "uint128" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
var buff: u128 = maxInt(u128);
@@ -45,7 +44,6 @@ test "undefined 128 bit int" {
test "int128" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
var buff: i128 = -1;
@@ -90,7 +88,6 @@ test "truncate int128" {
test "shift int128" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
const types = .{ u128, i128 };
diff --git a/test/behavior/ir_block_deps.zig b/test/behavior/ir_block_deps.zig
index 4708af87f4bd27060125a8e2c0e111e0996badab..d4218387ecd6987feaaa1c751947b2b27e8fb01f 100644
--- a/test/behavior/ir_block_deps.zig
+++ b/test/behavior/ir_block_deps.zig
@@ -19,6 +19,7 @@ fn getErrInt() anyerror!i32 {
test "ir block deps" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
try expect((foo(1) catch unreachable) == 0);
diff --git a/test/behavior/math.zig b/test/behavior/math.zig
index b7b383d358ea084ae2d340b0db8a97c8b44ec5d7..4f22fd04aef6e2dcb7db0c3387ef02df34409667 100644
--- a/test/behavior/math.zig
+++ b/test/behavior/math.zig
@@ -383,7 +383,6 @@ fn not(comptime T: type, a: T) T {
test "binary not" {
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try expect(not(u0, 0) == 0);
try expect(not(u1, 0) == 1);
@@ -424,7 +423,6 @@ test "binary not" {
test "binary not big int <= 128 bits" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
try expect(not(u65, 1) == 0x1_FFFFFFFF_FFFFFFFE);
@@ -458,8 +456,6 @@ test "division" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
try testIntDivision();
try comptime testIntDivision();
@@ -659,8 +655,6 @@ fn testSignedWrappingEval(x: i32) !void {
}
test "signed negation wrapping" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
try testSignedNegationWrappingEval(minInt(i16));
try comptime testSignedNegationWrappingEval(minInt(i16));
}
@@ -763,7 +757,6 @@ fn should_not_be_zero(x: f128) !void {
test "umax wrapped squaring" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
{
var x: u4 = maxInt(u4);
@@ -820,7 +813,6 @@ test "umax wrapped squaring" {
test "128-bit multiplication" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
@@ -873,7 +865,6 @@ test "@addWithOverflow <= 128 bits" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
try testAddWithOverflow(u65, 4, 105, 109, 0);
try testAddWithOverflow(u65, 1000, 100, 1100, 0);
@@ -1000,7 +991,6 @@ test "extensive @mulWithOverflow" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testMulWithOverflow(u5, 3, 10, 30, 0);
try testMulWithOverflow(u5, 3, 11, 1, 1);
@@ -1114,6 +1104,7 @@ test "@mulWithOverflow bitsize 128 bits" {
test "@mulWithOverflow > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testMulWithOverflow(u140, 0, maxInt(u140), 0, 0);
try testMulWithOverflow(u140, 1, maxInt(u140), maxInt(u140), 0);
@@ -1206,7 +1197,6 @@ test "@subWithOverflow <= 128 bits" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
try testSubWithOverflow(u65, 4, 105, maxInt(u65) - 100, 1);
try testSubWithOverflow(u65, 1000, 100, 900, 0);
@@ -1340,6 +1330,7 @@ test "@shlWithOverflow > 64 bits" {
test "@shlWithOverflow > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testShlWithOverflow(u140, 1 << 100, 20, 1 << 120, 0);
try testShlWithOverflow(u140, 1 << 100, 40, 0, 1);
@@ -1398,6 +1389,7 @@ fn testOr(comptime T: type, a: T, b: T, expected: T) !void {
test "or > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testOr(u140, 0, 1 << 139, 1 << 139);
try testOr(u140, (1 << 70) | 0xa, (1 << 69) | 0x5, (1 << 70) | (1 << 69) | 0xf);
@@ -1543,6 +1535,7 @@ fn testClz(comptime T: type, a: T, expected: u16) !void {
test "@clz > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testClz(u140, 0, 140);
try testClz(u140, 1 << 139, 0);
@@ -1572,6 +1565,7 @@ fn testCtz(comptime T: type, a: T, expected: u16) !void {
test "@ctz > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testCtz(u140, 0, 140);
try testCtz(u140, 1 << 139, 139);
@@ -1601,6 +1595,7 @@ fn testPopCount(comptime T: type, a: T, expected: u16) !void {
test "@popCount > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testPopCount(u140, 0, 0);
try testPopCount(u140, maxInt(u140), 140);
@@ -1630,6 +1625,7 @@ fn testBitReverse(comptime T: type, a: T, expected: T) !void {
test "@bitReverse > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testBitReverse(u140, 1 << 139, 1);
try testBitReverse(u140, 1 << 70, 1 << 69);
@@ -1659,6 +1655,7 @@ fn testByteSwap(comptime T: type, a: T, expected: T) !void {
test "@byteSwap > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testByteSwap(u144, 1 << 136, 1);
try testByteSwap(u144, 1, 1 << 136);
@@ -1688,6 +1685,7 @@ fn testMax(comptime T: type, a: T, b: T, expected: T) !void {
test "@max > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testMax(u140, 0, maxInt(u140), maxInt(u140));
try testMax(u140, 1 << 139, 1 << 138, 1 << 139);
@@ -1717,6 +1715,7 @@ fn testMin(comptime T: type, a: T, b: T, expected: T) !void {
test "@min > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testMin(u140, 0, maxInt(u140), 0);
try testMin(u140, 1 << 139, 1 << 138, 1 << 138);
@@ -1746,6 +1745,7 @@ fn testAbs(comptime T: type, a: T, expected: anytype) !void {
test "@abs > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testAbs(u140, 0, 0);
try testAbs(u140, 1 << 139, 1 << 139);
@@ -1770,6 +1770,7 @@ fn testRem(comptime T: type, numerator: T, denominator: T, expected: T) !void {
test "@rem > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testRem(u140, 0, maxInt(u140), 0);
try testRem(u140, maxInt(u140), maxInt(u140), 0);
@@ -1797,6 +1798,7 @@ fn testMod(comptime T: type, numerator: T, denominator: T, expected: T) !void {
test "@mod > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testMod(u140, 0, maxInt(u140), 0);
try testMod(u140, maxInt(u140), maxInt(u140), 0);
@@ -1824,6 +1826,7 @@ fn testDivFloor(comptime T: type, numerator: T, denominator: T, expected: T) !vo
test "@divFloor > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testDivFloor(u140, 0, maxInt(u140), 0);
try testDivFloor(u140, maxInt(u140), maxInt(u140), 1);
@@ -1852,6 +1855,7 @@ fn testDivTrunc(comptime T: type, numerator: T, denominator: T, expected: T) !vo
test "@divTrunc > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testDivTrunc(u140, 0, maxInt(u140), 0);
try testDivTrunc(u140, maxInt(u140), maxInt(u140), 1);
@@ -2514,7 +2518,6 @@ test "partially-runtime integer vector division would be illegal if vector eleme
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
var lhs: @Vector(2, i8) = .{ -128, 5 };
@@ -2542,7 +2545,6 @@ test "float vector division of comptime zero by runtime nan is nan" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const ct_zero: @Vector(1, f32) = .{0};
var rt_nan: @Vector(1, f32) = .{math.nan(f32)};
@@ -2559,7 +2561,6 @@ test "float vector multiplication of comptime zero by runtime nan is nan" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const ct_zero: @Vector(1, f32) = .{0};
var rt_nan: @Vector(1, f32) = .{math.nan(f32)};
@@ -2574,7 +2575,6 @@ test "comptime float vector division of zero by nan is nan" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const ct_zero: @Vector(1, f32) = .{0};
const ct_nan: @Vector(1, f32) = .{math.nan(f32)};
@@ -2588,7 +2588,6 @@ test "comptime float vector multiplication of zero by nan is nan" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const ct_zero: @Vector(1, f32) = .{0};
const ct_nan: @Vector(1, f32) = .{math.nan(f32)};
@@ -2598,6 +2597,8 @@ test "comptime float vector multiplication of zero by nan is nan" {
}
test "i96 operations" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
// This is coverage for some stuff used by std.Io timestamps, to catch
// issues earlier than bootstrapping.
const Op_i96 = union(enum) {
diff --git a/test/behavior/maximum_minimum.zig b/test/behavior/maximum_minimum.zig
index efe2a7f108b79fa7a589fa7e4e78671b6f091b0f..22db5a75502f8456ac0637ef134a137434d3da75 100644
--- a/test/behavior/maximum_minimum.zig
+++ b/test/behavior/maximum_minimum.zig
@@ -160,6 +160,7 @@ test "@min/@max more than two arguments" {
}
test "@min/@max more than two vector arguments" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -189,6 +190,7 @@ test "@min/@max notices bounds" {
}
test "@min/@max notices vector bounds" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -239,6 +241,7 @@ test "@min/@max notices bounds from types" {
}
test "@min/@max notices bounds from vector types" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -301,8 +304,6 @@ test "@min/@max notices bounds from vector types when element of comptime-known
}
test "@min/@max of signed and unsigned runtime integers" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
var x: i32 = -1;
var y: u31 = 1;
_ = .{ &x, &y };
@@ -348,6 +349,7 @@ test "@min/@max with runtime signed and unsigned integers of same size" {
}
test "@min/@max with runtime vectors of signed and unsigned integers of same size" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
diff --git a/test/behavior/memcpy.zig b/test/behavior/memcpy.zig
index fd2cc8fe6a86c9fd8651b274a37eeecb506656f3..462ce44b1b4720971aa735230692a07165eabb73 100644
--- a/test/behavior/memcpy.zig
+++ b/test/behavior/memcpy.zig
@@ -168,8 +168,6 @@ test "@memcpy with sentinel" {
}
test "@memcpy no sentinel source into sentinel destination" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const S = struct {
fn doTheTest() void {
const src: []const u8 = &.{ 1, 2, 3 };
diff --git a/test/behavior/memset.zig b/test/behavior/memset.zig
index 067f89c628a9b331ae57372b9d48cf3e566a6fe3..ed9df298ac0b327506efdbe68871044974ba75dc 100644
--- a/test/behavior/memset.zig
+++ b/test/behavior/memset.zig
@@ -179,6 +179,8 @@ test "@memset with zero-length array" {
}
test "@memset a global array" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const S = struct {
var buf: [1]u32 = .{123};
};
@@ -190,6 +192,8 @@ test "@memset a global array" {
}
test "@memset array of booleans" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const S = struct {
var x: bool = false;
var y: [1]bool = undefined;
diff --git a/test/behavior/muladd.zig b/test/behavior/muladd.zig
index 6a7e18d4102944513b91b9eb95331004ebf8467f..a6fddd62fe10a87ba72dd9b92e9fd72be46bca40 100644
--- a/test/behavior/muladd.zig
+++ b/test/behavior/muladd.zig
@@ -6,7 +6,6 @@ test "@mulAdd" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try comptime testMulAdd();
try testMulAdd();
@@ -33,7 +32,6 @@ test "@mulAdd f16" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try comptime testMulAdd16();
try testMulAdd16();
diff --git a/test/behavior/multiple_externs_with_conflicting_types.zig b/test/behavior/multiple_externs_with_conflicting_types.zig
index 7fa72506aaa450ba24a3b48ddc13cf35a74bfacf..e0965665b697b61d10017da94ace744150ba7c91 100644
--- a/test/behavior/multiple_externs_with_conflicting_types.zig
+++ b/test/behavior/multiple_externs_with_conflicting_types.zig
@@ -5,7 +5,9 @@ const A = extern struct {
extern fn issue529(?*A) void;
comptime {
- _ = @import("conflicting_externs/b.zig");
+ if (builtin.zig_backend != .stage2_spirv) {
+ _ = @import("conflicting_externs/b.zig");
+ }
}
const builtin = @import("builtin");
diff --git a/test/behavior/namespace_depends_on_compile_var.zig b/test/behavior/namespace_depends_on_compile_var.zig
index 8cc7a9b85e01a37be83a8f82645a1c8114ea95b2..36c2b5ae666043d26317b63afcf71afd04e67275 100644
--- a/test/behavior/namespace_depends_on_compile_var.zig
+++ b/test/behavior/namespace_depends_on_compile_var.zig
@@ -3,7 +3,6 @@ const builtin = @import("builtin");
const expect = std.testing.expect;
test "namespace depends on compile var" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
if (some_namespace.a_bool) {
diff --git a/test/behavior/optional.zig b/test/behavior/optional.zig
index ce104bf931b0e115812759e82cedefd51dad52ef..e812cd4c08b655cd2d21ad61cc8c4fd2fffd17d7 100644
--- a/test/behavior/optional.zig
+++ b/test/behavior/optional.zig
@@ -338,7 +338,6 @@ test "coerce an anon struct literal to optional struct" {
test "0-bit child type coerced to optional return ptr result location" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
-
const S = struct {
fn doTheTest() !void {
var y = Foo{};
@@ -364,7 +363,6 @@ test "0-bit child type coerced to optional" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const S = struct {
fn doTheTest() !void {
var it: Foo = .{
@@ -428,6 +426,7 @@ test "optional pointer to zero bit optional payload" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const B = struct {
fn foo(_: *@This()) void {}
@@ -655,6 +654,8 @@ test "result location initialization of optional with OPV payload" {
}
test "global comptime only optional" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const S = struct {
const @"null": ?*type = null;
const @"void": ?*const type = &void;
@@ -664,3 +665,14 @@ test "global comptime only optional" {
assert(S.void.?.* == void);
}
}
+
+test "optional ptr payload alignment" {
+ const S = struct {
+ fn doTheTest(p: *align(1) ?u32) !void {
+ comptime assert(@TypeOf(&p.*.?) == *align(1) u32);
+ try expect(p.*.? == 10);
+ }
+ };
+ var x: ?u32 = 10;
+ try S.doTheTest(&x);
+}
diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig
index 1eb69ace532ea46cae3e12ca840663e31bbf4ceb..103d6a21775fdb3590e7ed873ccb07b5210907bd 100644
--- a/test/behavior/packed-struct.zig
+++ b/test/behavior/packed-struct.zig
@@ -227,7 +227,6 @@ test "nested packed structs" {
test "regular in irregular packed struct" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
const Irregular = packed struct {
@@ -248,7 +247,7 @@ test "nested packed struct unaligned" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
-
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S1 = packed struct {
a: u4,
b: u4,
@@ -407,7 +406,6 @@ test "nested packed struct field pointers" {
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // ubsan unaligned pointer access
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
-
const S2 = packed struct {
base: u8,
p0: packed struct {
@@ -816,6 +814,7 @@ test "packed struct passed to callconv(.c) function" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
const Packed = packed struct(u64) {
@@ -893,6 +892,7 @@ test "store undefined to packed result location" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
var x: u4 = 0;
_ = &x;
diff --git a/test/behavior/packed-union.zig b/test/behavior/packed-union.zig
index b0850392aa51efd60cac8af9403656bc07bae9a3..20732eab98a312ba077ffde4494e8deec179225d 100644
--- a/test/behavior/packed-union.zig
+++ b/test/behavior/packed-union.zig
@@ -201,6 +201,8 @@ test "packed union with explicit backing integer" {
}
test "packed union equality" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const Foo = packed union {
a: u4,
b: i4,
diff --git a/test/behavior/pointers.zig b/test/behavior/pointers.zig
index 357599bb449308f51f0779003b69146dce0e0a6e..9ac875fad4990e03554fc217fb38f42d0dfa6e62 100644
--- a/test/behavior/pointers.zig
+++ b/test/behavior/pointers.zig
@@ -144,7 +144,6 @@ test "initialize const optional C pointer to null" {
test "assigning integer to C pointer" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
var x: i32 = 0;
var y: i32 = 1;
var ptr: [*c]u8 = 0;
@@ -696,7 +695,6 @@ fn constant() !void {
test "pointer-to-array constness for zero-size elements, var" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
try mutable();
try comptime mutable();
}
@@ -720,6 +718,8 @@ test "cast pointers with zero sized elements" {
}
test "comptime pointer equality through distinct fields with well-defined layout" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const A = extern struct {
x: u32,
z: u16,
@@ -744,6 +744,8 @@ test "comptime pointer equality through distinct fields with well-defined layout
}
test "comptime pointer equality through distinct elements with well-defined layout" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const buf: [2]u32 = .{ 123, 456 };
const ptr: *const [2]u32 = &buf;
@@ -780,9 +782,11 @@ test "pointers to elements of many-ptr to zero-bit type" {
}
test "comptime C pointer to optional pointer" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const opt: ?*u8 = @ptrFromInt(0x1000);
const outer_ptr: [*c]const ?*u8 = &opt;
const inner_ptr = &outer_ptr.*.?;
- comptime assert(@TypeOf(inner_ptr) == [*c]const *u8);
+ comptime assert(@TypeOf(inner_ptr) == *const *u8);
comptime assert(@intFromPtr(inner_ptr.*) == 0x1000);
}
diff --git a/test/behavior/ptrcast.zig b/test/behavior/ptrcast.zig
index b8b8fa32243871ad7a6faf48ff8517506eff4b0a..31de4f08b474620680a5d43252530124e12b736d 100644
--- a/test/behavior/ptrcast.zig
+++ b/test/behavior/ptrcast.zig
@@ -193,6 +193,7 @@ const Bytes = struct {
test "ptrcast of const integer has the correct object size" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const is_value = ~@as(isize, @intCast(std.math.minInt(isize)));
const is_bytes = @as([*]const u8, @ptrCast(&is_value))[0..@sizeOf(isize)];
@@ -279,6 +280,8 @@ test "@ptrCast undefined value at comptime" {
}
test "comptime @ptrCast with packed struct leaves value unmodified" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const S = packed struct { three: u3 };
const st: S = .{ .three = 6 };
try expect(st.three == 6);
@@ -288,6 +291,8 @@ test "comptime @ptrCast with packed struct leaves value unmodified" {
}
test "@ptrCast restructures comptime-only array" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
{
const a3a2: [3][2]comptime_int = .{
.{ 1, 2 },
@@ -330,6 +335,8 @@ test "@ptrCast restructures comptime-only array" {
}
test "@ptrCast restructures sliced comptime-only array" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const a3a2: [4][2]comptime_int = .{
.{ 1, 2 },
.{ 3, 4 },
@@ -552,6 +559,8 @@ test "@ptrCast single-item pointer to slice of bytes" {
}
test "@ptrCast array pointer removing sentinel" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const in: *const [4:0]u8 = &.{ 1, 2, 3, 4 };
const out: []const i8 = @ptrCast(in);
comptime assert(out.len == 4);
@@ -562,6 +571,8 @@ test "@ptrCast array pointer removing sentinel" {
}
test "@ptrcast larger type to smaller one" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const T = packed struct { x: u17 };
const a: u32 = 0;
const b: *const T = @ptrCast(&a);
diff --git a/test/behavior/pub_enum.zig b/test/behavior/pub_enum.zig
index 39ee14b9dc52151f0adecec02a4add23adfc3d72..fe397fdc640d2aa280050cfcd8ce95a40bd45328 100644
--- a/test/behavior/pub_enum.zig
+++ b/test/behavior/pub_enum.zig
@@ -3,7 +3,6 @@ const other = @import("pub_enum/other.zig");
const expect = @import("std").testing.expect;
test "pub enum" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
try pubEnumTest(other.APubEnum.Two);
@@ -13,7 +12,6 @@ fn pubEnumTest(foo: other.APubEnum) !void {
}
test "cast with imported symbol" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
try expect(@as(other.size_t, 42) == 42);
diff --git a/test/behavior/saturating_arithmetic.zig b/test/behavior/saturating_arithmetic.zig
index 0e2978bd9b13819905cc1d29c705f33247dc3c7b..c434f014f36e40f2cfea9fc0c2508320d09c74a4 100644
--- a/test/behavior/saturating_arithmetic.zig
+++ b/test/behavior/saturating_arithmetic.zig
@@ -362,6 +362,7 @@ test "saturating shl uses the LHS type" {
test "sat add > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testSatAdd(u140, 0, 0, 0);
try testSatAdd(u140, maxInt(u140), 1, maxInt(u140));
@@ -377,6 +378,7 @@ test "sat add > 128 bits" {
test "sat sub > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testSatSub(u140, 0, 1, 0);
try testSatSub(u140, maxInt(u140), maxInt(u140), 0);
@@ -392,6 +394,7 @@ test "sat sub > 128 bits" {
test "sat mul > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testSatMul(u140, 0, maxInt(u140), 0);
try testSatMul(u140, 1 << 70, 1 << 69, 1 << 139);
@@ -407,6 +410,7 @@ test "sat mul > 128 bits" {
test "sat shl > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testSatShl(u140, 0, u8, 17, 0);
try testSatShl(u140, 1 << 100, u8, 20, 1 << 120);
diff --git a/test/behavior/shuffle.zig b/test/behavior/shuffle.zig
index a3d899bc9ba41cf133e6e862af25f1d367aa9443..871852111025055a87858b65656ad15dc27062fe 100644
--- a/test/behavior/shuffle.zig
+++ b/test/behavior/shuffle.zig
@@ -54,8 +54,6 @@ test "@shuffle int strange sizes" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
try comptime testShuffle(2, 2, 2);
try testShuffle(2, 2, 2);
try comptime testShuffle(4, 4, 4);
@@ -136,7 +134,6 @@ test "@shuffle bool 1" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const S = struct {
fn doTheTest() !void {
var x: @Vector(4, bool) = [4]bool{ false, true, false, true };
diff --git a/test/behavior/sizeof_and_typeof.zig b/test/behavior/sizeof_and_typeof.zig
index cb6c334cb7448bdd403c419baaad2eb9d92443d9..36288f2668777bfe0f2df7780531b2ebaf58c7c1 100644
--- a/test/behavior/sizeof_and_typeof.zig
+++ b/test/behavior/sizeof_and_typeof.zig
@@ -151,9 +151,6 @@ test "branching logic inside @TypeOf" {
test "@bitSizeOf" {
try expect(@bitSizeOf(u2) == 2);
try expect(@bitSizeOf(u8) == @sizeOf(u8) * 8);
- try expect(@bitSizeOf(struct {
- a: u2,
- }) == 8);
try expect(@bitSizeOf(packed struct {
a: u2,
}) == 2);
@@ -211,8 +208,6 @@ test "@sizeOf comparison against zero" {
}
test "hardcoded address in typeof expression" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const S = struct {
fn func() @TypeOf(@as(*[]u8, @ptrFromInt(0x10)).*[0]) {
return 0;
@@ -283,14 +278,6 @@ test "@offsetOf zero-bit field" {
try expect(@offsetOf(S, "b") == @offsetOf(S, "c"));
}
-test "@bitSizeOf on array of structs" {
- const S = struct {
- foo: u64,
- };
-
- try expectEqual(128, @bitSizeOf([2]S));
-}
-
test "lazy abi size used in comparison" {
const S = struct { a: usize };
var rhs: i32 = 100;
@@ -301,7 +288,6 @@ test "lazy abi size used in comparison" {
test "peer type resolution with @TypeOf doesn't trigger dependency loop check" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const T = struct {
next: @TypeOf(null, @as(*const @This(), undefined)),
};
@@ -340,7 +326,7 @@ const exp = struct {
}
};
comptime {
- _ = exp;
+ if (builtin.zig_backend != .stage2_spirv) _ = exp;
}
test "Extern function calls in @TypeOf" {
@@ -426,3 +412,8 @@ test "@sizeOf struct is resolved when used as operand of slicing" {
S.buf[@sizeOf(dummy)..][0] = 0;
try expect(S.buf[0] == 0);
}
+
+test "@TypeOf null C pointer dereference" {
+ comptime assert(@TypeOf(@as([*c]u8, null).*) == u8);
+ comptime assert(@TypeOf(&@as([*c]u8, null).*) == *u8);
+}
diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig
index b0be08391b83db7a4260fee68c01c9dbb26b47de..a30469821a3a279766dd6302bbc2272c7dfa826f 100644
--- a/test/behavior/slice.zig
+++ b/test/behavior/slice.zig
@@ -67,6 +67,7 @@ test "comptime slice of undefined pointer of length 0" {
test "implicitly cast array of size 0 to slice" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
var msg = [_]u8{};
try assertLenIsZero(&msg);
@@ -172,7 +173,6 @@ test "pass a slice of types to a function" {
test "generic malloc free" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
-
const a = memAlloc(u8, 10) catch unreachable;
memFree(u8, a);
}
@@ -186,7 +186,6 @@ fn memFree(comptime T: type, memory: []T) void {
test "slice of hardcoded address to pointer" {
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const S = struct {
fn doTheTest() !void {
const pointer = @as([*]u8, @ptrFromInt(0x04))[0..2];
@@ -225,7 +224,6 @@ test "comptime pointer cast array and then slice" {
test "slicing zero length array" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const s1 = ""[0..];
const s2 = ([_]u32{})[0..];
try expect(s1.len == 0);
@@ -276,6 +274,7 @@ test "slice string literal has correct type" {
test "result location zero sized array inside struct field implicit cast to slice" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const E = struct {
entries: []u32,
@@ -382,6 +381,8 @@ test "obtaining a null terminated slice" {
}
test "empty array to slice" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const S = struct {
fn doTheTest() !void {
const empty: []align(16) u8 = &[_]u8{};
@@ -786,6 +787,8 @@ test "slice bounds in comptime concatenation" {
}
test "slice sentinel access at comptime" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
{
const str0 = &[_:0]u8{ '1', '2', '3' };
const slice0: [:0]const u8 = str0;
@@ -852,6 +855,8 @@ test "slice len modification at comptime" {
}
test "slice field ptr const" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const const_slice: []const u8 = "string";
const const_ptr_const_slice = &const_slice;
@@ -865,6 +870,7 @@ test "slice field ptr const" {
test "slice field ptr var" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
var var_slice: []const u8 = "string";
@@ -1050,6 +1056,8 @@ test "peer slices keep abi alignment with empty struct" {
}
test "sentinel expression in slice operation has result type" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const sentinel = std.math.maxInt(u16);
const arr: [3]u16 = .{ 1, 2, sentinel };
@@ -1075,3 +1083,15 @@ test "conditionally return second argument slice" {
try expectEqualStrings("", S.foo(false, "false"));
try expectEqualStrings("true", S.foo(true, "true"));
}
+
+test "slice field alignment" {
+ const S = struct {
+ fn doTheTest(p: *align(1) const []u8) !void {
+ comptime assert(@TypeOf(&p.ptr) == *align(1) const [*]u8);
+ comptime assert(@TypeOf(&p.len) == *align(1) const usize);
+ try expect(p.len == 10);
+ }
+ };
+ var arr: [10]u8 = @splat(0);
+ try S.doTheTest(&&arr);
+}
diff --git a/test/behavior/spirv.zig b/test/behavior/spirv.zig
new file mode 100644
index 0000000000000000000000000000000000000000..6d11032959e665ed26063894e494cd7084f953e4
--- /dev/null
+++ b/test/behavior/spirv.zig
@@ -0,0 +1,47 @@
+const Sampler = @SpirvType(.sampler);
+const Image = @SpirvType(.{ .image = .{
+ .usage = .{ .sampled = u32 },
+ .format = .unknown,
+ .dim = .@"2d",
+ .depth = .unknown,
+ .arrayed = false,
+ .multisampled = false,
+ .access = .unknown,
+} });
+const SampledImage = @SpirvType(.{ .sampled_image = Image });
+const StorageImage = @SpirvType(.{ .image = .{
+ .usage = .{ .storage = u32 },
+ .format = .unknown,
+ .dim = .@"2d",
+ .depth = .unknown,
+ .arrayed = false,
+ .multisampled = false,
+ .access = .unknown,
+} });
+const RuntimeArray = @SpirvType(.{ .runtime_array = u32 });
+
+const RuntimeArrayBuf = extern struct { e: RuntimeArray };
+
+const sampler = @extern(*addrspace(.constant) const Sampler, .{
+ .name = "sampler",
+ .decoration = .{ .descriptor = .{ .set = 0, .binding = 0 } },
+});
+const sampled_image = @extern(*addrspace(.constant) const SampledImage, .{
+ .name = "sampled_image",
+ .decoration = .{ .descriptor = .{ .set = 0, .binding = 1 } },
+});
+const storage_image = @extern(*addrspace(.constant) const StorageImage, .{
+ .name = "storage_image",
+ .decoration = .{ .descriptor = .{ .set = 0, .binding = 2 } },
+});
+const runtime_array = @extern(*addrspace(.storage_buffer) const RuntimeArrayBuf, .{
+ .name = "runtime_array",
+ .decoration = .{ .descriptor = .{ .set = 0, .binding = 3 } },
+});
+
+test "@SpirvType" {
+ _ = sampler;
+ _ = sampled_image;
+ _ = storage_image;
+ _ = runtime_array;
+}
diff --git a/test/behavior/string_literals.zig b/test/behavior/string_literals.zig
index c1e89bacb2b296b7d5dc193e0f90650bab257745..ff5f57f23510f598127e950a828b41a40dbcac5a 100644
--- a/test/behavior/string_literals.zig
+++ b/test/behavior/string_literals.zig
@@ -101,7 +101,6 @@ test "Peer type resolution with string literals and unknown length u8 pointers"
test "including the sentinel when dereferencing a string literal" {
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
var var_str = "abc";
const var_derefed = var_str[0 .. var_str.len + 1].*;
diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig
index 4a4906699578f5f36e7bd9e0b31a563f7718c384..103ecc8994a6c66ab2be8a0aeee6781cf7ba66ef 100644
--- a/test/behavior/struct.zig
+++ b/test/behavior/struct.zig
@@ -378,7 +378,6 @@ const APackedStruct = packed struct {
test "packed struct" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
var foo = APackedStruct{
@@ -447,7 +446,6 @@ test "runtime struct initialization of bitfield" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
const s1 = Nibbles{
@@ -488,7 +486,6 @@ test "packed struct fields are ordered from LSB to MSB" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
var all: u64 = 0x7765443322221111;
var bytes: [8]u8 align(@alignOf(Bitfields)) = undefined;
@memcpy(bytes[0..8], @as([*]u8, @ptrCast(&all)));
@@ -507,7 +504,6 @@ test "implicit cast packed struct field to const ptr" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
const LevelUpMove = packed struct {
@@ -991,6 +987,7 @@ test "struct with 0-length union array field" {
}
test "packed struct with undefined initializers" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -1645,6 +1642,8 @@ test "struct init with no result pointer sets field result types" {
}
test "runtime side-effects in comptime-known struct init" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
var side_effects: u4 = 0;
const S = struct { a: u4, b: u4, c: u4, d: u4 };
const init = S{
@@ -1921,6 +1920,7 @@ test "runtime value in nested initializer passed as pointer to function" {
}
test "struct field default value is a call" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -2182,6 +2182,7 @@ test "pass a pointer to a comptime-only struct field to a function" {
}
test "overaligned extern struct fields" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const A = struct {
a: *anyopaque,
b: u64,
@@ -2231,6 +2232,7 @@ test "overaligned extern struct fields" {
}
test "runtime-known slice of comptime-only struct" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const Mixed = struct { index: u32, T: type };
const static = struct {
@@ -2252,6 +2254,7 @@ test "runtime-known slice of comptime-only struct" {
}
test "struct contains aligned pointer to itself through type decl" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const Slab = struct {
const Ptr = *align(64) const @This();
next: Ptr,
@@ -2269,6 +2272,7 @@ test "struct contains aligned pointer to itself through type decl" {
}
test "struct contains underaligned field with overaligned pointer to itself" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
const S = struct {
ptr: *align(8) @This() align(1),
@@ -2281,6 +2285,7 @@ test "struct contains underaligned field with overaligned pointer to itself" {
}
test "struct contains pointer to function accepting that struct" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
const FnPtr = ?*const fn (@This()) void;
fn_ptr: FnPtr,
@@ -2303,6 +2308,7 @@ test "struct queries typeinfo of struct containing pointer back to first struct"
}
test "pointer to runtime field of struct containing struct containing comptime-only optional" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const Foo = struct {
padding: struct { a: u8, b: ?comptime_int },
number: u8,
@@ -2314,3 +2320,12 @@ test "pointer to runtime field of struct containing struct containing comptime-o
ptr = &foo.number;
try expect(ptr.* == 123);
}
+
+test "struct field referencing comptime var isn't comptime" {
+ comptime var v: u8 = 0;
+ const s = .{ .v = &v };
+ // field isn't comptime but struct is still comptime-known
+ comptime assert(!@typeInfo(@TypeOf(s)).@"struct".field_attrs[0].@"comptime");
+ v = 1;
+ comptime assert(s.v.* == 1);
+}
diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig
index 43286ea0fcefdd3ca1371243ea81a5f483e96349..e56da92324e578190ea4119e04b5379abf687c2d 100644
--- a/test/behavior/switch.zig
+++ b/test/behavior/switch.zig
@@ -9,7 +9,6 @@ const maxInt = std.math.maxInt;
test "switch with numbers" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testSwitchWithNumbers(13);
}
@@ -25,7 +24,6 @@ fn testSwitchWithNumbers(x: u32) !void {
test "switch with all ranges" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
try expect(testSwitchWithAllRanges(50, 3) == 1);
try expect(testSwitchWithAllRanges(101, 0) == 2);
@@ -214,8 +212,6 @@ test "undefined.u0" {
test "switch with disjoint range" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
-
var q: u8 = 0;
_ = &q;
switch (q) {
@@ -226,8 +222,6 @@ test "switch with disjoint range" {
}
test "switch variable for range and multiple prongs" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
-
const S = struct {
fn doTheTest() !void {
try doTheSwitch(16);
@@ -276,6 +270,7 @@ test "switch prong with variable" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 });
try switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 });
@@ -299,6 +294,7 @@ fn switchProngWithVarFn(a: SwitchProngWithVarEnum) !void {
test "switch on enum using pointer capture" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testSwitchEnumPtrCapture();
try comptime testSwitchEnumPtrCapture();
@@ -359,6 +355,7 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 {
test "switch on union with some prongs capturing" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const X = union(enum) {
a,
@@ -395,6 +392,7 @@ test "switch on const enum with var" {
test "anon enum literal used in switch on union enum" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const Foo = union(enum) {
a: i32,
@@ -576,6 +574,7 @@ test "switch with null and T peer types and inferred result location type" {
test "switch prongs with cases with identical payload types" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const Union = union(enum) {
A: usize,
@@ -617,6 +616,8 @@ test "switch prongs with cases with identical payload types" {
}
test "switch prong pointer capture alignment" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const U = union(enum) {
a: u8 align(8),
b: u8 align(4),
@@ -794,6 +795,7 @@ test "enum value without tag name used as switch item" {
}
test "switch item sizeof" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
fn doTheTest() !void {
var a: usize = 0;
@@ -840,6 +842,7 @@ test "switch capture peer type resolution" {
test "switch capture peer type resolution for in-memory coercible payloads" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const T1 = c_int;
const t1_info = @typeInfo(T1).int;
@@ -863,6 +866,7 @@ test "switch capture peer type resolution for in-memory coercible payloads" {
test "switch pointer capture peer type resolution" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const T1 = c_int;
const t1_info = @typeInfo(T1).int;
@@ -968,6 +972,8 @@ test "switch prong captures range" {
}
test "prong with inline call to unreachable" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const U = union(enum) {
void: void,
bool: bool,
@@ -1174,6 +1180,8 @@ test "switch with uninstantiable union fields" {
}
test "switch with tag capture" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const U = union(enum) {
a,
b: i32,
@@ -1307,6 +1315,8 @@ test "single-item prong in switch on enum has comptime-known capture" {
}
test "single range switch prong capture" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const S = struct {
fn doTheTest(x: u8) !void {
switch (x) {
@@ -1328,6 +1338,8 @@ test "single range switch prong capture" {
}
test "switch on packed struct" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const P = packed struct {
a: u1,
b: u1,
@@ -1358,6 +1370,8 @@ test "switch on packed struct" {
}
test "switch on packed union" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const P = packed union(u2) {
a: u2,
b: i2,
@@ -1405,6 +1419,8 @@ test "switch on packed union" {
}
test "switch on nested packed containers" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const P = packed struct {
iu: u17,
is: i31,
@@ -1458,6 +1474,8 @@ test "switch on nested packed containers" {
}
test "switch on large types" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const S = struct {
fn doTheTest(a: u128, b: i500) !void {
switch (a) {
@@ -1519,3 +1537,59 @@ test "error captures narrow error sets" {
try comptime S.doTheTest(error.B);
try comptime S.doTheTest(error.C);
}
+
+test "repeated switch analysis overrides previous analysis results" {
+ // This tests an implementation detail where semantic analysis of switch
+ // statements uses the switch inst itself to store capture values and result
+ // type information while analyzing (parts of) that switch inst.
+ // If that inst has already been assigned a result by a previous analysis
+ // that result needs to be overwritten.
+
+ comptime {
+ const x: u32 = 123;
+ for (0..2) |_| _ = switch (x) {
+ 123 => |capture| capture,
+ else => unreachable,
+ };
+ }
+ comptime {
+ const x: union(enum) { a, b, c } = .a;
+ for (0..2) |_| _ = switch (x) {
+ .a => |_, tag| tag,
+ else => unreachable,
+ };
+ }
+ comptime {
+ const x: enum { a, b, c } = .a;
+ for (0..2) |_| _ = label: switch (x) {
+ .a => continue :label .b,
+ else => 123,
+ };
+ }
+ comptime {
+ const x: anyerror!void = error.MyError;
+ for (0..2) |_| _ = x catch |err| switch (err) {
+ error.MyError => {},
+ else => unreachable,
+ };
+ }
+}
+
+test "union field pointer capture preserves alignment in inline prong" {
+ const U = union(enum) {
+ a: u32,
+ b: u32,
+ fn doTheTest(u: *align(1) const @This()) !void {
+ switch (u.*) {
+ inline .a, .b => |*a_ptr| {
+ comptime assert(@TypeOf(a_ptr) == *align(1) const u32);
+ try expect(a_ptr.* == 123);
+ },
+ }
+ }
+ };
+ try U.doTheTest(&.{ .a = 123 });
+ try U.doTheTest(&.{ .b = 123 });
+ try comptime U.doTheTest(&.{ .a = 123 });
+ try comptime U.doTheTest(&.{ .b = 123 });
+}
diff --git a/test/behavior/switch_loop.zig b/test/behavior/switch_loop.zig
index 19293a472bc2a6dc12b319412fe54870e55dec0c..c86c297fa42836456f1b7f64002dffc6aa96313d 100644
--- a/test/behavior/switch_loop.zig
+++ b/test/behavior/switch_loop.zig
@@ -7,7 +7,6 @@ test "simple switch loop" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
const S = struct {
fn doTheTest() !void {
@@ -31,7 +30,6 @@ test "switch loop with ranges" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
const S = struct {
fn doTheTest() !void {
@@ -52,7 +50,6 @@ test "switch loop on enum" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
const S = struct {
const E = enum { a, b, c };
@@ -76,7 +73,6 @@ test "switch loop with error set" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
const S = struct {
const E = error{ Foo, Bar, Baz };
@@ -252,7 +248,6 @@ test "switch loop on non-exhaustive enum" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
const S = struct {
const E = enum(u8) { a, b, c, _ };
@@ -275,8 +270,6 @@ test "switch loop on non-exhaustive enum" {
test "switch loop with discarded tag capture" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const S = struct {
const U = union(enum) {
a: u32,
@@ -301,7 +294,6 @@ test "switch loop with discarded tag capture" {
test "switch loop with single catch-all prong" {
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const S = struct {
const E = enum { a, b, c };
const U = union(E) { a: u32, b: u16, c: u8 };
@@ -397,6 +389,8 @@ test "switch loop on type with opv" {
}
test "switch loop with tag capture" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const U = union(enum) {
a,
b: i32,
@@ -511,6 +505,7 @@ test "switch loop for error handling" {
}
test "switch loop with packed structs" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const P = packed struct {
a: u7,
b: u20,
@@ -528,6 +523,8 @@ test "switch loop with packed structs" {
}
test "switch loop with packed unions" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const P = packed union {
a: u7,
b: i7,
@@ -566,6 +563,8 @@ test "switch loop with packed unions with OPV" {
}
test "switch loop on large types" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const S = struct {
fn doTheTest(a: u128, b: i500) !void {
label: switch (a) {
diff --git a/test/behavior/switch_prong_err_enum.zig b/test/behavior/switch_prong_err_enum.zig
index a2eed86c0f6e30db3f16182e31bdf2529cce3078..a316cacc61cd24cc3eac913fed77d33fe1430f7e 100644
--- a/test/behavior/switch_prong_err_enum.zig
+++ b/test/behavior/switch_prong_err_enum.zig
@@ -24,6 +24,7 @@ test "switch prong returns error enum" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
switch (doThing(17) catch unreachable) {
FormValue.Address => |payload| {
diff --git a/test/behavior/switch_prong_implicit_cast.zig b/test/behavior/switch_prong_implicit_cast.zig
index 0de343898df9a5b0a47b381bd25d45c0d265cb91..aab365f027ea17273c77e05bf96da48cfbedd612 100644
--- a/test/behavior/switch_prong_implicit_cast.zig
+++ b/test/behavior/switch_prong_implicit_cast.zig
@@ -18,6 +18,7 @@ test "switch prong implicit cast" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const result = switch (foo(2) catch unreachable) {
FormValue.One => false,
diff --git a/test/behavior/truncate.zig b/test/behavior/truncate.zig
index 01d9490d0c033678f5876bb4b633004c10e53d91..07d19f29c0da73a045ae58d35836502cbebe5cdc 100644
--- a/test/behavior/truncate.zig
+++ b/test/behavior/truncate.zig
@@ -50,6 +50,7 @@ fn testTruncate(comptime S: type, a: S, comptime D: type, expected: D) !void {
test "@truncate > 128 bits" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testTruncate(u140, 0, u128, 0);
try testTruncate(u140, maxInt(u140), u128, maxInt(u128));
diff --git a/test/behavior/try.zig b/test/behavior/try.zig
index df852abfa15d9c6618b15dd0ebfbfc23ae880208..649e22d5f94b1e30bd7892816b1ddbeb0da22db3 100644
--- a/test/behavior/try.zig
+++ b/test/behavior/try.zig
@@ -1,5 +1,6 @@
const std = @import("std");
const builtin = @import("builtin");
+const assert = std.debug.assert;
const expect = std.testing.expect;
test "try on error union" {
@@ -197,3 +198,14 @@ test "try ptr propagation mutate" {
try S.doTheTest();
try comptime S.doTheTest();
}
+
+test "try pointer expression alignment" {
+ const S = struct {
+ fn doTheTest(p: *align(1) (anyerror!u32)) !void {
+ comptime assert(@TypeOf(&(try p.*)) == *align(1) u32);
+ try expect((try p.*) == 10);
+ }
+ };
+ var x: anyerror!u32 = 10;
+ try S.doTheTest(&x);
+}
diff --git a/test/behavior/tuple.zig b/test/behavior/tuple.zig
index d8510b664b690980c1233eb83bd2351c74209e35..dabc3eb01af28b08e8cdcae8de076069ff054693 100644
--- a/test/behavior/tuple.zig
+++ b/test/behavior/tuple.zig
@@ -105,8 +105,6 @@ test "tuple initializer for var" {
test "array-like initializer for tuple types" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const T = @Tuple(&.{ i32, u8 });
const S = struct {
fn doTheTest() !void {
@@ -172,7 +170,6 @@ test "fieldParentPtr of tuple" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
var x: u32 = 0;
_ = &x;
const tuple = .{ x, x };
@@ -217,8 +214,6 @@ test "initializing tuple with mixed comptime-runtime fields" {
}
test "initializing anon struct with mixed comptime-runtime fields" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
var x: u32 = 15;
_ = &x;
const T = @TypeOf(.{ .foo = @as(i32, -1234), .bar = x });
@@ -230,8 +225,6 @@ test "initializing anon struct with mixed comptime-runtime fields" {
test "tuple in tuple passed to generic function" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const S = struct {
fn pair(x: f32, y: f32) @Tuple(&.{ f32, f32 }) {
return .{ x, y };
@@ -299,6 +292,7 @@ test "tuple type with void field and a runtime field" {
test "branching inside tuple literal" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
fn foo(a: anytype) !void {
@@ -559,6 +553,8 @@ test "OPV tuple fields aren't comptime" {
}
test "array of tuples that end with a zero-bit field followed by padding" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const S = struct {
var foo: [2]struct { u32, u8, void } = .{ .{ 1, 2, {} }, .{ 3, 4, {} } };
};
diff --git a/test/behavior/type.zig b/test/behavior/type.zig
index 79f6769940713716288333d26fb290db3f3240a6..c2d1fc2f4fbf36674bdf3eab2b506fd4acd1fdb4 100644
--- a/test/behavior/type.zig
+++ b/test/behavior/type.zig
@@ -277,6 +277,7 @@ test "Type.Union from empty Type.Enum" {
test "Type.Fn" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const some_opaque = opaque {};
const some_ptr = *some_opaque;
diff --git a/test/behavior/type_info.zig b/test/behavior/type_info.zig
index 882edcf3aba30b33d9f611837ed293551c42c91d..eeea34879b7a7cb8226a8c9107b381a79981a474 100644
--- a/test/behavior/type_info.zig
+++ b/test/behavior/type_info.zig
@@ -253,11 +253,11 @@ fn testUnion() !void {
try expect(typeinfo_info == .@"union");
try expect(typeinfo_info.@"union".layout == .auto);
try expect(typeinfo_info.@"union".tag_type.? == TypeId);
- try expect(typeinfo_info.@"union".field_names.len == 24);
+ try expect(typeinfo_info.@"union".field_names.len == 25);
try expect(typeinfo_info.@"union".field_names.len == typeinfo_info.@"union".field_types.len);
try expect(typeinfo_info.@"union".field_names.len == typeinfo_info.@"union".field_attrs.len);
try expect(typeinfo_info.@"union".field_types[4] == @TypeOf(@typeInfo(u8).int));
- try expect(typeinfo_info.@"union".decl_names.len == 16);
+ try expect(typeinfo_info.@"union".decl_names.len == 17);
const TestNoTagUnion = union {
Foo: void,
@@ -310,6 +310,8 @@ const TestStruct = struct {
};
test "type info: packed struct info" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
try testPackedStruct();
try comptime testPackedStruct();
}
@@ -594,6 +596,8 @@ test "value from struct @typeInfo default_value_ptr can be loaded at comptime" {
}
test "type info of tuple of string literal default value" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const struct_info = @typeInfo(@TypeOf(.{"hi"})).@"struct";
const struct_field_attrs = struct_info.field_attrs[0];
const struct_field_type = struct_info.field_types[0];
@@ -609,3 +613,43 @@ test "@typeInfo function with generic return type and inferred error set" {
const ret_ty = @typeInfo(@TypeOf(S.testFn)).@"fn".return_type;
comptime assert(ret_ty == null);
}
+
+test "type info: spirv info" {
+ if (builtin.zig_backend != .stage2_spirv) return error.SkipZigTest;
+
+ try testSpirv();
+ try comptime testSpirv();
+}
+
+fn testSpirv() !void {
+ const image_info = @typeInfo(Image);
+ try expect(image_info.spirv.image.usage.sampled == f32);
+ try expect(image_info.spirv.image.format == .unknown);
+ try expect(image_info.spirv.image.dim == .@"2d");
+ try expect(image_info.spirv.image.depth == .not_depth);
+ try expect(image_info.spirv.image.arrayed == false);
+ try expect(image_info.spirv.image.multisampled == false);
+ try expect(image_info.spirv.image.access == .unknown);
+
+ const sampled_image_info = @typeInfo(SampledImage);
+ try expect(sampled_image_info.spirv.sampled_image == Image);
+
+ const sampler_info = @typeInfo(Sampler);
+ try expect(sampler_info.spirv.sampler == {});
+
+ const runtime_array_info = @typeInfo(RuntimeArray);
+ try expect(runtime_array_info.spirv.runtime_array == f32);
+}
+
+pub const Image = @SpirvType(.{ .image = .{
+ .usage = .{ .sampled = f32 },
+ .format = .unknown,
+ .dim = .@"2d",
+ .depth = .not_depth,
+ .arrayed = false,
+ .multisampled = false,
+ .access = .unknown,
+} });
+pub const SampledImage = @SpirvType(.{ .sampled_image = Image });
+pub const Sampler = @SpirvType(.sampler);
+pub const RuntimeArray = @SpirvType(.{ .runtime_array = f32 });
diff --git a/test/behavior/union.zig b/test/behavior/union.zig
index e9dbc49aaa9876b3c40ff9816749150a26aa6f1a..be8ae37a4eb5e9287f4392b62d35e73a5f5f1777 100644
--- a/test/behavior/union.zig
+++ b/test/behavior/union.zig
@@ -31,6 +31,7 @@ test "init union with runtime value - floats" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
var foo: FooWithFloats = undefined;
@@ -407,6 +408,7 @@ test "tagged union with no payloads" {
test "union with only 1 field casted to its enum type" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const Literal = union(enum) {
Number: f64,
@@ -443,6 +445,7 @@ var glbl: Foo1 = undefined;
test "global union with single field is correctly initialized" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
glbl = Foo1{
.f = @typeInfo(Foo1).@"union".field_types[0]{ .x = 123 },
@@ -485,6 +488,7 @@ test "update the tag value for zero-sized unions" {
test "union initializer generates padding only if needed" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const U = union(enum) {
A: u24,
@@ -550,6 +554,7 @@ const Baz = enum { A, B, C, D };
test "tagged union type" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const foo1 = TaggedFoo{ .One = 13 };
const foo2 = TaggedFoo{
@@ -654,6 +659,7 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) !void {
test "switch on union with only 1 field" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
var r: PartialInst = undefined;
r = PartialInst.Compiled;
@@ -682,6 +688,7 @@ const PartialInstWithPayload = union(enum) {
test "union with only 1 field casted to its enum type which has enum value specified" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const Literal = union(enum) {
number: f64,
@@ -706,6 +713,7 @@ test "union with only 1 field casted to its enum type which has enum value speci
test "@intFromEnum works on unions" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const Bar = union(enum) {
A: bool,
@@ -765,6 +773,7 @@ test "return union init with void payload" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
fn entry() !void {
@@ -789,6 +798,7 @@ test "@unionInit stored to a const" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
const U = union(enum) {
@@ -818,6 +828,7 @@ test "@unionInit stored to a const" {
test "@unionInit can modify a union type" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const UnionInitEnum = union(enum) {
Boolean: bool,
@@ -840,6 +851,7 @@ test "@unionInit can modify a union type" {
test "@unionInit can modify a pointer value" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const UnionInitEnum = union(enum) {
Boolean: bool,
@@ -887,7 +899,6 @@ test "anonymous union literal syntax" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const S = struct {
const Number = union {
int: i32,
@@ -914,6 +925,7 @@ test "function call result coerces from tagged union to the tag" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
const Arch = union(enum) {
@@ -948,6 +960,7 @@ test "function call result coerces from tagged union to the tag" {
test "switching on non exhaustive union" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
const E = enum(u8) {
@@ -1004,6 +1017,7 @@ test "containers with single-field enums" {
test "@unionInit on union with u8 tag but no fields" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
const Type = enum(u8) { no_op = 105 };
@@ -1108,6 +1122,8 @@ test "union with a large struct field" {
}
test "comptime equality of extern unions with same tag" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const S = struct {
const U = extern union {
a: i32,
@@ -1126,6 +1142,7 @@ test "union tag is set when initiated as a temporary value at runtime" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const U = union(enum) {
a,
@@ -1165,6 +1182,7 @@ test "return an extern union from C calling convention" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const namespace = struct {
const S = extern struct {
@@ -1195,7 +1213,6 @@ test "return an extern union from C calling convention" {
test "noreturn field in union" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
-
const U = union(enum) {
a: u32,
b: noreturn,
@@ -1246,7 +1263,7 @@ test "@unionInit uses tag value instead of field index" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
-
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const E = enum(u8) {
b = 255,
a = 3,
@@ -1303,6 +1320,7 @@ test "packed union in packed struct" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = packed struct {
nested: packed union {
@@ -1374,6 +1392,7 @@ test "no dependency loop when function pointer in union returns the union" {
test "union reassignment can use previous value" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const U = union {
a: u32,
@@ -1386,6 +1405,7 @@ test "union reassignment can use previous value" {
test "reinterpreting enum value inside packed union" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const U = packed union {
tag: enum(u8) { a, b },
@@ -1864,6 +1884,7 @@ test "extern union initialized via reintepreted struct field initializer" {
test "packed union initialized via reintepreted struct field initializer" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };
@@ -1909,6 +1930,7 @@ test "store of comptime reinterpreted memory to extern union" {
test "store of comptime reinterpreted memory to packed union" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };
@@ -2256,6 +2278,8 @@ test "assign global tagged union" {
}
test "set mutable union by switching on same union" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const U = union(enum) {
foo,
bar: usize,
diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig
index a01fc0a218dac64e24d7c43637d9dfcae43fe8f3..deedc94eab33a748e1d76a1ca08ea0d2241f0071 100644
--- a/test/behavior/vector.zig
+++ b/test/behavior/vector.zig
@@ -8,6 +8,7 @@ const expectEqual = std.testing.expectEqual;
test "implicit cast vector to array - bool" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
fn doTheTest() !void {
@@ -30,6 +31,7 @@ test "implicit cast vector to array - bool" {
}
test "implicit cast array to vector - bool" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
const S = struct {
@@ -311,6 +313,7 @@ test "peer type resolution with coercible element types" {
}
test "tuple to vector" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -376,8 +379,6 @@ test "vector @splat" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const S = struct {
fn testForT(comptime N: comptime_int, v: anytype) !void {
const T = @TypeOf(v);
@@ -413,6 +414,7 @@ test "vector @splat" {
}
test "load vector elements via comptime index" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -433,6 +435,7 @@ test "load vector elements via comptime index" {
}
test "store vector elements via comptime index" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -528,8 +531,6 @@ test "vector division operators" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const S = struct {
fn doTheTestDiv(comptime T: type, x: @Vector(4, T), y: @Vector(4, T)) !void {
const is_signed_int = switch (@typeInfo(T)) {
@@ -1223,6 +1224,7 @@ test "@subWithOverflow" {
}
test "@mulWithOverflow" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -1243,6 +1245,7 @@ test "@mulWithOverflow" {
}
test "@shlWithOverflow" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -1371,6 +1374,7 @@ test "zero multiplicand" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const zeros = @Vector(2, u32){ 0.0, 0.0 };
var ones = @Vector(2, u32){ 1.0, 1.0 };
@@ -1413,6 +1417,7 @@ test "modRem with zero divisor" {
}
test "array operands to shuffle are coerced to vectors" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -1438,6 +1443,7 @@ test "load packed vector element" {
}
test "store packed vector element" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -1500,6 +1506,7 @@ test "store vector with memset" {
}
test "addition of vectors represented as strings" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
@@ -1510,6 +1517,7 @@ test "addition of vectors represented as strings" {
}
test "compare vectors with different element types" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -1528,12 +1536,12 @@ test "vector pointer is indexable" {
const V = @Vector(2, u32);
const x: V = .{ 123, 456 };
- comptime assert(@TypeOf(&(&x)[0]) == *const u32); // validate constness
+ comptime assert(@typeInfo(@TypeOf(&(&x)[0])).pointer.attrs.@"const");
try expectEqual(@as(u32, 123), (&x)[0]);
try expectEqual(@as(u32, 456), (&x)[1]);
var y: V = .{ 123, 456 };
- comptime assert(@TypeOf(&(&y)[0]) == *u32); // validate constness
+ comptime assert(!@typeInfo(@TypeOf(&(&y)[0])).pointer.attrs.@"const");
try expectEqual(@as(u32, 123), (&y)[0]);
try expectEqual(@as(u32, 456), (&y)[1]);
@@ -1612,6 +1620,7 @@ test "bitcast vector to array of smaller vectors" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
const u8x32 = @Vector(32, u8);
const u8x64 = @Vector(64, u8);
diff --git a/test/behavior/while.zig b/test/behavior/while.zig
index 2854f8a8d492615f3c3a244b86e6f796a012b42f..d62495589b9458a441aaed0000514f60a0942528 100644
--- a/test/behavior/while.zig
+++ b/test/behavior/while.zig
@@ -38,8 +38,6 @@ fn staticWhileLoop2() i32 {
}
test "while with continue expression" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
var sum: i32 = 0;
{
var i: i32 = 0;
@@ -158,7 +156,6 @@ test "while with optional as condition with else" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
numbers_left = 10;
var sum: i32 = 0;
@@ -176,7 +173,6 @@ test "while with optional as condition with else" {
test "while with error union condition" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
numbers_left = 10;
var sum: i32 = 0;
@@ -401,6 +397,8 @@ test "breaking from a loop in an if statement" {
}
test "labeled break from else" {
+ if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
const S = struct {
fn doTheTest(x: u32) !void {
const arr: []const u32 = &.{ 1, 3, 10 };
diff --git a/test/behavior/widening.zig b/test/behavior/widening.zig
index 48d0a7407ca126454a9bf12ff7e00fae7bc0a93e..c6571319d4fbb3a2265dd48fd31e67a9061e2055 100644
--- a/test/behavior/widening.zig
+++ b/test/behavior/widening.zig
@@ -6,7 +6,6 @@ const builtin = @import("builtin");
test "integer widening" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
var a: u8 = 250;
diff --git a/test/behavior/wrapping_arithmetic.zig b/test/behavior/wrapping_arithmetic.zig
index 247023c17a4d3531f5c45b66b9cc8742fe681b4a..2ea35241efbd2e236bc2d2ff2f3f02c7b58cbc64 100644
--- a/test/behavior/wrapping_arithmetic.zig
+++ b/test/behavior/wrapping_arithmetic.zig
@@ -5,7 +5,6 @@ const maxInt = std.math.maxInt;
const expect = std.testing.expect;
test "wrapping add" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
const S = struct {
@@ -43,7 +42,6 @@ test "wrapping add" {
}
test "wrapping subtraction" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
const S = struct {
@@ -79,7 +77,6 @@ test "wrapping subtraction" {
}
test "wrapping multiplication" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
const S = struct {
diff --git a/test/behavior/x86_64/unary.zig b/test/behavior/x86_64/unary.zig
index a8446caae6e0ed7b125e6997eab8601a4253d2e6..2b2a9e288b30c1c0a1d0ab1de61b23522582b6e8 100644
--- a/test/behavior/x86_64/unary.zig
+++ b/test/behavior/x86_64/unary.zig
@@ -5262,6 +5262,7 @@ inline fn splat(comptime Type: type, rhs: Type) Type {
}
test splat {
const test_splat = unary(splat, .{});
+ try test_splat.testBoolVectors();
try test_splat.testIntVectors();
try test_splat.testFloatVectors();
}
diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c
index 5e9d192c6ffc83fd4352281742730a6a58712995..302503ad4d839449c9aad546e712f3ebb6bdff3d 100644
--- a/test/c_abi/cfuncs.c
+++ b/test/c_abi/cfuncs.c
@@ -13,7 +13,15 @@ static void assert_or_panic(bool ok) {
}
}
-#if defined __powerpc__ && !defined _ARCH_PPC64
+#if defined(__mips64__)
+# define ZIG_MIPS64
+#elif defined(__mips__)
+# define ZIG_MIPS32
+#endif
+
+#if defined(_ARCH_PPC64)
+# define ZIG_PPC64
+#elif defined(__powerpc__)
# define ZIG_PPC32
#endif
@@ -69,7 +77,7 @@ static void assert_or_panic(bool ok) {
# define ZIG_NO_COMPLEX
#endif
-#ifdef __powerpc__
+#ifdef ZIG_PPC32
# define ZIG_NO_COMPLEX
#endif
@@ -153,6 +161,10 @@ static void assert_or_panic(bool ok) {
#define ZIG_NO_F128
#endif
+#ifdef _MSC_VER
+#define ZIG_NO_F128
+#endif
+
#ifndef ZIG_NO_I128
struct i128 {
__int128 value;
@@ -198,414 +210,93 @@ void zig_ptr(void *);
void zig_bool(bool);
+#ifndef ZIG_NO_COMPLEX
// Note: These two functions match the signature of __mulsc3 and __muldc3 in compiler-rt (and libgcc)
float complex zig_cmultf_comp(float a_r, float a_i, float b_r, float b_i);
double complex zig_cmultd_comp(double a_r, double a_i, double b_r, double b_i);
float complex zig_cmultf(float complex a, float complex b);
double complex zig_cmultd(double complex a, double complex b);
-
-struct Struct_u8 {
- uint8_t a;
-};
-
-struct Struct_u8 zig_ret_struct_u8(void);
-
-void zig_struct_u8(struct Struct_u8, size_t);
-
-struct Struct_u8 c_ret_struct_u8(void) {
- return (struct Struct_u8){ .a = 4 };
-}
-
-void c_struct_u8(struct Struct_u8 s, size_t i) {
- assert_or_panic(s.a == 5);
- assert_or_panic(i == 6);
-}
-
-struct Struct_u16 {
- uint16_t a;
-};
-
-struct Struct_u16 zig_ret_struct_u16(void);
-
-void zig_struct_u16(struct Struct_u16, size_t);
-
-struct Struct_u16 c_ret_struct_u16(void) {
- return (struct Struct_u16){ .a = 10 };
-}
-
-void c_struct_u16(struct Struct_u16 s, size_t i) {
- assert_or_panic(s.a == 11);
- assert_or_panic(i == 12);
-}
-
-struct Struct_u32 {
- uint32_t a;
-};
-
-struct Struct_u32 zig_ret_struct_u32(void);
-
-void zig_struct_u32(struct Struct_u32, size_t);
-
-struct Struct_u32 c_ret_struct_u32(void) {
- return (struct Struct_u32){ .a = 16 };
-}
-
-void c_struct_u32(struct Struct_u32 s, size_t i) {
- assert_or_panic(s.a == 17);
- assert_or_panic(i == 18);
-}
-
-struct Struct_u64 {
- uint64_t a;
-};
-
-struct Struct_u64 zig_ret_struct_u64(void);
-
-void zig_struct_u64(struct Struct_u64, size_t);
-
-struct Struct_u64 c_ret_struct_u64(void) {
- return (struct Struct_u64){ .a = 22 };
-}
-
-void c_struct_u64(struct Struct_u64 s, size_t i) {
- assert_or_panic(s.a == 23);
- assert_or_panic(i == 24);
-}
-
-struct Struct_u64_u64 {
- uint64_t a;
- uint64_t b;
-};
-
-struct Struct_u64_u64 zig_ret_struct_u64_u64(void);
-
-void zig_struct_u64_u64_0(struct Struct_u64_u64, size_t);
-void zig_struct_u64_u64_1(size_t, struct Struct_u64_u64, size_t);
-void zig_struct_u64_u64_2(size_t, size_t, struct Struct_u64_u64, size_t);
-void zig_struct_u64_u64_3(size_t, size_t, size_t, struct Struct_u64_u64, size_t);
-void zig_struct_u64_u64_4(size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t);
-void zig_struct_u64_u64_5(size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t);
-void zig_struct_u64_u64_6(size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t);
-void zig_struct_u64_u64_7(size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t);
-void zig_struct_u64_u64_8(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t);
-
-struct Struct_u64_u64 c_ret_struct_u64_u64(void) {
- return (struct Struct_u64_u64){ .a = 21, .b = 22 };
-}
-
-void c_struct_u64_u64_0(struct Struct_u64_u64 s, size_t i) {
- assert_or_panic(s.a == 23);
- assert_or_panic(s.b == 24);
- assert_or_panic(i == 1);
-}
-void c_struct_u64_u64_1(size_t a0, struct Struct_u64_u64 s, size_t i) {
- assert_or_panic(s.a == 25);
- assert_or_panic(s.b == 26);
- assert_or_panic(i == 2);
-}
-void c_struct_u64_u64_2(size_t, size_t, struct Struct_u64_u64 s, size_t i) {
- assert_or_panic(s.a == 27);
- assert_or_panic(s.b == 28);
- assert_or_panic(i == 3);
-}
-void c_struct_u64_u64_3(size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) {
- assert_or_panic(s.a == 29);
- assert_or_panic(s.b == 30);
- assert_or_panic(i == 4);
-}
-void c_struct_u64_u64_4(size_t, size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) {
- assert_or_panic(s.a == 31);
- assert_or_panic(s.b == 32);
- assert_or_panic(i == 5);
-}
-void c_struct_u64_u64_5(size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) {
- assert_or_panic(s.a == 33);
- assert_or_panic(s.b == 34);
- assert_or_panic(i == 6);
-}
-void c_struct_u64_u64_6(size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) {
- assert_or_panic(s.a == 35);
- assert_or_panic(s.b == 36);
- assert_or_panic(i == 7);
-}
-void c_struct_u64_u64_7(size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) {
- assert_or_panic(s.a == 37);
- assert_or_panic(s.b == 38);
- assert_or_panic(i == 8);
-}
-void c_struct_u64_u64_8(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) {
- assert_or_panic(s.a == 39);
- assert_or_panic(s.b == 40);
- assert_or_panic(i == 9);
-}
-
-struct Struct_f32 {
- float a;
-};
-
-struct Struct_f32 zig_ret_struct_f32(void);
-
-void zig_struct_f32(struct Struct_f32);
-
-struct Struct_f32 c_ret_struct_f32(void) {
- return (struct Struct_f32){ .a = 2.5f };
-}
-
-void c_struct_f32(struct Struct_f32 s) {
- assert_or_panic(s.a == 2.5f);
-}
-
-struct Struct_f64 {
- double a;
-};
-
-struct Struct_f64 zig_ret_struct_f64(void);
-
-void zig_struct_f64(struct Struct_f64);
-
-struct Struct_f64 c_ret_struct_f64(void) {
- return (struct Struct_f64){ .a = 2.5 };
-}
-
-void c_struct_f64(struct Struct_f64 s) {
- assert_or_panic(s.a == 2.5);
-}
-
-struct Struct_f32a8 {
- alignas(8) float a;
-};
-
-struct Struct_f32a8 zig_ret_struct_f32a8(void);
-
-void zig_struct_f32a8(struct Struct_f32a8, float);
-
-struct Struct_f32a8 c_ret_struct_f32a8(void) {
- return (struct Struct_f32a8){ .a = 4.125f };
-}
-
-void c_struct_f32a8(struct Struct_f32a8 s, float f) {
- assert_or_panic(s.a == 5.375f);
- assert_or_panic(f == 6.5f);
-}
-
-struct Struct_f32a8_f32a8 {
- alignas(8) float a;
- alignas(8) float b;
-};
-
-struct Struct_f32a8_f32a8 zig_ret_struct_f32a8_f32a8(void);
-
-void zig_struct_f32a8_f32a8(struct Struct_f32a8_f32a8, float);
-
-struct Struct_f32a8_f32a8 c_ret_struct_f32a8_f32a8(void) {
- return (struct Struct_f32a8_f32a8){ .a = 6.625f, .b = 7.875f };
-}
-
-void c_struct_f32a8_f32a8(struct Struct_f32a8_f32a8 s, float f) {
- assert_or_panic(s.a == 8.0625f);
- assert_or_panic(s.b == 9.1875f);
- assert_or_panic(f == 10.5f);
-}
-
-struct Struct_f32f32_f32 {
- struct {
- float b, c;
- } a;
- float d;
-};
-
-struct Struct_f32f32_f32 zig_ret_struct_f32f32_f32(void);
-
-void zig_struct_f32f32_f32(struct Struct_f32f32_f32);
-
-struct Struct_f32f32_f32 c_ret_struct_f32f32_f32(void) {
- return (struct Struct_f32f32_f32){ .a = { .b = 1.0f, .c = 2.0f }, .d = 3.0f };
-}
-
-void c_struct_f32f32_f32(struct Struct_f32f32_f32 s) {
- assert_or_panic(s.a.b == 1.0f);
- assert_or_panic(s.a.c == 2.0f);
- assert_or_panic(s.d == 3.0f);
-}
-
-struct Struct_f32_f32f32 {
- float a;
- struct {
- float c, d;
- } b;
-};
-
-struct Struct_f32_f32f32 zig_ret_struct_f32_f32f32(void);
-
-void zig_struct_f32_f32f32(struct Struct_f32_f32f32);
-
-struct Struct_f32_f32f32 c_ret_struct_f32_f32f32(void) {
- return (struct Struct_f32_f32f32){ .a = 1.0f, .b = { .c = 2.0f, .d = 3.0f } };
-}
-
-void c_struct_f32_f32f32(struct Struct_f32_f32f32 s) {
- assert_or_panic(s.a == 1.0f);
- assert_or_panic(s.b.c == 2.0f);
- assert_or_panic(s.b.d == 3.0f);
-}
-
-struct Struct_u32_Union_u32_u32u32 {
- uint32_t a;
- union {
- struct {
- uint32_t d, e;
- } c;
- } b;
-};
-
-struct Struct_u32_Union_u32_u32u32 zig_ret_struct_u32_union_u32_u32u32(void);
-
-void zig_struct_u32_union_u32_u32u32(struct Struct_u32_Union_u32_u32u32);
-
-struct Struct_u32_Union_u32_u32u32 c_ret_struct_u32_union_u32_u32u32(void) {
- struct Struct_u32_Union_u32_u32u32 s;
- s.a = 1;
- s.b.c.d = 2;
- s.b.c.e = 3;
- return s;
-}
-
-void c_struct_u32_union_u32_u32u32(struct Struct_u32_Union_u32_u32u32 s) {
- assert_or_panic(s.a == 1);
- assert_or_panic(s.b.c.d == 2);
- assert_or_panic(s.b.c.e == 3);
-}
-
-struct Struct_i32_i32 {
- int32_t a;
- int32_t b;
-};
-
-void zig_struct_i32_i32(struct Struct_i32_i32);
-
-struct BigStruct {
- uint64_t a;
- uint64_t b;
- uint64_t c;
- uint64_t d;
- uint8_t e;
-};
-
-void zig_big_struct(struct BigStruct);
-
-union BigUnion {
- struct BigStruct a;
-};
-
-void zig_big_union(union BigUnion);
-
-struct SmallStructInts {
- uint8_t a;
- uint8_t b;
- uint8_t c;
- uint8_t d;
-};
-
-void zig_small_struct_ints(struct SmallStructInts);
-struct SmallStructInts zig_ret_small_struct_ints();
-
-struct MedStructInts {
- int32_t x;
- int32_t y;
- int32_t z;
-};
-
-void zig_med_struct_ints(struct MedStructInts);
-struct MedStructInts zig_ret_med_struct_ints();
-
-struct MedStructMixed {
- uint32_t a;
- float b;
- float c;
- uint32_t d;
-};
-
-void zig_med_struct_mixed(struct MedStructMixed);
-struct MedStructMixed zig_ret_med_struct_mixed();
-
-void zig_small_packed_struct(uint8_t);
-#ifndef ZIG_NO_I128
-void zig_big_packed_struct(__int128);
#endif
-struct SplitStructInts {
- uint64_t a;
- uint8_t b;
- uint32_t c;
-};
-void zig_split_struct_ints(struct SplitStructInts);
-
-struct SplitStructMixed {
- uint64_t a;
- uint8_t b;
- float c;
-};
-void zig_split_struct_mixed(struct SplitStructMixed);
-struct SplitStructMixed zig_ret_split_struct_mixed();
-
-struct BigStruct zig_big_struct_both(struct BigStruct);
-
-typedef float Vector2Float __attribute__((ext_vector_type(2)));
-typedef float Vector4Float __attribute__((ext_vector_type(4)));
-
-void c_vector_2_float(Vector2Float vec) {
- assert_or_panic(vec[0] == 1.0);
- assert_or_panic(vec[1] == 2.0);
-}
-
-void c_vector_4_float(Vector4Float vec) {
- assert_or_panic(vec[0] == 1.0);
- assert_or_panic(vec[1] == 2.0);
- assert_or_panic(vec[2] == 3.0);
- assert_or_panic(vec[3] == 4.0);
-}
-
-Vector2Float c_ret_vector_2_float(void) {
- return (Vector2Float){
- 1.0,
- 2.0,
- };
-}
-Vector4Float c_ret_vector_4_float(void) {
- return (Vector4Float){
- 1.0,
- 2.0,
- 3.0,
- 4.0,
- };
-}
-
#if defined(ZIG_BACKEND_STAGE2_X86_64) || defined(ZIG_PPC32) || defined(__wasm__)
-typedef bool Vector2Bool __attribute__((ext_vector_type(2)));
-typedef bool Vector4Bool __attribute__((ext_vector_type(4)));
-typedef bool Vector8Bool __attribute__((ext_vector_type(8)));
-typedef bool Vector16Bool __attribute__((ext_vector_type(16)));
-typedef bool Vector32Bool __attribute__((ext_vector_type(32)));
-typedef bool Vector64Bool __attribute__((ext_vector_type(64)));
-typedef bool Vector128Bool __attribute__((ext_vector_type(128)));
-typedef bool Vector256Bool __attribute__((ext_vector_type(256)));
-typedef bool Vector512Bool __attribute__((ext_vector_type(512)));
+typedef bool Vector_2_bool __attribute__((ext_vector_type(2)));
-void c_vector_2_bool(Vector2Bool vec) {
+Vector_2_bool zig_ret_vector_2_bool(void);
+void zig_vector_2_bool(Vector_2_bool vec);
+
+Vector_2_bool c_ret_vector_2_bool(void) {
+ return (Vector_2_bool){
+ true,
+ false,
+ };
+}
+void c_vector_2_bool(Vector_2_bool vec) {
assert_or_panic(vec[0] == true);
assert_or_panic(vec[1] == true);
}
+void c_test_vector_2_bool(void) {
+ Vector_2_bool vec = zig_ret_vector_2_bool();
+ assert_or_panic(vec[0] == false);
+ assert_or_panic(vec[1] == false);
+ zig_vector_2_bool((Vector_2_bool){
+ false,
+ true,
+ });
+}
-void c_vector_4_bool(Vector4Bool vec) {
+typedef bool Vector_4_bool __attribute__((ext_vector_type(4)));
+
+Vector_4_bool zig_ret_vector_4_bool(void);
+void zig_vector_4_bool(Vector_4_bool vec);
+
+Vector_4_bool c_ret_vector_4_bool(void) {
+ return (Vector_4_bool){
+ true,
+ false,
+ true,
+ false,
+ };
+}
+void c_vector_4_bool(Vector_4_bool vec) {
assert_or_panic(vec[0] == true);
assert_or_panic(vec[1] == true);
assert_or_panic(vec[2] == false);
assert_or_panic(vec[3] == true);
}
+void c_test_vector_4_bool(void) {
+ Vector_4_bool vec = zig_ret_vector_4_bool();
+ assert_or_panic(vec[0] == false);
+ assert_or_panic(vec[1] == true);
+ assert_or_panic(vec[2] == true);
+ assert_or_panic(vec[3] == true);
+ zig_vector_4_bool((Vector_4_bool){
+ false,
+ false,
+ false,
+ false,
+ });
+}
-void c_vector_8_bool(Vector8Bool vec) {
+typedef bool Vector_8_bool __attribute__((ext_vector_type(8)));
+
+Vector_8_bool zig_ret_vector_8_bool(void);
+void zig_vector_8_bool(Vector_8_bool vec);
+
+Vector_8_bool c_ret_vector_8_bool(void) {
+ return (Vector_8_bool){
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ };
+}
+void c_vector_8_bool(Vector_8_bool vec) {
assert_or_panic(vec[0] == true);
assert_or_panic(vec[1] == false);
assert_or_panic(vec[2] == true);
@@ -615,8 +306,54 @@ void c_vector_8_bool(Vector8Bool vec) {
assert_or_panic(vec[6] == false);
assert_or_panic(vec[7] == true);
}
+void c_test_vector_8_bool(void) {
+ Vector_8_bool vec = zig_ret_vector_8_bool();
+ assert_or_panic(vec[0] == false);
+ assert_or_panic(vec[1] == false);
+ assert_or_panic(vec[2] == false);
+ assert_or_panic(vec[3] == false);
+ assert_or_panic(vec[4] == true);
+ assert_or_panic(vec[5] == false);
+ assert_or_panic(vec[6] == false);
+ assert_or_panic(vec[7] == false);
+ zig_vector_8_bool((Vector_8_bool){
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ });
+}
-void c_vector_16_bool(Vector16Bool vec) {
+typedef bool Vector_16_bool __attribute__((ext_vector_type(16)));
+
+Vector_16_bool zig_ret_vector_16_bool(void);
+void zig_vector_16_bool(Vector_16_bool vec);
+
+Vector_16_bool c_ret_vector_16_bool(void) {
+ return (Vector_16_bool){
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ };
+}
+void c_vector_16_bool(Vector_16_bool vec) {
assert_or_panic(vec[0] == true);
assert_or_panic(vec[1] == false);
assert_or_panic(vec[2] == false);
@@ -634,8 +371,86 @@ void c_vector_16_bool(Vector16Bool vec) {
assert_or_panic(vec[14] == false);
assert_or_panic(vec[15] == false);
}
+void c_test_vector_16_bool(void) {
+ Vector_16_bool vec = zig_ret_vector_16_bool();
+ assert_or_panic(vec[0] == false);
+ assert_or_panic(vec[1] == true);
+ assert_or_panic(vec[2] == false);
+ assert_or_panic(vec[3] == false);
+ assert_or_panic(vec[4] == false);
+ assert_or_panic(vec[5] == true);
+ assert_or_panic(vec[6] == false);
+ assert_or_panic(vec[7] == false);
+ assert_or_panic(vec[8] == true);
+ assert_or_panic(vec[9] == false);
+ assert_or_panic(vec[10] == false);
+ assert_or_panic(vec[11] == false);
+ assert_or_panic(vec[12] == false);
+ assert_or_panic(vec[13] == true);
+ assert_or_panic(vec[14] == false);
+ assert_or_panic(vec[15] == false);
+ zig_vector_16_bool((Vector_16_bool){
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ });
+}
-void c_vector_32_bool(Vector32Bool vec) {
+typedef bool Vector_32_bool __attribute__((ext_vector_type(32)));
+
+Vector_32_bool zig_ret_vector_32_bool(void);
+void zig_vector_32_bool(Vector_32_bool vec);
+
+Vector_32_bool c_ret_vector_32_bool(void) {
+ return (Vector_32_bool){
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ };
+}
+void c_vector_32_bool(Vector_32_bool vec) {
assert_or_panic(vec[0] == true);
assert_or_panic(vec[1] == false);
assert_or_panic(vec[2] == true);
@@ -669,8 +484,150 @@ void c_vector_32_bool(Vector32Bool vec) {
assert_or_panic(vec[30] == true);
assert_or_panic(vec[31] == false);
}
+void c_test_vector_32_bool(void) {
+ Vector_32_bool vec = zig_ret_vector_32_bool();
+ assert_or_panic(vec[0] == false);
+ assert_or_panic(vec[1] == true);
+ assert_or_panic(vec[2] == false);
+ assert_or_panic(vec[3] == false);
+ assert_or_panic(vec[4] == true);
+ assert_or_panic(vec[5] == false);
+ assert_or_panic(vec[6] == true);
+ assert_or_panic(vec[7] == true);
+ assert_or_panic(vec[8] == true);
+ assert_or_panic(vec[9] == true);
+ assert_or_panic(vec[10] == true);
+ assert_or_panic(vec[11] == true);
+ assert_or_panic(vec[12] == false);
+ assert_or_panic(vec[13] == false);
+ assert_or_panic(vec[14] == false);
+ assert_or_panic(vec[15] == false);
+ assert_or_panic(vec[16] == false);
+ assert_or_panic(vec[17] == false);
+ assert_or_panic(vec[18] == true);
+ assert_or_panic(vec[19] == true);
+ assert_or_panic(vec[20] == true);
+ assert_or_panic(vec[21] == false);
+ assert_or_panic(vec[22] == true);
+ assert_or_panic(vec[23] == false);
+ assert_or_panic(vec[24] == true);
+ assert_or_panic(vec[25] == false);
+ assert_or_panic(vec[26] == false);
+ assert_or_panic(vec[27] == true);
+ assert_or_panic(vec[28] == false);
+ assert_or_panic(vec[29] == false);
+ assert_or_panic(vec[30] == true);
+ assert_or_panic(vec[31] == true);
+ zig_vector_32_bool((Vector_32_bool){
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ });
+}
-void c_vector_64_bool(Vector64Bool vec) {
+typedef bool Vector_64_bool __attribute__((ext_vector_type(64)));
+
+Vector_64_bool zig_ret_vector_64_bool(void);
+void zig_vector_64_bool(Vector_64_bool vec);
+
+Vector_64_bool c_ret_vector_64_bool(void) {
+ return (Vector_64_bool){
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ };
+}
+void c_vector_64_bool(Vector_64_bool vec) {
assert_or_panic(vec[0] == true);
assert_or_panic(vec[1] == true);
assert_or_panic(vec[2] == true);
@@ -736,8 +693,278 @@ void c_vector_64_bool(Vector64Bool vec) {
assert_or_panic(vec[62] == true);
assert_or_panic(vec[63] == false);
}
+void c_test_vector_64_bool(void) {
+ Vector_64_bool vec = zig_ret_vector_64_bool();
+ assert_or_panic(vec[0] == true);
+ assert_or_panic(vec[1] == false);
+ assert_or_panic(vec[2] == true);
+ assert_or_panic(vec[3] == false);
+ assert_or_panic(vec[4] == false);
+ assert_or_panic(vec[5] == true);
+ assert_or_panic(vec[6] == false);
+ assert_or_panic(vec[7] == true);
+ assert_or_panic(vec[8] == true);
+ assert_or_panic(vec[9] == false);
+ assert_or_panic(vec[10] == true);
+ assert_or_panic(vec[11] == false);
+ assert_or_panic(vec[12] == true);
+ assert_or_panic(vec[13] == false);
+ assert_or_panic(vec[14] == false);
+ assert_or_panic(vec[15] == true);
+ assert_or_panic(vec[16] == false);
+ assert_or_panic(vec[17] == false);
+ assert_or_panic(vec[18] == true);
+ assert_or_panic(vec[19] == true);
+ assert_or_panic(vec[20] == false);
+ assert_or_panic(vec[21] == false);
+ assert_or_panic(vec[22] == true);
+ assert_or_panic(vec[23] == false);
+ assert_or_panic(vec[24] == false);
+ assert_or_panic(vec[25] == true);
+ assert_or_panic(vec[26] == true);
+ assert_or_panic(vec[27] == true);
+ assert_or_panic(vec[28] == true);
+ assert_or_panic(vec[29] == true);
+ assert_or_panic(vec[30] == false);
+ assert_or_panic(vec[31] == false);
+ assert_or_panic(vec[32] == true);
+ assert_or_panic(vec[33] == true);
+ assert_or_panic(vec[34] == true);
+ assert_or_panic(vec[35] == true);
+ assert_or_panic(vec[36] == false);
+ assert_or_panic(vec[37] == true);
+ assert_or_panic(vec[38] == false);
+ assert_or_panic(vec[39] == true);
+ assert_or_panic(vec[40] == true);
+ assert_or_panic(vec[41] == true);
+ assert_or_panic(vec[42] == true);
+ assert_or_panic(vec[43] == true);
+ assert_or_panic(vec[44] == false);
+ assert_or_panic(vec[45] == false);
+ assert_or_panic(vec[46] == false);
+ assert_or_panic(vec[47] == true);
+ assert_or_panic(vec[48] == true);
+ assert_or_panic(vec[49] == true);
+ assert_or_panic(vec[50] == false);
+ assert_or_panic(vec[51] == true);
+ assert_or_panic(vec[52] == true);
+ assert_or_panic(vec[53] == true);
+ assert_or_panic(vec[54] == false);
+ assert_or_panic(vec[55] == false);
+ assert_or_panic(vec[56] == false);
+ assert_or_panic(vec[57] == true);
+ assert_or_panic(vec[58] == false);
+ assert_or_panic(vec[59] == false);
+ assert_or_panic(vec[60] == true);
+ assert_or_panic(vec[61] == false);
+ assert_or_panic(vec[62] == true);
+ assert_or_panic(vec[63] == false);
+ zig_vector_64_bool((Vector_64_bool){
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ });
+}
-void c_vector_128_bool(Vector128Bool vec) {
+typedef bool Vector_128_bool __attribute__((ext_vector_type(128)));
+
+Vector_128_bool zig_ret_vector_128_bool(void);
+void zig_vector_128_bool(Vector_128_bool vec);
+
+Vector_128_bool c_ret_vector_128_bool(void) {
+ return (Vector_128_bool){
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ };
+}
+void c_vector_128_bool(Vector_128_bool vec) {
assert_or_panic(vec[0] == false);
assert_or_panic(vec[1] == false);
assert_or_panic(vec[2] == false);
@@ -867,11 +1094,536 @@ void c_vector_128_bool(Vector128Bool vec) {
assert_or_panic(vec[126] == true);
assert_or_panic(vec[127] == true);
}
+void c_test_vector_128_bool(void) {
+ Vector_128_bool vec = zig_ret_vector_128_bool();
+ assert_or_panic(vec[0] == true);
+ assert_or_panic(vec[1] == true);
+ assert_or_panic(vec[2] == false);
+ assert_or_panic(vec[3] == false);
+ assert_or_panic(vec[4] == false);
+ assert_or_panic(vec[5] == true);
+ assert_or_panic(vec[6] == true);
+ assert_or_panic(vec[7] == false);
+ assert_or_panic(vec[8] == false);
+ assert_or_panic(vec[9] == true);
+ assert_or_panic(vec[10] == false);
+ assert_or_panic(vec[11] == false);
+ assert_or_panic(vec[12] == false);
+ assert_or_panic(vec[13] == true);
+ assert_or_panic(vec[14] == false);
+ assert_or_panic(vec[15] == true);
+ assert_or_panic(vec[16] == true);
+ assert_or_panic(vec[17] == false);
+ assert_or_panic(vec[18] == false);
+ assert_or_panic(vec[19] == true);
+ assert_or_panic(vec[20] == true);
+ assert_or_panic(vec[21] == true);
+ assert_or_panic(vec[22] == true);
+ assert_or_panic(vec[23] == true);
+ assert_or_panic(vec[24] == false);
+ assert_or_panic(vec[25] == false);
+ assert_or_panic(vec[26] == true);
+ assert_or_panic(vec[27] == true);
+ assert_or_panic(vec[28] == true);
+ assert_or_panic(vec[29] == false);
+ assert_or_panic(vec[30] == false);
+ assert_or_panic(vec[31] == true);
+ assert_or_panic(vec[32] == true);
+ assert_or_panic(vec[33] == false);
+ assert_or_panic(vec[34] == true);
+ assert_or_panic(vec[35] == true);
+ assert_or_panic(vec[36] == true);
+ assert_or_panic(vec[37] == false);
+ assert_or_panic(vec[38] == true);
+ assert_or_panic(vec[39] == true);
+ assert_or_panic(vec[40] == true);
+ assert_or_panic(vec[41] == false);
+ assert_or_panic(vec[42] == true);
+ assert_or_panic(vec[43] == true);
+ assert_or_panic(vec[44] == false);
+ assert_or_panic(vec[45] == false);
+ assert_or_panic(vec[46] == false);
+ assert_or_panic(vec[47] == true);
+ assert_or_panic(vec[48] == false);
+ assert_or_panic(vec[49] == false);
+ assert_or_panic(vec[50] == false);
+ assert_or_panic(vec[51] == false);
+ assert_or_panic(vec[52] == true);
+ assert_or_panic(vec[53] == false);
+ assert_or_panic(vec[54] == true);
+ assert_or_panic(vec[55] == false);
+ assert_or_panic(vec[56] == true);
+ assert_or_panic(vec[57] == false);
+ assert_or_panic(vec[58] == false);
+ assert_or_panic(vec[59] == true);
+ assert_or_panic(vec[60] == true);
+ assert_or_panic(vec[61] == true);
+ assert_or_panic(vec[62] == true);
+ assert_or_panic(vec[63] == true);
+ assert_or_panic(vec[64] == false);
+ assert_or_panic(vec[65] == false);
+ assert_or_panic(vec[66] == false);
+ assert_or_panic(vec[67] == true);
+ assert_or_panic(vec[68] == true);
+ assert_or_panic(vec[69] == false);
+ assert_or_panic(vec[70] == true);
+ assert_or_panic(vec[71] == true);
+ assert_or_panic(vec[72] == false);
+ assert_or_panic(vec[73] == true);
+ assert_or_panic(vec[74] == true);
+ assert_or_panic(vec[75] == false);
+ assert_or_panic(vec[76] == false);
+ assert_or_panic(vec[77] == true);
+ assert_or_panic(vec[78] == false);
+ assert_or_panic(vec[79] == true);
+ assert_or_panic(vec[80] == false);
+ assert_or_panic(vec[81] == false);
+ assert_or_panic(vec[82] == true);
+ assert_or_panic(vec[83] == true);
+ assert_or_panic(vec[84] == false);
+ assert_or_panic(vec[85] == true);
+ assert_or_panic(vec[86] == false);
+ assert_or_panic(vec[87] == false);
+ assert_or_panic(vec[88] == true);
+ assert_or_panic(vec[89] == true);
+ assert_or_panic(vec[90] == true);
+ assert_or_panic(vec[91] == true);
+ assert_or_panic(vec[92] == true);
+ assert_or_panic(vec[93] == false);
+ assert_or_panic(vec[94] == false);
+ assert_or_panic(vec[95] == true);
+ assert_or_panic(vec[96] == false);
+ assert_or_panic(vec[97] == false);
+ assert_or_panic(vec[98] == true);
+ assert_or_panic(vec[99] == true);
+ assert_or_panic(vec[100] == true);
+ assert_or_panic(vec[101] == true);
+ assert_or_panic(vec[102] == true);
+ assert_or_panic(vec[103] == true);
+ assert_or_panic(vec[104] == true);
+ assert_or_panic(vec[105] == false);
+ assert_or_panic(vec[106] == false);
+ assert_or_panic(vec[107] == true);
+ assert_or_panic(vec[108] == false);
+ assert_or_panic(vec[109] == false);
+ assert_or_panic(vec[110] == true);
+ assert_or_panic(vec[111] == false);
+ assert_or_panic(vec[112] == false);
+ assert_or_panic(vec[113] == true);
+ assert_or_panic(vec[114] == false);
+ assert_or_panic(vec[115] == false);
+ assert_or_panic(vec[116] == false);
+ assert_or_panic(vec[117] == false);
+ assert_or_panic(vec[118] == false);
+ assert_or_panic(vec[119] == false);
+ assert_or_panic(vec[120] == true);
+ assert_or_panic(vec[121] == true);
+ assert_or_panic(vec[122] == true);
+ assert_or_panic(vec[123] == false);
+ assert_or_panic(vec[124] == true);
+ assert_or_panic(vec[125] == false);
+ assert_or_panic(vec[126] == false);
+ assert_or_panic(vec[127] == true);
+ zig_vector_128_bool((Vector_128_bool){
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ });
+}
+typedef bool Vector_256_bool __attribute__((ext_vector_type(256)));
+
+Vector_256_bool zig_ret_vector_256_bool(void);
+void zig_vector_256_bool(Vector_256_bool vec);
+
+Vector_256_bool c_ret_vector_256_bool(void) {
+ return (Vector_256_bool){
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ };
+}
// WASM: The following vector functions define too many Wasm locals for wasmtime in debug mode and are therefore disabled for the wasm target.
-#if !defined(__wasm__)
-
-void c_vector_256_bool(Vector256Bool vec) {
+#ifndef __wasm__
+void c_vector_256_bool(Vector_256_bool vec) {
assert_or_panic(vec[0] == false);
assert_or_panic(vec[1] == true);
assert_or_panic(vec[2] == true);
@@ -1129,8 +1881,1049 @@ void c_vector_256_bool(Vector256Bool vec) {
assert_or_panic(vec[254] == true);
assert_or_panic(vec[255] == false);
}
+#endif
+void c_test_vector_256_bool(void) {
+ Vector_256_bool vec = zig_ret_vector_256_bool();
+ assert_or_panic(vec[0] == true);
+ assert_or_panic(vec[1] == true);
+ assert_or_panic(vec[2] == true);
+ assert_or_panic(vec[3] == false);
+ assert_or_panic(vec[4] == true);
+ assert_or_panic(vec[5] == false);
+ assert_or_panic(vec[6] == false);
+ assert_or_panic(vec[7] == true);
+ assert_or_panic(vec[8] == false);
+ assert_or_panic(vec[9] == false);
+ assert_or_panic(vec[10] == false);
+ assert_or_panic(vec[11] == false);
+ assert_or_panic(vec[12] == false);
+ assert_or_panic(vec[13] == false);
+ assert_or_panic(vec[14] == false);
+ assert_or_panic(vec[15] == false);
+ assert_or_panic(vec[16] == true);
+ assert_or_panic(vec[17] == false);
+ assert_or_panic(vec[18] == true);
+ assert_or_panic(vec[19] == false);
+ assert_or_panic(vec[20] == false);
+ assert_or_panic(vec[21] == true);
+ assert_or_panic(vec[22] == true);
+ assert_or_panic(vec[23] == false);
+ assert_or_panic(vec[24] == false);
+ assert_or_panic(vec[25] == true);
+ assert_or_panic(vec[26] == true);
+ assert_or_panic(vec[27] == false);
+ assert_or_panic(vec[28] == true);
+ assert_or_panic(vec[29] == true);
+ assert_or_panic(vec[30] == true);
+ assert_or_panic(vec[31] == false);
+ assert_or_panic(vec[32] == true);
+ assert_or_panic(vec[33] == false);
+ assert_or_panic(vec[34] == true);
+ assert_or_panic(vec[35] == false);
+ assert_or_panic(vec[36] == true);
+ assert_or_panic(vec[37] == false);
+ assert_or_panic(vec[38] == true);
+ assert_or_panic(vec[39] == false);
+ assert_or_panic(vec[40] == false);
+ assert_or_panic(vec[41] == false);
+ assert_or_panic(vec[42] == true);
+ assert_or_panic(vec[43] == true);
+ assert_or_panic(vec[44] == true);
+ assert_or_panic(vec[45] == false);
+ assert_or_panic(vec[46] == false);
+ assert_or_panic(vec[47] == false);
+ assert_or_panic(vec[48] == true);
+ assert_or_panic(vec[49] == false);
+ assert_or_panic(vec[50] == true);
+ assert_or_panic(vec[51] == false);
+ assert_or_panic(vec[52] == true);
+ assert_or_panic(vec[53] == false);
+ assert_or_panic(vec[54] == true);
+ assert_or_panic(vec[55] == true);
+ assert_or_panic(vec[56] == false);
+ assert_or_panic(vec[57] == false);
+ assert_or_panic(vec[58] == false);
+ assert_or_panic(vec[59] == true);
+ assert_or_panic(vec[60] == true);
+ assert_or_panic(vec[61] == true);
+ assert_or_panic(vec[62] == false);
+ assert_or_panic(vec[63] == true);
+ assert_or_panic(vec[64] == false);
+ assert_or_panic(vec[65] == true);
+ assert_or_panic(vec[66] == false);
+ assert_or_panic(vec[67] == true);
+ assert_or_panic(vec[68] == true);
+ assert_or_panic(vec[69] == false);
+ assert_or_panic(vec[70] == true);
+ assert_or_panic(vec[71] == false);
+ assert_or_panic(vec[72] == true);
+ assert_or_panic(vec[73] == true);
+ assert_or_panic(vec[74] == false);
+ assert_or_panic(vec[75] == false);
+ assert_or_panic(vec[76] == false);
+ assert_or_panic(vec[77] == false);
+ assert_or_panic(vec[78] == false);
+ assert_or_panic(vec[79] == false);
+ assert_or_panic(vec[80] == false);
+ assert_or_panic(vec[81] == false);
+ assert_or_panic(vec[82] == false);
+ assert_or_panic(vec[83] == true);
+ assert_or_panic(vec[84] == false);
+ assert_or_panic(vec[85] == false);
+ assert_or_panic(vec[86] == false);
+ assert_or_panic(vec[87] == true);
+ assert_or_panic(vec[88] == false);
+ assert_or_panic(vec[89] == true);
+ assert_or_panic(vec[90] == true);
+ assert_or_panic(vec[91] == false);
+ assert_or_panic(vec[92] == false);
+ assert_or_panic(vec[93] == true);
+ assert_or_panic(vec[94] == true);
+ assert_or_panic(vec[95] == false);
+ assert_or_panic(vec[96] == false);
+ assert_or_panic(vec[97] == true);
+ assert_or_panic(vec[98] == false);
+ assert_or_panic(vec[99] == false);
+ assert_or_panic(vec[100] == false);
+ assert_or_panic(vec[101] == false);
+ assert_or_panic(vec[102] == false);
+ assert_or_panic(vec[103] == false);
+ assert_or_panic(vec[104] == false);
+ assert_or_panic(vec[105] == true);
+ assert_or_panic(vec[106] == true);
+ assert_or_panic(vec[107] == false);
+ assert_or_panic(vec[108] == true);
+ assert_or_panic(vec[109] == false);
+ assert_or_panic(vec[110] == true);
+ assert_or_panic(vec[111] == true);
+ assert_or_panic(vec[112] == false);
+ assert_or_panic(vec[113] == false);
+ assert_or_panic(vec[114] == false);
+ assert_or_panic(vec[115] == false);
+ assert_or_panic(vec[116] == false);
+ assert_or_panic(vec[117] == false);
+ assert_or_panic(vec[118] == false);
+ assert_or_panic(vec[119] == true);
+ assert_or_panic(vec[120] == true);
+ assert_or_panic(vec[121] == true);
+ assert_or_panic(vec[122] == false);
+ assert_or_panic(vec[123] == true);
+ assert_or_panic(vec[124] == true);
+ assert_or_panic(vec[125] == false);
+ assert_or_panic(vec[126] == false);
+ assert_or_panic(vec[127] == true);
+ assert_or_panic(vec[128] == true);
+ assert_or_panic(vec[129] == true);
+ assert_or_panic(vec[130] == true);
+ assert_or_panic(vec[131] == true);
+ assert_or_panic(vec[132] == false);
+ assert_or_panic(vec[133] == true);
+ assert_or_panic(vec[134] == true);
+ assert_or_panic(vec[135] == false);
+ assert_or_panic(vec[136] == false);
+ assert_or_panic(vec[137] == true);
+ assert_or_panic(vec[138] == true);
+ assert_or_panic(vec[139] == false);
+ assert_or_panic(vec[140] == true);
+ assert_or_panic(vec[141] == false);
+ assert_or_panic(vec[142] == true);
+ assert_or_panic(vec[143] == false);
+ assert_or_panic(vec[144] == true);
+ assert_or_panic(vec[145] == true);
+ assert_or_panic(vec[146] == true);
+ assert_or_panic(vec[147] == true);
+ assert_or_panic(vec[148] == false);
+ assert_or_panic(vec[149] == false);
+ assert_or_panic(vec[150] == false);
+ assert_or_panic(vec[151] == true);
+ assert_or_panic(vec[152] == false);
+ assert_or_panic(vec[153] == true);
+ assert_or_panic(vec[154] == false);
+ assert_or_panic(vec[155] == true);
+ assert_or_panic(vec[156] == true);
+ assert_or_panic(vec[157] == false);
+ assert_or_panic(vec[158] == true);
+ assert_or_panic(vec[159] == true);
+ assert_or_panic(vec[160] == true);
+ assert_or_panic(vec[161] == true);
+ assert_or_panic(vec[162] == true);
+ assert_or_panic(vec[163] == false);
+ assert_or_panic(vec[164] == false);
+ assert_or_panic(vec[165] == true);
+ assert_or_panic(vec[166] == false);
+ assert_or_panic(vec[167] == true);
+ assert_or_panic(vec[168] == true);
+ assert_or_panic(vec[169] == true);
+ assert_or_panic(vec[170] == true);
+ assert_or_panic(vec[171] == false);
+ assert_or_panic(vec[172] == true);
+ assert_or_panic(vec[173] == true);
+ assert_or_panic(vec[174] == true);
+ assert_or_panic(vec[175] == true);
+ assert_or_panic(vec[176] == true);
+ assert_or_panic(vec[177] == true);
+ assert_or_panic(vec[178] == true);
+ assert_or_panic(vec[179] == false);
+ assert_or_panic(vec[180] == true);
+ assert_or_panic(vec[181] == false);
+ assert_or_panic(vec[182] == false);
+ assert_or_panic(vec[183] == false);
+ assert_or_panic(vec[184] == true);
+ assert_or_panic(vec[185] == false);
+ assert_or_panic(vec[186] == true);
+ assert_or_panic(vec[187] == true);
+ assert_or_panic(vec[188] == false);
+ assert_or_panic(vec[189] == true);
+ assert_or_panic(vec[190] == false);
+ assert_or_panic(vec[191] == true);
+ assert_or_panic(vec[192] == false);
+ assert_or_panic(vec[193] == true);
+ assert_or_panic(vec[194] == false);
+ assert_or_panic(vec[195] == false);
+ assert_or_panic(vec[196] == true);
+ assert_or_panic(vec[197] == true);
+ assert_or_panic(vec[198] == true);
+ assert_or_panic(vec[199] == true);
+ assert_or_panic(vec[200] == true);
+ assert_or_panic(vec[201] == true);
+ assert_or_panic(vec[202] == true);
+ assert_or_panic(vec[203] == false);
+ assert_or_panic(vec[204] == true);
+ assert_or_panic(vec[205] == false);
+ assert_or_panic(vec[206] == false);
+ assert_or_panic(vec[207] == true);
+ assert_or_panic(vec[208] == true);
+ assert_or_panic(vec[209] == false);
+ assert_or_panic(vec[210] == false);
+ assert_or_panic(vec[211] == false);
+ assert_or_panic(vec[212] == true);
+ assert_or_panic(vec[213] == true);
+ assert_or_panic(vec[214] == true);
+ assert_or_panic(vec[215] == false);
+ assert_or_panic(vec[216] == false);
+ assert_or_panic(vec[217] == true);
+ assert_or_panic(vec[218] == true);
+ assert_or_panic(vec[219] == true);
+ assert_or_panic(vec[220] == true);
+ assert_or_panic(vec[221] == false);
+ assert_or_panic(vec[222] == true);
+ assert_or_panic(vec[223] == false);
+ assert_or_panic(vec[224] == true);
+ assert_or_panic(vec[225] == true);
+ assert_or_panic(vec[226] == true);
+ assert_or_panic(vec[227] == false);
+ assert_or_panic(vec[228] == false);
+ assert_or_panic(vec[229] == false);
+ assert_or_panic(vec[230] == false);
+ assert_or_panic(vec[231] == false);
+ assert_or_panic(vec[232] == true);
+ assert_or_panic(vec[233] == true);
+ assert_or_panic(vec[234] == false);
+ assert_or_panic(vec[235] == false);
+ assert_or_panic(vec[236] == false);
+ assert_or_panic(vec[237] == true);
+ assert_or_panic(vec[238] == true);
+ assert_or_panic(vec[239] == false);
+ assert_or_panic(vec[240] == true);
+ assert_or_panic(vec[241] == true);
+ assert_or_panic(vec[242] == true);
+ assert_or_panic(vec[243] == false);
+ assert_or_panic(vec[244] == true);
+ assert_or_panic(vec[245] == true);
+ assert_or_panic(vec[246] == false);
+ assert_or_panic(vec[247] == true);
+ assert_or_panic(vec[248] == false);
+ assert_or_panic(vec[249] == false);
+ assert_or_panic(vec[250] == true);
+ assert_or_panic(vec[251] == true);
+ assert_or_panic(vec[252] == false);
+ assert_or_panic(vec[253] == true);
+ assert_or_panic(vec[254] == false);
+ assert_or_panic(vec[255] == true);
+ zig_vector_256_bool((Vector_256_bool){
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ });
+}
-void c_vector_512_bool(Vector512Bool vec) {
+typedef bool Vector_512_bool __attribute__((ext_vector_type(512)));
+
+Vector_512_bool zig_ret_vector_512_bool(void);
+void zig_vector_512_bool(Vector_512_bool vec);
+
+Vector_512_bool c_ret_vector_512_bool(void) {
+ return (Vector_512_bool){
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ };
+}
+// WASM: The following vector functions define too many Wasm locals for wasmtime in debug mode and are therefore disabled for the wasm target.
+#ifndef __wasm__
+void c_vector_512_bool(Vector_512_bool vec) {
assert_or_panic(vec[0] == true);
assert_or_panic(vec[1] == true);
assert_or_panic(vec[2] == true);
@@ -1644,43 +3437,531 @@ void c_vector_512_bool(Vector512Bool vec) {
assert_or_panic(vec[510] == false);
assert_or_panic(vec[511] == true);
}
-
#endif
-
-Vector2Bool c_ret_vector_2_bool(void) {
- return (Vector2Bool){
- true,
+void c_test_vector_512_bool(void) {
+ Vector_512_bool vec = zig_ret_vector_512_bool();
+ assert_or_panic(vec[0] == true);
+ assert_or_panic(vec[1] == true);
+ assert_or_panic(vec[2] == true);
+ assert_or_panic(vec[3] == true);
+ assert_or_panic(vec[4] == false);
+ assert_or_panic(vec[5] == true);
+ assert_or_panic(vec[6] == false);
+ assert_or_panic(vec[7] == true);
+ assert_or_panic(vec[8] == true);
+ assert_or_panic(vec[9] == true);
+ assert_or_panic(vec[10] == false);
+ assert_or_panic(vec[11] == true);
+ assert_or_panic(vec[12] == false);
+ assert_or_panic(vec[13] == false);
+ assert_or_panic(vec[14] == false);
+ assert_or_panic(vec[15] == true);
+ assert_or_panic(vec[16] == true);
+ assert_or_panic(vec[17] == false);
+ assert_or_panic(vec[18] == false);
+ assert_or_panic(vec[19] == false);
+ assert_or_panic(vec[20] == true);
+ assert_or_panic(vec[21] == true);
+ assert_or_panic(vec[22] == false);
+ assert_or_panic(vec[23] == false);
+ assert_or_panic(vec[24] == false);
+ assert_or_panic(vec[25] == false);
+ assert_or_panic(vec[26] == true);
+ assert_or_panic(vec[27] == false);
+ assert_or_panic(vec[28] == false);
+ assert_or_panic(vec[29] == false);
+ assert_or_panic(vec[30] == true);
+ assert_or_panic(vec[31] == true);
+ assert_or_panic(vec[32] == true);
+ assert_or_panic(vec[33] == true);
+ assert_or_panic(vec[34] == false);
+ assert_or_panic(vec[35] == false);
+ assert_or_panic(vec[36] == false);
+ assert_or_panic(vec[37] == true);
+ assert_or_panic(vec[38] == true);
+ assert_or_panic(vec[39] == true);
+ assert_or_panic(vec[40] == false);
+ assert_or_panic(vec[41] == false);
+ assert_or_panic(vec[42] == true);
+ assert_or_panic(vec[43] == false);
+ assert_or_panic(vec[44] == false);
+ assert_or_panic(vec[45] == true);
+ assert_or_panic(vec[46] == false);
+ assert_or_panic(vec[47] == false);
+ assert_or_panic(vec[48] == true);
+ assert_or_panic(vec[49] == true);
+ assert_or_panic(vec[50] == true);
+ assert_or_panic(vec[51] == true);
+ assert_or_panic(vec[52] == false);
+ assert_or_panic(vec[53] == false);
+ assert_or_panic(vec[54] == false);
+ assert_or_panic(vec[55] == true);
+ assert_or_panic(vec[56] == false);
+ assert_or_panic(vec[57] == true);
+ assert_or_panic(vec[58] == false);
+ assert_or_panic(vec[59] == true);
+ assert_or_panic(vec[60] == true);
+ assert_or_panic(vec[61] == false);
+ assert_or_panic(vec[62] == false);
+ assert_or_panic(vec[63] == true);
+ assert_or_panic(vec[64] == true);
+ assert_or_panic(vec[65] == false);
+ assert_or_panic(vec[66] == true);
+ assert_or_panic(vec[67] == false);
+ assert_or_panic(vec[68] == false);
+ assert_or_panic(vec[69] == false);
+ assert_or_panic(vec[70] == true);
+ assert_or_panic(vec[71] == true);
+ assert_or_panic(vec[72] == true);
+ assert_or_panic(vec[73] == true);
+ assert_or_panic(vec[74] == true);
+ assert_or_panic(vec[75] == false);
+ assert_or_panic(vec[76] == true);
+ assert_or_panic(vec[77] == false);
+ assert_or_panic(vec[78] == true);
+ assert_or_panic(vec[79] == true);
+ assert_or_panic(vec[80] == true);
+ assert_or_panic(vec[81] == true);
+ assert_or_panic(vec[82] == true);
+ assert_or_panic(vec[83] == false);
+ assert_or_panic(vec[84] == true);
+ assert_or_panic(vec[85] == true);
+ assert_or_panic(vec[86] == false);
+ assert_or_panic(vec[87] == true);
+ assert_or_panic(vec[88] == false);
+ assert_or_panic(vec[89] == false);
+ assert_or_panic(vec[90] == true);
+ assert_or_panic(vec[91] == false);
+ assert_or_panic(vec[92] == true);
+ assert_or_panic(vec[93] == false);
+ assert_or_panic(vec[94] == false);
+ assert_or_panic(vec[95] == false);
+ assert_or_panic(vec[96] == true);
+ assert_or_panic(vec[97] == true);
+ assert_or_panic(vec[98] == false);
+ assert_or_panic(vec[99] == true);
+ assert_or_panic(vec[100] == true);
+ assert_or_panic(vec[101] == false);
+ assert_or_panic(vec[102] == true);
+ assert_or_panic(vec[103] == false);
+ assert_or_panic(vec[104] == true);
+ assert_or_panic(vec[105] == false);
+ assert_or_panic(vec[106] == true);
+ assert_or_panic(vec[107] == false);
+ assert_or_panic(vec[108] == false);
+ assert_or_panic(vec[109] == true);
+ assert_or_panic(vec[110] == false);
+ assert_or_panic(vec[111] == false);
+ assert_or_panic(vec[112] == true);
+ assert_or_panic(vec[113] == false);
+ assert_or_panic(vec[114] == true);
+ assert_or_panic(vec[115] == false);
+ assert_or_panic(vec[116] == true);
+ assert_or_panic(vec[117] == false);
+ assert_or_panic(vec[118] == false);
+ assert_or_panic(vec[119] == true);
+ assert_or_panic(vec[120] == true);
+ assert_or_panic(vec[121] == true);
+ assert_or_panic(vec[122] == false);
+ assert_or_panic(vec[123] == true);
+ assert_or_panic(vec[124] == false);
+ assert_or_panic(vec[125] == false);
+ assert_or_panic(vec[126] == true);
+ assert_or_panic(vec[127] == true);
+ assert_or_panic(vec[128] == false);
+ assert_or_panic(vec[129] == true);
+ assert_or_panic(vec[130] == true);
+ assert_or_panic(vec[131] == false);
+ assert_or_panic(vec[132] == true);
+ assert_or_panic(vec[133] == true);
+ assert_or_panic(vec[134] == false);
+ assert_or_panic(vec[135] == true);
+ assert_or_panic(vec[136] == true);
+ assert_or_panic(vec[137] == false);
+ assert_or_panic(vec[138] == false);
+ assert_or_panic(vec[139] == false);
+ assert_or_panic(vec[140] == true);
+ assert_or_panic(vec[141] == false);
+ assert_or_panic(vec[142] == true);
+ assert_or_panic(vec[143] == false);
+ assert_or_panic(vec[144] == false);
+ assert_or_panic(vec[145] == false);
+ assert_or_panic(vec[146] == true);
+ assert_or_panic(vec[147] == false);
+ assert_or_panic(vec[148] == true);
+ assert_or_panic(vec[149] == false);
+ assert_or_panic(vec[150] == false);
+ assert_or_panic(vec[151] == true);
+ assert_or_panic(vec[152] == false);
+ assert_or_panic(vec[153] == true);
+ assert_or_panic(vec[154] == true);
+ assert_or_panic(vec[155] == false);
+ assert_or_panic(vec[156] == true);
+ assert_or_panic(vec[157] == true);
+ assert_or_panic(vec[158] == false);
+ assert_or_panic(vec[159] == true);
+ assert_or_panic(vec[160] == true);
+ assert_or_panic(vec[161] == false);
+ assert_or_panic(vec[162] == false);
+ assert_or_panic(vec[163] == false);
+ assert_or_panic(vec[164] == true);
+ assert_or_panic(vec[165] == false);
+ assert_or_panic(vec[166] == true);
+ assert_or_panic(vec[167] == true);
+ assert_or_panic(vec[168] == true);
+ assert_or_panic(vec[169] == true);
+ assert_or_panic(vec[170] == false);
+ assert_or_panic(vec[171] == true);
+ assert_or_panic(vec[172] == false);
+ assert_or_panic(vec[173] == false);
+ assert_or_panic(vec[174] == true);
+ assert_or_panic(vec[175] == true);
+ assert_or_panic(vec[176] == true);
+ assert_or_panic(vec[177] == false);
+ assert_or_panic(vec[178] == false);
+ assert_or_panic(vec[179] == false);
+ assert_or_panic(vec[180] == true);
+ assert_or_panic(vec[181] == false);
+ assert_or_panic(vec[182] == false);
+ assert_or_panic(vec[183] == true);
+ assert_or_panic(vec[184] == true);
+ assert_or_panic(vec[185] == false);
+ assert_or_panic(vec[186] == true);
+ assert_or_panic(vec[187] == false);
+ assert_or_panic(vec[188] == true);
+ assert_or_panic(vec[189] == true);
+ assert_or_panic(vec[190] == true);
+ assert_or_panic(vec[191] == true);
+ assert_or_panic(vec[192] == true);
+ assert_or_panic(vec[193] == true);
+ assert_or_panic(vec[194] == true);
+ assert_or_panic(vec[195] == false);
+ assert_or_panic(vec[196] == false);
+ assert_or_panic(vec[197] == false);
+ assert_or_panic(vec[198] == false);
+ assert_or_panic(vec[199] == false);
+ assert_or_panic(vec[200] == true);
+ assert_or_panic(vec[201] == false);
+ assert_or_panic(vec[202] == true);
+ assert_or_panic(vec[203] == false);
+ assert_or_panic(vec[204] == true);
+ assert_or_panic(vec[205] == true);
+ assert_or_panic(vec[206] == false);
+ assert_or_panic(vec[207] == false);
+ assert_or_panic(vec[208] == false);
+ assert_or_panic(vec[209] == true);
+ assert_or_panic(vec[210] == true);
+ assert_or_panic(vec[211] == true);
+ assert_or_panic(vec[212] == false);
+ assert_or_panic(vec[213] == false);
+ assert_or_panic(vec[214] == true);
+ assert_or_panic(vec[215] == true);
+ assert_or_panic(vec[216] == true);
+ assert_or_panic(vec[217] == false);
+ assert_or_panic(vec[218] == false);
+ assert_or_panic(vec[219] == true);
+ assert_or_panic(vec[220] == false);
+ assert_or_panic(vec[221] == true);
+ assert_or_panic(vec[222] == true);
+ assert_or_panic(vec[223] == false);
+ assert_or_panic(vec[224] == true);
+ assert_or_panic(vec[225] == false);
+ assert_or_panic(vec[226] == false);
+ assert_or_panic(vec[227] == true);
+ assert_or_panic(vec[228] == false);
+ assert_or_panic(vec[229] == false);
+ assert_or_panic(vec[230] == true);
+ assert_or_panic(vec[231] == true);
+ assert_or_panic(vec[232] == false);
+ assert_or_panic(vec[233] == true);
+ assert_or_panic(vec[234] == true);
+ assert_or_panic(vec[235] == true);
+ assert_or_panic(vec[236] == true);
+ assert_or_panic(vec[237] == true);
+ assert_or_panic(vec[238] == false);
+ assert_or_panic(vec[239] == true);
+ assert_or_panic(vec[240] == false);
+ assert_or_panic(vec[241] == false);
+ assert_or_panic(vec[242] == true);
+ assert_or_panic(vec[243] == false);
+ assert_or_panic(vec[244] == true);
+ assert_or_panic(vec[245] == false);
+ assert_or_panic(vec[246] == true);
+ assert_or_panic(vec[247] == false);
+ assert_or_panic(vec[248] == true);
+ assert_or_panic(vec[249] == true);
+ assert_or_panic(vec[250] == true);
+ assert_or_panic(vec[251] == true);
+ assert_or_panic(vec[252] == true);
+ assert_or_panic(vec[253] == false);
+ assert_or_panic(vec[254] == false);
+ assert_or_panic(vec[255] == false);
+ assert_or_panic(vec[256] == false);
+ assert_or_panic(vec[257] == false);
+ assert_or_panic(vec[258] == false);
+ assert_or_panic(vec[259] == true);
+ assert_or_panic(vec[260] == true);
+ assert_or_panic(vec[261] == true);
+ assert_or_panic(vec[262] == true);
+ assert_or_panic(vec[263] == false);
+ assert_or_panic(vec[264] == false);
+ assert_or_panic(vec[265] == false);
+ assert_or_panic(vec[266] == true);
+ assert_or_panic(vec[267] == false);
+ assert_or_panic(vec[268] == true);
+ assert_or_panic(vec[269] == false);
+ assert_or_panic(vec[270] == true);
+ assert_or_panic(vec[271] == true);
+ assert_or_panic(vec[272] == true);
+ assert_or_panic(vec[273] == true);
+ assert_or_panic(vec[274] == true);
+ assert_or_panic(vec[275] == true);
+ assert_or_panic(vec[276] == false);
+ assert_or_panic(vec[277] == false);
+ assert_or_panic(vec[278] == true);
+ assert_or_panic(vec[279] == true);
+ assert_or_panic(vec[280] == false);
+ assert_or_panic(vec[281] == false);
+ assert_or_panic(vec[282] == false);
+ assert_or_panic(vec[283] == false);
+ assert_or_panic(vec[284] == true);
+ assert_or_panic(vec[285] == true);
+ assert_or_panic(vec[286] == true);
+ assert_or_panic(vec[287] == false);
+ assert_or_panic(vec[288] == false);
+ assert_or_panic(vec[289] == false);
+ assert_or_panic(vec[290] == true);
+ assert_or_panic(vec[291] == false);
+ assert_or_panic(vec[292] == true);
+ assert_or_panic(vec[293] == true);
+ assert_or_panic(vec[294] == false);
+ assert_or_panic(vec[295] == true);
+ assert_or_panic(vec[296] == true);
+ assert_or_panic(vec[297] == true);
+ assert_or_panic(vec[298] == false);
+ assert_or_panic(vec[299] == true);
+ assert_or_panic(vec[300] == true);
+ assert_or_panic(vec[301] == false);
+ assert_or_panic(vec[302] == false);
+ assert_or_panic(vec[303] == true);
+ assert_or_panic(vec[304] == false);
+ assert_or_panic(vec[305] == false);
+ assert_or_panic(vec[306] == true);
+ assert_or_panic(vec[307] == true);
+ assert_or_panic(vec[308] == true);
+ assert_or_panic(vec[309] == true);
+ assert_or_panic(vec[310] == false);
+ assert_or_panic(vec[311] == false);
+ assert_or_panic(vec[312] == false);
+ assert_or_panic(vec[313] == false);
+ assert_or_panic(vec[314] == false);
+ assert_or_panic(vec[315] == true);
+ assert_or_panic(vec[316] == false);
+ assert_or_panic(vec[317] == false);
+ assert_or_panic(vec[318] == true);
+ assert_or_panic(vec[319] == false);
+ assert_or_panic(vec[320] == false);
+ assert_or_panic(vec[321] == true);
+ assert_or_panic(vec[322] == true);
+ assert_or_panic(vec[323] == true);
+ assert_or_panic(vec[324] == true);
+ assert_or_panic(vec[325] == false);
+ assert_or_panic(vec[326] == false);
+ assert_or_panic(vec[327] == false);
+ assert_or_panic(vec[328] == true);
+ assert_or_panic(vec[329] == true);
+ assert_or_panic(vec[330] == false);
+ assert_or_panic(vec[331] == true);
+ assert_or_panic(vec[332] == true);
+ assert_or_panic(vec[333] == false);
+ assert_or_panic(vec[334] == false);
+ assert_or_panic(vec[335] == true);
+ assert_or_panic(vec[336] == true);
+ assert_or_panic(vec[337] == false);
+ assert_or_panic(vec[338] == true);
+ assert_or_panic(vec[339] == true);
+ assert_or_panic(vec[340] == true);
+ assert_or_panic(vec[341] == false);
+ assert_or_panic(vec[342] == false);
+ assert_or_panic(vec[343] == false);
+ assert_or_panic(vec[344] == true);
+ assert_or_panic(vec[345] == true);
+ assert_or_panic(vec[346] == false);
+ assert_or_panic(vec[347] == true);
+ assert_or_panic(vec[348] == false);
+ assert_or_panic(vec[349] == true);
+ assert_or_panic(vec[350] == false);
+ assert_or_panic(vec[351] == false);
+ assert_or_panic(vec[352] == true);
+ assert_or_panic(vec[353] == false);
+ assert_or_panic(vec[354] == true);
+ assert_or_panic(vec[355] == false);
+ assert_or_panic(vec[356] == false);
+ assert_or_panic(vec[357] == false);
+ assert_or_panic(vec[358] == false);
+ assert_or_panic(vec[359] == false);
+ assert_or_panic(vec[360] == true);
+ assert_or_panic(vec[361] == true);
+ assert_or_panic(vec[362] == false);
+ assert_or_panic(vec[363] == false);
+ assert_or_panic(vec[364] == false);
+ assert_or_panic(vec[365] == false);
+ assert_or_panic(vec[366] == true);
+ assert_or_panic(vec[367] == false);
+ assert_or_panic(vec[368] == true);
+ assert_or_panic(vec[369] == false);
+ assert_or_panic(vec[370] == true);
+ assert_or_panic(vec[371] == true);
+ assert_or_panic(vec[372] == false);
+ assert_or_panic(vec[373] == true);
+ assert_or_panic(vec[374] == true);
+ assert_or_panic(vec[375] == true);
+ assert_or_panic(vec[376] == true);
+ assert_or_panic(vec[377] == true);
+ assert_or_panic(vec[378] == false);
+ assert_or_panic(vec[379] == true);
+ assert_or_panic(vec[380] == false);
+ assert_or_panic(vec[381] == true);
+ assert_or_panic(vec[382] == true);
+ assert_or_panic(vec[383] == true);
+ assert_or_panic(vec[384] == true);
+ assert_or_panic(vec[385] == true);
+ assert_or_panic(vec[386] == false);
+ assert_or_panic(vec[387] == true);
+ assert_or_panic(vec[388] == true);
+ assert_or_panic(vec[389] == false);
+ assert_or_panic(vec[390] == true);
+ assert_or_panic(vec[391] == false);
+ assert_or_panic(vec[392] == true);
+ assert_or_panic(vec[393] == false);
+ assert_or_panic(vec[394] == true);
+ assert_or_panic(vec[395] == false);
+ assert_or_panic(vec[396] == true);
+ assert_or_panic(vec[397] == false);
+ assert_or_panic(vec[398] == false);
+ assert_or_panic(vec[399] == true);
+ assert_or_panic(vec[400] == true);
+ assert_or_panic(vec[401] == true);
+ assert_or_panic(vec[402] == true);
+ assert_or_panic(vec[403] == false);
+ assert_or_panic(vec[404] == false);
+ assert_or_panic(vec[405] == true);
+ assert_or_panic(vec[406] == false);
+ assert_or_panic(vec[407] == false);
+ assert_or_panic(vec[408] == false);
+ assert_or_panic(vec[409] == true);
+ assert_or_panic(vec[410] == false);
+ assert_or_panic(vec[411] == true);
+ assert_or_panic(vec[412] == true);
+ assert_or_panic(vec[413] == false);
+ assert_or_panic(vec[414] == true);
+ assert_or_panic(vec[415] == true);
+ assert_or_panic(vec[416] == false);
+ assert_or_panic(vec[417] == true);
+ assert_or_panic(vec[418] == true);
+ assert_or_panic(vec[419] == false);
+ assert_or_panic(vec[420] == false);
+ assert_or_panic(vec[421] == true);
+ assert_or_panic(vec[422] == false);
+ assert_or_panic(vec[423] == false);
+ assert_or_panic(vec[424] == true);
+ assert_or_panic(vec[425] == false);
+ assert_or_panic(vec[426] == true);
+ assert_or_panic(vec[427] == false);
+ assert_or_panic(vec[428] == false);
+ assert_or_panic(vec[429] == true);
+ assert_or_panic(vec[430] == false);
+ assert_or_panic(vec[431] == true);
+ assert_or_panic(vec[432] == true);
+ assert_or_panic(vec[433] == false);
+ assert_or_panic(vec[434] == true);
+ assert_or_panic(vec[435] == false);
+ assert_or_panic(vec[436] == true);
+ assert_or_panic(vec[437] == false);
+ assert_or_panic(vec[438] == true);
+ assert_or_panic(vec[439] == false);
+ assert_or_panic(vec[440] == false);
+ assert_or_panic(vec[441] == true);
+ assert_or_panic(vec[442] == true);
+ assert_or_panic(vec[443] == false);
+ assert_or_panic(vec[444] == true);
+ assert_or_panic(vec[445] == true);
+ assert_or_panic(vec[446] == false);
+ assert_or_panic(vec[447] == true);
+ assert_or_panic(vec[448] == true);
+ assert_or_panic(vec[449] == false);
+ assert_or_panic(vec[450] == false);
+ assert_or_panic(vec[451] == false);
+ assert_or_panic(vec[452] == false);
+ assert_or_panic(vec[453] == false);
+ assert_or_panic(vec[454] == true);
+ assert_or_panic(vec[455] == false);
+ assert_or_panic(vec[456] == false);
+ assert_or_panic(vec[457] == true);
+ assert_or_panic(vec[458] == false);
+ assert_or_panic(vec[459] == true);
+ assert_or_panic(vec[460] == false);
+ assert_or_panic(vec[461] == false);
+ assert_or_panic(vec[462] == false);
+ assert_or_panic(vec[463] == true);
+ assert_or_panic(vec[464] == false);
+ assert_or_panic(vec[465] == true);
+ assert_or_panic(vec[466] == false);
+ assert_or_panic(vec[467] == false);
+ assert_or_panic(vec[468] == false);
+ assert_or_panic(vec[469] == false);
+ assert_or_panic(vec[470] == true);
+ assert_or_panic(vec[471] == true);
+ assert_or_panic(vec[472] == false);
+ assert_or_panic(vec[473] == true);
+ assert_or_panic(vec[474] == true);
+ assert_or_panic(vec[475] == false);
+ assert_or_panic(vec[476] == false);
+ assert_or_panic(vec[477] == true);
+ assert_or_panic(vec[478] == true);
+ assert_or_panic(vec[479] == true);
+ assert_or_panic(vec[480] == false);
+ assert_or_panic(vec[481] == false);
+ assert_or_panic(vec[482] == true);
+ assert_or_panic(vec[483] == false);
+ assert_or_panic(vec[484] == false);
+ assert_or_panic(vec[485] == false);
+ assert_or_panic(vec[486] == true);
+ assert_or_panic(vec[487] == true);
+ assert_or_panic(vec[488] == false);
+ assert_or_panic(vec[489] == false);
+ assert_or_panic(vec[490] == false);
+ assert_or_panic(vec[491] == false);
+ assert_or_panic(vec[492] == false);
+ assert_or_panic(vec[493] == true);
+ assert_or_panic(vec[494] == true);
+ assert_or_panic(vec[495] == true);
+ assert_or_panic(vec[496] == true);
+ assert_or_panic(vec[497] == false);
+ assert_or_panic(vec[498] == false);
+ assert_or_panic(vec[499] == false);
+ assert_or_panic(vec[500] == true);
+ assert_or_panic(vec[501] == false);
+ assert_or_panic(vec[502] == true);
+ assert_or_panic(vec[503] == true);
+ assert_or_panic(vec[504] == true);
+ assert_or_panic(vec[505] == true);
+ assert_or_panic(vec[506] == false);
+ assert_or_panic(vec[507] == false);
+ assert_or_panic(vec[508] == true);
+ assert_or_panic(vec[509] == true);
+ assert_or_panic(vec[510] == false);
+ assert_or_panic(vec[511] == false);
+ zig_vector_512_bool((Vector_512_bool){
false,
- };
-}
-
-Vector4Bool c_ret_vector_4_bool(void) {
- return (Vector4Bool){
true,
- false,
true,
false,
- };
-}
-
-Vector8Bool c_ret_vector_8_bool(void) {
- return (Vector8Bool){
- false,
true,
false,
- false,
true,
false,
false,
- true,
- };
-}
-
-Vector16Bool c_ret_vector_16_bool(void) {
- return (Vector16Bool){
- true,
- true,
- false,
false,
false,
false,
@@ -1689,68 +3970,49 @@ Vector16Bool c_ret_vector_16_bool(void) {
true,
false,
false,
- true,
- true,
false,
true,
true,
- };
-}
-
-Vector32Bool c_ret_vector_32_bool(void) {
- return (Vector32Bool){
- true,
- false,
- true,
true,
true,
false,
- true,
false,
- true,
- true,
- true,
false,
true,
true,
false,
- false,
+ true,
true,
false,
false,
- false,
- false,
- true,
true,
true,
false,
- true,
false,
false,
- true,
false,
false,
false,
- };
-}
-
-Vector64Bool c_ret_vector_64_bool(void) {
- return (Vector64Bool){
false,
true,
+ true,
+ true,
false,
true,
true,
true,
- false,
true,
true,
+ false,
true,
true,
true,
+ false,
true,
false,
+ false,
true,
+ false,
true,
true,
false,
@@ -1758,35 +4020,36 @@ Vector64Bool c_ret_vector_64_bool(void) {
false,
true,
true,
- false,
true,
- false,
true,
false,
- true,
false,
true,
+ true,
false,
true,
+ true,
false,
false,
true,
- true,
false,
false,
false,
true,
true,
true,
- true,
false,
false,
+ true,
false,
true,
+ false,
+ false,
true,
false,
false,
true,
+ true,
false,
false,
false,
@@ -1795,76 +4058,68 @@ Vector64Bool c_ret_vector_64_bool(void) {
false,
false,
false,
+ false,
+ false,
+ false,
true,
true,
true,
true,
true,
- };
-}
-
-Vector128Bool c_ret_vector_128_bool(void) {
- return (Vector128Bool){
false,
- true,
- true,
false,
- true,
false,
false,
true,
true,
false,
true,
- false,
- false,
- false,
- true,
- false,
true,
false,
false,
true,
false,
- true,
false,
false,
false,
true,
true,
true,
+ true,
false,
false,
false,
false,
true,
- true,
- true,
- false,
- true,
- true,
false,
false,
false,
false,
true,
true,
+ false,
true,
false,
+ true,
false,
false,
+ true,
+ true,
false,
true,
+ true,
false,
false,
- true,
false,
+ true,
false,
false,
false,
false,
true,
true,
+ false,
+ false,
true,
false,
true,
@@ -1875,12 +4130,6 @@ Vector128Bool c_ret_vector_128_bool(void) {
false,
false,
false,
- false,
- false,
- true,
- true,
- true,
- true,
true,
false,
false,
@@ -1890,41 +4139,35 @@ Vector128Bool c_ret_vector_128_bool(void) {
false,
true,
false,
- true,
false,
- true,
false,
- true,
false,
true,
- true,
- true,
- true,
false,
false,
- true,
false,
false,
- true,
+ false,
+ false,
true,
true,
true,
false,
true,
true,
- true,
false,
false,
- true,
+ false,
false,
false,
true,
true,
false,
- true,
+ false,
false,
true,
- true,
+ false,
+ false,
true,
true,
true,
@@ -1933,53 +4176,39 @@ Vector128Bool c_ret_vector_128_bool(void) {
true,
false,
true,
- };
-}
-
-Vector256Bool c_ret_vector_256_bool(void) {
- return (Vector256Bool){
true,
- false,
true,
true,
false,
- false,
+ true,
false,
false,
false,
true,
false,
- true,
false,
- true,
false,
false,
- true,
- true,
- true,
false,
false,
false,
true,
false,
- true,
false,
false,
true,
true,
true,
- false,
- false,
- true,
- true,
true,
false,
true,
true,
- true,
+ false,
+ false,
false,
true,
false,
+ false,
true,
true,
false,
@@ -1989,38 +4218,33 @@ Vector256Bool c_ret_vector_256_bool(void) {
true,
false,
false,
- true,
- true,
false,
false,
true,
false,
true,
true,
- true,
false,
- true,
- true,
false,
true,
true,
+ true,
false,
true,
false,
+ false,
true,
true,
+ false,
true,
false,
true,
true,
- false,
true,
true,
true,
true,
- false,
true,
- false,
true,
true,
true,
@@ -2029,23 +4253,22 @@ Vector256Bool c_ret_vector_256_bool(void) {
false,
true,
false,
- false,
+ true,
true,
false,
+ true,
false,
+ true,
false,
true,
true,
false,
- false,
- false,
true,
true,
true,
false,
false,
false,
- true,
false,
true,
true,
@@ -2055,24 +4278,17 @@ Vector256Bool c_ret_vector_256_bool(void) {
true,
true,
true,
- false,
true,
false,
true,
false,
false,
true,
- true,
- false,
- true,
- false,
false,
false,
false,
- true,
false,
false,
- true,
false,
false,
false,
@@ -2080,22 +4296,12 @@ Vector256Bool c_ret_vector_256_bool(void) {
false,
false,
true,
- false,
true,
false,
- true,
- true,
- true,
false,
- true,
- true,
false,
- true,
- true,
false,
- true,
- true,
- true,
+ false,
true,
true,
true,
@@ -2103,18 +4309,19 @@ Vector256Bool c_ret_vector_256_bool(void) {
false,
false,
false,
+ false,
+ true,
true,
false,
false,
- true,
false,
true,
true,
- true,
false,
false,
- true,
- true,
+ false,
+ false,
+ false,
true,
true,
false,
@@ -2122,19 +4329,19 @@ Vector256Bool c_ret_vector_256_bool(void) {
true,
false,
true,
- false,
- false,
+ true,
false,
true,
true,
+ false,
true,
true,
+ false,
true,
+ false,
true,
true,
true,
- false,
- false,
true,
false,
false,
@@ -2143,20 +4350,15 @@ Vector256Bool c_ret_vector_256_bool(void) {
true,
true,
true,
- true,
- true,
- false,
- false,
false,
true,
true,
true,
false,
- true,
false,
true,
false,
- true,
+ false,
false,
true,
true,
@@ -2164,53 +4366,28 @@ Vector256Bool c_ret_vector_256_bool(void) {
false,
true,
false,
- true,
false,
- true,
false,
true,
false,
false,
true,
- false,
true,
true,
- false,
- false,
true,
false,
- false,
- false,
true,
true,
false,
false,
false,
- false,
- false,
- true,
- false,
true,
- false,
- false,
- false,
- };
-}
-
-Vector512Bool c_ret_vector_512_bool(void) {
- return (Vector512Bool){
false,
true,
- false,
- false,
- false,
true,
false,
false,
false,
- true,
- false,
- false,
false,
true,
false,
@@ -2219,46 +4396,34 @@ Vector512Bool c_ret_vector_512_bool(void) {
false,
false,
false,
- false,
- false,
- true,
true,
false,
false,
- false,
- false,
true,
true,
- false,
true,
false,
true,
true,
- true,
- false,
false,
true,
+ false,
true,
false,
false,
false,
+ true,
false,
false,
- true,
false,
true,
true,
- false,
- true,
true,
true,
true,
false,
false,
false,
- true,
- true,
- false,
false,
false,
false,
@@ -2268,44 +4433,26 @@ Vector512Bool c_ret_vector_512_bool(void) {
true,
true,
false,
- false,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
true,
true,
false,
- false,
- false,
true,
false,
true,
- true,
- true,
false,
true,
false,
false,
- true,
- true,
false,
true,
- true,
false,
- true,
false,
- true,
- true,
false,
true,
true,
false,
false,
+ true,
false,
true,
false,
@@ -2314,459 +4461,10843 @@ Vector512Bool c_ret_vector_512_bool(void) {
true,
true,
true,
- false,
true,
false,
- true,
false,
true,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
+ });
+}
+
+#endif
+
+typedef uint8_t Vector_1_u8 __attribute__((vector_size(1 * sizeof(uint8_t))));
+
+Vector_1_u8 zig_ret_vector_1_u8(void);
+void zig_vector_1_u8(Vector_1_u8, size_t);
+
+Vector_1_u8 c_ret_vector_1_u8(void) {
+ return (Vector_1_u8){ 3 };
+}
+void c_vector_1_u8(Vector_1_u8 v, size_t i) {
+ assert_or_panic(v[0] == 4);
+ assert_or_panic(i == 1);
+}
+void c_test_vector_1_u8(void) {
+ Vector_1_u8 v = zig_ret_vector_1_u8();
+ assert_or_panic(v[0] == 1);
+ zig_vector_1_u8((Vector_1_u8){ 2 }, 1);
+}
+
+typedef uint8_t Vector_2_u8 __attribute__((vector_size(2 * sizeof(uint8_t))));
+
+Vector_2_u8 zig_ret_vector_2_u8(void);
+void zig_vector_2_u8(Vector_2_u8, size_t);
+
+Vector_2_u8 c_ret_vector_2_u8(void) {
+ return (Vector_2_u8){ 9, 10 };
+}
+void c_vector_2_u8(Vector_2_u8 v, size_t i) {
+ assert_or_panic(v[0] == 11);
+ assert_or_panic(v[1] == 12);
+ assert_or_panic(i == 2);
+}
+void c_test_vector_2_u8(void) {
+ Vector_2_u8 v = zig_ret_vector_2_u8();
+ assert_or_panic(v[0] == 5);
+ assert_or_panic(v[1] == 6);
+ zig_vector_2_u8((Vector_2_u8){ 7, 8 }, 2);
+}
+
+typedef uint8_t Vector_3_u8 __attribute__((vector_size(3 * sizeof(uint8_t))));
+
+Vector_3_u8 zig_ret_vector_3_u8(void);
+void zig_vector_3_u8(Vector_3_u8, size_t);
+
+Vector_3_u8 c_ret_vector_3_u8(void) {
+ return (Vector_3_u8){ 19, 20, 21 };
+}
+void c_vector_3_u8(Vector_3_u8 v, size_t i) {
+ assert_or_panic(v[0] == 22);
+ assert_or_panic(v[1] == 23);
+ assert_or_panic(v[2] == 24);
+ assert_or_panic(i == 3);
+}
+void c_test_vector_3_u8(void) {
+ Vector_3_u8 v = zig_ret_vector_3_u8();
+ assert_or_panic(v[0] == 13);
+ assert_or_panic(v[1] == 14);
+ assert_or_panic(v[2] == 15);
+ zig_vector_3_u8((Vector_3_u8){ 16, 17, 18 }, 3);
+}
+
+typedef uint8_t Vector_4_u8 __attribute__((vector_size(4 * sizeof(uint8_t))));
+
+Vector_4_u8 zig_ret_vector_4_u8(void);
+void zig_vector_4_u8(Vector_4_u8, size_t);
+void zig_vector_4_u8_vector_4_u8(Vector_4_u8, Vector_4_u8, size_t);
+
+Vector_4_u8 c_ret_vector_4_u8(void) {
+ return (Vector_4_u8){ 41, 42, 43, 44 };
+}
+void c_vector_4_u8(Vector_4_u8 v, size_t i) {
+ assert_or_panic(v[0] == 45);
+ assert_or_panic(v[1] == 46);
+ assert_or_panic(v[2] == 47);
+ assert_or_panic(v[3] == 48);
+ assert_or_panic(i == 4);
+}
+void c_vector_4_u8_vector_4_u8(Vector_4_u8 v0, Vector_4_u8 v1, size_t i) {
+ assert_or_panic(v0[0] == 49);
+ assert_or_panic(v0[1] == 50);
+ assert_or_panic(v0[2] == 51);
+ assert_or_panic(v0[3] == 52);
+ assert_or_panic(v1[0] == 53);
+ assert_or_panic(v1[1] == 54);
+ assert_or_panic(v1[2] == 55);
+ assert_or_panic(v1[3] == 56);
+ assert_or_panic(i == 8);
+}
+void c_test_vector_4_u8(void) {
+ Vector_4_u8 v = zig_ret_vector_4_u8();
+ assert_or_panic(v[0] == 25);
+ assert_or_panic(v[1] == 26);
+ assert_or_panic(v[2] == 27);
+ assert_or_panic(v[3] == 28);
+ zig_vector_4_u8((Vector_4_u8){ 29, 30, 31, 32 }, 4);
+ zig_vector_4_u8_vector_4_u8((Vector_4_u8){ 33, 34, 35, 36 }, (Vector_4_u8){ 37, 38, 39, 40 }, 8);
+}
+
+typedef uint8_t Vector_6_u8 __attribute__((vector_size(6 * sizeof(uint8_t))));
+
+Vector_6_u8 zig_ret_vector_6_u8(void);
+void zig_vector_6_u8(Vector_6_u8, size_t);
+
+Vector_6_u8 c_ret_vector_6_u8(void) {
+ return (Vector_6_u8){ 53, 54, 55, 56, 57, 58 };
+}
+void c_vector_6_u8(Vector_6_u8 v, size_t i) {
+ assert_or_panic(v[0] == 59);
+ assert_or_panic(v[1] == 60);
+ assert_or_panic(v[2] == 61);
+ assert_or_panic(v[3] == 62);
+ assert_or_panic(v[4] == 63);
+ assert_or_panic(v[5] == 64);
+ assert_or_panic(i == 6);
+}
+void c_test_vector_6_u8(void) {
+ Vector_6_u8 v = zig_ret_vector_6_u8();
+ assert_or_panic(v[0] == 41);
+ assert_or_panic(v[1] == 42);
+ assert_or_panic(v[2] == 43);
+ assert_or_panic(v[3] == 44);
+ assert_or_panic(v[4] == 45);
+ assert_or_panic(v[5] == 46);
+ zig_vector_6_u8((Vector_6_u8){ 47, 48, 49, 50, 51, 52 }, 6);
+}
+
+typedef uint8_t Vector_8_u8 __attribute__((vector_size(8 * sizeof(uint8_t))));
+
+Vector_8_u8 zig_ret_vector_8_u8(void);
+void zig_vector_8_u8(Vector_8_u8, size_t);
+
+Vector_8_u8 c_ret_vector_8_u8(void) {
+ return (Vector_8_u8){ 81, 82, 83, 84, 85, 86, 87, 88 };
+}
+void c_vector_8_u8(Vector_8_u8 v, size_t i) {
+ assert_or_panic(v[0] == 89);
+ assert_or_panic(v[1] == 90);
+ assert_or_panic(v[2] == 91);
+ assert_or_panic(v[3] == 92);
+ assert_or_panic(v[4] == 93);
+ assert_or_panic(v[5] == 94);
+ assert_or_panic(v[6] == 95);
+ assert_or_panic(v[7] == 96);
+ assert_or_panic(i == 8);
+}
+void c_test_vector_8_u8(void) {
+ Vector_8_u8 v = zig_ret_vector_8_u8();
+ assert_or_panic(v[0] == 65);
+ assert_or_panic(v[1] == 66);
+ assert_or_panic(v[2] == 67);
+ assert_or_panic(v[3] == 68);
+ assert_or_panic(v[4] == 69);
+ assert_or_panic(v[5] == 70);
+ assert_or_panic(v[6] == 71);
+ assert_or_panic(v[7] == 72);
+ zig_vector_8_u8((Vector_8_u8){ 73, 74, 75, 76, 77, 78, 79, 80 }, 8);
+}
+
+typedef uint8_t Vector_12_u8 __attribute__((vector_size(12 * sizeof(uint8_t))));
+
+Vector_12_u8 zig_ret_vector_12_u8(void);
+void zig_vector_12_u8(Vector_12_u8, size_t);
+
+Vector_12_u8 c_ret_vector_12_u8(void) {
+ return (Vector_12_u8){ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 };
+}
+void c_vector_12_u8(Vector_12_u8 v, size_t i) {
+ assert_or_panic(v[0] == 33);
+ assert_or_panic(v[1] == 34);
+ assert_or_panic(v[2] == 35);
+ assert_or_panic(v[3] == 36);
+ assert_or_panic(v[4] == 37);
+ assert_or_panic(v[5] == 38);
+ assert_or_panic(v[6] == 39);
+ assert_or_panic(v[7] == 40);
+ assert_or_panic(v[8] == 41);
+ assert_or_panic(v[9] == 42);
+ assert_or_panic(v[10] == 43);
+ assert_or_panic(v[11] == 44);
+ assert_or_panic(i == 12);
+}
+void c_test_vector_12_u8(void) {
+ Vector_12_u8 v = zig_ret_vector_12_u8();
+ assert_or_panic(v[0] == 97);
+ assert_or_panic(v[1] == 98);
+ assert_or_panic(v[2] == 99);
+ assert_or_panic(v[3] == 0);
+ assert_or_panic(v[4] == 1);
+ assert_or_panic(v[5] == 2);
+ assert_or_panic(v[6] == 3);
+ assert_or_panic(v[7] == 4);
+ assert_or_panic(v[8] == 5);
+ assert_or_panic(v[9] == 6);
+ assert_or_panic(v[10] == 7);
+ assert_or_panic(v[11] == 8);
+ zig_vector_12_u8((Vector_12_u8){ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }, 12);
+}
+
+typedef uint8_t Vector_16_u8 __attribute__((vector_size(16 * sizeof(uint8_t))));
+
+Vector_16_u8 zig_ret_vector_16_u8(void);
+void zig_vector_16_u8(Vector_16_u8, size_t);
+
+Vector_16_u8 c_ret_vector_16_u8(void) {
+ return (Vector_16_u8){ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92 };
+}
+void c_vector_16_u8(Vector_16_u8 v, size_t i) {
+ assert_or_panic(v[0] == 93);
+ assert_or_panic(v[1] == 94);
+ assert_or_panic(v[2] == 95);
+ assert_or_panic(v[3] == 96);
+ assert_or_panic(v[4] == 97);
+ assert_or_panic(v[5] == 98);
+ assert_or_panic(v[6] == 99);
+ assert_or_panic(v[7] == 0);
+ assert_or_panic(v[8] == 1);
+ assert_or_panic(v[9] == 2);
+ assert_or_panic(v[10] == 3);
+ assert_or_panic(v[11] == 4);
+ assert_or_panic(v[12] == 5);
+ assert_or_panic(v[13] == 6);
+ assert_or_panic(v[14] == 7);
+ assert_or_panic(v[15] == 8);
+ assert_or_panic(i == 16);
+}
+void c_test_vector_16_u8(void) {
+ Vector_16_u8 v = zig_ret_vector_16_u8();
+ assert_or_panic(v[0] == 45);
+ assert_or_panic(v[1] == 46);
+ assert_or_panic(v[2] == 47);
+ assert_or_panic(v[3] == 48);
+ assert_or_panic(v[4] == 49);
+ assert_or_panic(v[5] == 50);
+ assert_or_panic(v[6] == 51);
+ assert_or_panic(v[7] == 52);
+ assert_or_panic(v[8] == 53);
+ assert_or_panic(v[9] == 54);
+ assert_or_panic(v[10] == 55);
+ assert_or_panic(v[11] == 56);
+ assert_or_panic(v[12] == 57);
+ assert_or_panic(v[13] == 58);
+ assert_or_panic(v[14] == 59);
+ assert_or_panic(v[15] == 60);
+ zig_vector_16_u8((Vector_16_u8){ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76 }, 16);
+}
+
+typedef uint8_t Vector_24_u8 __attribute__((vector_size(24 * sizeof(uint8_t))));
+
+Vector_24_u8 zig_ret_vector_24_u8(void);
+void zig_vector_24_u8(Vector_24_u8, size_t);
+
+Vector_24_u8 c_ret_vector_24_u8(void) {
+ return (Vector_24_u8){
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80,
+ };
+}
+void c_vector_24_u8(Vector_24_u8 v, size_t i) {
+ assert_or_panic(v[0] == 81);
+ assert_or_panic(v[1] == 82);
+ assert_or_panic(v[2] == 83);
+ assert_or_panic(v[3] == 84);
+ assert_or_panic(v[4] == 85);
+ assert_or_panic(v[5] == 86);
+ assert_or_panic(v[6] == 87);
+ assert_or_panic(v[7] == 88);
+ assert_or_panic(v[8] == 89);
+ assert_or_panic(v[9] == 90);
+ assert_or_panic(v[10] == 91);
+ assert_or_panic(v[11] == 92);
+ assert_or_panic(v[12] == 93);
+ assert_or_panic(v[13] == 94);
+ assert_or_panic(v[14] == 95);
+ assert_or_panic(v[15] == 96);
+ assert_or_panic(v[16] == 97);
+ assert_or_panic(v[17] == 98);
+ assert_or_panic(v[18] == 99);
+ assert_or_panic(v[19] == 0);
+ assert_or_panic(v[20] == 1);
+ assert_or_panic(v[21] == 2);
+ assert_or_panic(v[22] == 3);
+ assert_or_panic(v[23] == 4);
+ assert_or_panic(i == 24);
+}
+void c_test_vector_24_u8(void) {
+ Vector_24_u8 v = zig_ret_vector_24_u8();
+ assert_or_panic(v[0] == 9);
+ assert_or_panic(v[1] == 10);
+ assert_or_panic(v[2] == 11);
+ assert_or_panic(v[3] == 12);
+ assert_or_panic(v[4] == 13);
+ assert_or_panic(v[5] == 14);
+ assert_or_panic(v[6] == 15);
+ assert_or_panic(v[7] == 16);
+ assert_or_panic(v[8] == 17);
+ assert_or_panic(v[9] == 18);
+ assert_or_panic(v[10] == 19);
+ assert_or_panic(v[11] == 20);
+ assert_or_panic(v[12] == 21);
+ assert_or_panic(v[13] == 22);
+ assert_or_panic(v[14] == 23);
+ assert_or_panic(v[15] == 24);
+ assert_or_panic(v[16] == 25);
+ assert_or_panic(v[17] == 26);
+ assert_or_panic(v[18] == 27);
+ assert_or_panic(v[19] == 28);
+ assert_or_panic(v[20] == 29);
+ assert_or_panic(v[21] == 30);
+ assert_or_panic(v[22] == 31);
+ assert_or_panic(v[23] == 32);
+ zig_vector_24_u8((Vector_24_u8){
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56,
+ }, 24);
+}
+
+typedef uint8_t Vector_32_u8 __attribute__((vector_size(32 * sizeof(uint8_t))));
+
+Vector_32_u8 zig_ret_vector_32_u8(void);
+void zig_vector_32_u8(Vector_32_u8, size_t);
+
+Vector_32_u8 c_ret_vector_32_u8(void) {
+ return (Vector_32_u8){
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0,
+ };
+}
+void c_vector_32_u8(Vector_32_u8 v, size_t i) {
+ assert_or_panic(v[0] == 1);
+ assert_or_panic(v[1] == 2);
+ assert_or_panic(v[2] == 3);
+ assert_or_panic(v[3] == 4);
+ assert_or_panic(v[4] == 5);
+ assert_or_panic(v[5] == 6);
+ assert_or_panic(v[6] == 7);
+ assert_or_panic(v[7] == 8);
+ assert_or_panic(v[8] == 9);
+ assert_or_panic(v[9] == 10);
+ assert_or_panic(v[10] == 11);
+ assert_or_panic(v[11] == 12);
+ assert_or_panic(v[12] == 13);
+ assert_or_panic(v[13] == 14);
+ assert_or_panic(v[14] == 15);
+ assert_or_panic(v[15] == 16);
+ assert_or_panic(v[16] == 17);
+ assert_or_panic(v[17] == 18);
+ assert_or_panic(v[18] == 19);
+ assert_or_panic(v[19] == 20);
+ assert_or_panic(v[20] == 21);
+ assert_or_panic(v[21] == 22);
+ assert_or_panic(v[22] == 23);
+ assert_or_panic(v[23] == 24);
+ assert_or_panic(v[24] == 25);
+ assert_or_panic(v[25] == 26);
+ assert_or_panic(v[26] == 27);
+ assert_or_panic(v[27] == 28);
+ assert_or_panic(v[28] == 29);
+ assert_or_panic(v[29] == 30);
+ assert_or_panic(v[30] == 31);
+ assert_or_panic(v[31] == 32);
+ assert_or_panic(i == 32);
+}
+void c_test_vector_32_u8(void) {
+ Vector_32_u8 v = zig_ret_vector_32_u8();
+ assert_or_panic(v[0] == 5);
+ assert_or_panic(v[1] == 6);
+ assert_or_panic(v[2] == 7);
+ assert_or_panic(v[3] == 8);
+ assert_or_panic(v[4] == 9);
+ assert_or_panic(v[5] == 10);
+ assert_or_panic(v[6] == 11);
+ assert_or_panic(v[7] == 12);
+ assert_or_panic(v[8] == 13);
+ assert_or_panic(v[9] == 14);
+ assert_or_panic(v[10] == 15);
+ assert_or_panic(v[11] == 16);
+ assert_or_panic(v[12] == 17);
+ assert_or_panic(v[13] == 18);
+ assert_or_panic(v[14] == 19);
+ assert_or_panic(v[15] == 20);
+ assert_or_panic(v[16] == 21);
+ assert_or_panic(v[17] == 22);
+ assert_or_panic(v[18] == 23);
+ assert_or_panic(v[19] == 24);
+ assert_or_panic(v[20] == 25);
+ assert_or_panic(v[21] == 26);
+ assert_or_panic(v[22] == 27);
+ assert_or_panic(v[23] == 28);
+ assert_or_panic(v[24] == 29);
+ assert_or_panic(v[25] == 30);
+ assert_or_panic(v[26] == 31);
+ assert_or_panic(v[27] == 32);
+ assert_or_panic(v[28] == 33);
+ assert_or_panic(v[29] == 34);
+ assert_or_panic(v[30] == 35);
+ assert_or_panic(v[31] == 36);
+ zig_vector_32_u8((Vector_32_u8){
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ }, 32);
+}
+
+typedef uint8_t Vector_48_u8 __attribute__((vector_size(48 * sizeof(uint8_t))));
+
+Vector_48_u8 zig_ret_vector_48_u8(void);
+void zig_vector_48_u8(Vector_48_u8, size_t);
+
+Vector_48_u8 c_ret_vector_48_u8(void) {
+ return (Vector_48_u8){
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ };
+}
+void c_vector_48_u8(Vector_48_u8 v, size_t i) {
+ assert_or_panic(v[0] == 77);
+ assert_or_panic(v[1] == 78);
+ assert_or_panic(v[2] == 79);
+ assert_or_panic(v[3] == 80);
+ assert_or_panic(v[4] == 81);
+ assert_or_panic(v[5] == 82);
+ assert_or_panic(v[6] == 83);
+ assert_or_panic(v[7] == 84);
+ assert_or_panic(v[8] == 85);
+ assert_or_panic(v[9] == 86);
+ assert_or_panic(v[10] == 87);
+ assert_or_panic(v[11] == 88);
+ assert_or_panic(v[12] == 89);
+ assert_or_panic(v[13] == 90);
+ assert_or_panic(v[14] == 91);
+ assert_or_panic(v[15] == 92);
+ assert_or_panic(v[16] == 93);
+ assert_or_panic(v[17] == 94);
+ assert_or_panic(v[18] == 95);
+ assert_or_panic(v[19] == 96);
+ assert_or_panic(v[20] == 97);
+ assert_or_panic(v[21] == 98);
+ assert_or_panic(v[22] == 99);
+ assert_or_panic(v[23] == 0);
+ assert_or_panic(v[24] == 1);
+ assert_or_panic(v[25] == 2);
+ assert_or_panic(v[26] == 3);
+ assert_or_panic(v[27] == 4);
+ assert_or_panic(v[28] == 5);
+ assert_or_panic(v[29] == 6);
+ assert_or_panic(v[30] == 7);
+ assert_or_panic(v[31] == 8);
+ assert_or_panic(v[32] == 9);
+ assert_or_panic(v[33] == 10);
+ assert_or_panic(v[34] == 11);
+ assert_or_panic(v[35] == 12);
+ assert_or_panic(v[36] == 13);
+ assert_or_panic(v[37] == 14);
+ assert_or_panic(v[38] == 15);
+ assert_or_panic(v[39] == 16);
+ assert_or_panic(v[40] == 17);
+ assert_or_panic(v[41] == 18);
+ assert_or_panic(v[42] == 19);
+ assert_or_panic(v[43] == 20);
+ assert_or_panic(v[44] == 21);
+ assert_or_panic(v[45] == 22);
+ assert_or_panic(v[46] == 23);
+ assert_or_panic(v[47] == 24);
+ assert_or_panic(i == 48);
+}
+void c_test_vector_48_u8(void) {
+ Vector_48_u8 v = zig_ret_vector_48_u8();
+ assert_or_panic(v[0] == 33);
+ assert_or_panic(v[1] == 34);
+ assert_or_panic(v[2] == 35);
+ assert_or_panic(v[3] == 36);
+ assert_or_panic(v[4] == 37);
+ assert_or_panic(v[5] == 38);
+ assert_or_panic(v[6] == 39);
+ assert_or_panic(v[7] == 40);
+ assert_or_panic(v[8] == 41);
+ assert_or_panic(v[9] == 42);
+ assert_or_panic(v[10] == 43);
+ assert_or_panic(v[11] == 44);
+ assert_or_panic(v[12] == 45);
+ assert_or_panic(v[13] == 46);
+ assert_or_panic(v[14] == 47);
+ assert_or_panic(v[15] == 48);
+ assert_or_panic(v[16] == 49);
+ assert_or_panic(v[17] == 50);
+ assert_or_panic(v[18] == 51);
+ assert_or_panic(v[19] == 52);
+ assert_or_panic(v[20] == 53);
+ assert_or_panic(v[21] == 54);
+ assert_or_panic(v[22] == 55);
+ assert_or_panic(v[23] == 56);
+ assert_or_panic(v[24] == 57);
+ assert_or_panic(v[25] == 58);
+ assert_or_panic(v[26] == 59);
+ assert_or_panic(v[27] == 60);
+ assert_or_panic(v[28] == 61);
+ assert_or_panic(v[29] == 62);
+ assert_or_panic(v[30] == 63);
+ assert_or_panic(v[31] == 64);
+ assert_or_panic(v[32] == 65);
+ assert_or_panic(v[33] == 66);
+ assert_or_panic(v[34] == 67);
+ assert_or_panic(v[35] == 68);
+ assert_or_panic(v[36] == 69);
+ assert_or_panic(v[37] == 70);
+ assert_or_panic(v[38] == 71);
+ assert_or_panic(v[39] == 72);
+ assert_or_panic(v[40] == 73);
+ assert_or_panic(v[41] == 74);
+ assert_or_panic(v[42] == 75);
+ assert_or_panic(v[43] == 76);
+ assert_or_panic(v[44] == 77);
+ assert_or_panic(v[45] == 78);
+ assert_or_panic(v[46] == 79);
+ assert_or_panic(v[47] == 80);
+ zig_vector_48_u8((Vector_48_u8){
+ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ }, 48);
+}
+
+typedef uint8_t Vector_64_u8 __attribute__((vector_size(64 * sizeof(uint8_t))));
+
+Vector_64_u8 zig_ret_vector_64_u8(void);
+void zig_vector_64_u8(Vector_64_u8, size_t);
+
+Vector_64_u8 c_ret_vector_64_u8(void) {
+ return (Vector_64_u8){
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ };
+}
+void c_vector_64_u8(Vector_64_u8 v, size_t i) {
+ assert_or_panic(v[0] == 17);
+ assert_or_panic(v[1] == 18);
+ assert_or_panic(v[2] == 19);
+ assert_or_panic(v[3] == 20);
+ assert_or_panic(v[4] == 21);
+ assert_or_panic(v[5] == 22);
+ assert_or_panic(v[6] == 23);
+ assert_or_panic(v[7] == 24);
+ assert_or_panic(v[8] == 25);
+ assert_or_panic(v[9] == 26);
+ assert_or_panic(v[10] == 27);
+ assert_or_panic(v[11] == 28);
+ assert_or_panic(v[12] == 29);
+ assert_or_panic(v[13] == 30);
+ assert_or_panic(v[14] == 31);
+ assert_or_panic(v[15] == 32);
+ assert_or_panic(v[16] == 33);
+ assert_or_panic(v[17] == 34);
+ assert_or_panic(v[18] == 35);
+ assert_or_panic(v[19] == 36);
+ assert_or_panic(v[20] == 37);
+ assert_or_panic(v[21] == 38);
+ assert_or_panic(v[22] == 39);
+ assert_or_panic(v[23] == 40);
+ assert_or_panic(v[24] == 41);
+ assert_or_panic(v[25] == 42);
+ assert_or_panic(v[26] == 43);
+ assert_or_panic(v[27] == 44);
+ assert_or_panic(v[28] == 45);
+ assert_or_panic(v[29] == 46);
+ assert_or_panic(v[30] == 47);
+ assert_or_panic(v[31] == 48);
+ assert_or_panic(v[32] == 49);
+ assert_or_panic(v[33] == 50);
+ assert_or_panic(v[34] == 51);
+ assert_or_panic(v[35] == 52);
+ assert_or_panic(v[36] == 53);
+ assert_or_panic(v[37] == 54);
+ assert_or_panic(v[38] == 55);
+ assert_or_panic(v[39] == 56);
+ assert_or_panic(v[40] == 57);
+ assert_or_panic(v[41] == 58);
+ assert_or_panic(v[42] == 59);
+ assert_or_panic(v[43] == 60);
+ assert_or_panic(v[44] == 61);
+ assert_or_panic(v[45] == 62);
+ assert_or_panic(v[46] == 63);
+ assert_or_panic(v[47] == 64);
+ assert_or_panic(v[48] == 65);
+ assert_or_panic(v[49] == 66);
+ assert_or_panic(v[50] == 67);
+ assert_or_panic(v[51] == 68);
+ assert_or_panic(v[52] == 69);
+ assert_or_panic(v[53] == 70);
+ assert_or_panic(v[54] == 71);
+ assert_or_panic(v[55] == 72);
+ assert_or_panic(v[56] == 73);
+ assert_or_panic(v[57] == 74);
+ assert_or_panic(v[58] == 75);
+ assert_or_panic(v[59] == 76);
+ assert_or_panic(v[60] == 77);
+ assert_or_panic(v[61] == 78);
+ assert_or_panic(v[62] == 79);
+ assert_or_panic(v[63] == 80);
+ assert_or_panic(i == 64);
+}
+void c_test_vector_64_u8(void) {
+ Vector_64_u8 v = zig_ret_vector_64_u8();
+ assert_or_panic(v[0] == 25);
+ assert_or_panic(v[1] == 26);
+ assert_or_panic(v[2] == 27);
+ assert_or_panic(v[3] == 28);
+ assert_or_panic(v[4] == 29);
+ assert_or_panic(v[5] == 30);
+ assert_or_panic(v[6] == 31);
+ assert_or_panic(v[7] == 32);
+ assert_or_panic(v[8] == 33);
+ assert_or_panic(v[9] == 34);
+ assert_or_panic(v[10] == 35);
+ assert_or_panic(v[11] == 36);
+ assert_or_panic(v[12] == 37);
+ assert_or_panic(v[13] == 38);
+ assert_or_panic(v[14] == 39);
+ assert_or_panic(v[15] == 40);
+ assert_or_panic(v[16] == 41);
+ assert_or_panic(v[17] == 42);
+ assert_or_panic(v[18] == 43);
+ assert_or_panic(v[19] == 44);
+ assert_or_panic(v[20] == 45);
+ assert_or_panic(v[21] == 46);
+ assert_or_panic(v[22] == 47);
+ assert_or_panic(v[23] == 48);
+ assert_or_panic(v[24] == 49);
+ assert_or_panic(v[25] == 50);
+ assert_or_panic(v[26] == 51);
+ assert_or_panic(v[27] == 52);
+ assert_or_panic(v[28] == 53);
+ assert_or_panic(v[29] == 54);
+ assert_or_panic(v[30] == 55);
+ assert_or_panic(v[31] == 56);
+ assert_or_panic(v[32] == 57);
+ assert_or_panic(v[33] == 58);
+ assert_or_panic(v[34] == 59);
+ assert_or_panic(v[35] == 60);
+ assert_or_panic(v[36] == 61);
+ assert_or_panic(v[37] == 62);
+ assert_or_panic(v[38] == 63);
+ assert_or_panic(v[39] == 64);
+ assert_or_panic(v[40] == 65);
+ assert_or_panic(v[41] == 66);
+ assert_or_panic(v[42] == 67);
+ assert_or_panic(v[43] == 68);
+ assert_or_panic(v[44] == 69);
+ assert_or_panic(v[45] == 70);
+ assert_or_panic(v[46] == 71);
+ assert_or_panic(v[47] == 72);
+ assert_or_panic(v[48] == 73);
+ assert_or_panic(v[49] == 74);
+ assert_or_panic(v[50] == 75);
+ assert_or_panic(v[51] == 76);
+ assert_or_panic(v[52] == 77);
+ assert_or_panic(v[53] == 78);
+ assert_or_panic(v[54] == 79);
+ assert_or_panic(v[55] == 80);
+ assert_or_panic(v[56] == 81);
+ assert_or_panic(v[57] == 82);
+ assert_or_panic(v[58] == 83);
+ assert_or_panic(v[59] == 84);
+ assert_or_panic(v[60] == 85);
+ assert_or_panic(v[61] == 86);
+ assert_or_panic(v[62] == 87);
+ assert_or_panic(v[63] == 88);
+ zig_vector_64_u8((Vector_64_u8){
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ }, 64);
+}
+
+typedef uint8_t Vector_96_u8 __attribute__((vector_size(96 * sizeof(uint8_t))));
+
+Vector_96_u8 zig_ret_vector_96_u8(void);
+void zig_vector_96_u8(Vector_96_u8, size_t);
+
+Vector_96_u8 c_ret_vector_96_u8(void) {
+ return (Vector_96_u8){
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ };
+}
+void c_vector_96_u8(Vector_96_u8 v, size_t i) {
+ assert_or_panic(v[0] == 78);
+ assert_or_panic(v[1] == 79);
+ assert_or_panic(v[2] == 80);
+ assert_or_panic(v[3] == 81);
+ assert_or_panic(v[4] == 82);
+ assert_or_panic(v[5] == 83);
+ assert_or_panic(v[6] == 84);
+ assert_or_panic(v[7] == 85);
+ assert_or_panic(v[8] == 86);
+ assert_or_panic(v[9] == 87);
+ assert_or_panic(v[10] == 88);
+ assert_or_panic(v[11] == 89);
+ assert_or_panic(v[12] == 90);
+ assert_or_panic(v[13] == 91);
+ assert_or_panic(v[14] == 92);
+ assert_or_panic(v[15] == 93);
+ assert_or_panic(v[16] == 94);
+ assert_or_panic(v[17] == 95);
+ assert_or_panic(v[18] == 96);
+ assert_or_panic(v[19] == 97);
+ assert_or_panic(v[20] == 98);
+ assert_or_panic(v[21] == 99);
+ assert_or_panic(v[22] == 0);
+ assert_or_panic(v[23] == 1);
+ assert_or_panic(v[24] == 2);
+ assert_or_panic(v[25] == 3);
+ assert_or_panic(v[26] == 4);
+ assert_or_panic(v[27] == 5);
+ assert_or_panic(v[28] == 6);
+ assert_or_panic(v[29] == 7);
+ assert_or_panic(v[30] == 8);
+ assert_or_panic(v[31] == 9);
+ assert_or_panic(v[32] == 10);
+ assert_or_panic(v[33] == 11);
+ assert_or_panic(v[34] == 12);
+ assert_or_panic(v[35] == 13);
+ assert_or_panic(v[36] == 14);
+ assert_or_panic(v[37] == 15);
+ assert_or_panic(v[38] == 16);
+ assert_or_panic(v[39] == 17);
+ assert_or_panic(v[40] == 18);
+ assert_or_panic(v[41] == 19);
+ assert_or_panic(v[42] == 20);
+ assert_or_panic(v[43] == 21);
+ assert_or_panic(v[44] == 22);
+ assert_or_panic(v[45] == 23);
+ assert_or_panic(v[46] == 24);
+ assert_or_panic(v[47] == 25);
+ assert_or_panic(v[48] == 26);
+ assert_or_panic(v[49] == 27);
+ assert_or_panic(v[50] == 28);
+ assert_or_panic(v[51] == 29);
+ assert_or_panic(v[52] == 30);
+ assert_or_panic(v[53] == 31);
+ assert_or_panic(v[54] == 32);
+ assert_or_panic(v[55] == 33);
+ assert_or_panic(v[56] == 34);
+ assert_or_panic(v[57] == 35);
+ assert_or_panic(v[58] == 36);
+ assert_or_panic(v[59] == 37);
+ assert_or_panic(v[60] == 38);
+ assert_or_panic(v[61] == 39);
+ assert_or_panic(v[62] == 40);
+ assert_or_panic(v[63] == 41);
+ assert_or_panic(v[64] == 42);
+ assert_or_panic(v[65] == 43);
+ assert_or_panic(v[66] == 44);
+ assert_or_panic(v[67] == 45);
+ assert_or_panic(v[68] == 46);
+ assert_or_panic(v[69] == 47);
+ assert_or_panic(v[70] == 48);
+ assert_or_panic(v[71] == 49);
+ assert_or_panic(v[72] == 50);
+ assert_or_panic(v[73] == 51);
+ assert_or_panic(v[74] == 52);
+ assert_or_panic(v[75] == 53);
+ assert_or_panic(v[76] == 54);
+ assert_or_panic(v[77] == 55);
+ assert_or_panic(v[80] == 58);
+ assert_or_panic(v[81] == 59);
+ assert_or_panic(v[82] == 60);
+ assert_or_panic(v[83] == 61);
+ assert_or_panic(v[84] == 62);
+ assert_or_panic(v[85] == 63);
+ assert_or_panic(v[86] == 64);
+ assert_or_panic(v[87] == 65);
+ assert_or_panic(v[88] == 66);
+ assert_or_panic(v[89] == 67);
+ assert_or_panic(v[90] == 68);
+ assert_or_panic(v[91] == 69);
+ assert_or_panic(v[92] == 70);
+ assert_or_panic(v[93] == 71);
+ assert_or_panic(v[94] == 72);
+ assert_or_panic(v[95] == 73);
+ assert_or_panic(i == 96);
+}
+void c_test_vector_96_u8(void) {
+ Vector_96_u8 v = zig_ret_vector_96_u8();
+ assert_or_panic(v[0] == 90);
+ assert_or_panic(v[1] == 91);
+ assert_or_panic(v[2] == 92);
+ assert_or_panic(v[3] == 93);
+ assert_or_panic(v[4] == 94);
+ assert_or_panic(v[5] == 95);
+ assert_or_panic(v[6] == 96);
+ assert_or_panic(v[7] == 97);
+ assert_or_panic(v[8] == 98);
+ assert_or_panic(v[9] == 99);
+ assert_or_panic(v[10] == 0);
+ assert_or_panic(v[11] == 1);
+ assert_or_panic(v[12] == 2);
+ assert_or_panic(v[13] == 3);
+ assert_or_panic(v[14] == 4);
+ assert_or_panic(v[15] == 5);
+ assert_or_panic(v[16] == 6);
+ assert_or_panic(v[17] == 7);
+ assert_or_panic(v[18] == 8);
+ assert_or_panic(v[19] == 9);
+ assert_or_panic(v[20] == 10);
+ assert_or_panic(v[21] == 11);
+ assert_or_panic(v[22] == 12);
+ assert_or_panic(v[23] == 13);
+ assert_or_panic(v[24] == 14);
+ assert_or_panic(v[25] == 15);
+ assert_or_panic(v[26] == 16);
+ assert_or_panic(v[27] == 17);
+ assert_or_panic(v[28] == 18);
+ assert_or_panic(v[29] == 19);
+ assert_or_panic(v[30] == 20);
+ assert_or_panic(v[31] == 21);
+ assert_or_panic(v[32] == 22);
+ assert_or_panic(v[33] == 23);
+ assert_or_panic(v[34] == 24);
+ assert_or_panic(v[35] == 25);
+ assert_or_panic(v[36] == 26);
+ assert_or_panic(v[37] == 27);
+ assert_or_panic(v[38] == 28);
+ assert_or_panic(v[39] == 29);
+ assert_or_panic(v[40] == 30);
+ assert_or_panic(v[41] == 31);
+ assert_or_panic(v[42] == 32);
+ assert_or_panic(v[43] == 33);
+ assert_or_panic(v[44] == 34);
+ assert_or_panic(v[45] == 35);
+ assert_or_panic(v[46] == 36);
+ assert_or_panic(v[47] == 37);
+ assert_or_panic(v[48] == 38);
+ assert_or_panic(v[49] == 39);
+ assert_or_panic(v[50] == 40);
+ assert_or_panic(v[51] == 41);
+ assert_or_panic(v[52] == 42);
+ assert_or_panic(v[53] == 43);
+ assert_or_panic(v[54] == 44);
+ assert_or_panic(v[55] == 45);
+ assert_or_panic(v[56] == 46);
+ assert_or_panic(v[57] == 47);
+ assert_or_panic(v[58] == 48);
+ assert_or_panic(v[59] == 49);
+ assert_or_panic(v[60] == 50);
+ assert_or_panic(v[61] == 51);
+ assert_or_panic(v[62] == 52);
+ assert_or_panic(v[63] == 53);
+ assert_or_panic(v[64] == 54);
+ assert_or_panic(v[65] == 55);
+ assert_or_panic(v[66] == 56);
+ assert_or_panic(v[67] == 57);
+ assert_or_panic(v[68] == 58);
+ assert_or_panic(v[69] == 59);
+ assert_or_panic(v[70] == 60);
+ assert_or_panic(v[71] == 61);
+ assert_or_panic(v[72] == 62);
+ assert_or_panic(v[73] == 63);
+ assert_or_panic(v[74] == 64);
+ assert_or_panic(v[75] == 65);
+ assert_or_panic(v[76] == 66);
+ assert_or_panic(v[77] == 67);
+ assert_or_panic(v[78] == 68);
+ assert_or_panic(v[79] == 69);
+ assert_or_panic(v[80] == 70);
+ assert_or_panic(v[81] == 71);
+ assert_or_panic(v[82] == 72);
+ assert_or_panic(v[83] == 73);
+ assert_or_panic(v[84] == 74);
+ assert_or_panic(v[85] == 75);
+ assert_or_panic(v[86] == 76);
+ assert_or_panic(v[87] == 77);
+ assert_or_panic(v[88] == 78);
+ assert_or_panic(v[89] == 79);
+ assert_or_panic(v[90] == 80);
+ assert_or_panic(v[91] == 81);
+ assert_or_panic(v[92] == 82);
+ assert_or_panic(v[93] == 83);
+ assert_or_panic(v[94] == 84);
+ assert_or_panic(v[95] == 85);
+ zig_vector_96_u8((Vector_96_u8){
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ }, 96);
+}
+
+typedef uint8_t Vector_128_u8 __attribute__((vector_size(128 * sizeof(uint8_t))));
+
+Vector_128_u8 zig_ret_vector_128_u8(void);
+void zig_vector_128_u8(Vector_128_u8, size_t);
+
+Vector_128_u8 c_ret_vector_128_u8(void) {
+ return (Vector_128_u8){
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ };
+}
+void c_vector_128_u8(Vector_128_u8 v, size_t i) {
+ assert_or_panic(v[0] == 58);
+ assert_or_panic(v[1] == 59);
+ assert_or_panic(v[2] == 60);
+ assert_or_panic(v[3] == 61);
+ assert_or_panic(v[4] == 62);
+ assert_or_panic(v[5] == 63);
+ assert_or_panic(v[6] == 64);
+ assert_or_panic(v[7] == 65);
+ assert_or_panic(v[8] == 66);
+ assert_or_panic(v[9] == 67);
+ assert_or_panic(v[10] == 68);
+ assert_or_panic(v[11] == 69);
+ assert_or_panic(v[12] == 70);
+ assert_or_panic(v[13] == 71);
+ assert_or_panic(v[14] == 72);
+ assert_or_panic(v[15] == 73);
+ assert_or_panic(v[16] == 74);
+ assert_or_panic(v[17] == 75);
+ assert_or_panic(v[18] == 76);
+ assert_or_panic(v[19] == 77);
+ assert_or_panic(v[20] == 78);
+ assert_or_panic(v[21] == 79);
+ assert_or_panic(v[22] == 80);
+ assert_or_panic(v[23] == 81);
+ assert_or_panic(v[24] == 82);
+ assert_or_panic(v[25] == 83);
+ assert_or_panic(v[26] == 84);
+ assert_or_panic(v[27] == 85);
+ assert_or_panic(v[28] == 86);
+ assert_or_panic(v[29] == 87);
+ assert_or_panic(v[30] == 88);
+ assert_or_panic(v[31] == 89);
+ assert_or_panic(v[32] == 90);
+ assert_or_panic(v[33] == 91);
+ assert_or_panic(v[34] == 92);
+ assert_or_panic(v[35] == 93);
+ assert_or_panic(v[36] == 94);
+ assert_or_panic(v[37] == 95);
+ assert_or_panic(v[38] == 96);
+ assert_or_panic(v[39] == 97);
+ assert_or_panic(v[40] == 98);
+ assert_or_panic(v[41] == 99);
+ assert_or_panic(v[42] == 0);
+ assert_or_panic(v[43] == 1);
+ assert_or_panic(v[44] == 2);
+ assert_or_panic(v[45] == 3);
+ assert_or_panic(v[46] == 4);
+ assert_or_panic(v[47] == 5);
+ assert_or_panic(v[48] == 6);
+ assert_or_panic(v[49] == 7);
+ assert_or_panic(v[50] == 8);
+ assert_or_panic(v[51] == 9);
+ assert_or_panic(v[52] == 10);
+ assert_or_panic(v[53] == 11);
+ assert_or_panic(v[54] == 12);
+ assert_or_panic(v[55] == 13);
+ assert_or_panic(v[56] == 14);
+ assert_or_panic(v[57] == 15);
+ assert_or_panic(v[58] == 16);
+ assert_or_panic(v[59] == 17);
+ assert_or_panic(v[60] == 18);
+ assert_or_panic(v[61] == 19);
+ assert_or_panic(v[62] == 20);
+ assert_or_panic(v[63] == 21);
+ assert_or_panic(v[64] == 22);
+ assert_or_panic(v[65] == 23);
+ assert_or_panic(v[66] == 24);
+ assert_or_panic(v[67] == 25);
+ assert_or_panic(v[68] == 26);
+ assert_or_panic(v[69] == 27);
+ assert_or_panic(v[70] == 28);
+ assert_or_panic(v[71] == 29);
+ assert_or_panic(v[72] == 30);
+ assert_or_panic(v[73] == 31);
+ assert_or_panic(v[74] == 32);
+ assert_or_panic(v[75] == 33);
+ assert_or_panic(v[76] == 34);
+ assert_or_panic(v[77] == 35);
+ assert_or_panic(v[78] == 36);
+ assert_or_panic(v[79] == 37);
+ assert_or_panic(v[80] == 38);
+ assert_or_panic(v[81] == 39);
+ assert_or_panic(v[82] == 40);
+ assert_or_panic(v[83] == 41);
+ assert_or_panic(v[84] == 42);
+ assert_or_panic(v[85] == 43);
+ assert_or_panic(v[86] == 44);
+ assert_or_panic(v[87] == 45);
+ assert_or_panic(v[88] == 46);
+ assert_or_panic(v[89] == 47);
+ assert_or_panic(v[90] == 48);
+ assert_or_panic(v[91] == 49);
+ assert_or_panic(v[92] == 50);
+ assert_or_panic(v[93] == 51);
+ assert_or_panic(v[94] == 52);
+ assert_or_panic(v[95] == 53);
+ assert_or_panic(v[96] == 54);
+ assert_or_panic(v[97] == 55);
+ assert_or_panic(v[98] == 56);
+ assert_or_panic(v[99] == 57);
+ assert_or_panic(v[100] == 58);
+ assert_or_panic(v[101] == 59);
+ assert_or_panic(v[102] == 60);
+ assert_or_panic(v[103] == 61);
+ assert_or_panic(v[104] == 62);
+ assert_or_panic(v[105] == 63);
+ assert_or_panic(v[106] == 64);
+ assert_or_panic(v[107] == 65);
+ assert_or_panic(v[108] == 66);
+ assert_or_panic(v[109] == 67);
+ assert_or_panic(v[110] == 68);
+ assert_or_panic(v[111] == 69);
+ assert_or_panic(v[112] == 70);
+ assert_or_panic(v[113] == 71);
+ assert_or_panic(v[114] == 72);
+ assert_or_panic(v[115] == 73);
+ assert_or_panic(v[116] == 74);
+ assert_or_panic(v[117] == 75);
+ assert_or_panic(v[118] == 76);
+ assert_or_panic(v[119] == 77);
+ assert_or_panic(v[120] == 78);
+ assert_or_panic(v[121] == 79);
+ assert_or_panic(v[122] == 80);
+ assert_or_panic(v[123] == 81);
+ assert_or_panic(v[124] == 82);
+ assert_or_panic(v[125] == 83);
+ assert_or_panic(v[126] == 84);
+ assert_or_panic(v[127] == 85);
+ assert_or_panic(i == 128);
+}
+void c_test_vector_128_u8(void) {
+ Vector_128_u8 v = zig_ret_vector_128_u8();
+ assert_or_panic(v[0] == 74);
+ assert_or_panic(v[1] == 75);
+ assert_or_panic(v[2] == 76);
+ assert_or_panic(v[3] == 77);
+ assert_or_panic(v[4] == 78);
+ assert_or_panic(v[5] == 79);
+ assert_or_panic(v[6] == 80);
+ assert_or_panic(v[7] == 81);
+ assert_or_panic(v[8] == 82);
+ assert_or_panic(v[9] == 83);
+ assert_or_panic(v[10] == 84);
+ assert_or_panic(v[11] == 85);
+ assert_or_panic(v[12] == 86);
+ assert_or_panic(v[13] == 87);
+ assert_or_panic(v[14] == 88);
+ assert_or_panic(v[15] == 89);
+ assert_or_panic(v[16] == 90);
+ assert_or_panic(v[17] == 91);
+ assert_or_panic(v[18] == 92);
+ assert_or_panic(v[19] == 93);
+ assert_or_panic(v[20] == 94);
+ assert_or_panic(v[21] == 95);
+ assert_or_panic(v[22] == 96);
+ assert_or_panic(v[23] == 97);
+ assert_or_panic(v[24] == 98);
+ assert_or_panic(v[25] == 99);
+ assert_or_panic(v[26] == 0);
+ assert_or_panic(v[27] == 1);
+ assert_or_panic(v[28] == 2);
+ assert_or_panic(v[29] == 3);
+ assert_or_panic(v[30] == 4);
+ assert_or_panic(v[31] == 5);
+ assert_or_panic(v[32] == 6);
+ assert_or_panic(v[33] == 7);
+ assert_or_panic(v[34] == 8);
+ assert_or_panic(v[35] == 9);
+ assert_or_panic(v[36] == 10);
+ assert_or_panic(v[37] == 11);
+ assert_or_panic(v[38] == 12);
+ assert_or_panic(v[39] == 13);
+ assert_or_panic(v[40] == 14);
+ assert_or_panic(v[41] == 15);
+ assert_or_panic(v[42] == 16);
+ assert_or_panic(v[43] == 17);
+ assert_or_panic(v[44] == 18);
+ assert_or_panic(v[45] == 19);
+ assert_or_panic(v[46] == 20);
+ assert_or_panic(v[47] == 21);
+ assert_or_panic(v[48] == 22);
+ assert_or_panic(v[49] == 23);
+ assert_or_panic(v[50] == 24);
+ assert_or_panic(v[51] == 25);
+ assert_or_panic(v[52] == 26);
+ assert_or_panic(v[53] == 27);
+ assert_or_panic(v[54] == 28);
+ assert_or_panic(v[55] == 29);
+ assert_or_panic(v[56] == 30);
+ assert_or_panic(v[57] == 31);
+ assert_or_panic(v[58] == 32);
+ assert_or_panic(v[59] == 33);
+ assert_or_panic(v[60] == 34);
+ assert_or_panic(v[61] == 35);
+ assert_or_panic(v[62] == 36);
+ assert_or_panic(v[63] == 37);
+ assert_or_panic(v[64] == 38);
+ assert_or_panic(v[65] == 39);
+ assert_or_panic(v[66] == 40);
+ assert_or_panic(v[67] == 41);
+ assert_or_panic(v[68] == 42);
+ assert_or_panic(v[69] == 43);
+ assert_or_panic(v[70] == 44);
+ assert_or_panic(v[71] == 45);
+ assert_or_panic(v[72] == 46);
+ assert_or_panic(v[73] == 47);
+ assert_or_panic(v[74] == 48);
+ assert_or_panic(v[75] == 49);
+ assert_or_panic(v[76] == 50);
+ assert_or_panic(v[77] == 51);
+ assert_or_panic(v[78] == 52);
+ assert_or_panic(v[79] == 53);
+ assert_or_panic(v[80] == 54);
+ assert_or_panic(v[81] == 55);
+ assert_or_panic(v[82] == 56);
+ assert_or_panic(v[83] == 57);
+ assert_or_panic(v[84] == 58);
+ assert_or_panic(v[85] == 59);
+ assert_or_panic(v[86] == 60);
+ assert_or_panic(v[87] == 61);
+ assert_or_panic(v[88] == 62);
+ assert_or_panic(v[89] == 63);
+ assert_or_panic(v[90] == 64);
+ assert_or_panic(v[91] == 65);
+ assert_or_panic(v[92] == 66);
+ assert_or_panic(v[93] == 67);
+ assert_or_panic(v[94] == 68);
+ assert_or_panic(v[95] == 69);
+ assert_or_panic(v[96] == 70);
+ assert_or_panic(v[97] == 71);
+ assert_or_panic(v[98] == 72);
+ assert_or_panic(v[99] == 73);
+ assert_or_panic(v[100] == 74);
+ assert_or_panic(v[101] == 75);
+ assert_or_panic(v[102] == 76);
+ assert_or_panic(v[103] == 77);
+ assert_or_panic(v[104] == 78);
+ assert_or_panic(v[105] == 79);
+ assert_or_panic(v[106] == 80);
+ assert_or_panic(v[107] == 81);
+ assert_or_panic(v[108] == 82);
+ assert_or_panic(v[109] == 83);
+ assert_or_panic(v[110] == 84);
+ assert_or_panic(v[111] == 85);
+ assert_or_panic(v[112] == 86);
+ assert_or_panic(v[113] == 87);
+ assert_or_panic(v[114] == 88);
+ assert_or_panic(v[115] == 89);
+ assert_or_panic(v[116] == 90);
+ assert_or_panic(v[117] == 91);
+ assert_or_panic(v[118] == 92);
+ assert_or_panic(v[119] == 93);
+ assert_or_panic(v[120] == 94);
+ assert_or_panic(v[121] == 95);
+ assert_or_panic(v[122] == 96);
+ assert_or_panic(v[123] == 97);
+ assert_or_panic(v[124] == 98);
+ assert_or_panic(v[125] == 99);
+ assert_or_panic(v[126] == 0);
+ assert_or_panic(v[127] == 1);
+ zig_vector_128_u8((Vector_128_u8){
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ }, 128);
+}
+
+typedef uint8_t Vector_192_u8 __attribute__((vector_size(192 * sizeof(uint8_t))));
+
+Vector_192_u8 zig_ret_vector_192_u8(void);
+void zig_vector_192_u8(Vector_192_u8, size_t);
+
+Vector_192_u8 c_ret_vector_192_u8(void) {
+ return (Vector_192_u8){
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ };
+}
+void c_vector_192_u8(Vector_192_u8 v, size_t i) {
+ assert_or_panic(v[0] == 62);
+ assert_or_panic(v[1] == 63);
+ assert_or_panic(v[2] == 64);
+ assert_or_panic(v[3] == 65);
+ assert_or_panic(v[4] == 66);
+ assert_or_panic(v[5] == 67);
+ assert_or_panic(v[6] == 68);
+ assert_or_panic(v[7] == 69);
+ assert_or_panic(v[8] == 70);
+ assert_or_panic(v[9] == 71);
+ assert_or_panic(v[10] == 72);
+ assert_or_panic(v[11] == 73);
+ assert_or_panic(v[12] == 74);
+ assert_or_panic(v[13] == 75);
+ assert_or_panic(v[14] == 76);
+ assert_or_panic(v[15] == 77);
+ assert_or_panic(v[16] == 78);
+ assert_or_panic(v[17] == 79);
+ assert_or_panic(v[18] == 80);
+ assert_or_panic(v[19] == 81);
+ assert_or_panic(v[20] == 82);
+ assert_or_panic(v[21] == 83);
+ assert_or_panic(v[22] == 84);
+ assert_or_panic(v[23] == 85);
+ assert_or_panic(v[24] == 86);
+ assert_or_panic(v[25] == 87);
+ assert_or_panic(v[26] == 88);
+ assert_or_panic(v[27] == 89);
+ assert_or_panic(v[28] == 90);
+ assert_or_panic(v[29] == 91);
+ assert_or_panic(v[30] == 92);
+ assert_or_panic(v[31] == 93);
+ assert_or_panic(v[32] == 94);
+ assert_or_panic(v[33] == 95);
+ assert_or_panic(v[34] == 96);
+ assert_or_panic(v[35] == 97);
+ assert_or_panic(v[36] == 98);
+ assert_or_panic(v[37] == 99);
+ assert_or_panic(v[38] == 0);
+ assert_or_panic(v[39] == 1);
+ assert_or_panic(v[40] == 2);
+ assert_or_panic(v[41] == 3);
+ assert_or_panic(v[42] == 4);
+ assert_or_panic(v[43] == 5);
+ assert_or_panic(v[44] == 6);
+ assert_or_panic(v[45] == 7);
+ assert_or_panic(v[46] == 8);
+ assert_or_panic(v[47] == 9);
+ assert_or_panic(v[48] == 10);
+ assert_or_panic(v[49] == 11);
+ assert_or_panic(v[50] == 12);
+ assert_or_panic(v[51] == 13);
+ assert_or_panic(v[52] == 14);
+ assert_or_panic(v[53] == 15);
+ assert_or_panic(v[54] == 16);
+ assert_or_panic(v[55] == 17);
+ assert_or_panic(v[56] == 18);
+ assert_or_panic(v[57] == 19);
+ assert_or_panic(v[58] == 20);
+ assert_or_panic(v[59] == 21);
+ assert_or_panic(v[60] == 22);
+ assert_or_panic(v[61] == 23);
+ assert_or_panic(v[62] == 24);
+ assert_or_panic(v[63] == 25);
+ assert_or_panic(v[64] == 26);
+ assert_or_panic(v[65] == 27);
+ assert_or_panic(v[66] == 28);
+ assert_or_panic(v[67] == 29);
+ assert_or_panic(v[68] == 30);
+ assert_or_panic(v[69] == 31);
+ assert_or_panic(v[70] == 32);
+ assert_or_panic(v[71] == 33);
+ assert_or_panic(v[72] == 34);
+ assert_or_panic(v[73] == 35);
+ assert_or_panic(v[74] == 36);
+ assert_or_panic(v[75] == 37);
+ assert_or_panic(v[76] == 38);
+ assert_or_panic(v[77] == 39);
+ assert_or_panic(v[78] == 40);
+ assert_or_panic(v[79] == 41);
+ assert_or_panic(v[80] == 42);
+ assert_or_panic(v[81] == 43);
+ assert_or_panic(v[82] == 44);
+ assert_or_panic(v[83] == 45);
+ assert_or_panic(v[84] == 46);
+ assert_or_panic(v[85] == 47);
+ assert_or_panic(v[86] == 48);
+ assert_or_panic(v[87] == 49);
+ assert_or_panic(v[88] == 50);
+ assert_or_panic(v[89] == 51);
+ assert_or_panic(v[90] == 52);
+ assert_or_panic(v[91] == 53);
+ assert_or_panic(v[92] == 54);
+ assert_or_panic(v[93] == 55);
+ assert_or_panic(v[94] == 56);
+ assert_or_panic(v[95] == 57);
+ assert_or_panic(v[96] == 58);
+ assert_or_panic(v[97] == 59);
+ assert_or_panic(v[98] == 60);
+ assert_or_panic(v[99] == 61);
+ assert_or_panic(v[100] == 62);
+ assert_or_panic(v[101] == 63);
+ assert_or_panic(v[102] == 64);
+ assert_or_panic(v[103] == 65);
+ assert_or_panic(v[104] == 66);
+ assert_or_panic(v[105] == 67);
+ assert_or_panic(v[106] == 68);
+ assert_or_panic(v[107] == 69);
+ assert_or_panic(v[108] == 70);
+ assert_or_panic(v[109] == 71);
+ assert_or_panic(v[110] == 72);
+ assert_or_panic(v[111] == 73);
+ assert_or_panic(v[112] == 74);
+ assert_or_panic(v[113] == 75);
+ assert_or_panic(v[114] == 76);
+ assert_or_panic(v[115] == 77);
+ assert_or_panic(v[116] == 78);
+ assert_or_panic(v[117] == 79);
+ assert_or_panic(v[118] == 80);
+ assert_or_panic(v[119] == 81);
+ assert_or_panic(v[120] == 82);
+ assert_or_panic(v[121] == 83);
+ assert_or_panic(v[122] == 84);
+ assert_or_panic(v[123] == 85);
+ assert_or_panic(v[124] == 86);
+ assert_or_panic(v[125] == 87);
+ assert_or_panic(v[126] == 88);
+ assert_or_panic(v[127] == 89);
+ assert_or_panic(v[128] == 90);
+ assert_or_panic(v[129] == 91);
+ assert_or_panic(v[130] == 92);
+ assert_or_panic(v[131] == 93);
+ assert_or_panic(v[132] == 94);
+ assert_or_panic(v[133] == 95);
+ assert_or_panic(v[134] == 96);
+ assert_or_panic(v[135] == 97);
+ assert_or_panic(v[136] == 98);
+ assert_or_panic(v[137] == 99);
+ assert_or_panic(v[138] == 0);
+ assert_or_panic(v[139] == 1);
+ assert_or_panic(v[140] == 2);
+ assert_or_panic(v[141] == 3);
+ assert_or_panic(v[142] == 4);
+ assert_or_panic(v[143] == 5);
+ assert_or_panic(v[144] == 6);
+ assert_or_panic(v[145] == 7);
+ assert_or_panic(v[146] == 8);
+ assert_or_panic(v[147] == 9);
+ assert_or_panic(v[148] == 10);
+ assert_or_panic(v[149] == 11);
+ assert_or_panic(v[150] == 12);
+ assert_or_panic(v[151] == 13);
+ assert_or_panic(v[152] == 14);
+ assert_or_panic(v[153] == 15);
+ assert_or_panic(v[154] == 16);
+ assert_or_panic(v[155] == 17);
+ assert_or_panic(v[156] == 18);
+ assert_or_panic(v[157] == 19);
+ assert_or_panic(v[158] == 20);
+ assert_or_panic(v[159] == 21);
+ assert_or_panic(v[160] == 22);
+ assert_or_panic(v[161] == 23);
+ assert_or_panic(v[162] == 24);
+ assert_or_panic(v[163] == 25);
+ assert_or_panic(v[164] == 26);
+ assert_or_panic(v[165] == 27);
+ assert_or_panic(v[166] == 28);
+ assert_or_panic(v[167] == 29);
+ assert_or_panic(v[168] == 30);
+ assert_or_panic(v[169] == 31);
+ assert_or_panic(v[170] == 32);
+ assert_or_panic(v[171] == 33);
+ assert_or_panic(v[172] == 34);
+ assert_or_panic(v[173] == 35);
+ assert_or_panic(v[174] == 36);
+ assert_or_panic(v[175] == 37);
+ assert_or_panic(v[176] == 38);
+ assert_or_panic(v[177] == 39);
+ assert_or_panic(v[178] == 40);
+ assert_or_panic(v[179] == 41);
+ assert_or_panic(v[180] == 42);
+ assert_or_panic(v[181] == 43);
+ assert_or_panic(v[182] == 44);
+ assert_or_panic(v[183] == 45);
+ assert_or_panic(v[184] == 46);
+ assert_or_panic(v[185] == 47);
+ assert_or_panic(v[186] == 48);
+ assert_or_panic(v[187] == 49);
+ assert_or_panic(v[188] == 50);
+ assert_or_panic(v[189] == 51);
+ assert_or_panic(v[190] == 52);
+ assert_or_panic(v[191] == 53);
+ assert_or_panic(i == 192);
+}
+void c_test_vector_192_u8(void) {
+ Vector_192_u8 v = zig_ret_vector_192_u8();
+ assert_or_panic(v[0] == 86);
+ assert_or_panic(v[1] == 87);
+ assert_or_panic(v[2] == 88);
+ assert_or_panic(v[3] == 89);
+ assert_or_panic(v[4] == 90);
+ assert_or_panic(v[5] == 91);
+ assert_or_panic(v[6] == 92);
+ assert_or_panic(v[7] == 93);
+ assert_or_panic(v[8] == 94);
+ assert_or_panic(v[9] == 95);
+ assert_or_panic(v[10] == 96);
+ assert_or_panic(v[11] == 97);
+ assert_or_panic(v[12] == 98);
+ assert_or_panic(v[13] == 99);
+ assert_or_panic(v[14] == 0);
+ assert_or_panic(v[15] == 1);
+ assert_or_panic(v[16] == 2);
+ assert_or_panic(v[17] == 3);
+ assert_or_panic(v[18] == 4);
+ assert_or_panic(v[19] == 5);
+ assert_or_panic(v[20] == 6);
+ assert_or_panic(v[21] == 7);
+ assert_or_panic(v[22] == 8);
+ assert_or_panic(v[23] == 9);
+ assert_or_panic(v[24] == 10);
+ assert_or_panic(v[25] == 11);
+ assert_or_panic(v[26] == 12);
+ assert_or_panic(v[27] == 13);
+ assert_or_panic(v[28] == 14);
+ assert_or_panic(v[29] == 15);
+ assert_or_panic(v[30] == 16);
+ assert_or_panic(v[31] == 17);
+ assert_or_panic(v[32] == 18);
+ assert_or_panic(v[33] == 19);
+ assert_or_panic(v[34] == 20);
+ assert_or_panic(v[35] == 21);
+ assert_or_panic(v[36] == 22);
+ assert_or_panic(v[37] == 23);
+ assert_or_panic(v[38] == 24);
+ assert_or_panic(v[39] == 25);
+ assert_or_panic(v[40] == 26);
+ assert_or_panic(v[41] == 27);
+ assert_or_panic(v[42] == 28);
+ assert_or_panic(v[43] == 29);
+ assert_or_panic(v[44] == 30);
+ assert_or_panic(v[45] == 31);
+ assert_or_panic(v[46] == 32);
+ assert_or_panic(v[47] == 33);
+ assert_or_panic(v[48] == 34);
+ assert_or_panic(v[49] == 35);
+ assert_or_panic(v[50] == 36);
+ assert_or_panic(v[51] == 37);
+ assert_or_panic(v[52] == 38);
+ assert_or_panic(v[53] == 39);
+ assert_or_panic(v[54] == 40);
+ assert_or_panic(v[55] == 41);
+ assert_or_panic(v[56] == 42);
+ assert_or_panic(v[57] == 43);
+ assert_or_panic(v[58] == 44);
+ assert_or_panic(v[59] == 45);
+ assert_or_panic(v[60] == 46);
+ assert_or_panic(v[61] == 47);
+ assert_or_panic(v[62] == 48);
+ assert_or_panic(v[63] == 49);
+ assert_or_panic(v[64] == 50);
+ assert_or_panic(v[65] == 51);
+ assert_or_panic(v[66] == 52);
+ assert_or_panic(v[67] == 53);
+ assert_or_panic(v[68] == 54);
+ assert_or_panic(v[69] == 55);
+ assert_or_panic(v[70] == 56);
+ assert_or_panic(v[71] == 57);
+ assert_or_panic(v[72] == 58);
+ assert_or_panic(v[73] == 59);
+ assert_or_panic(v[74] == 60);
+ assert_or_panic(v[75] == 61);
+ assert_or_panic(v[76] == 62);
+ assert_or_panic(v[77] == 63);
+ assert_or_panic(v[78] == 64);
+ assert_or_panic(v[79] == 65);
+ assert_or_panic(v[80] == 66);
+ assert_or_panic(v[81] == 67);
+ assert_or_panic(v[82] == 68);
+ assert_or_panic(v[83] == 69);
+ assert_or_panic(v[84] == 70);
+ assert_or_panic(v[85] == 71);
+ assert_or_panic(v[86] == 72);
+ assert_or_panic(v[87] == 73);
+ assert_or_panic(v[88] == 74);
+ assert_or_panic(v[89] == 75);
+ assert_or_panic(v[90] == 76);
+ assert_or_panic(v[91] == 77);
+ assert_or_panic(v[92] == 78);
+ assert_or_panic(v[93] == 79);
+ assert_or_panic(v[94] == 80);
+ assert_or_panic(v[95] == 81);
+ assert_or_panic(v[96] == 82);
+ assert_or_panic(v[97] == 83);
+ assert_or_panic(v[98] == 84);
+ assert_or_panic(v[99] == 85);
+ assert_or_panic(v[100] == 86);
+ assert_or_panic(v[101] == 87);
+ assert_or_panic(v[102] == 88);
+ assert_or_panic(v[103] == 89);
+ assert_or_panic(v[104] == 90);
+ assert_or_panic(v[105] == 91);
+ assert_or_panic(v[106] == 92);
+ assert_or_panic(v[107] == 93);
+ assert_or_panic(v[108] == 94);
+ assert_or_panic(v[109] == 95);
+ assert_or_panic(v[110] == 96);
+ assert_or_panic(v[111] == 97);
+ assert_or_panic(v[112] == 98);
+ assert_or_panic(v[113] == 99);
+ assert_or_panic(v[114] == 0);
+ assert_or_panic(v[115] == 1);
+ assert_or_panic(v[116] == 2);
+ assert_or_panic(v[117] == 3);
+ assert_or_panic(v[118] == 4);
+ assert_or_panic(v[119] == 5);
+ assert_or_panic(v[120] == 6);
+ assert_or_panic(v[121] == 7);
+ assert_or_panic(v[122] == 8);
+ assert_or_panic(v[123] == 9);
+ assert_or_panic(v[124] == 10);
+ assert_or_panic(v[125] == 11);
+ assert_or_panic(v[126] == 12);
+ assert_or_panic(v[127] == 13);
+ assert_or_panic(v[128] == 14);
+ assert_or_panic(v[129] == 15);
+ assert_or_panic(v[130] == 16);
+ assert_or_panic(v[131] == 17);
+ assert_or_panic(v[132] == 18);
+ assert_or_panic(v[133] == 19);
+ assert_or_panic(v[134] == 20);
+ assert_or_panic(v[135] == 21);
+ assert_or_panic(v[136] == 22);
+ assert_or_panic(v[137] == 23);
+ assert_or_panic(v[138] == 24);
+ assert_or_panic(v[139] == 25);
+ assert_or_panic(v[140] == 26);
+ assert_or_panic(v[141] == 27);
+ assert_or_panic(v[142] == 28);
+ assert_or_panic(v[143] == 29);
+ assert_or_panic(v[144] == 30);
+ assert_or_panic(v[145] == 31);
+ assert_or_panic(v[146] == 32);
+ assert_or_panic(v[147] == 33);
+ assert_or_panic(v[148] == 34);
+ assert_or_panic(v[149] == 35);
+ assert_or_panic(v[150] == 36);
+ assert_or_panic(v[151] == 37);
+ assert_or_panic(v[152] == 38);
+ assert_or_panic(v[153] == 39);
+ assert_or_panic(v[154] == 40);
+ assert_or_panic(v[155] == 41);
+ assert_or_panic(v[156] == 42);
+ assert_or_panic(v[157] == 43);
+ assert_or_panic(v[158] == 44);
+ assert_or_panic(v[159] == 45);
+ assert_or_panic(v[160] == 46);
+ assert_or_panic(v[161] == 47);
+ assert_or_panic(v[162] == 48);
+ assert_or_panic(v[163] == 49);
+ assert_or_panic(v[164] == 50);
+ assert_or_panic(v[165] == 51);
+ assert_or_panic(v[166] == 52);
+ assert_or_panic(v[167] == 53);
+ assert_or_panic(v[168] == 54);
+ assert_or_panic(v[169] == 55);
+ assert_or_panic(v[170] == 56);
+ assert_or_panic(v[171] == 57);
+ assert_or_panic(v[172] == 58);
+ assert_or_panic(v[173] == 59);
+ assert_or_panic(v[174] == 60);
+ assert_or_panic(v[175] == 61);
+ assert_or_panic(v[176] == 62);
+ assert_or_panic(v[177] == 63);
+ assert_or_panic(v[178] == 64);
+ assert_or_panic(v[179] == 65);
+ assert_or_panic(v[180] == 66);
+ assert_or_panic(v[181] == 67);
+ assert_or_panic(v[182] == 68);
+ assert_or_panic(v[183] == 69);
+ assert_or_panic(v[184] == 70);
+ assert_or_panic(v[185] == 71);
+ assert_or_panic(v[186] == 72);
+ assert_or_panic(v[187] == 73);
+ assert_or_panic(v[188] == 74);
+ assert_or_panic(v[189] == 75);
+ assert_or_panic(v[190] == 76);
+ assert_or_panic(v[191] == 77);
+ zig_vector_192_u8((Vector_192_u8){
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ }, 192);
+}
+
+typedef uint8_t Vector_256_u8 __attribute__((vector_size(256 * sizeof(uint8_t))));
+
+Vector_256_u8 zig_ret_vector_256_u8(void);
+void zig_vector_256_u8(Vector_256_u8, size_t);
+
+Vector_256_u8 c_ret_vector_256_u8(void) {
+ return (Vector_256_u8){
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ };
+}
+void c_vector_256_u8(Vector_256_u8 v, size_t i) {
+ assert_or_panic(v[0] == 22);
+ assert_or_panic(v[1] == 23);
+ assert_or_panic(v[2] == 24);
+ assert_or_panic(v[3] == 25);
+ assert_or_panic(v[4] == 26);
+ assert_or_panic(v[5] == 27);
+ assert_or_panic(v[6] == 28);
+ assert_or_panic(v[7] == 29);
+ assert_or_panic(v[8] == 30);
+ assert_or_panic(v[9] == 31);
+ assert_or_panic(v[10] == 32);
+ assert_or_panic(v[11] == 33);
+ assert_or_panic(v[12] == 34);
+ assert_or_panic(v[13] == 35);
+ assert_or_panic(v[14] == 36);
+ assert_or_panic(v[15] == 37);
+ assert_or_panic(v[16] == 38);
+ assert_or_panic(v[17] == 39);
+ assert_or_panic(v[18] == 40);
+ assert_or_panic(v[19] == 41);
+ assert_or_panic(v[20] == 42);
+ assert_or_panic(v[21] == 43);
+ assert_or_panic(v[22] == 44);
+ assert_or_panic(v[23] == 45);
+ assert_or_panic(v[24] == 46);
+ assert_or_panic(v[25] == 47);
+ assert_or_panic(v[26] == 48);
+ assert_or_panic(v[27] == 49);
+ assert_or_panic(v[28] == 50);
+ assert_or_panic(v[29] == 51);
+ assert_or_panic(v[30] == 52);
+ assert_or_panic(v[31] == 53);
+ assert_or_panic(v[32] == 54);
+ assert_or_panic(v[33] == 55);
+ assert_or_panic(v[34] == 56);
+ assert_or_panic(v[35] == 57);
+ assert_or_panic(v[36] == 58);
+ assert_or_panic(v[37] == 59);
+ assert_or_panic(v[38] == 60);
+ assert_or_panic(v[39] == 61);
+ assert_or_panic(v[40] == 62);
+ assert_or_panic(v[41] == 63);
+ assert_or_panic(v[42] == 64);
+ assert_or_panic(v[43] == 65);
+ assert_or_panic(v[44] == 66);
+ assert_or_panic(v[45] == 67);
+ assert_or_panic(v[46] == 68);
+ assert_or_panic(v[47] == 69);
+ assert_or_panic(v[48] == 70);
+ assert_or_panic(v[49] == 71);
+ assert_or_panic(v[50] == 72);
+ assert_or_panic(v[51] == 73);
+ assert_or_panic(v[52] == 74);
+ assert_or_panic(v[53] == 75);
+ assert_or_panic(v[54] == 76);
+ assert_or_panic(v[55] == 77);
+ assert_or_panic(v[56] == 78);
+ assert_or_panic(v[57] == 79);
+ assert_or_panic(v[58] == 80);
+ assert_or_panic(v[59] == 81);
+ assert_or_panic(v[60] == 82);
+ assert_or_panic(v[61] == 83);
+ assert_or_panic(v[62] == 84);
+ assert_or_panic(v[63] == 85);
+ assert_or_panic(v[64] == 86);
+ assert_or_panic(v[65] == 87);
+ assert_or_panic(v[66] == 88);
+ assert_or_panic(v[67] == 89);
+ assert_or_panic(v[68] == 90);
+ assert_or_panic(v[69] == 91);
+ assert_or_panic(v[70] == 92);
+ assert_or_panic(v[71] == 93);
+ assert_or_panic(v[72] == 94);
+ assert_or_panic(v[73] == 95);
+ assert_or_panic(v[74] == 96);
+ assert_or_panic(v[75] == 97);
+ assert_or_panic(v[76] == 98);
+ assert_or_panic(v[77] == 99);
+ assert_or_panic(v[78] == 0);
+ assert_or_panic(v[79] == 1);
+ assert_or_panic(v[80] == 2);
+ assert_or_panic(v[81] == 3);
+ assert_or_panic(v[82] == 4);
+ assert_or_panic(v[83] == 5);
+ assert_or_panic(v[84] == 6);
+ assert_or_panic(v[85] == 7);
+ assert_or_panic(v[86] == 8);
+ assert_or_panic(v[87] == 9);
+ assert_or_panic(v[88] == 10);
+ assert_or_panic(v[89] == 11);
+ assert_or_panic(v[90] == 12);
+ assert_or_panic(v[91] == 13);
+ assert_or_panic(v[92] == 14);
+ assert_or_panic(v[93] == 15);
+ assert_or_panic(v[94] == 16);
+ assert_or_panic(v[95] == 17);
+ assert_or_panic(v[96] == 18);
+ assert_or_panic(v[97] == 19);
+ assert_or_panic(v[98] == 20);
+ assert_or_panic(v[99] == 21);
+ assert_or_panic(v[100] == 22);
+ assert_or_panic(v[101] == 23);
+ assert_or_panic(v[102] == 24);
+ assert_or_panic(v[103] == 25);
+ assert_or_panic(v[104] == 26);
+ assert_or_panic(v[105] == 27);
+ assert_or_panic(v[106] == 28);
+ assert_or_panic(v[107] == 29);
+ assert_or_panic(v[108] == 30);
+ assert_or_panic(v[109] == 31);
+ assert_or_panic(v[110] == 32);
+ assert_or_panic(v[111] == 33);
+ assert_or_panic(v[112] == 34);
+ assert_or_panic(v[113] == 35);
+ assert_or_panic(v[114] == 36);
+ assert_or_panic(v[115] == 37);
+ assert_or_panic(v[116] == 38);
+ assert_or_panic(v[117] == 39);
+ assert_or_panic(v[118] == 40);
+ assert_or_panic(v[119] == 41);
+ assert_or_panic(v[120] == 42);
+ assert_or_panic(v[121] == 43);
+ assert_or_panic(v[122] == 44);
+ assert_or_panic(v[123] == 45);
+ assert_or_panic(v[124] == 46);
+ assert_or_panic(v[125] == 47);
+ assert_or_panic(v[126] == 48);
+ assert_or_panic(v[127] == 49);
+ assert_or_panic(v[128] == 50);
+ assert_or_panic(v[129] == 51);
+ assert_or_panic(v[130] == 52);
+ assert_or_panic(v[131] == 53);
+ assert_or_panic(v[132] == 54);
+ assert_or_panic(v[133] == 55);
+ assert_or_panic(v[134] == 56);
+ assert_or_panic(v[135] == 57);
+ assert_or_panic(v[136] == 58);
+ assert_or_panic(v[137] == 59);
+ assert_or_panic(v[138] == 60);
+ assert_or_panic(v[139] == 61);
+ assert_or_panic(v[140] == 62);
+ assert_or_panic(v[141] == 63);
+ assert_or_panic(v[142] == 64);
+ assert_or_panic(v[143] == 65);
+ assert_or_panic(v[144] == 66);
+ assert_or_panic(v[145] == 67);
+ assert_or_panic(v[146] == 68);
+ assert_or_panic(v[147] == 69);
+ assert_or_panic(v[148] == 70);
+ assert_or_panic(v[149] == 71);
+ assert_or_panic(v[150] == 72);
+ assert_or_panic(v[151] == 73);
+ assert_or_panic(v[152] == 74);
+ assert_or_panic(v[153] == 75);
+ assert_or_panic(v[154] == 76);
+ assert_or_panic(v[155] == 77);
+ assert_or_panic(v[156] == 78);
+ assert_or_panic(v[157] == 79);
+ assert_or_panic(v[158] == 80);
+ assert_or_panic(v[159] == 81);
+ assert_or_panic(v[160] == 82);
+ assert_or_panic(v[161] == 83);
+ assert_or_panic(v[162] == 84);
+ assert_or_panic(v[163] == 85);
+ assert_or_panic(v[164] == 86);
+ assert_or_panic(v[165] == 87);
+ assert_or_panic(v[166] == 88);
+ assert_or_panic(v[167] == 89);
+ assert_or_panic(v[168] == 90);
+ assert_or_panic(v[169] == 91);
+ assert_or_panic(v[170] == 92);
+ assert_or_panic(v[171] == 93);
+ assert_or_panic(v[172] == 94);
+ assert_or_panic(v[173] == 95);
+ assert_or_panic(v[174] == 96);
+ assert_or_panic(v[175] == 97);
+ assert_or_panic(v[176] == 98);
+ assert_or_panic(v[177] == 99);
+ assert_or_panic(v[178] == 0);
+ assert_or_panic(v[179] == 1);
+ assert_or_panic(v[180] == 2);
+ assert_or_panic(v[181] == 3);
+ assert_or_panic(v[182] == 4);
+ assert_or_panic(v[183] == 5);
+ assert_or_panic(v[184] == 6);
+ assert_or_panic(v[185] == 7);
+ assert_or_panic(v[186] == 8);
+ assert_or_panic(v[187] == 9);
+ assert_or_panic(v[188] == 10);
+ assert_or_panic(v[189] == 11);
+ assert_or_panic(v[190] == 12);
+ assert_or_panic(v[191] == 13);
+ assert_or_panic(v[192] == 14);
+ assert_or_panic(v[193] == 15);
+ assert_or_panic(v[194] == 16);
+ assert_or_panic(v[195] == 17);
+ assert_or_panic(v[196] == 18);
+ assert_or_panic(v[197] == 19);
+ assert_or_panic(v[198] == 20);
+ assert_or_panic(v[199] == 21);
+ assert_or_panic(v[200] == 22);
+ assert_or_panic(v[201] == 23);
+ assert_or_panic(v[202] == 24);
+ assert_or_panic(v[203] == 25);
+ assert_or_panic(v[204] == 26);
+ assert_or_panic(v[205] == 27);
+ assert_or_panic(v[206] == 28);
+ assert_or_panic(v[207] == 29);
+ assert_or_panic(v[208] == 30);
+ assert_or_panic(v[209] == 31);
+ assert_or_panic(v[210] == 32);
+ assert_or_panic(v[211] == 33);
+ assert_or_panic(v[212] == 34);
+ assert_or_panic(v[213] == 35);
+ assert_or_panic(v[214] == 36);
+ assert_or_panic(v[215] == 37);
+ assert_or_panic(v[216] == 38);
+ assert_or_panic(v[217] == 39);
+ assert_or_panic(v[218] == 40);
+ assert_or_panic(v[219] == 41);
+ assert_or_panic(v[220] == 42);
+ assert_or_panic(v[221] == 43);
+ assert_or_panic(v[222] == 44);
+ assert_or_panic(v[223] == 45);
+ assert_or_panic(v[224] == 46);
+ assert_or_panic(v[225] == 47);
+ assert_or_panic(v[226] == 48);
+ assert_or_panic(v[227] == 49);
+ assert_or_panic(v[228] == 50);
+ assert_or_panic(v[229] == 51);
+ assert_or_panic(v[230] == 52);
+ assert_or_panic(v[231] == 53);
+ assert_or_panic(v[232] == 54);
+ assert_or_panic(v[233] == 55);
+ assert_or_panic(v[234] == 56);
+ assert_or_panic(v[235] == 57);
+ assert_or_panic(v[236] == 58);
+ assert_or_panic(v[237] == 59);
+ assert_or_panic(v[238] == 60);
+ assert_or_panic(v[239] == 61);
+ assert_or_panic(v[240] == 62);
+ assert_or_panic(v[241] == 63);
+ assert_or_panic(v[242] == 64);
+ assert_or_panic(v[243] == 65);
+ assert_or_panic(v[244] == 66);
+ assert_or_panic(v[245] == 67);
+ assert_or_panic(v[246] == 68);
+ assert_or_panic(v[247] == 69);
+ assert_or_panic(v[248] == 70);
+ assert_or_panic(v[249] == 71);
+ assert_or_panic(v[250] == 72);
+ assert_or_panic(v[251] == 73);
+ assert_or_panic(v[252] == 74);
+ assert_or_panic(v[253] == 75);
+ assert_or_panic(v[254] == 76);
+ assert_or_panic(v[255] == 77);
+ assert_or_panic(i == 256);
+}
+void c_test_vector_256_u8(void) {
+ Vector_256_u8 v = zig_ret_vector_256_u8();
+ assert_or_panic(v[0] == 54);
+ assert_or_panic(v[1] == 55);
+ assert_or_panic(v[2] == 56);
+ assert_or_panic(v[3] == 57);
+ assert_or_panic(v[4] == 58);
+ assert_or_panic(v[5] == 59);
+ assert_or_panic(v[6] == 60);
+ assert_or_panic(v[7] == 61);
+ assert_or_panic(v[8] == 62);
+ assert_or_panic(v[9] == 63);
+ assert_or_panic(v[10] == 64);
+ assert_or_panic(v[11] == 65);
+ assert_or_panic(v[12] == 66);
+ assert_or_panic(v[13] == 67);
+ assert_or_panic(v[14] == 68);
+ assert_or_panic(v[15] == 69);
+ assert_or_panic(v[16] == 70);
+ assert_or_panic(v[17] == 71);
+ assert_or_panic(v[18] == 72);
+ assert_or_panic(v[19] == 73);
+ assert_or_panic(v[20] == 74);
+ assert_or_panic(v[21] == 75);
+ assert_or_panic(v[22] == 76);
+ assert_or_panic(v[23] == 77);
+ assert_or_panic(v[24] == 78);
+ assert_or_panic(v[25] == 79);
+ assert_or_panic(v[26] == 80);
+ assert_or_panic(v[27] == 81);
+ assert_or_panic(v[28] == 82);
+ assert_or_panic(v[29] == 83);
+ assert_or_panic(v[30] == 84);
+ assert_or_panic(v[31] == 85);
+ assert_or_panic(v[32] == 86);
+ assert_or_panic(v[33] == 87);
+ assert_or_panic(v[34] == 88);
+ assert_or_panic(v[35] == 89);
+ assert_or_panic(v[36] == 90);
+ assert_or_panic(v[37] == 91);
+ assert_or_panic(v[38] == 92);
+ assert_or_panic(v[39] == 93);
+ assert_or_panic(v[40] == 94);
+ assert_or_panic(v[41] == 95);
+ assert_or_panic(v[42] == 96);
+ assert_or_panic(v[43] == 97);
+ assert_or_panic(v[44] == 98);
+ assert_or_panic(v[45] == 99);
+ assert_or_panic(v[46] == 0);
+ assert_or_panic(v[47] == 1);
+ assert_or_panic(v[48] == 2);
+ assert_or_panic(v[49] == 3);
+ assert_or_panic(v[50] == 4);
+ assert_or_panic(v[51] == 5);
+ assert_or_panic(v[52] == 6);
+ assert_or_panic(v[53] == 7);
+ assert_or_panic(v[54] == 8);
+ assert_or_panic(v[55] == 9);
+ assert_or_panic(v[56] == 10);
+ assert_or_panic(v[57] == 11);
+ assert_or_panic(v[58] == 12);
+ assert_or_panic(v[59] == 13);
+ assert_or_panic(v[60] == 14);
+ assert_or_panic(v[61] == 15);
+ assert_or_panic(v[62] == 16);
+ assert_or_panic(v[63] == 17);
+ assert_or_panic(v[64] == 18);
+ assert_or_panic(v[65] == 19);
+ assert_or_panic(v[66] == 20);
+ assert_or_panic(v[67] == 21);
+ assert_or_panic(v[68] == 22);
+ assert_or_panic(v[69] == 23);
+ assert_or_panic(v[70] == 24);
+ assert_or_panic(v[71] == 25);
+ assert_or_panic(v[72] == 26);
+ assert_or_panic(v[73] == 27);
+ assert_or_panic(v[74] == 28);
+ assert_or_panic(v[75] == 29);
+ assert_or_panic(v[76] == 30);
+ assert_or_panic(v[77] == 31);
+ assert_or_panic(v[78] == 32);
+ assert_or_panic(v[79] == 33);
+ assert_or_panic(v[80] == 34);
+ assert_or_panic(v[81] == 35);
+ assert_or_panic(v[82] == 36);
+ assert_or_panic(v[83] == 37);
+ assert_or_panic(v[84] == 38);
+ assert_or_panic(v[85] == 39);
+ assert_or_panic(v[86] == 40);
+ assert_or_panic(v[87] == 41);
+ assert_or_panic(v[88] == 42);
+ assert_or_panic(v[89] == 43);
+ assert_or_panic(v[90] == 44);
+ assert_or_panic(v[91] == 45);
+ assert_or_panic(v[92] == 46);
+ assert_or_panic(v[93] == 47);
+ assert_or_panic(v[94] == 48);
+ assert_or_panic(v[95] == 49);
+ assert_or_panic(v[96] == 50);
+ assert_or_panic(v[97] == 51);
+ assert_or_panic(v[98] == 52);
+ assert_or_panic(v[99] == 53);
+ assert_or_panic(v[100] == 54);
+ assert_or_panic(v[101] == 55);
+ assert_or_panic(v[102] == 56);
+ assert_or_panic(v[103] == 57);
+ assert_or_panic(v[104] == 58);
+ assert_or_panic(v[105] == 59);
+ assert_or_panic(v[106] == 60);
+ assert_or_panic(v[107] == 61);
+ assert_or_panic(v[108] == 62);
+ assert_or_panic(v[109] == 63);
+ assert_or_panic(v[110] == 64);
+ assert_or_panic(v[111] == 65);
+ assert_or_panic(v[112] == 66);
+ assert_or_panic(v[113] == 67);
+ assert_or_panic(v[114] == 68);
+ assert_or_panic(v[115] == 69);
+ assert_or_panic(v[116] == 70);
+ assert_or_panic(v[117] == 71);
+ assert_or_panic(v[118] == 72);
+ assert_or_panic(v[119] == 73);
+ assert_or_panic(v[120] == 74);
+ assert_or_panic(v[121] == 75);
+ assert_or_panic(v[122] == 76);
+ assert_or_panic(v[123] == 77);
+ assert_or_panic(v[124] == 78);
+ assert_or_panic(v[125] == 79);
+ assert_or_panic(v[126] == 80);
+ assert_or_panic(v[127] == 81);
+ assert_or_panic(v[128] == 82);
+ assert_or_panic(v[129] == 83);
+ assert_or_panic(v[130] == 84);
+ assert_or_panic(v[131] == 85);
+ assert_or_panic(v[132] == 86);
+ assert_or_panic(v[133] == 87);
+ assert_or_panic(v[134] == 88);
+ assert_or_panic(v[135] == 89);
+ assert_or_panic(v[136] == 90);
+ assert_or_panic(v[137] == 91);
+ assert_or_panic(v[138] == 92);
+ assert_or_panic(v[139] == 93);
+ assert_or_panic(v[140] == 94);
+ assert_or_panic(v[141] == 95);
+ assert_or_panic(v[142] == 96);
+ assert_or_panic(v[143] == 97);
+ assert_or_panic(v[144] == 98);
+ assert_or_panic(v[145] == 99);
+ assert_or_panic(v[146] == 0);
+ assert_or_panic(v[147] == 1);
+ assert_or_panic(v[148] == 2);
+ assert_or_panic(v[149] == 3);
+ assert_or_panic(v[150] == 4);
+ assert_or_panic(v[151] == 5);
+ assert_or_panic(v[152] == 6);
+ assert_or_panic(v[153] == 7);
+ assert_or_panic(v[154] == 8);
+ assert_or_panic(v[155] == 9);
+ assert_or_panic(v[156] == 10);
+ assert_or_panic(v[157] == 11);
+ assert_or_panic(v[158] == 12);
+ assert_or_panic(v[159] == 13);
+ assert_or_panic(v[160] == 14);
+ assert_or_panic(v[161] == 15);
+ assert_or_panic(v[162] == 16);
+ assert_or_panic(v[163] == 17);
+ assert_or_panic(v[164] == 18);
+ assert_or_panic(v[165] == 19);
+ assert_or_panic(v[166] == 20);
+ assert_or_panic(v[167] == 21);
+ assert_or_panic(v[168] == 22);
+ assert_or_panic(v[169] == 23);
+ assert_or_panic(v[170] == 24);
+ assert_or_panic(v[171] == 25);
+ assert_or_panic(v[172] == 26);
+ assert_or_panic(v[173] == 27);
+ assert_or_panic(v[174] == 28);
+ assert_or_panic(v[175] == 29);
+ assert_or_panic(v[176] == 30);
+ assert_or_panic(v[177] == 31);
+ assert_or_panic(v[178] == 32);
+ assert_or_panic(v[179] == 33);
+ assert_or_panic(v[180] == 34);
+ assert_or_panic(v[181] == 35);
+ assert_or_panic(v[182] == 36);
+ assert_or_panic(v[183] == 37);
+ assert_or_panic(v[184] == 38);
+ assert_or_panic(v[185] == 39);
+ assert_or_panic(v[186] == 40);
+ assert_or_panic(v[187] == 41);
+ assert_or_panic(v[188] == 42);
+ assert_or_panic(v[189] == 43);
+ assert_or_panic(v[190] == 44);
+ assert_or_panic(v[191] == 45);
+ assert_or_panic(v[192] == 46);
+ assert_or_panic(v[193] == 47);
+ assert_or_panic(v[194] == 48);
+ assert_or_panic(v[195] == 49);
+ assert_or_panic(v[196] == 50);
+ assert_or_panic(v[197] == 51);
+ assert_or_panic(v[198] == 52);
+ assert_or_panic(v[199] == 53);
+ assert_or_panic(v[200] == 54);
+ assert_or_panic(v[201] == 55);
+ assert_or_panic(v[202] == 56);
+ assert_or_panic(v[203] == 57);
+ assert_or_panic(v[204] == 58);
+ assert_or_panic(v[205] == 59);
+ assert_or_panic(v[206] == 60);
+ assert_or_panic(v[207] == 61);
+ assert_or_panic(v[208] == 62);
+ assert_or_panic(v[209] == 63);
+ assert_or_panic(v[210] == 64);
+ assert_or_panic(v[211] == 65);
+ assert_or_panic(v[212] == 66);
+ assert_or_panic(v[213] == 67);
+ assert_or_panic(v[214] == 68);
+ assert_or_panic(v[215] == 69);
+ assert_or_panic(v[216] == 70);
+ assert_or_panic(v[217] == 71);
+ assert_or_panic(v[218] == 72);
+ assert_or_panic(v[219] == 73);
+ assert_or_panic(v[220] == 74);
+ assert_or_panic(v[221] == 75);
+ assert_or_panic(v[222] == 76);
+ assert_or_panic(v[223] == 77);
+ assert_or_panic(v[224] == 78);
+ assert_or_panic(v[225] == 79);
+ assert_or_panic(v[226] == 80);
+ assert_or_panic(v[227] == 81);
+ assert_or_panic(v[228] == 82);
+ assert_or_panic(v[229] == 83);
+ assert_or_panic(v[230] == 84);
+ assert_or_panic(v[231] == 85);
+ assert_or_panic(v[232] == 86);
+ assert_or_panic(v[233] == 87);
+ assert_or_panic(v[234] == 88);
+ assert_or_panic(v[235] == 89);
+ assert_or_panic(v[236] == 90);
+ assert_or_panic(v[237] == 91);
+ assert_or_panic(v[238] == 92);
+ assert_or_panic(v[239] == 93);
+ assert_or_panic(v[240] == 94);
+ assert_or_panic(v[241] == 95);
+ assert_or_panic(v[242] == 96);
+ assert_or_panic(v[243] == 97);
+ assert_or_panic(v[244] == 98);
+ assert_or_panic(v[245] == 99);
+ assert_or_panic(v[246] == 0);
+ assert_or_panic(v[247] == 1);
+ assert_or_panic(v[248] == 2);
+ assert_or_panic(v[249] == 3);
+ assert_or_panic(v[250] == 4);
+ assert_or_panic(v[251] == 5);
+ assert_or_panic(v[252] == 6);
+ assert_or_panic(v[253] == 7);
+ assert_or_panic(v[254] == 8);
+ assert_or_panic(v[255] == 9);
+ zig_vector_256_u8((Vector_256_u8){
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ }, 256);
+}
+
+typedef uint8_t Vector_384_u8 __attribute__((vector_size(384 * sizeof(uint8_t))));
+
+Vector_384_u8 zig_ret_vector_384_u8(void);
+void zig_vector_384_u8(Vector_384_u8, size_t);
+
+Vector_384_u8 c_ret_vector_384_u8(void) {
+ return (Vector_384_u8){
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ };
+}
+void c_vector_384_u8(Vector_384_u8 v, size_t i) {
+ assert_or_panic(v[0] == 30);
+ assert_or_panic(v[1] == 31);
+ assert_or_panic(v[2] == 32);
+ assert_or_panic(v[3] == 33);
+ assert_or_panic(v[4] == 34);
+ assert_or_panic(v[5] == 35);
+ assert_or_panic(v[6] == 36);
+ assert_or_panic(v[7] == 37);
+ assert_or_panic(v[8] == 38);
+ assert_or_panic(v[9] == 39);
+ assert_or_panic(v[10] == 40);
+ assert_or_panic(v[11] == 41);
+ assert_or_panic(v[12] == 42);
+ assert_or_panic(v[13] == 43);
+ assert_or_panic(v[14] == 44);
+ assert_or_panic(v[15] == 45);
+ assert_or_panic(v[16] == 46);
+ assert_or_panic(v[17] == 47);
+ assert_or_panic(v[18] == 48);
+ assert_or_panic(v[19] == 49);
+ assert_or_panic(v[20] == 50);
+ assert_or_panic(v[21] == 51);
+ assert_or_panic(v[22] == 52);
+ assert_or_panic(v[23] == 53);
+ assert_or_panic(v[24] == 54);
+ assert_or_panic(v[25] == 55);
+ assert_or_panic(v[26] == 56);
+ assert_or_panic(v[27] == 57);
+ assert_or_panic(v[28] == 58);
+ assert_or_panic(v[29] == 59);
+ assert_or_panic(v[30] == 60);
+ assert_or_panic(v[31] == 61);
+ assert_or_panic(v[32] == 62);
+ assert_or_panic(v[33] == 63);
+ assert_or_panic(v[34] == 64);
+ assert_or_panic(v[35] == 65);
+ assert_or_panic(v[36] == 66);
+ assert_or_panic(v[37] == 67);
+ assert_or_panic(v[38] == 68);
+ assert_or_panic(v[39] == 69);
+ assert_or_panic(v[40] == 70);
+ assert_or_panic(v[41] == 71);
+ assert_or_panic(v[42] == 72);
+ assert_or_panic(v[43] == 73);
+ assert_or_panic(v[44] == 74);
+ assert_or_panic(v[45] == 75);
+ assert_or_panic(v[46] == 76);
+ assert_or_panic(v[47] == 77);
+ assert_or_panic(v[48] == 78);
+ assert_or_panic(v[49] == 79);
+ assert_or_panic(v[50] == 80);
+ assert_or_panic(v[51] == 81);
+ assert_or_panic(v[52] == 82);
+ assert_or_panic(v[53] == 83);
+ assert_or_panic(v[54] == 84);
+ assert_or_panic(v[55] == 85);
+ assert_or_panic(v[56] == 86);
+ assert_or_panic(v[57] == 87);
+ assert_or_panic(v[58] == 88);
+ assert_or_panic(v[59] == 89);
+ assert_or_panic(v[60] == 90);
+ assert_or_panic(v[61] == 91);
+ assert_or_panic(v[62] == 92);
+ assert_or_panic(v[63] == 93);
+ assert_or_panic(v[64] == 94);
+ assert_or_panic(v[65] == 95);
+ assert_or_panic(v[66] == 96);
+ assert_or_panic(v[67] == 97);
+ assert_or_panic(v[68] == 98);
+ assert_or_panic(v[69] == 99);
+ assert_or_panic(v[70] == 0);
+ assert_or_panic(v[71] == 1);
+ assert_or_panic(v[72] == 2);
+ assert_or_panic(v[73] == 3);
+ assert_or_panic(v[74] == 4);
+ assert_or_panic(v[75] == 5);
+ assert_or_panic(v[76] == 6);
+ assert_or_panic(v[77] == 7);
+ assert_or_panic(v[78] == 8);
+ assert_or_panic(v[79] == 9);
+ assert_or_panic(v[80] == 10);
+ assert_or_panic(v[81] == 11);
+ assert_or_panic(v[82] == 12);
+ assert_or_panic(v[83] == 13);
+ assert_or_panic(v[84] == 14);
+ assert_or_panic(v[85] == 15);
+ assert_or_panic(v[86] == 16);
+ assert_or_panic(v[87] == 17);
+ assert_or_panic(v[88] == 18);
+ assert_or_panic(v[89] == 19);
+ assert_or_panic(v[90] == 20);
+ assert_or_panic(v[91] == 21);
+ assert_or_panic(v[92] == 22);
+ assert_or_panic(v[93] == 23);
+ assert_or_panic(v[94] == 24);
+ assert_or_panic(v[95] == 25);
+ assert_or_panic(v[96] == 26);
+ assert_or_panic(v[97] == 27);
+ assert_or_panic(v[98] == 28);
+ assert_or_panic(v[99] == 29);
+ assert_or_panic(v[100] == 30);
+ assert_or_panic(v[101] == 31);
+ assert_or_panic(v[102] == 32);
+ assert_or_panic(v[103] == 33);
+ assert_or_panic(v[104] == 34);
+ assert_or_panic(v[105] == 35);
+ assert_or_panic(v[106] == 36);
+ assert_or_panic(v[107] == 37);
+ assert_or_panic(v[108] == 38);
+ assert_or_panic(v[109] == 39);
+ assert_or_panic(v[110] == 40);
+ assert_or_panic(v[111] == 41);
+ assert_or_panic(v[112] == 42);
+ assert_or_panic(v[113] == 43);
+ assert_or_panic(v[114] == 44);
+ assert_or_panic(v[115] == 45);
+ assert_or_panic(v[116] == 46);
+ assert_or_panic(v[117] == 47);
+ assert_or_panic(v[118] == 48);
+ assert_or_panic(v[119] == 49);
+ assert_or_panic(v[120] == 50);
+ assert_or_panic(v[121] == 51);
+ assert_or_panic(v[122] == 52);
+ assert_or_panic(v[123] == 53);
+ assert_or_panic(v[124] == 54);
+ assert_or_panic(v[125] == 55);
+ assert_or_panic(v[126] == 56);
+ assert_or_panic(v[127] == 57);
+ assert_or_panic(v[128] == 58);
+ assert_or_panic(v[129] == 59);
+ assert_or_panic(v[130] == 60);
+ assert_or_panic(v[131] == 61);
+ assert_or_panic(v[132] == 62);
+ assert_or_panic(v[133] == 63);
+ assert_or_panic(v[134] == 64);
+ assert_or_panic(v[135] == 65);
+ assert_or_panic(v[136] == 66);
+ assert_or_panic(v[137] == 67);
+ assert_or_panic(v[138] == 68);
+ assert_or_panic(v[139] == 69);
+ assert_or_panic(v[140] == 70);
+ assert_or_panic(v[141] == 71);
+ assert_or_panic(v[142] == 72);
+ assert_or_panic(v[143] == 73);
+ assert_or_panic(v[144] == 74);
+ assert_or_panic(v[145] == 75);
+ assert_or_panic(v[146] == 76);
+ assert_or_panic(v[147] == 77);
+ assert_or_panic(v[148] == 78);
+ assert_or_panic(v[149] == 79);
+ assert_or_panic(v[150] == 80);
+ assert_or_panic(v[151] == 81);
+ assert_or_panic(v[152] == 82);
+ assert_or_panic(v[153] == 83);
+ assert_or_panic(v[154] == 84);
+ assert_or_panic(v[155] == 85);
+ assert_or_panic(v[156] == 86);
+ assert_or_panic(v[157] == 87);
+ assert_or_panic(v[158] == 88);
+ assert_or_panic(v[159] == 89);
+ assert_or_panic(v[160] == 90);
+ assert_or_panic(v[161] == 91);
+ assert_or_panic(v[162] == 92);
+ assert_or_panic(v[163] == 93);
+ assert_or_panic(v[164] == 94);
+ assert_or_panic(v[165] == 95);
+ assert_or_panic(v[166] == 96);
+ assert_or_panic(v[167] == 97);
+ assert_or_panic(v[168] == 98);
+ assert_or_panic(v[169] == 99);
+ assert_or_panic(v[170] == 0);
+ assert_or_panic(v[171] == 1);
+ assert_or_panic(v[172] == 2);
+ assert_or_panic(v[173] == 3);
+ assert_or_panic(v[174] == 4);
+ assert_or_panic(v[175] == 5);
+ assert_or_panic(v[176] == 6);
+ assert_or_panic(v[177] == 7);
+ assert_or_panic(v[178] == 8);
+ assert_or_panic(v[179] == 9);
+ assert_or_panic(v[180] == 10);
+ assert_or_panic(v[181] == 11);
+ assert_or_panic(v[182] == 12);
+ assert_or_panic(v[183] == 13);
+ assert_or_panic(v[184] == 14);
+ assert_or_panic(v[185] == 15);
+ assert_or_panic(v[186] == 16);
+ assert_or_panic(v[187] == 17);
+ assert_or_panic(v[188] == 18);
+ assert_or_panic(v[189] == 19);
+ assert_or_panic(v[190] == 20);
+ assert_or_panic(v[191] == 21);
+ assert_or_panic(v[192] == 22);
+ assert_or_panic(v[193] == 23);
+ assert_or_panic(v[194] == 24);
+ assert_or_panic(v[195] == 25);
+ assert_or_panic(v[196] == 26);
+ assert_or_panic(v[197] == 27);
+ assert_or_panic(v[198] == 28);
+ assert_or_panic(v[199] == 29);
+ assert_or_panic(v[200] == 30);
+ assert_or_panic(v[201] == 31);
+ assert_or_panic(v[202] == 32);
+ assert_or_panic(v[203] == 33);
+ assert_or_panic(v[204] == 34);
+ assert_or_panic(v[205] == 35);
+ assert_or_panic(v[206] == 36);
+ assert_or_panic(v[207] == 37);
+ assert_or_panic(v[208] == 38);
+ assert_or_panic(v[209] == 39);
+ assert_or_panic(v[210] == 40);
+ assert_or_panic(v[211] == 41);
+ assert_or_panic(v[212] == 42);
+ assert_or_panic(v[213] == 43);
+ assert_or_panic(v[214] == 44);
+ assert_or_panic(v[215] == 45);
+ assert_or_panic(v[216] == 46);
+ assert_or_panic(v[217] == 47);
+ assert_or_panic(v[218] == 48);
+ assert_or_panic(v[219] == 49);
+ assert_or_panic(v[220] == 50);
+ assert_or_panic(v[221] == 51);
+ assert_or_panic(v[222] == 52);
+ assert_or_panic(v[223] == 53);
+ assert_or_panic(v[224] == 54);
+ assert_or_panic(v[225] == 55);
+ assert_or_panic(v[226] == 56);
+ assert_or_panic(v[227] == 57);
+ assert_or_panic(v[228] == 58);
+ assert_or_panic(v[229] == 59);
+ assert_or_panic(v[230] == 60);
+ assert_or_panic(v[231] == 61);
+ assert_or_panic(v[232] == 62);
+ assert_or_panic(v[233] == 63);
+ assert_or_panic(v[234] == 64);
+ assert_or_panic(v[235] == 65);
+ assert_or_panic(v[236] == 66);
+ assert_or_panic(v[237] == 67);
+ assert_or_panic(v[238] == 68);
+ assert_or_panic(v[239] == 69);
+ assert_or_panic(v[240] == 70);
+ assert_or_panic(v[241] == 71);
+ assert_or_panic(v[242] == 72);
+ assert_or_panic(v[243] == 73);
+ assert_or_panic(v[244] == 74);
+ assert_or_panic(v[245] == 75);
+ assert_or_panic(v[246] == 76);
+ assert_or_panic(v[247] == 77);
+ assert_or_panic(v[248] == 78);
+ assert_or_panic(v[249] == 79);
+ assert_or_panic(v[250] == 80);
+ assert_or_panic(v[251] == 81);
+ assert_or_panic(v[252] == 82);
+ assert_or_panic(v[253] == 83);
+ assert_or_panic(v[254] == 84);
+ assert_or_panic(v[255] == 85);
+ assert_or_panic(v[256] == 86);
+ assert_or_panic(v[257] == 87);
+ assert_or_panic(v[258] == 88);
+ assert_or_panic(v[259] == 89);
+ assert_or_panic(v[260] == 90);
+ assert_or_panic(v[261] == 91);
+ assert_or_panic(v[262] == 92);
+ assert_or_panic(v[263] == 93);
+ assert_or_panic(v[264] == 94);
+ assert_or_panic(v[265] == 95);
+ assert_or_panic(v[266] == 96);
+ assert_or_panic(v[267] == 97);
+ assert_or_panic(v[268] == 98);
+ assert_or_panic(v[269] == 99);
+ assert_or_panic(v[270] == 0);
+ assert_or_panic(v[271] == 1);
+ assert_or_panic(v[272] == 2);
+ assert_or_panic(v[273] == 3);
+ assert_or_panic(v[274] == 4);
+ assert_or_panic(v[275] == 5);
+ assert_or_panic(v[276] == 6);
+ assert_or_panic(v[277] == 7);
+ assert_or_panic(v[278] == 8);
+ assert_or_panic(v[279] == 9);
+ assert_or_panic(v[280] == 10);
+ assert_or_panic(v[281] == 11);
+ assert_or_panic(v[282] == 12);
+ assert_or_panic(v[283] == 13);
+ assert_or_panic(v[284] == 14);
+ assert_or_panic(v[285] == 15);
+ assert_or_panic(v[286] == 16);
+ assert_or_panic(v[287] == 17);
+ assert_or_panic(v[288] == 18);
+ assert_or_panic(v[289] == 19);
+ assert_or_panic(v[290] == 20);
+ assert_or_panic(v[291] == 21);
+ assert_or_panic(v[292] == 22);
+ assert_or_panic(v[293] == 23);
+ assert_or_panic(v[294] == 24);
+ assert_or_panic(v[295] == 25);
+ assert_or_panic(v[296] == 26);
+ assert_or_panic(v[297] == 27);
+ assert_or_panic(v[298] == 28);
+ assert_or_panic(v[299] == 29);
+ assert_or_panic(v[300] == 30);
+ assert_or_panic(v[301] == 31);
+ assert_or_panic(v[302] == 32);
+ assert_or_panic(v[303] == 33);
+ assert_or_panic(v[304] == 34);
+ assert_or_panic(v[305] == 35);
+ assert_or_panic(v[306] == 36);
+ assert_or_panic(v[307] == 37);
+ assert_or_panic(v[308] == 38);
+ assert_or_panic(v[309] == 39);
+ assert_or_panic(v[310] == 40);
+ assert_or_panic(v[311] == 41);
+ assert_or_panic(v[312] == 42);
+ assert_or_panic(v[313] == 43);
+ assert_or_panic(v[314] == 44);
+ assert_or_panic(v[315] == 45);
+ assert_or_panic(v[316] == 46);
+ assert_or_panic(v[317] == 47);
+ assert_or_panic(v[318] == 48);
+ assert_or_panic(v[319] == 49);
+ assert_or_panic(v[320] == 50);
+ assert_or_panic(v[321] == 51);
+ assert_or_panic(v[322] == 52);
+ assert_or_panic(v[323] == 53);
+ assert_or_panic(v[324] == 54);
+ assert_or_panic(v[325] == 55);
+ assert_or_panic(v[326] == 56);
+ assert_or_panic(v[327] == 57);
+ assert_or_panic(v[328] == 58);
+ assert_or_panic(v[329] == 59);
+ assert_or_panic(v[330] == 60);
+ assert_or_panic(v[331] == 61);
+ assert_or_panic(v[332] == 62);
+ assert_or_panic(v[333] == 63);
+ assert_or_panic(v[334] == 64);
+ assert_or_panic(v[335] == 65);
+ assert_or_panic(v[336] == 66);
+ assert_or_panic(v[337] == 67);
+ assert_or_panic(v[338] == 68);
+ assert_or_panic(v[339] == 69);
+ assert_or_panic(v[340] == 70);
+ assert_or_panic(v[341] == 71);
+ assert_or_panic(v[342] == 72);
+ assert_or_panic(v[343] == 73);
+ assert_or_panic(v[344] == 74);
+ assert_or_panic(v[345] == 75);
+ assert_or_panic(v[346] == 76);
+ assert_or_panic(v[347] == 77);
+ assert_or_panic(v[348] == 78);
+ assert_or_panic(v[349] == 79);
+ assert_or_panic(v[350] == 80);
+ assert_or_panic(v[351] == 81);
+ assert_or_panic(v[352] == 82);
+ assert_or_panic(v[353] == 83);
+ assert_or_panic(v[354] == 84);
+ assert_or_panic(v[355] == 85);
+ assert_or_panic(v[356] == 86);
+ assert_or_panic(v[357] == 87);
+ assert_or_panic(v[358] == 88);
+ assert_or_panic(v[359] == 89);
+ assert_or_panic(v[360] == 90);
+ assert_or_panic(v[361] == 91);
+ assert_or_panic(v[362] == 92);
+ assert_or_panic(v[363] == 93);
+ assert_or_panic(v[364] == 94);
+ assert_or_panic(v[365] == 95);
+ assert_or_panic(v[366] == 96);
+ assert_or_panic(v[367] == 97);
+ assert_or_panic(v[368] == 98);
+ assert_or_panic(v[369] == 99);
+ assert_or_panic(v[370] == 0);
+ assert_or_panic(v[371] == 1);
+ assert_or_panic(v[372] == 2);
+ assert_or_panic(v[373] == 3);
+ assert_or_panic(v[374] == 4);
+ assert_or_panic(v[375] == 5);
+ assert_or_panic(v[376] == 6);
+ assert_or_panic(v[377] == 7);
+ assert_or_panic(v[378] == 8);
+ assert_or_panic(v[379] == 9);
+ assert_or_panic(v[380] == 10);
+ assert_or_panic(v[381] == 11);
+ assert_or_panic(v[382] == 12);
+ assert_or_panic(v[383] == 13);
+ assert_or_panic(i == 384);
+}
+void c_test_vector_384_u8(void) {
+ Vector_384_u8 v = zig_ret_vector_384_u8();
+ assert_or_panic(v[0] == 78);
+ assert_or_panic(v[1] == 79);
+ assert_or_panic(v[2] == 80);
+ assert_or_panic(v[3] == 81);
+ assert_or_panic(v[4] == 82);
+ assert_or_panic(v[5] == 83);
+ assert_or_panic(v[6] == 84);
+ assert_or_panic(v[7] == 85);
+ assert_or_panic(v[8] == 86);
+ assert_or_panic(v[9] == 87);
+ assert_or_panic(v[10] == 88);
+ assert_or_panic(v[11] == 89);
+ assert_or_panic(v[12] == 90);
+ assert_or_panic(v[13] == 91);
+ assert_or_panic(v[14] == 92);
+ assert_or_panic(v[15] == 93);
+ assert_or_panic(v[16] == 94);
+ assert_or_panic(v[17] == 95);
+ assert_or_panic(v[18] == 96);
+ assert_or_panic(v[19] == 97);
+ assert_or_panic(v[20] == 98);
+ assert_or_panic(v[21] == 99);
+ assert_or_panic(v[22] == 0);
+ assert_or_panic(v[23] == 1);
+ assert_or_panic(v[24] == 2);
+ assert_or_panic(v[25] == 3);
+ assert_or_panic(v[26] == 4);
+ assert_or_panic(v[27] == 5);
+ assert_or_panic(v[28] == 6);
+ assert_or_panic(v[29] == 7);
+ assert_or_panic(v[30] == 8);
+ assert_or_panic(v[31] == 9);
+ assert_or_panic(v[32] == 10);
+ assert_or_panic(v[33] == 11);
+ assert_or_panic(v[34] == 12);
+ assert_or_panic(v[35] == 13);
+ assert_or_panic(v[36] == 14);
+ assert_or_panic(v[37] == 15);
+ assert_or_panic(v[38] == 16);
+ assert_or_panic(v[39] == 17);
+ assert_or_panic(v[40] == 18);
+ assert_or_panic(v[41] == 19);
+ assert_or_panic(v[42] == 20);
+ assert_or_panic(v[43] == 21);
+ assert_or_panic(v[44] == 22);
+ assert_or_panic(v[45] == 23);
+ assert_or_panic(v[46] == 24);
+ assert_or_panic(v[47] == 25);
+ assert_or_panic(v[48] == 26);
+ assert_or_panic(v[49] == 27);
+ assert_or_panic(v[50] == 28);
+ assert_or_panic(v[51] == 29);
+ assert_or_panic(v[52] == 30);
+ assert_or_panic(v[53] == 31);
+ assert_or_panic(v[54] == 32);
+ assert_or_panic(v[55] == 33);
+ assert_or_panic(v[56] == 34);
+ assert_or_panic(v[57] == 35);
+ assert_or_panic(v[58] == 36);
+ assert_or_panic(v[59] == 37);
+ assert_or_panic(v[60] == 38);
+ assert_or_panic(v[61] == 39);
+ assert_or_panic(v[62] == 40);
+ assert_or_panic(v[63] == 41);
+ assert_or_panic(v[64] == 42);
+ assert_or_panic(v[65] == 43);
+ assert_or_panic(v[66] == 44);
+ assert_or_panic(v[67] == 45);
+ assert_or_panic(v[68] == 46);
+ assert_or_panic(v[69] == 47);
+ assert_or_panic(v[70] == 48);
+ assert_or_panic(v[71] == 49);
+ assert_or_panic(v[72] == 50);
+ assert_or_panic(v[73] == 51);
+ assert_or_panic(v[74] == 52);
+ assert_or_panic(v[75] == 53);
+ assert_or_panic(v[76] == 54);
+ assert_or_panic(v[77] == 55);
+ assert_or_panic(v[78] == 56);
+ assert_or_panic(v[79] == 57);
+ assert_or_panic(v[80] == 58);
+ assert_or_panic(v[81] == 59);
+ assert_or_panic(v[82] == 60);
+ assert_or_panic(v[83] == 61);
+ assert_or_panic(v[84] == 62);
+ assert_or_panic(v[85] == 63);
+ assert_or_panic(v[86] == 64);
+ assert_or_panic(v[87] == 65);
+ assert_or_panic(v[88] == 66);
+ assert_or_panic(v[89] == 67);
+ assert_or_panic(v[90] == 68);
+ assert_or_panic(v[91] == 69);
+ assert_or_panic(v[92] == 70);
+ assert_or_panic(v[93] == 71);
+ assert_or_panic(v[94] == 72);
+ assert_or_panic(v[95] == 73);
+ assert_or_panic(v[96] == 74);
+ assert_or_panic(v[97] == 75);
+ assert_or_panic(v[98] == 76);
+ assert_or_panic(v[99] == 77);
+ assert_or_panic(v[100] == 78);
+ assert_or_panic(v[101] == 79);
+ assert_or_panic(v[102] == 80);
+ assert_or_panic(v[103] == 81);
+ assert_or_panic(v[104] == 82);
+ assert_or_panic(v[105] == 83);
+ assert_or_panic(v[106] == 84);
+ assert_or_panic(v[107] == 85);
+ assert_or_panic(v[108] == 86);
+ assert_or_panic(v[109] == 87);
+ assert_or_panic(v[110] == 88);
+ assert_or_panic(v[111] == 89);
+ assert_or_panic(v[112] == 90);
+ assert_or_panic(v[113] == 91);
+ assert_or_panic(v[114] == 92);
+ assert_or_panic(v[115] == 93);
+ assert_or_panic(v[116] == 94);
+ assert_or_panic(v[117] == 95);
+ assert_or_panic(v[118] == 96);
+ assert_or_panic(v[119] == 97);
+ assert_or_panic(v[120] == 98);
+ assert_or_panic(v[121] == 99);
+ assert_or_panic(v[122] == 0);
+ assert_or_panic(v[123] == 1);
+ assert_or_panic(v[124] == 2);
+ assert_or_panic(v[125] == 3);
+ assert_or_panic(v[126] == 4);
+ assert_or_panic(v[127] == 5);
+ assert_or_panic(v[128] == 6);
+ assert_or_panic(v[129] == 7);
+ assert_or_panic(v[130] == 8);
+ assert_or_panic(v[131] == 9);
+ assert_or_panic(v[132] == 10);
+ assert_or_panic(v[133] == 11);
+ assert_or_panic(v[134] == 12);
+ assert_or_panic(v[135] == 13);
+ assert_or_panic(v[136] == 14);
+ assert_or_panic(v[137] == 15);
+ assert_or_panic(v[138] == 16);
+ assert_or_panic(v[139] == 17);
+ assert_or_panic(v[140] == 18);
+ assert_or_panic(v[141] == 19);
+ assert_or_panic(v[142] == 20);
+ assert_or_panic(v[143] == 21);
+ assert_or_panic(v[144] == 22);
+ assert_or_panic(v[145] == 23);
+ assert_or_panic(v[146] == 24);
+ assert_or_panic(v[147] == 25);
+ assert_or_panic(v[148] == 26);
+ assert_or_panic(v[149] == 27);
+ assert_or_panic(v[150] == 28);
+ assert_or_panic(v[151] == 29);
+ assert_or_panic(v[152] == 30);
+ assert_or_panic(v[153] == 31);
+ assert_or_panic(v[154] == 32);
+ assert_or_panic(v[155] == 33);
+ assert_or_panic(v[156] == 34);
+ assert_or_panic(v[157] == 35);
+ assert_or_panic(v[158] == 36);
+ assert_or_panic(v[159] == 37);
+ assert_or_panic(v[160] == 38);
+ assert_or_panic(v[161] == 39);
+ assert_or_panic(v[162] == 40);
+ assert_or_panic(v[163] == 41);
+ assert_or_panic(v[164] == 42);
+ assert_or_panic(v[165] == 43);
+ assert_or_panic(v[166] == 44);
+ assert_or_panic(v[167] == 45);
+ assert_or_panic(v[168] == 46);
+ assert_or_panic(v[169] == 47);
+ assert_or_panic(v[170] == 48);
+ assert_or_panic(v[171] == 49);
+ assert_or_panic(v[172] == 50);
+ assert_or_panic(v[173] == 51);
+ assert_or_panic(v[174] == 52);
+ assert_or_panic(v[175] == 53);
+ assert_or_panic(v[176] == 54);
+ assert_or_panic(v[177] == 55);
+ assert_or_panic(v[178] == 56);
+ assert_or_panic(v[179] == 57);
+ assert_or_panic(v[180] == 58);
+ assert_or_panic(v[181] == 59);
+ assert_or_panic(v[182] == 60);
+ assert_or_panic(v[183] == 61);
+ assert_or_panic(v[184] == 62);
+ assert_or_panic(v[185] == 63);
+ assert_or_panic(v[186] == 64);
+ assert_or_panic(v[187] == 65);
+ assert_or_panic(v[188] == 66);
+ assert_or_panic(v[189] == 67);
+ assert_or_panic(v[190] == 68);
+ assert_or_panic(v[191] == 69);
+ assert_or_panic(v[192] == 70);
+ assert_or_panic(v[193] == 71);
+ assert_or_panic(v[194] == 72);
+ assert_or_panic(v[195] == 73);
+ assert_or_panic(v[196] == 74);
+ assert_or_panic(v[197] == 75);
+ assert_or_panic(v[198] == 76);
+ assert_or_panic(v[199] == 77);
+ assert_or_panic(v[200] == 78);
+ assert_or_panic(v[201] == 79);
+ assert_or_panic(v[202] == 80);
+ assert_or_panic(v[203] == 81);
+ assert_or_panic(v[204] == 82);
+ assert_or_panic(v[205] == 83);
+ assert_or_panic(v[206] == 84);
+ assert_or_panic(v[207] == 85);
+ assert_or_panic(v[208] == 86);
+ assert_or_panic(v[209] == 87);
+ assert_or_panic(v[210] == 88);
+ assert_or_panic(v[211] == 89);
+ assert_or_panic(v[212] == 90);
+ assert_or_panic(v[213] == 91);
+ assert_or_panic(v[214] == 92);
+ assert_or_panic(v[215] == 93);
+ assert_or_panic(v[216] == 94);
+ assert_or_panic(v[217] == 95);
+ assert_or_panic(v[218] == 96);
+ assert_or_panic(v[219] == 97);
+ assert_or_panic(v[220] == 98);
+ assert_or_panic(v[221] == 99);
+ assert_or_panic(v[222] == 0);
+ assert_or_panic(v[223] == 1);
+ assert_or_panic(v[224] == 2);
+ assert_or_panic(v[225] == 3);
+ assert_or_panic(v[226] == 4);
+ assert_or_panic(v[227] == 5);
+ assert_or_panic(v[228] == 6);
+ assert_or_panic(v[229] == 7);
+ assert_or_panic(v[230] == 8);
+ assert_or_panic(v[231] == 9);
+ assert_or_panic(v[232] == 10);
+ assert_or_panic(v[233] == 11);
+ assert_or_panic(v[234] == 12);
+ assert_or_panic(v[235] == 13);
+ assert_or_panic(v[236] == 14);
+ assert_or_panic(v[237] == 15);
+ assert_or_panic(v[238] == 16);
+ assert_or_panic(v[239] == 17);
+ assert_or_panic(v[240] == 18);
+ assert_or_panic(v[241] == 19);
+ assert_or_panic(v[242] == 20);
+ assert_or_panic(v[243] == 21);
+ assert_or_panic(v[244] == 22);
+ assert_or_panic(v[245] == 23);
+ assert_or_panic(v[246] == 24);
+ assert_or_panic(v[247] == 25);
+ assert_or_panic(v[248] == 26);
+ assert_or_panic(v[249] == 27);
+ assert_or_panic(v[250] == 28);
+ assert_or_panic(v[251] == 29);
+ assert_or_panic(v[252] == 30);
+ assert_or_panic(v[253] == 31);
+ assert_or_panic(v[254] == 32);
+ assert_or_panic(v[255] == 33);
+ assert_or_panic(v[256] == 34);
+ assert_or_panic(v[257] == 35);
+ assert_or_panic(v[258] == 36);
+ assert_or_panic(v[259] == 37);
+ assert_or_panic(v[260] == 38);
+ assert_or_panic(v[261] == 39);
+ assert_or_panic(v[262] == 40);
+ assert_or_panic(v[263] == 41);
+ assert_or_panic(v[264] == 42);
+ assert_or_panic(v[265] == 43);
+ assert_or_panic(v[266] == 44);
+ assert_or_panic(v[267] == 45);
+ assert_or_panic(v[268] == 46);
+ assert_or_panic(v[269] == 47);
+ assert_or_panic(v[270] == 48);
+ assert_or_panic(v[271] == 49);
+ assert_or_panic(v[272] == 50);
+ assert_or_panic(v[273] == 51);
+ assert_or_panic(v[274] == 52);
+ assert_or_panic(v[275] == 53);
+ assert_or_panic(v[276] == 54);
+ assert_or_panic(v[277] == 55);
+ assert_or_panic(v[278] == 56);
+ assert_or_panic(v[279] == 57);
+ assert_or_panic(v[280] == 58);
+ assert_or_panic(v[281] == 59);
+ assert_or_panic(v[282] == 60);
+ assert_or_panic(v[283] == 61);
+ assert_or_panic(v[284] == 62);
+ assert_or_panic(v[285] == 63);
+ assert_or_panic(v[286] == 64);
+ assert_or_panic(v[287] == 65);
+ assert_or_panic(v[288] == 66);
+ assert_or_panic(v[289] == 67);
+ assert_or_panic(v[290] == 68);
+ assert_or_panic(v[291] == 69);
+ assert_or_panic(v[292] == 70);
+ assert_or_panic(v[293] == 71);
+ assert_or_panic(v[294] == 72);
+ assert_or_panic(v[295] == 73);
+ assert_or_panic(v[296] == 74);
+ assert_or_panic(v[297] == 75);
+ assert_or_panic(v[298] == 76);
+ assert_or_panic(v[299] == 77);
+ assert_or_panic(v[300] == 78);
+ assert_or_panic(v[301] == 79);
+ assert_or_panic(v[302] == 80);
+ assert_or_panic(v[303] == 81);
+ assert_or_panic(v[304] == 82);
+ assert_or_panic(v[305] == 83);
+ assert_or_panic(v[306] == 84);
+ assert_or_panic(v[307] == 85);
+ assert_or_panic(v[308] == 86);
+ assert_or_panic(v[309] == 87);
+ assert_or_panic(v[310] == 88);
+ assert_or_panic(v[311] == 89);
+ assert_or_panic(v[312] == 90);
+ assert_or_panic(v[313] == 91);
+ assert_or_panic(v[314] == 92);
+ assert_or_panic(v[315] == 93);
+ assert_or_panic(v[316] == 94);
+ assert_or_panic(v[317] == 95);
+ assert_or_panic(v[318] == 96);
+ assert_or_panic(v[319] == 97);
+ assert_or_panic(v[320] == 98);
+ assert_or_panic(v[321] == 99);
+ assert_or_panic(v[322] == 0);
+ assert_or_panic(v[323] == 1);
+ assert_or_panic(v[324] == 2);
+ assert_or_panic(v[325] == 3);
+ assert_or_panic(v[326] == 4);
+ assert_or_panic(v[327] == 5);
+ assert_or_panic(v[328] == 6);
+ assert_or_panic(v[329] == 7);
+ assert_or_panic(v[330] == 8);
+ assert_or_panic(v[331] == 9);
+ assert_or_panic(v[332] == 10);
+ assert_or_panic(v[333] == 11);
+ assert_or_panic(v[334] == 12);
+ assert_or_panic(v[335] == 13);
+ assert_or_panic(v[336] == 14);
+ assert_or_panic(v[337] == 15);
+ assert_or_panic(v[338] == 16);
+ assert_or_panic(v[339] == 17);
+ assert_or_panic(v[340] == 18);
+ assert_or_panic(v[341] == 19);
+ assert_or_panic(v[342] == 20);
+ assert_or_panic(v[343] == 21);
+ assert_or_panic(v[344] == 22);
+ assert_or_panic(v[345] == 23);
+ assert_or_panic(v[346] == 24);
+ assert_or_panic(v[347] == 25);
+ assert_or_panic(v[348] == 26);
+ assert_or_panic(v[349] == 27);
+ assert_or_panic(v[350] == 28);
+ assert_or_panic(v[351] == 29);
+ assert_or_panic(v[352] == 30);
+ assert_or_panic(v[353] == 31);
+ assert_or_panic(v[354] == 32);
+ assert_or_panic(v[355] == 33);
+ assert_or_panic(v[356] == 34);
+ assert_or_panic(v[357] == 35);
+ assert_or_panic(v[358] == 36);
+ assert_or_panic(v[359] == 37);
+ assert_or_panic(v[360] == 38);
+ assert_or_panic(v[361] == 39);
+ assert_or_panic(v[362] == 40);
+ assert_or_panic(v[363] == 41);
+ assert_or_panic(v[364] == 42);
+ assert_or_panic(v[365] == 43);
+ assert_or_panic(v[366] == 44);
+ assert_or_panic(v[367] == 45);
+ assert_or_panic(v[368] == 46);
+ assert_or_panic(v[369] == 47);
+ assert_or_panic(v[370] == 48);
+ assert_or_panic(v[371] == 49);
+ assert_or_panic(v[372] == 50);
+ assert_or_panic(v[373] == 51);
+ assert_or_panic(v[374] == 52);
+ assert_or_panic(v[375] == 53);
+ assert_or_panic(v[376] == 54);
+ assert_or_panic(v[377] == 55);
+ assert_or_panic(v[378] == 56);
+ assert_or_panic(v[379] == 57);
+ assert_or_panic(v[380] == 58);
+ assert_or_panic(v[381] == 59);
+ assert_or_panic(v[382] == 60);
+ assert_or_panic(v[383] == 61);
+ zig_vector_384_u8((Vector_384_u8){
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ }, 384);
+}
+
+typedef uint8_t Vector_512_u8 __attribute__((vector_size(512 * sizeof(uint8_t))));
+
+Vector_512_u8 zig_ret_vector_512_u8(void);
+void zig_vector_512_u8(Vector_512_u8, size_t);
+
+Vector_512_u8 c_ret_vector_512_u8(void) {
+ return (Vector_512_u8){
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ };
+}
+void c_vector_512_u8(Vector_512_u8 v, size_t i) {
+ assert_or_panic(v[0] == 50);
+ assert_or_panic(v[1] == 51);
+ assert_or_panic(v[2] == 52);
+ assert_or_panic(v[3] == 53);
+ assert_or_panic(v[4] == 54);
+ assert_or_panic(v[5] == 55);
+ assert_or_panic(v[6] == 56);
+ assert_or_panic(v[7] == 57);
+ assert_or_panic(v[8] == 58);
+ assert_or_panic(v[9] == 59);
+ assert_or_panic(v[10] == 60);
+ assert_or_panic(v[11] == 61);
+ assert_or_panic(v[12] == 62);
+ assert_or_panic(v[13] == 63);
+ assert_or_panic(v[14] == 64);
+ assert_or_panic(v[15] == 65);
+ assert_or_panic(v[16] == 66);
+ assert_or_panic(v[17] == 67);
+ assert_or_panic(v[18] == 68);
+ assert_or_panic(v[19] == 69);
+ assert_or_panic(v[20] == 70);
+ assert_or_panic(v[21] == 71);
+ assert_or_panic(v[22] == 72);
+ assert_or_panic(v[23] == 73);
+ assert_or_panic(v[24] == 74);
+ assert_or_panic(v[25] == 75);
+ assert_or_panic(v[26] == 76);
+ assert_or_panic(v[27] == 77);
+ assert_or_panic(v[28] == 78);
+ assert_or_panic(v[29] == 79);
+ assert_or_panic(v[30] == 80);
+ assert_or_panic(v[31] == 81);
+ assert_or_panic(v[32] == 82);
+ assert_or_panic(v[33] == 83);
+ assert_or_panic(v[34] == 84);
+ assert_or_panic(v[35] == 85);
+ assert_or_panic(v[36] == 86);
+ assert_or_panic(v[37] == 87);
+ assert_or_panic(v[38] == 88);
+ assert_or_panic(v[39] == 89);
+ assert_or_panic(v[40] == 90);
+ assert_or_panic(v[41] == 91);
+ assert_or_panic(v[42] == 92);
+ assert_or_panic(v[43] == 93);
+ assert_or_panic(v[44] == 94);
+ assert_or_panic(v[45] == 95);
+ assert_or_panic(v[46] == 96);
+ assert_or_panic(v[47] == 97);
+ assert_or_panic(v[48] == 98);
+ assert_or_panic(v[49] == 99);
+ assert_or_panic(v[50] == 0);
+ assert_or_panic(v[51] == 1);
+ assert_or_panic(v[52] == 2);
+ assert_or_panic(v[53] == 3);
+ assert_or_panic(v[54] == 4);
+ assert_or_panic(v[55] == 5);
+ assert_or_panic(v[56] == 6);
+ assert_or_panic(v[57] == 7);
+ assert_or_panic(v[58] == 8);
+ assert_or_panic(v[59] == 9);
+ assert_or_panic(v[60] == 10);
+ assert_or_panic(v[61] == 11);
+ assert_or_panic(v[62] == 12);
+ assert_or_panic(v[63] == 13);
+ assert_or_panic(v[64] == 14);
+ assert_or_panic(v[65] == 15);
+ assert_or_panic(v[66] == 16);
+ assert_or_panic(v[67] == 17);
+ assert_or_panic(v[68] == 18);
+ assert_or_panic(v[69] == 19);
+ assert_or_panic(v[70] == 20);
+ assert_or_panic(v[71] == 21);
+ assert_or_panic(v[72] == 22);
+ assert_or_panic(v[73] == 23);
+ assert_or_panic(v[74] == 24);
+ assert_or_panic(v[75] == 25);
+ assert_or_panic(v[76] == 26);
+ assert_or_panic(v[77] == 27);
+ assert_or_panic(v[78] == 28);
+ assert_or_panic(v[79] == 29);
+ assert_or_panic(v[80] == 30);
+ assert_or_panic(v[81] == 31);
+ assert_or_panic(v[82] == 32);
+ assert_or_panic(v[83] == 33);
+ assert_or_panic(v[84] == 34);
+ assert_or_panic(v[85] == 35);
+ assert_or_panic(v[86] == 36);
+ assert_or_panic(v[87] == 37);
+ assert_or_panic(v[88] == 38);
+ assert_or_panic(v[89] == 39);
+ assert_or_panic(v[90] == 40);
+ assert_or_panic(v[91] == 41);
+ assert_or_panic(v[92] == 42);
+ assert_or_panic(v[93] == 43);
+ assert_or_panic(v[94] == 44);
+ assert_or_panic(v[95] == 45);
+ assert_or_panic(v[96] == 46);
+ assert_or_panic(v[97] == 47);
+ assert_or_panic(v[98] == 48);
+ assert_or_panic(v[99] == 49);
+ assert_or_panic(v[100] == 50);
+ assert_or_panic(v[101] == 51);
+ assert_or_panic(v[102] == 52);
+ assert_or_panic(v[103] == 53);
+ assert_or_panic(v[104] == 54);
+ assert_or_panic(v[105] == 55);
+ assert_or_panic(v[106] == 56);
+ assert_or_panic(v[107] == 57);
+ assert_or_panic(v[108] == 58);
+ assert_or_panic(v[109] == 59);
+ assert_or_panic(v[110] == 60);
+ assert_or_panic(v[111] == 61);
+ assert_or_panic(v[112] == 62);
+ assert_or_panic(v[113] == 63);
+ assert_or_panic(v[114] == 64);
+ assert_or_panic(v[115] == 65);
+ assert_or_panic(v[116] == 66);
+ assert_or_panic(v[117] == 67);
+ assert_or_panic(v[118] == 68);
+ assert_or_panic(v[119] == 69);
+ assert_or_panic(v[120] == 70);
+ assert_or_panic(v[121] == 71);
+ assert_or_panic(v[122] == 72);
+ assert_or_panic(v[123] == 73);
+ assert_or_panic(v[124] == 74);
+ assert_or_panic(v[125] == 75);
+ assert_or_panic(v[126] == 76);
+ assert_or_panic(v[127] == 77);
+ assert_or_panic(v[128] == 78);
+ assert_or_panic(v[129] == 79);
+ assert_or_panic(v[130] == 80);
+ assert_or_panic(v[131] == 81);
+ assert_or_panic(v[132] == 82);
+ assert_or_panic(v[133] == 83);
+ assert_or_panic(v[134] == 84);
+ assert_or_panic(v[135] == 85);
+ assert_or_panic(v[136] == 86);
+ assert_or_panic(v[137] == 87);
+ assert_or_panic(v[138] == 88);
+ assert_or_panic(v[139] == 89);
+ assert_or_panic(v[140] == 90);
+ assert_or_panic(v[141] == 91);
+ assert_or_panic(v[142] == 92);
+ assert_or_panic(v[143] == 93);
+ assert_or_panic(v[144] == 94);
+ assert_or_panic(v[145] == 95);
+ assert_or_panic(v[146] == 96);
+ assert_or_panic(v[147] == 97);
+ assert_or_panic(v[148] == 98);
+ assert_or_panic(v[149] == 99);
+ assert_or_panic(v[150] == 0);
+ assert_or_panic(v[151] == 1);
+ assert_or_panic(v[152] == 2);
+ assert_or_panic(v[153] == 3);
+ assert_or_panic(v[154] == 4);
+ assert_or_panic(v[155] == 5);
+ assert_or_panic(v[156] == 6);
+ assert_or_panic(v[157] == 7);
+ assert_or_panic(v[158] == 8);
+ assert_or_panic(v[159] == 9);
+ assert_or_panic(v[160] == 10);
+ assert_or_panic(v[161] == 11);
+ assert_or_panic(v[162] == 12);
+ assert_or_panic(v[163] == 13);
+ assert_or_panic(v[164] == 14);
+ assert_or_panic(v[165] == 15);
+ assert_or_panic(v[166] == 16);
+ assert_or_panic(v[167] == 17);
+ assert_or_panic(v[168] == 18);
+ assert_or_panic(v[169] == 19);
+ assert_or_panic(v[170] == 20);
+ assert_or_panic(v[171] == 21);
+ assert_or_panic(v[172] == 22);
+ assert_or_panic(v[173] == 23);
+ assert_or_panic(v[174] == 24);
+ assert_or_panic(v[175] == 25);
+ assert_or_panic(v[176] == 26);
+ assert_or_panic(v[177] == 27);
+ assert_or_panic(v[178] == 28);
+ assert_or_panic(v[179] == 29);
+ assert_or_panic(v[180] == 30);
+ assert_or_panic(v[181] == 31);
+ assert_or_panic(v[182] == 32);
+ assert_or_panic(v[183] == 33);
+ assert_or_panic(v[184] == 34);
+ assert_or_panic(v[185] == 35);
+ assert_or_panic(v[186] == 36);
+ assert_or_panic(v[187] == 37);
+ assert_or_panic(v[188] == 38);
+ assert_or_panic(v[189] == 39);
+ assert_or_panic(v[190] == 40);
+ assert_or_panic(v[191] == 41);
+ assert_or_panic(v[192] == 42);
+ assert_or_panic(v[193] == 43);
+ assert_or_panic(v[194] == 44);
+ assert_or_panic(v[195] == 45);
+ assert_or_panic(v[196] == 46);
+ assert_or_panic(v[197] == 47);
+ assert_or_panic(v[198] == 48);
+ assert_or_panic(v[199] == 49);
+ assert_or_panic(v[200] == 50);
+ assert_or_panic(v[201] == 51);
+ assert_or_panic(v[202] == 52);
+ assert_or_panic(v[203] == 53);
+ assert_or_panic(v[204] == 54);
+ assert_or_panic(v[205] == 55);
+ assert_or_panic(v[206] == 56);
+ assert_or_panic(v[207] == 57);
+ assert_or_panic(v[208] == 58);
+ assert_or_panic(v[209] == 59);
+ assert_or_panic(v[210] == 60);
+ assert_or_panic(v[211] == 61);
+ assert_or_panic(v[212] == 62);
+ assert_or_panic(v[213] == 63);
+ assert_or_panic(v[214] == 64);
+ assert_or_panic(v[215] == 65);
+ assert_or_panic(v[216] == 66);
+ assert_or_panic(v[217] == 67);
+ assert_or_panic(v[218] == 68);
+ assert_or_panic(v[219] == 69);
+ assert_or_panic(v[220] == 70);
+ assert_or_panic(v[221] == 71);
+ assert_or_panic(v[222] == 72);
+ assert_or_panic(v[223] == 73);
+ assert_or_panic(v[224] == 74);
+ assert_or_panic(v[225] == 75);
+ assert_or_panic(v[226] == 76);
+ assert_or_panic(v[227] == 77);
+ assert_or_panic(v[228] == 78);
+ assert_or_panic(v[229] == 79);
+ assert_or_panic(v[230] == 80);
+ assert_or_panic(v[231] == 81);
+ assert_or_panic(v[232] == 82);
+ assert_or_panic(v[233] == 83);
+ assert_or_panic(v[234] == 84);
+ assert_or_panic(v[235] == 85);
+ assert_or_panic(v[236] == 86);
+ assert_or_panic(v[237] == 87);
+ assert_or_panic(v[238] == 88);
+ assert_or_panic(v[239] == 89);
+ assert_or_panic(v[240] == 90);
+ assert_or_panic(v[241] == 91);
+ assert_or_panic(v[242] == 92);
+ assert_or_panic(v[243] == 93);
+ assert_or_panic(v[244] == 94);
+ assert_or_panic(v[245] == 95);
+ assert_or_panic(v[246] == 96);
+ assert_or_panic(v[247] == 97);
+ assert_or_panic(v[248] == 98);
+ assert_or_panic(v[249] == 99);
+ assert_or_panic(v[250] == 0);
+ assert_or_panic(v[251] == 1);
+ assert_or_panic(v[252] == 2);
+ assert_or_panic(v[253] == 3);
+ assert_or_panic(v[254] == 4);
+ assert_or_panic(v[255] == 5);
+ assert_or_panic(v[256] == 6);
+ assert_or_panic(v[257] == 7);
+ assert_or_panic(v[258] == 8);
+ assert_or_panic(v[259] == 9);
+ assert_or_panic(v[260] == 10);
+ assert_or_panic(v[261] == 11);
+ assert_or_panic(v[262] == 12);
+ assert_or_panic(v[263] == 13);
+ assert_or_panic(v[264] == 14);
+ assert_or_panic(v[265] == 15);
+ assert_or_panic(v[266] == 16);
+ assert_or_panic(v[267] == 17);
+ assert_or_panic(v[268] == 18);
+ assert_or_panic(v[269] == 19);
+ assert_or_panic(v[270] == 20);
+ assert_or_panic(v[271] == 21);
+ assert_or_panic(v[272] == 22);
+ assert_or_panic(v[273] == 23);
+ assert_or_panic(v[274] == 24);
+ assert_or_panic(v[275] == 25);
+ assert_or_panic(v[276] == 26);
+ assert_or_panic(v[277] == 27);
+ assert_or_panic(v[278] == 28);
+ assert_or_panic(v[279] == 29);
+ assert_or_panic(v[280] == 30);
+ assert_or_panic(v[281] == 31);
+ assert_or_panic(v[282] == 32);
+ assert_or_panic(v[283] == 33);
+ assert_or_panic(v[284] == 34);
+ assert_or_panic(v[285] == 35);
+ assert_or_panic(v[286] == 36);
+ assert_or_panic(v[287] == 37);
+ assert_or_panic(v[288] == 38);
+ assert_or_panic(v[289] == 39);
+ assert_or_panic(v[290] == 40);
+ assert_or_panic(v[291] == 41);
+ assert_or_panic(v[292] == 42);
+ assert_or_panic(v[293] == 43);
+ assert_or_panic(v[294] == 44);
+ assert_or_panic(v[295] == 45);
+ assert_or_panic(v[296] == 46);
+ assert_or_panic(v[297] == 47);
+ assert_or_panic(v[298] == 48);
+ assert_or_panic(v[299] == 49);
+ assert_or_panic(v[300] == 50);
+ assert_or_panic(v[301] == 51);
+ assert_or_panic(v[302] == 52);
+ assert_or_panic(v[303] == 53);
+ assert_or_panic(v[304] == 54);
+ assert_or_panic(v[305] == 55);
+ assert_or_panic(v[306] == 56);
+ assert_or_panic(v[307] == 57);
+ assert_or_panic(v[308] == 58);
+ assert_or_panic(v[309] == 59);
+ assert_or_panic(v[310] == 60);
+ assert_or_panic(v[311] == 61);
+ assert_or_panic(v[312] == 62);
+ assert_or_panic(v[313] == 63);
+ assert_or_panic(v[314] == 64);
+ assert_or_panic(v[315] == 65);
+ assert_or_panic(v[316] == 66);
+ assert_or_panic(v[317] == 67);
+ assert_or_panic(v[318] == 68);
+ assert_or_panic(v[319] == 69);
+ assert_or_panic(v[320] == 70);
+ assert_or_panic(v[321] == 71);
+ assert_or_panic(v[322] == 72);
+ assert_or_panic(v[323] == 73);
+ assert_or_panic(v[324] == 74);
+ assert_or_panic(v[325] == 75);
+ assert_or_panic(v[326] == 76);
+ assert_or_panic(v[327] == 77);
+ assert_or_panic(v[328] == 78);
+ assert_or_panic(v[329] == 79);
+ assert_or_panic(v[330] == 80);
+ assert_or_panic(v[331] == 81);
+ assert_or_panic(v[332] == 82);
+ assert_or_panic(v[333] == 83);
+ assert_or_panic(v[334] == 84);
+ assert_or_panic(v[335] == 85);
+ assert_or_panic(v[336] == 86);
+ assert_or_panic(v[337] == 87);
+ assert_or_panic(v[338] == 88);
+ assert_or_panic(v[339] == 89);
+ assert_or_panic(v[340] == 90);
+ assert_or_panic(v[341] == 91);
+ assert_or_panic(v[342] == 92);
+ assert_or_panic(v[343] == 93);
+ assert_or_panic(v[344] == 94);
+ assert_or_panic(v[345] == 95);
+ assert_or_panic(v[346] == 96);
+ assert_or_panic(v[347] == 97);
+ assert_or_panic(v[348] == 98);
+ assert_or_panic(v[349] == 99);
+ assert_or_panic(v[350] == 0);
+ assert_or_panic(v[351] == 1);
+ assert_or_panic(v[352] == 2);
+ assert_or_panic(v[353] == 3);
+ assert_or_panic(v[354] == 4);
+ assert_or_panic(v[355] == 5);
+ assert_or_panic(v[356] == 6);
+ assert_or_panic(v[357] == 7);
+ assert_or_panic(v[358] == 8);
+ assert_or_panic(v[359] == 9);
+ assert_or_panic(v[360] == 10);
+ assert_or_panic(v[361] == 11);
+ assert_or_panic(v[362] == 12);
+ assert_or_panic(v[363] == 13);
+ assert_or_panic(v[364] == 14);
+ assert_or_panic(v[365] == 15);
+ assert_or_panic(v[366] == 16);
+ assert_or_panic(v[367] == 17);
+ assert_or_panic(v[368] == 18);
+ assert_or_panic(v[369] == 19);
+ assert_or_panic(v[370] == 20);
+ assert_or_panic(v[371] == 21);
+ assert_or_panic(v[372] == 22);
+ assert_or_panic(v[373] == 23);
+ assert_or_panic(v[374] == 24);
+ assert_or_panic(v[375] == 25);
+ assert_or_panic(v[376] == 26);
+ assert_or_panic(v[377] == 27);
+ assert_or_panic(v[378] == 28);
+ assert_or_panic(v[379] == 29);
+ assert_or_panic(v[380] == 30);
+ assert_or_panic(v[381] == 31);
+ assert_or_panic(v[382] == 32);
+ assert_or_panic(v[383] == 33);
+ assert_or_panic(v[384] == 34);
+ assert_or_panic(v[385] == 35);
+ assert_or_panic(v[386] == 36);
+ assert_or_panic(v[387] == 37);
+ assert_or_panic(v[388] == 38);
+ assert_or_panic(v[389] == 39);
+ assert_or_panic(v[390] == 40);
+ assert_or_panic(v[391] == 41);
+ assert_or_panic(v[392] == 42);
+ assert_or_panic(v[393] == 43);
+ assert_or_panic(v[394] == 44);
+ assert_or_panic(v[395] == 45);
+ assert_or_panic(v[396] == 46);
+ assert_or_panic(v[397] == 47);
+ assert_or_panic(v[398] == 48);
+ assert_or_panic(v[399] == 49);
+ assert_or_panic(v[400] == 50);
+ assert_or_panic(v[401] == 51);
+ assert_or_panic(v[402] == 52);
+ assert_or_panic(v[403] == 53);
+ assert_or_panic(v[404] == 54);
+ assert_or_panic(v[405] == 55);
+ assert_or_panic(v[406] == 56);
+ assert_or_panic(v[407] == 57);
+ assert_or_panic(v[408] == 58);
+ assert_or_panic(v[409] == 59);
+ assert_or_panic(v[410] == 60);
+ assert_or_panic(v[411] == 61);
+ assert_or_panic(v[412] == 62);
+ assert_or_panic(v[413] == 63);
+ assert_or_panic(v[414] == 64);
+ assert_or_panic(v[415] == 65);
+ assert_or_panic(v[416] == 66);
+ assert_or_panic(v[417] == 67);
+ assert_or_panic(v[418] == 68);
+ assert_or_panic(v[419] == 69);
+ assert_or_panic(v[420] == 70);
+ assert_or_panic(v[421] == 71);
+ assert_or_panic(v[422] == 72);
+ assert_or_panic(v[423] == 73);
+ assert_or_panic(v[424] == 74);
+ assert_or_panic(v[425] == 75);
+ assert_or_panic(v[426] == 76);
+ assert_or_panic(v[427] == 77);
+ assert_or_panic(v[428] == 78);
+ assert_or_panic(v[429] == 79);
+ assert_or_panic(v[430] == 80);
+ assert_or_panic(v[431] == 81);
+ assert_or_panic(v[432] == 82);
+ assert_or_panic(v[433] == 83);
+ assert_or_panic(v[434] == 84);
+ assert_or_panic(v[435] == 85);
+ assert_or_panic(v[436] == 86);
+ assert_or_panic(v[437] == 87);
+ assert_or_panic(v[438] == 88);
+ assert_or_panic(v[439] == 89);
+ assert_or_panic(v[440] == 90);
+ assert_or_panic(v[441] == 91);
+ assert_or_panic(v[442] == 92);
+ assert_or_panic(v[443] == 93);
+ assert_or_panic(v[444] == 94);
+ assert_or_panic(v[445] == 95);
+ assert_or_panic(v[446] == 96);
+ assert_or_panic(v[447] == 97);
+ assert_or_panic(v[448] == 98);
+ assert_or_panic(v[449] == 99);
+ assert_or_panic(v[450] == 0);
+ assert_or_panic(v[451] == 1);
+ assert_or_panic(v[452] == 2);
+ assert_or_panic(v[453] == 3);
+ assert_or_panic(v[454] == 4);
+ assert_or_panic(v[455] == 5);
+ assert_or_panic(v[456] == 6);
+ assert_or_panic(v[457] == 7);
+ assert_or_panic(v[458] == 8);
+ assert_or_panic(v[459] == 9);
+ assert_or_panic(v[460] == 10);
+ assert_or_panic(v[461] == 11);
+ assert_or_panic(v[462] == 12);
+ assert_or_panic(v[463] == 13);
+ assert_or_panic(v[464] == 14);
+ assert_or_panic(v[465] == 15);
+ assert_or_panic(v[466] == 16);
+ assert_or_panic(v[467] == 17);
+ assert_or_panic(v[468] == 18);
+ assert_or_panic(v[469] == 19);
+ assert_or_panic(v[470] == 20);
+ assert_or_panic(v[471] == 21);
+ assert_or_panic(v[472] == 22);
+ assert_or_panic(v[473] == 23);
+ assert_or_panic(v[474] == 24);
+ assert_or_panic(v[475] == 25);
+ assert_or_panic(v[476] == 26);
+ assert_or_panic(v[477] == 27);
+ assert_or_panic(v[478] == 28);
+ assert_or_panic(v[479] == 29);
+ assert_or_panic(v[480] == 30);
+ assert_or_panic(v[481] == 31);
+ assert_or_panic(v[482] == 32);
+ assert_or_panic(v[483] == 33);
+ assert_or_panic(v[484] == 34);
+ assert_or_panic(v[485] == 35);
+ assert_or_panic(v[486] == 36);
+ assert_or_panic(v[487] == 37);
+ assert_or_panic(v[488] == 38);
+ assert_or_panic(v[489] == 39);
+ assert_or_panic(v[490] == 40);
+ assert_or_panic(v[491] == 41);
+ assert_or_panic(v[492] == 42);
+ assert_or_panic(v[493] == 43);
+ assert_or_panic(v[494] == 44);
+ assert_or_panic(v[495] == 45);
+ assert_or_panic(v[496] == 46);
+ assert_or_panic(v[497] == 47);
+ assert_or_panic(v[498] == 48);
+ assert_or_panic(v[499] == 49);
+ assert_or_panic(v[500] == 50);
+ assert_or_panic(v[501] == 51);
+ assert_or_panic(v[502] == 52);
+ assert_or_panic(v[503] == 53);
+ assert_or_panic(v[504] == 54);
+ assert_or_panic(v[505] == 55);
+ assert_or_panic(v[506] == 56);
+ assert_or_panic(v[507] == 57);
+ assert_or_panic(v[508] == 58);
+ assert_or_panic(v[509] == 59);
+ assert_or_panic(v[510] == 60);
+ assert_or_panic(v[511] == 61);
+ assert_or_panic(i == 512);
+}
+void c_test_vector_512_u8(void) {
+ Vector_512_u8 v = zig_ret_vector_512_u8();
+ assert_or_panic(v[0] == 14);
+ assert_or_panic(v[1] == 15);
+ assert_or_panic(v[2] == 16);
+ assert_or_panic(v[3] == 17);
+ assert_or_panic(v[4] == 18);
+ assert_or_panic(v[5] == 19);
+ assert_or_panic(v[6] == 20);
+ assert_or_panic(v[7] == 21);
+ assert_or_panic(v[8] == 22);
+ assert_or_panic(v[9] == 23);
+ assert_or_panic(v[10] == 24);
+ assert_or_panic(v[11] == 25);
+ assert_or_panic(v[12] == 26);
+ assert_or_panic(v[13] == 27);
+ assert_or_panic(v[14] == 28);
+ assert_or_panic(v[15] == 29);
+ assert_or_panic(v[16] == 30);
+ assert_or_panic(v[17] == 31);
+ assert_or_panic(v[18] == 32);
+ assert_or_panic(v[19] == 33);
+ assert_or_panic(v[20] == 34);
+ assert_or_panic(v[21] == 35);
+ assert_or_panic(v[22] == 36);
+ assert_or_panic(v[23] == 37);
+ assert_or_panic(v[24] == 38);
+ assert_or_panic(v[25] == 39);
+ assert_or_panic(v[26] == 40);
+ assert_or_panic(v[27] == 41);
+ assert_or_panic(v[28] == 42);
+ assert_or_panic(v[29] == 43);
+ assert_or_panic(v[30] == 44);
+ assert_or_panic(v[31] == 45);
+ assert_or_panic(v[32] == 46);
+ assert_or_panic(v[33] == 47);
+ assert_or_panic(v[34] == 48);
+ assert_or_panic(v[35] == 49);
+ assert_or_panic(v[36] == 50);
+ assert_or_panic(v[37] == 51);
+ assert_or_panic(v[38] == 52);
+ assert_or_panic(v[39] == 53);
+ assert_or_panic(v[40] == 54);
+ assert_or_panic(v[41] == 55);
+ assert_or_panic(v[42] == 56);
+ assert_or_panic(v[43] == 57);
+ assert_or_panic(v[44] == 58);
+ assert_or_panic(v[45] == 59);
+ assert_or_panic(v[46] == 60);
+ assert_or_panic(v[47] == 61);
+ assert_or_panic(v[48] == 62);
+ assert_or_panic(v[49] == 63);
+ assert_or_panic(v[50] == 64);
+ assert_or_panic(v[51] == 65);
+ assert_or_panic(v[52] == 66);
+ assert_or_panic(v[53] == 67);
+ assert_or_panic(v[54] == 68);
+ assert_or_panic(v[55] == 69);
+ assert_or_panic(v[56] == 70);
+ assert_or_panic(v[57] == 71);
+ assert_or_panic(v[58] == 72);
+ assert_or_panic(v[59] == 73);
+ assert_or_panic(v[60] == 74);
+ assert_or_panic(v[61] == 75);
+ assert_or_panic(v[62] == 76);
+ assert_or_panic(v[63] == 77);
+ assert_or_panic(v[64] == 78);
+ assert_or_panic(v[65] == 79);
+ assert_or_panic(v[66] == 80);
+ assert_or_panic(v[67] == 81);
+ assert_or_panic(v[68] == 82);
+ assert_or_panic(v[69] == 83);
+ assert_or_panic(v[70] == 84);
+ assert_or_panic(v[71] == 85);
+ assert_or_panic(v[72] == 86);
+ assert_or_panic(v[73] == 87);
+ assert_or_panic(v[74] == 88);
+ assert_or_panic(v[75] == 89);
+ assert_or_panic(v[76] == 90);
+ assert_or_panic(v[77] == 91);
+ assert_or_panic(v[78] == 92);
+ assert_or_panic(v[79] == 93);
+ assert_or_panic(v[80] == 94);
+ assert_or_panic(v[81] == 95);
+ assert_or_panic(v[82] == 96);
+ assert_or_panic(v[83] == 97);
+ assert_or_panic(v[84] == 98);
+ assert_or_panic(v[85] == 99);
+ assert_or_panic(v[86] == 0);
+ assert_or_panic(v[87] == 1);
+ assert_or_panic(v[88] == 2);
+ assert_or_panic(v[89] == 3);
+ assert_or_panic(v[90] == 4);
+ assert_or_panic(v[91] == 5);
+ assert_or_panic(v[92] == 6);
+ assert_or_panic(v[93] == 7);
+ assert_or_panic(v[94] == 8);
+ assert_or_panic(v[95] == 9);
+ assert_or_panic(v[96] == 10);
+ assert_or_panic(v[97] == 11);
+ assert_or_panic(v[98] == 12);
+ assert_or_panic(v[99] == 13);
+ assert_or_panic(v[100] == 14);
+ assert_or_panic(v[101] == 15);
+ assert_or_panic(v[102] == 16);
+ assert_or_panic(v[103] == 17);
+ assert_or_panic(v[104] == 18);
+ assert_or_panic(v[105] == 19);
+ assert_or_panic(v[106] == 20);
+ assert_or_panic(v[107] == 21);
+ assert_or_panic(v[108] == 22);
+ assert_or_panic(v[109] == 23);
+ assert_or_panic(v[110] == 24);
+ assert_or_panic(v[111] == 25);
+ assert_or_panic(v[112] == 26);
+ assert_or_panic(v[113] == 27);
+ assert_or_panic(v[114] == 28);
+ assert_or_panic(v[115] == 29);
+ assert_or_panic(v[116] == 30);
+ assert_or_panic(v[117] == 31);
+ assert_or_panic(v[118] == 32);
+ assert_or_panic(v[119] == 33);
+ assert_or_panic(v[120] == 34);
+ assert_or_panic(v[121] == 35);
+ assert_or_panic(v[122] == 36);
+ assert_or_panic(v[123] == 37);
+ assert_or_panic(v[124] == 38);
+ assert_or_panic(v[125] == 39);
+ assert_or_panic(v[126] == 40);
+ assert_or_panic(v[127] == 41);
+ assert_or_panic(v[128] == 42);
+ assert_or_panic(v[129] == 43);
+ assert_or_panic(v[130] == 44);
+ assert_or_panic(v[131] == 45);
+ assert_or_panic(v[132] == 46);
+ assert_or_panic(v[133] == 47);
+ assert_or_panic(v[134] == 48);
+ assert_or_panic(v[135] == 49);
+ assert_or_panic(v[136] == 50);
+ assert_or_panic(v[137] == 51);
+ assert_or_panic(v[138] == 52);
+ assert_or_panic(v[139] == 53);
+ assert_or_panic(v[140] == 54);
+ assert_or_panic(v[141] == 55);
+ assert_or_panic(v[142] == 56);
+ assert_or_panic(v[143] == 57);
+ assert_or_panic(v[144] == 58);
+ assert_or_panic(v[145] == 59);
+ assert_or_panic(v[146] == 60);
+ assert_or_panic(v[147] == 61);
+ assert_or_panic(v[148] == 62);
+ assert_or_panic(v[149] == 63);
+ assert_or_panic(v[150] == 64);
+ assert_or_panic(v[151] == 65);
+ assert_or_panic(v[152] == 66);
+ assert_or_panic(v[153] == 67);
+ assert_or_panic(v[154] == 68);
+ assert_or_panic(v[155] == 69);
+ assert_or_panic(v[156] == 70);
+ assert_or_panic(v[157] == 71);
+ assert_or_panic(v[158] == 72);
+ assert_or_panic(v[159] == 73);
+ assert_or_panic(v[160] == 74);
+ assert_or_panic(v[161] == 75);
+ assert_or_panic(v[162] == 76);
+ assert_or_panic(v[163] == 77);
+ assert_or_panic(v[164] == 78);
+ assert_or_panic(v[165] == 79);
+ assert_or_panic(v[166] == 80);
+ assert_or_panic(v[167] == 81);
+ assert_or_panic(v[168] == 82);
+ assert_or_panic(v[169] == 83);
+ assert_or_panic(v[170] == 84);
+ assert_or_panic(v[171] == 85);
+ assert_or_panic(v[172] == 86);
+ assert_or_panic(v[173] == 87);
+ assert_or_panic(v[174] == 88);
+ assert_or_panic(v[175] == 89);
+ assert_or_panic(v[176] == 90);
+ assert_or_panic(v[177] == 91);
+ assert_or_panic(v[178] == 92);
+ assert_or_panic(v[179] == 93);
+ assert_or_panic(v[180] == 94);
+ assert_or_panic(v[181] == 95);
+ assert_or_panic(v[182] == 96);
+ assert_or_panic(v[183] == 97);
+ assert_or_panic(v[184] == 98);
+ assert_or_panic(v[185] == 99);
+ assert_or_panic(v[186] == 0);
+ assert_or_panic(v[187] == 1);
+ assert_or_panic(v[188] == 2);
+ assert_or_panic(v[189] == 3);
+ assert_or_panic(v[190] == 4);
+ assert_or_panic(v[191] == 5);
+ assert_or_panic(v[192] == 6);
+ assert_or_panic(v[193] == 7);
+ assert_or_panic(v[194] == 8);
+ assert_or_panic(v[195] == 9);
+ assert_or_panic(v[196] == 10);
+ assert_or_panic(v[197] == 11);
+ assert_or_panic(v[198] == 12);
+ assert_or_panic(v[199] == 13);
+ assert_or_panic(v[200] == 14);
+ assert_or_panic(v[201] == 15);
+ assert_or_panic(v[202] == 16);
+ assert_or_panic(v[203] == 17);
+ assert_or_panic(v[204] == 18);
+ assert_or_panic(v[205] == 19);
+ assert_or_panic(v[206] == 20);
+ assert_or_panic(v[207] == 21);
+ assert_or_panic(v[208] == 22);
+ assert_or_panic(v[209] == 23);
+ assert_or_panic(v[210] == 24);
+ assert_or_panic(v[211] == 25);
+ assert_or_panic(v[212] == 26);
+ assert_or_panic(v[213] == 27);
+ assert_or_panic(v[214] == 28);
+ assert_or_panic(v[215] == 29);
+ assert_or_panic(v[216] == 30);
+ assert_or_panic(v[217] == 31);
+ assert_or_panic(v[218] == 32);
+ assert_or_panic(v[219] == 33);
+ assert_or_panic(v[220] == 34);
+ assert_or_panic(v[221] == 35);
+ assert_or_panic(v[222] == 36);
+ assert_or_panic(v[223] == 37);
+ assert_or_panic(v[224] == 38);
+ assert_or_panic(v[225] == 39);
+ assert_or_panic(v[226] == 40);
+ assert_or_panic(v[227] == 41);
+ assert_or_panic(v[228] == 42);
+ assert_or_panic(v[229] == 43);
+ assert_or_panic(v[230] == 44);
+ assert_or_panic(v[231] == 45);
+ assert_or_panic(v[232] == 46);
+ assert_or_panic(v[233] == 47);
+ assert_or_panic(v[234] == 48);
+ assert_or_panic(v[235] == 49);
+ assert_or_panic(v[236] == 50);
+ assert_or_panic(v[237] == 51);
+ assert_or_panic(v[238] == 52);
+ assert_or_panic(v[239] == 53);
+ assert_or_panic(v[240] == 54);
+ assert_or_panic(v[241] == 55);
+ assert_or_panic(v[242] == 56);
+ assert_or_panic(v[243] == 57);
+ assert_or_panic(v[244] == 58);
+ assert_or_panic(v[245] == 59);
+ assert_or_panic(v[246] == 60);
+ assert_or_panic(v[247] == 61);
+ assert_or_panic(v[248] == 62);
+ assert_or_panic(v[249] == 63);
+ assert_or_panic(v[250] == 64);
+ assert_or_panic(v[251] == 65);
+ assert_or_panic(v[252] == 66);
+ assert_or_panic(v[253] == 67);
+ assert_or_panic(v[254] == 68);
+ assert_or_panic(v[255] == 69);
+ assert_or_panic(v[256] == 70);
+ assert_or_panic(v[257] == 71);
+ assert_or_panic(v[258] == 72);
+ assert_or_panic(v[259] == 73);
+ assert_or_panic(v[260] == 74);
+ assert_or_panic(v[261] == 75);
+ assert_or_panic(v[262] == 76);
+ assert_or_panic(v[263] == 77);
+ assert_or_panic(v[264] == 78);
+ assert_or_panic(v[265] == 79);
+ assert_or_panic(v[266] == 80);
+ assert_or_panic(v[267] == 81);
+ assert_or_panic(v[268] == 82);
+ assert_or_panic(v[269] == 83);
+ assert_or_panic(v[270] == 84);
+ assert_or_panic(v[271] == 85);
+ assert_or_panic(v[272] == 86);
+ assert_or_panic(v[273] == 87);
+ assert_or_panic(v[274] == 88);
+ assert_or_panic(v[275] == 89);
+ assert_or_panic(v[276] == 90);
+ assert_or_panic(v[277] == 91);
+ assert_or_panic(v[278] == 92);
+ assert_or_panic(v[279] == 93);
+ assert_or_panic(v[280] == 94);
+ assert_or_panic(v[281] == 95);
+ assert_or_panic(v[282] == 96);
+ assert_or_panic(v[283] == 97);
+ assert_or_panic(v[284] == 98);
+ assert_or_panic(v[285] == 99);
+ assert_or_panic(v[286] == 0);
+ assert_or_panic(v[287] == 1);
+ assert_or_panic(v[288] == 2);
+ assert_or_panic(v[289] == 3);
+ assert_or_panic(v[290] == 4);
+ assert_or_panic(v[291] == 5);
+ assert_or_panic(v[292] == 6);
+ assert_or_panic(v[293] == 7);
+ assert_or_panic(v[294] == 8);
+ assert_or_panic(v[295] == 9);
+ assert_or_panic(v[296] == 10);
+ assert_or_panic(v[297] == 11);
+ assert_or_panic(v[298] == 12);
+ assert_or_panic(v[299] == 13);
+ assert_or_panic(v[300] == 14);
+ assert_or_panic(v[301] == 15);
+ assert_or_panic(v[302] == 16);
+ assert_or_panic(v[303] == 17);
+ assert_or_panic(v[304] == 18);
+ assert_or_panic(v[305] == 19);
+ assert_or_panic(v[306] == 20);
+ assert_or_panic(v[307] == 21);
+ assert_or_panic(v[308] == 22);
+ assert_or_panic(v[309] == 23);
+ assert_or_panic(v[310] == 24);
+ assert_or_panic(v[311] == 25);
+ assert_or_panic(v[312] == 26);
+ assert_or_panic(v[313] == 27);
+ assert_or_panic(v[314] == 28);
+ assert_or_panic(v[315] == 29);
+ assert_or_panic(v[316] == 30);
+ assert_or_panic(v[317] == 31);
+ assert_or_panic(v[318] == 32);
+ assert_or_panic(v[319] == 33);
+ assert_or_panic(v[320] == 34);
+ assert_or_panic(v[321] == 35);
+ assert_or_panic(v[322] == 36);
+ assert_or_panic(v[323] == 37);
+ assert_or_panic(v[324] == 38);
+ assert_or_panic(v[325] == 39);
+ assert_or_panic(v[326] == 40);
+ assert_or_panic(v[327] == 41);
+ assert_or_panic(v[328] == 42);
+ assert_or_panic(v[329] == 43);
+ assert_or_panic(v[330] == 44);
+ assert_or_panic(v[331] == 45);
+ assert_or_panic(v[332] == 46);
+ assert_or_panic(v[333] == 47);
+ assert_or_panic(v[334] == 48);
+ assert_or_panic(v[335] == 49);
+ assert_or_panic(v[336] == 50);
+ assert_or_panic(v[337] == 51);
+ assert_or_panic(v[338] == 52);
+ assert_or_panic(v[339] == 53);
+ assert_or_panic(v[340] == 54);
+ assert_or_panic(v[341] == 55);
+ assert_or_panic(v[342] == 56);
+ assert_or_panic(v[343] == 57);
+ assert_or_panic(v[344] == 58);
+ assert_or_panic(v[345] == 59);
+ assert_or_panic(v[346] == 60);
+ assert_or_panic(v[347] == 61);
+ assert_or_panic(v[348] == 62);
+ assert_or_panic(v[349] == 63);
+ assert_or_panic(v[350] == 64);
+ assert_or_panic(v[351] == 65);
+ assert_or_panic(v[352] == 66);
+ assert_or_panic(v[353] == 67);
+ assert_or_panic(v[354] == 68);
+ assert_or_panic(v[355] == 69);
+ assert_or_panic(v[356] == 70);
+ assert_or_panic(v[357] == 71);
+ assert_or_panic(v[358] == 72);
+ assert_or_panic(v[359] == 73);
+ assert_or_panic(v[360] == 74);
+ assert_or_panic(v[361] == 75);
+ assert_or_panic(v[362] == 76);
+ assert_or_panic(v[363] == 77);
+ assert_or_panic(v[364] == 78);
+ assert_or_panic(v[365] == 79);
+ assert_or_panic(v[366] == 80);
+ assert_or_panic(v[367] == 81);
+ assert_or_panic(v[368] == 82);
+ assert_or_panic(v[369] == 83);
+ assert_or_panic(v[370] == 84);
+ assert_or_panic(v[371] == 85);
+ assert_or_panic(v[372] == 86);
+ assert_or_panic(v[373] == 87);
+ assert_or_panic(v[374] == 88);
+ assert_or_panic(v[375] == 89);
+ assert_or_panic(v[376] == 90);
+ assert_or_panic(v[377] == 91);
+ assert_or_panic(v[378] == 92);
+ assert_or_panic(v[379] == 93);
+ assert_or_panic(v[380] == 94);
+ assert_or_panic(v[381] == 95);
+ assert_or_panic(v[382] == 96);
+ assert_or_panic(v[383] == 97);
+ assert_or_panic(v[384] == 98);
+ assert_or_panic(v[385] == 99);
+ assert_or_panic(v[386] == 0);
+ assert_or_panic(v[387] == 1);
+ assert_or_panic(v[388] == 2);
+ assert_or_panic(v[389] == 3);
+ assert_or_panic(v[390] == 4);
+ assert_or_panic(v[391] == 5);
+ assert_or_panic(v[392] == 6);
+ assert_or_panic(v[393] == 7);
+ assert_or_panic(v[394] == 8);
+ assert_or_panic(v[395] == 9);
+ assert_or_panic(v[396] == 10);
+ assert_or_panic(v[397] == 11);
+ assert_or_panic(v[398] == 12);
+ assert_or_panic(v[399] == 13);
+ assert_or_panic(v[400] == 14);
+ assert_or_panic(v[401] == 15);
+ assert_or_panic(v[402] == 16);
+ assert_or_panic(v[403] == 17);
+ assert_or_panic(v[404] == 18);
+ assert_or_panic(v[405] == 19);
+ assert_or_panic(v[406] == 20);
+ assert_or_panic(v[407] == 21);
+ assert_or_panic(v[408] == 22);
+ assert_or_panic(v[409] == 23);
+ assert_or_panic(v[410] == 24);
+ assert_or_panic(v[411] == 25);
+ assert_or_panic(v[412] == 26);
+ assert_or_panic(v[413] == 27);
+ assert_or_panic(v[414] == 28);
+ assert_or_panic(v[415] == 29);
+ assert_or_panic(v[416] == 30);
+ assert_or_panic(v[417] == 31);
+ assert_or_panic(v[418] == 32);
+ assert_or_panic(v[419] == 33);
+ assert_or_panic(v[420] == 34);
+ assert_or_panic(v[421] == 35);
+ assert_or_panic(v[422] == 36);
+ assert_or_panic(v[423] == 37);
+ assert_or_panic(v[424] == 38);
+ assert_or_panic(v[425] == 39);
+ assert_or_panic(v[426] == 40);
+ assert_or_panic(v[427] == 41);
+ assert_or_panic(v[428] == 42);
+ assert_or_panic(v[429] == 43);
+ assert_or_panic(v[430] == 44);
+ assert_or_panic(v[431] == 45);
+ assert_or_panic(v[432] == 46);
+ assert_or_panic(v[433] == 47);
+ assert_or_panic(v[434] == 48);
+ assert_or_panic(v[435] == 49);
+ assert_or_panic(v[436] == 50);
+ assert_or_panic(v[437] == 51);
+ assert_or_panic(v[438] == 52);
+ assert_or_panic(v[439] == 53);
+ assert_or_panic(v[440] == 54);
+ assert_or_panic(v[441] == 55);
+ assert_or_panic(v[442] == 56);
+ assert_or_panic(v[443] == 57);
+ assert_or_panic(v[444] == 58);
+ assert_or_panic(v[445] == 59);
+ assert_or_panic(v[446] == 60);
+ assert_or_panic(v[447] == 61);
+ assert_or_panic(v[448] == 62);
+ assert_or_panic(v[449] == 63);
+ assert_or_panic(v[450] == 64);
+ assert_or_panic(v[451] == 65);
+ assert_or_panic(v[452] == 66);
+ assert_or_panic(v[453] == 67);
+ assert_or_panic(v[454] == 68);
+ assert_or_panic(v[455] == 69);
+ assert_or_panic(v[456] == 70);
+ assert_or_panic(v[457] == 71);
+ assert_or_panic(v[458] == 72);
+ assert_or_panic(v[459] == 73);
+ assert_or_panic(v[460] == 74);
+ assert_or_panic(v[461] == 75);
+ assert_or_panic(v[462] == 76);
+ assert_or_panic(v[463] == 77);
+ assert_or_panic(v[464] == 78);
+ assert_or_panic(v[465] == 79);
+ assert_or_panic(v[466] == 80);
+ assert_or_panic(v[467] == 81);
+ assert_or_panic(v[468] == 82);
+ assert_or_panic(v[469] == 83);
+ assert_or_panic(v[470] == 84);
+ assert_or_panic(v[471] == 85);
+ assert_or_panic(v[472] == 86);
+ assert_or_panic(v[473] == 87);
+ assert_or_panic(v[474] == 88);
+ assert_or_panic(v[475] == 89);
+ assert_or_panic(v[476] == 90);
+ assert_or_panic(v[477] == 91);
+ assert_or_panic(v[478] == 92);
+ assert_or_panic(v[479] == 93);
+ assert_or_panic(v[480] == 94);
+ assert_or_panic(v[481] == 95);
+ assert_or_panic(v[482] == 96);
+ assert_or_panic(v[483] == 97);
+ assert_or_panic(v[484] == 98);
+ assert_or_panic(v[485] == 99);
+ assert_or_panic(v[486] == 0);
+ assert_or_panic(v[487] == 1);
+ assert_or_panic(v[488] == 2);
+ assert_or_panic(v[489] == 3);
+ assert_or_panic(v[490] == 4);
+ assert_or_panic(v[491] == 5);
+ assert_or_panic(v[492] == 6);
+ assert_or_panic(v[493] == 7);
+ assert_or_panic(v[494] == 8);
+ assert_or_panic(v[495] == 9);
+ assert_or_panic(v[496] == 10);
+ assert_or_panic(v[497] == 11);
+ assert_or_panic(v[498] == 12);
+ assert_or_panic(v[499] == 13);
+ assert_or_panic(v[500] == 14);
+ assert_or_panic(v[501] == 15);
+ assert_or_panic(v[502] == 16);
+ assert_or_panic(v[503] == 17);
+ assert_or_panic(v[504] == 18);
+ assert_or_panic(v[505] == 19);
+ assert_or_panic(v[506] == 20);
+ assert_or_panic(v[507] == 21);
+ assert_or_panic(v[508] == 22);
+ assert_or_panic(v[509] == 23);
+ assert_or_panic(v[510] == 24);
+ assert_or_panic(v[511] == 25);
+ zig_vector_512_u8((Vector_512_u8){
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ }, 512);
+}
+
+typedef uint16_t Vector_1_u16 __attribute__((vector_size(1 * sizeof(uint16_t))));
+
+Vector_1_u16 zig_ret_vector_1_u16(void);
+void zig_vector_1_u16(Vector_1_u16, size_t);
+
+Vector_1_u16 c_ret_vector_1_u16(void) {
+ return (Vector_1_u16){ 3 };
+}
+void c_vector_1_u16(Vector_1_u16 v, size_t i) {
+ assert_or_panic(v[0] == 4);
+ assert_or_panic(i == 1);
+}
+void c_test_vector_1_u16(void) {
+ Vector_1_u16 v = zig_ret_vector_1_u16();
+ assert_or_panic(v[0] == 1);
+ zig_vector_1_u16((Vector_1_u16){ 2 }, 1);
+}
+
+typedef uint16_t Vector_2_u16 __attribute__((vector_size(2 * sizeof(uint16_t))));
+
+Vector_2_u16 zig_ret_vector_2_u16(void);
+void zig_vector_2_u16(Vector_2_u16, size_t);
+
+Vector_2_u16 c_ret_vector_2_u16(void) {
+ return (Vector_2_u16){ 9, 10 };
+}
+void c_vector_2_u16(Vector_2_u16 v, size_t i) {
+ assert_or_panic(v[0] == 11);
+ assert_or_panic(v[1] == 12);
+ assert_or_panic(i == 2);
+}
+void c_test_vector_2_u16(void) {
+ Vector_2_u16 v = zig_ret_vector_2_u16();
+ assert_or_panic(v[0] == 5);
+ assert_or_panic(v[1] == 6);
+ zig_vector_2_u16((Vector_2_u16){ 7, 8 }, 2);
+}
+
+typedef uint16_t Vector_3_u16 __attribute__((vector_size(3 * sizeof(uint16_t))));
+
+Vector_3_u16 zig_ret_vector_3_u16(void);
+void zig_vector_3_u16(Vector_3_u16, size_t);
+
+Vector_3_u16 c_ret_vector_3_u16(void) {
+ return (Vector_3_u16){ 19, 20, 21 };
+}
+void c_vector_3_u16(Vector_3_u16 v, size_t i) {
+ assert_or_panic(v[0] == 22);
+ assert_or_panic(v[1] == 23);
+ assert_or_panic(v[2] == 24);
+ assert_or_panic(i == 3);
+}
+void c_test_vector_3_u16(void) {
+ Vector_3_u16 v = zig_ret_vector_3_u16();
+ assert_or_panic(v[0] == 13);
+ assert_or_panic(v[1] == 14);
+ assert_or_panic(v[2] == 15);
+ zig_vector_3_u16((Vector_3_u16){ 16, 17, 18 }, 3);
+}
+
+typedef uint16_t Vector_4_u16 __attribute__((vector_size(4 * sizeof(uint16_t))));
+
+Vector_4_u16 zig_ret_vector_4_u16(void);
+
+void zig_vector_4_u16(Vector_4_u16, size_t);
+void zig_vector_4_u16_vector_4_u16(Vector_4_u16, Vector_4_u16, size_t);
+
+Vector_4_u16 c_ret_vector_4_u16(void) {
+ return (Vector_4_u16){ 41, 42, 43, 44 };
+}
+void c_vector_4_u16(Vector_4_u16 v, size_t i) {
+ assert_or_panic(v[0] == 45);
+ assert_or_panic(v[1] == 46);
+ assert_or_panic(v[2] == 47);
+ assert_or_panic(v[3] == 48);
+ assert_or_panic(i == 4);
+}
+void c_vector_4_u16_vector_4_u16(Vector_4_u16 v0, Vector_4_u16 v1, size_t i) {
+ assert_or_panic(v0[0] == 49);
+ assert_or_panic(v0[1] == 50);
+ assert_or_panic(v0[2] == 51);
+ assert_or_panic(v0[3] == 52);
+ assert_or_panic(v1[0] == 53);
+ assert_or_panic(v1[1] == 54);
+ assert_or_panic(v1[2] == 55);
+ assert_or_panic(v1[3] == 56);
+ assert_or_panic(i == 8);
+}
+void c_test_vector_4_u16(void) {
+ Vector_4_u16 v = zig_ret_vector_4_u16();
+ assert_or_panic(v[0] == 25);
+ assert_or_panic(v[1] == 26);
+ assert_or_panic(v[2] == 27);
+ assert_or_panic(v[3] == 28);
+ zig_vector_4_u16((Vector_4_u16){ 29, 30, 31, 32 }, 4);
+ zig_vector_4_u16_vector_4_u16((Vector_4_u16){ 33, 34, 35, 36 }, (Vector_4_u16){ 37, 38, 39, 40 }, 8);
+}
+
+typedef uint16_t Vector_6_u16 __attribute__((vector_size(6 * sizeof(uint16_t))));
+
+Vector_6_u16 zig_ret_vector_6_u16(void);
+void zig_vector_6_u16(Vector_6_u16, size_t);
+
+Vector_6_u16 c_ret_vector_6_u16(void) {
+ return (Vector_6_u16){ 53, 54, 55, 56, 57, 58 };
+}
+void c_vector_6_u16(Vector_6_u16 v, size_t i) {
+ assert_or_panic(v[0] == 59);
+ assert_or_panic(v[1] == 60);
+ assert_or_panic(v[2] == 61);
+ assert_or_panic(v[3] == 62);
+ assert_or_panic(v[4] == 63);
+ assert_or_panic(v[5] == 64);
+ assert_or_panic(i == 6);
+}
+void c_test_vector_6_u16(void) {
+ Vector_6_u16 v = zig_ret_vector_6_u16();
+ assert_or_panic(v[0] == 41);
+ assert_or_panic(v[1] == 42);
+ assert_or_panic(v[2] == 43);
+ assert_or_panic(v[3] == 44);
+ assert_or_panic(v[4] == 45);
+ assert_or_panic(v[5] == 46);
+ zig_vector_6_u16((Vector_6_u16){ 47, 48, 49, 50, 51, 52 }, 6);
+}
+
+typedef uint16_t Vector_8_u16 __attribute__((vector_size(8 * sizeof(uint16_t))));
+
+Vector_8_u16 zig_ret_vector_8_u16(void);
+void zig_vector_8_u16(Vector_8_u16, size_t);
+
+Vector_8_u16 c_ret_vector_8_u16(void) {
+ return (Vector_8_u16){ 81, 82, 83, 84, 85, 86, 87, 88 };
+}
+void c_vector_8_u16(Vector_8_u16 v, size_t i) {
+ assert_or_panic(v[0] == 89);
+ assert_or_panic(v[1] == 90);
+ assert_or_panic(v[2] == 91);
+ assert_or_panic(v[3] == 92);
+ assert_or_panic(v[4] == 93);
+ assert_or_panic(v[5] == 94);
+ assert_or_panic(v[6] == 95);
+ assert_or_panic(v[7] == 96);
+ assert_or_panic(i == 8);
+}
+void c_test_vector_8_u16(void) {
+ Vector_8_u16 v = zig_ret_vector_8_u16();
+ assert_or_panic(v[0] == 65);
+ assert_or_panic(v[1] == 66);
+ assert_or_panic(v[2] == 67);
+ assert_or_panic(v[3] == 68);
+ assert_or_panic(v[4] == 69);
+ assert_or_panic(v[5] == 70);
+ assert_or_panic(v[6] == 71);
+ assert_or_panic(v[7] == 72);
+ zig_vector_8_u16((Vector_8_u16){ 73, 74, 75, 76, 77, 78, 79, 80 }, 8);
+}
+
+typedef uint16_t Vector_12_u16 __attribute__((vector_size(12 * sizeof(uint16_t))));
+
+Vector_12_u16 zig_ret_vector_12_u16(void);
+void zig_vector_12_u16(Vector_12_u16, size_t);
+
+Vector_12_u16 c_ret_vector_12_u16(void) {
+ return (Vector_12_u16){ 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132 };
+}
+void c_vector_12_u16(Vector_12_u16 v, size_t i) {
+ assert_or_panic(v[0] == 133);
+ assert_or_panic(v[1] == 134);
+ assert_or_panic(v[2] == 135);
+ assert_or_panic(v[3] == 136);
+ assert_or_panic(v[4] == 137);
+ assert_or_panic(v[5] == 138);
+ assert_or_panic(v[6] == 139);
+ assert_or_panic(v[7] == 140);
+ assert_or_panic(v[8] == 141);
+ assert_or_panic(v[9] == 142);
+ assert_or_panic(v[10] == 143);
+ assert_or_panic(v[11] == 144);
+ assert_or_panic(i == 12);
+}
+void c_test_vector_12_u16(void) {
+ Vector_12_u16 v = zig_ret_vector_12_u16();
+ assert_or_panic(v[0] == 97);
+ assert_or_panic(v[1] == 98);
+ assert_or_panic(v[2] == 99);
+ assert_or_panic(v[3] == 100);
+ assert_or_panic(v[4] == 101);
+ assert_or_panic(v[5] == 102);
+ assert_or_panic(v[6] == 103);
+ assert_or_panic(v[7] == 104);
+ assert_or_panic(v[8] == 105);
+ assert_or_panic(v[9] == 106);
+ assert_or_panic(v[10] == 107);
+ assert_or_panic(v[11] == 108);
+ zig_vector_12_u16((Vector_12_u16){ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120 }, 12);
+}
+
+typedef uint16_t Vector_16_u16 __attribute__((vector_size(16 * sizeof(uint16_t))));
+
+Vector_16_u16 zig_ret_vector_16_u16(void);
+void zig_vector_16_u16(Vector_16_u16, size_t);
+
+Vector_16_u16 c_ret_vector_16_u16(void) {
+ return (Vector_16_u16){ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192 };
+}
+void c_vector_16_u16(Vector_16_u16 v, size_t i) {
+ assert_or_panic(v[0] == 193);
+ assert_or_panic(v[1] == 194);
+ assert_or_panic(v[2] == 195);
+ assert_or_panic(v[3] == 196);
+ assert_or_panic(v[4] == 197);
+ assert_or_panic(v[5] == 198);
+ assert_or_panic(v[6] == 199);
+ assert_or_panic(v[7] == 200);
+ assert_or_panic(v[8] == 201);
+ assert_or_panic(v[9] == 202);
+ assert_or_panic(v[10] == 203);
+ assert_or_panic(v[11] == 204);
+ assert_or_panic(v[12] == 205);
+ assert_or_panic(v[13] == 206);
+ assert_or_panic(v[14] == 207);
+ assert_or_panic(v[15] == 208);
+ assert_or_panic(i == 16);
+}
+void c_test_vector_16_u16(void) {
+ Vector_16_u16 v = zig_ret_vector_16_u16();
+ assert_or_panic(v[0] == 145);
+ assert_or_panic(v[1] == 146);
+ assert_or_panic(v[2] == 147);
+ assert_or_panic(v[3] == 148);
+ assert_or_panic(v[4] == 149);
+ assert_or_panic(v[5] == 150);
+ assert_or_panic(v[6] == 151);
+ assert_or_panic(v[7] == 152);
+ assert_or_panic(v[8] == 153);
+ assert_or_panic(v[9] == 154);
+ assert_or_panic(v[10] == 155);
+ assert_or_panic(v[11] == 156);
+ assert_or_panic(v[12] == 157);
+ assert_or_panic(v[13] == 158);
+ assert_or_panic(v[14] == 159);
+ assert_or_panic(v[15] == 160);
+ zig_vector_16_u16((Vector_16_u16){ 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176 }, 16);
+}
+
+typedef uint16_t Vector_24_u16 __attribute__((vector_size(24 * sizeof(uint16_t))));
+
+Vector_24_u16 zig_ret_vector_24_u16(void);
+void zig_vector_24_u16(Vector_24_u16, size_t);
+
+Vector_24_u16 c_ret_vector_24_u16(void) {
+ return (Vector_24_u16){
+ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
+ 273, 274, 275, 276, 277, 278, 279, 280,
+ };
+}
+void c_vector_24_u16(Vector_24_u16 v, size_t i) {
+ assert_or_panic(v[0] == 281);
+ assert_or_panic(v[1] == 282);
+ assert_or_panic(v[2] == 283);
+ assert_or_panic(v[3] == 284);
+ assert_or_panic(v[4] == 285);
+ assert_or_panic(v[5] == 286);
+ assert_or_panic(v[6] == 287);
+ assert_or_panic(v[7] == 288);
+ assert_or_panic(v[8] == 289);
+ assert_or_panic(v[9] == 290);
+ assert_or_panic(v[10] == 291);
+ assert_or_panic(v[11] == 292);
+ assert_or_panic(v[12] == 293);
+ assert_or_panic(v[13] == 294);
+ assert_or_panic(v[14] == 295);
+ assert_or_panic(v[15] == 296);
+ assert_or_panic(v[16] == 297);
+ assert_or_panic(v[17] == 298);
+ assert_or_panic(v[18] == 299);
+ assert_or_panic(v[19] == 300);
+ assert_or_panic(v[20] == 301);
+ assert_or_panic(v[21] == 302);
+ assert_or_panic(v[22] == 303);
+ assert_or_panic(v[23] == 304);
+ assert_or_panic(i == 24);
+}
+void c_test_vector_24_u16(void) {
+ Vector_24_u16 v = zig_ret_vector_24_u16();
+ assert_or_panic(v[0] == 209);
+ assert_or_panic(v[1] == 210);
+ assert_or_panic(v[2] == 211);
+ assert_or_panic(v[3] == 212);
+ assert_or_panic(v[4] == 213);
+ assert_or_panic(v[5] == 214);
+ assert_or_panic(v[6] == 215);
+ assert_or_panic(v[7] == 216);
+ assert_or_panic(v[8] == 217);
+ assert_or_panic(v[9] == 218);
+ assert_or_panic(v[10] == 219);
+ assert_or_panic(v[11] == 220);
+ assert_or_panic(v[12] == 221);
+ assert_or_panic(v[13] == 222);
+ assert_or_panic(v[14] == 223);
+ assert_or_panic(v[15] == 224);
+ assert_or_panic(v[16] == 225);
+ assert_or_panic(v[17] == 226);
+ assert_or_panic(v[18] == 227);
+ assert_or_panic(v[19] == 228);
+ assert_or_panic(v[20] == 229);
+ assert_or_panic(v[21] == 230);
+ assert_or_panic(v[22] == 231);
+ assert_or_panic(v[23] == 232);
+ zig_vector_24_u16((Vector_24_u16){
+ 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255, 256,
+ }, 24);
+}
+
+typedef uint16_t Vector_32_u16 __attribute__((vector_size(32 * sizeof(uint16_t))));
+
+Vector_32_u16 zig_ret_vector_32_u16(void);
+void zig_vector_32_u16(Vector_32_u16, size_t);
+
+Vector_32_u16 c_ret_vector_32_u16(void) {
+ return (Vector_32_u16){
+ 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384,
+ 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400,
+ };
+}
+void c_vector_32_u16(Vector_32_u16 v, size_t i) {
+ assert_or_panic(v[0] == 401);
+ assert_or_panic(v[1] == 402);
+ assert_or_panic(v[2] == 403);
+ assert_or_panic(v[3] == 404);
+ assert_or_panic(v[4] == 405);
+ assert_or_panic(v[5] == 406);
+ assert_or_panic(v[6] == 407);
+ assert_or_panic(v[7] == 408);
+ assert_or_panic(v[8] == 409);
+ assert_or_panic(v[9] == 410);
+ assert_or_panic(v[10] == 411);
+ assert_or_panic(v[11] == 412);
+ assert_or_panic(v[12] == 413);
+ assert_or_panic(v[13] == 414);
+ assert_or_panic(v[14] == 415);
+ assert_or_panic(v[15] == 416);
+ assert_or_panic(v[16] == 417);
+ assert_or_panic(v[17] == 418);
+ assert_or_panic(v[18] == 419);
+ assert_or_panic(v[19] == 420);
+ assert_or_panic(v[20] == 421);
+ assert_or_panic(v[21] == 422);
+ assert_or_panic(v[22] == 423);
+ assert_or_panic(v[23] == 424);
+ assert_or_panic(v[24] == 425);
+ assert_or_panic(v[25] == 426);
+ assert_or_panic(v[26] == 427);
+ assert_or_panic(v[27] == 428);
+ assert_or_panic(v[28] == 429);
+ assert_or_panic(v[29] == 430);
+ assert_or_panic(v[30] == 431);
+ assert_or_panic(v[31] == 432);
+ assert_or_panic(i == 32);
+}
+void c_test_vector_32_u16(void) {
+ Vector_32_u16 v = zig_ret_vector_32_u16();
+ assert_or_panic(v[0] == 305);
+ assert_or_panic(v[1] == 306);
+ assert_or_panic(v[2] == 307);
+ assert_or_panic(v[3] == 308);
+ assert_or_panic(v[4] == 309);
+ assert_or_panic(v[5] == 310);
+ assert_or_panic(v[6] == 311);
+ assert_or_panic(v[7] == 312);
+ assert_or_panic(v[8] == 313);
+ assert_or_panic(v[9] == 314);
+ assert_or_panic(v[10] == 315);
+ assert_or_panic(v[11] == 316);
+ assert_or_panic(v[12] == 317);
+ assert_or_panic(v[13] == 318);
+ assert_or_panic(v[14] == 319);
+ assert_or_panic(v[15] == 320);
+ assert_or_panic(v[16] == 321);
+ assert_or_panic(v[17] == 322);
+ assert_or_panic(v[18] == 323);
+ assert_or_panic(v[19] == 324);
+ assert_or_panic(v[20] == 325);
+ assert_or_panic(v[21] == 326);
+ assert_or_panic(v[22] == 327);
+ assert_or_panic(v[23] == 328);
+ assert_or_panic(v[24] == 329);
+ assert_or_panic(v[25] == 330);
+ assert_or_panic(v[26] == 331);
+ assert_or_panic(v[27] == 332);
+ assert_or_panic(v[28] == 333);
+ assert_or_panic(v[29] == 334);
+ assert_or_panic(v[30] == 335);
+ assert_or_panic(v[31] == 336);
+ zig_vector_32_u16((Vector_32_u16){
+ 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352,
+ 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368,
+ }, 32);
+}
+
+typedef uint16_t Vector_48_u16 __attribute__((vector_size(48 * sizeof(uint16_t))));
+
+Vector_48_u16 zig_ret_vector_48_u16(void);
+void zig_vector_48_u16(Vector_48_u16, size_t);
+
+Vector_48_u16 c_ret_vector_48_u16(void) {
+ return (Vector_48_u16){
+ 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544,
+ 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560,
+ 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576,
+ };
+}
+void c_vector_48_u16(Vector_48_u16 v, size_t i) {
+ assert_or_panic(v[0] == 577);
+ assert_or_panic(v[1] == 578);
+ assert_or_panic(v[2] == 579);
+ assert_or_panic(v[3] == 580);
+ assert_or_panic(v[4] == 581);
+ assert_or_panic(v[5] == 582);
+ assert_or_panic(v[6] == 583);
+ assert_or_panic(v[7] == 584);
+ assert_or_panic(v[8] == 585);
+ assert_or_panic(v[9] == 586);
+ assert_or_panic(v[10] == 587);
+ assert_or_panic(v[11] == 588);
+ assert_or_panic(v[12] == 589);
+ assert_or_panic(v[13] == 590);
+ assert_or_panic(v[14] == 591);
+ assert_or_panic(v[15] == 592);
+ assert_or_panic(v[16] == 593);
+ assert_or_panic(v[17] == 594);
+ assert_or_panic(v[18] == 595);
+ assert_or_panic(v[19] == 596);
+ assert_or_panic(v[20] == 597);
+ assert_or_panic(v[21] == 598);
+ assert_or_panic(v[22] == 599);
+ assert_or_panic(v[23] == 600);
+ assert_or_panic(v[24] == 601);
+ assert_or_panic(v[25] == 602);
+ assert_or_panic(v[26] == 603);
+ assert_or_panic(v[27] == 604);
+ assert_or_panic(v[28] == 605);
+ assert_or_panic(v[29] == 606);
+ assert_or_panic(v[30] == 607);
+ assert_or_panic(v[31] == 608);
+ assert_or_panic(v[32] == 609);
+ assert_or_panic(v[33] == 610);
+ assert_or_panic(v[34] == 611);
+ assert_or_panic(v[35] == 612);
+ assert_or_panic(v[36] == 613);
+ assert_or_panic(v[37] == 614);
+ assert_or_panic(v[38] == 615);
+ assert_or_panic(v[39] == 616);
+ assert_or_panic(v[40] == 617);
+ assert_or_panic(v[41] == 618);
+ assert_or_panic(v[42] == 619);
+ assert_or_panic(v[43] == 620);
+ assert_or_panic(v[44] == 621);
+ assert_or_panic(v[45] == 622);
+ assert_or_panic(v[46] == 623);
+ assert_or_panic(v[47] == 624);
+ assert_or_panic(i == 48);
+}
+void c_test_vector_48_u16(void) {
+ Vector_48_u16 v = zig_ret_vector_48_u16();
+ assert_or_panic(v[0] == 433);
+ assert_or_panic(v[1] == 434);
+ assert_or_panic(v[2] == 435);
+ assert_or_panic(v[3] == 436);
+ assert_or_panic(v[4] == 437);
+ assert_or_panic(v[5] == 438);
+ assert_or_panic(v[6] == 439);
+ assert_or_panic(v[7] == 440);
+ assert_or_panic(v[8] == 441);
+ assert_or_panic(v[9] == 442);
+ assert_or_panic(v[10] == 443);
+ assert_or_panic(v[11] == 444);
+ assert_or_panic(v[12] == 445);
+ assert_or_panic(v[13] == 446);
+ assert_or_panic(v[14] == 447);
+ assert_or_panic(v[15] == 448);
+ assert_or_panic(v[16] == 449);
+ assert_or_panic(v[17] == 450);
+ assert_or_panic(v[18] == 451);
+ assert_or_panic(v[19] == 452);
+ assert_or_panic(v[20] == 453);
+ assert_or_panic(v[21] == 454);
+ assert_or_panic(v[22] == 455);
+ assert_or_panic(v[23] == 456);
+ assert_or_panic(v[24] == 457);
+ assert_or_panic(v[25] == 458);
+ assert_or_panic(v[26] == 459);
+ assert_or_panic(v[27] == 460);
+ assert_or_panic(v[28] == 461);
+ assert_or_panic(v[29] == 462);
+ assert_or_panic(v[30] == 463);
+ assert_or_panic(v[31] == 464);
+ assert_or_panic(v[32] == 465);
+ assert_or_panic(v[33] == 466);
+ assert_or_panic(v[34] == 467);
+ assert_or_panic(v[35] == 468);
+ assert_or_panic(v[36] == 469);
+ assert_or_panic(v[37] == 470);
+ assert_or_panic(v[38] == 471);
+ assert_or_panic(v[39] == 472);
+ assert_or_panic(v[40] == 473);
+ assert_or_panic(v[41] == 474);
+ assert_or_panic(v[42] == 475);
+ assert_or_panic(v[43] == 476);
+ assert_or_panic(v[44] == 477);
+ assert_or_panic(v[45] == 478);
+ assert_or_panic(v[46] == 479);
+ assert_or_panic(v[47] == 480);
+ zig_vector_48_u16((Vector_48_u16){
+ 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496,
+ 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512,
+ 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528,
+ }, 48);
+}
+
+typedef uint16_t Vector_64_u16 __attribute__((vector_size(64 * sizeof(uint16_t))));
+
+Vector_64_u16 zig_ret_vector_64_u16(void);
+void zig_vector_64_u16(Vector_64_u16, size_t);
+
+Vector_64_u16 c_ret_vector_64_u16(void) {
+ return (Vector_64_u16){
+ 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768,
+ 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784,
+ 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800,
+ 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816,
+ };
+}
+void c_vector_64_u16(Vector_64_u16 v, size_t i) {
+ assert_or_panic(v[0] == 817);
+ assert_or_panic(v[1] == 818);
+ assert_or_panic(v[2] == 819);
+ assert_or_panic(v[3] == 820);
+ assert_or_panic(v[4] == 821);
+ assert_or_panic(v[5] == 822);
+ assert_or_panic(v[6] == 823);
+ assert_or_panic(v[7] == 824);
+ assert_or_panic(v[8] == 825);
+ assert_or_panic(v[9] == 826);
+ assert_or_panic(v[10] == 827);
+ assert_or_panic(v[11] == 828);
+ assert_or_panic(v[12] == 829);
+ assert_or_panic(v[13] == 830);
+ assert_or_panic(v[14] == 831);
+ assert_or_panic(v[15] == 832);
+ assert_or_panic(v[16] == 833);
+ assert_or_panic(v[17] == 834);
+ assert_or_panic(v[18] == 835);
+ assert_or_panic(v[19] == 836);
+ assert_or_panic(v[20] == 837);
+ assert_or_panic(v[21] == 838);
+ assert_or_panic(v[22] == 839);
+ assert_or_panic(v[23] == 840);
+ assert_or_panic(v[24] == 841);
+ assert_or_panic(v[25] == 842);
+ assert_or_panic(v[26] == 843);
+ assert_or_panic(v[27] == 844);
+ assert_or_panic(v[28] == 845);
+ assert_or_panic(v[29] == 846);
+ assert_or_panic(v[30] == 847);
+ assert_or_panic(v[31] == 848);
+ assert_or_panic(v[32] == 849);
+ assert_or_panic(v[33] == 850);
+ assert_or_panic(v[34] == 851);
+ assert_or_panic(v[35] == 852);
+ assert_or_panic(v[36] == 853);
+ assert_or_panic(v[37] == 854);
+ assert_or_panic(v[38] == 855);
+ assert_or_panic(v[39] == 856);
+ assert_or_panic(v[40] == 857);
+ assert_or_panic(v[41] == 858);
+ assert_or_panic(v[42] == 859);
+ assert_or_panic(v[43] == 860);
+ assert_or_panic(v[44] == 861);
+ assert_or_panic(v[45] == 862);
+ assert_or_panic(v[46] == 863);
+ assert_or_panic(v[47] == 864);
+ assert_or_panic(v[48] == 865);
+ assert_or_panic(v[49] == 866);
+ assert_or_panic(v[50] == 867);
+ assert_or_panic(v[51] == 868);
+ assert_or_panic(v[52] == 869);
+ assert_or_panic(v[53] == 870);
+ assert_or_panic(v[54] == 871);
+ assert_or_panic(v[55] == 872);
+ assert_or_panic(v[56] == 873);
+ assert_or_panic(v[57] == 874);
+ assert_or_panic(v[58] == 875);
+ assert_or_panic(v[59] == 876);
+ assert_or_panic(v[60] == 877);
+ assert_or_panic(v[61] == 878);
+ assert_or_panic(v[62] == 879);
+ assert_or_panic(v[63] == 880);
+ assert_or_panic(i == 64);
+}
+void c_test_vector_64_u16(void) {
+ Vector_64_u16 v = zig_ret_vector_64_u16();
+ assert_or_panic(v[0] == 625);
+ assert_or_panic(v[1] == 626);
+ assert_or_panic(v[2] == 627);
+ assert_or_panic(v[3] == 628);
+ assert_or_panic(v[4] == 629);
+ assert_or_panic(v[5] == 630);
+ assert_or_panic(v[6] == 631);
+ assert_or_panic(v[7] == 632);
+ assert_or_panic(v[8] == 633);
+ assert_or_panic(v[9] == 634);
+ assert_or_panic(v[10] == 635);
+ assert_or_panic(v[11] == 636);
+ assert_or_panic(v[12] == 637);
+ assert_or_panic(v[13] == 638);
+ assert_or_panic(v[14] == 639);
+ assert_or_panic(v[15] == 640);
+ assert_or_panic(v[16] == 641);
+ assert_or_panic(v[17] == 642);
+ assert_or_panic(v[18] == 643);
+ assert_or_panic(v[19] == 644);
+ assert_or_panic(v[20] == 645);
+ assert_or_panic(v[21] == 646);
+ assert_or_panic(v[22] == 647);
+ assert_or_panic(v[23] == 648);
+ assert_or_panic(v[24] == 649);
+ assert_or_panic(v[25] == 650);
+ assert_or_panic(v[26] == 651);
+ assert_or_panic(v[27] == 652);
+ assert_or_panic(v[28] == 653);
+ assert_or_panic(v[29] == 654);
+ assert_or_panic(v[30] == 655);
+ assert_or_panic(v[31] == 656);
+ assert_or_panic(v[32] == 657);
+ assert_or_panic(v[33] == 658);
+ assert_or_panic(v[34] == 659);
+ assert_or_panic(v[35] == 660);
+ assert_or_panic(v[36] == 661);
+ assert_or_panic(v[37] == 662);
+ assert_or_panic(v[38] == 663);
+ assert_or_panic(v[39] == 664);
+ assert_or_panic(v[40] == 665);
+ assert_or_panic(v[41] == 666);
+ assert_or_panic(v[42] == 667);
+ assert_or_panic(v[43] == 668);
+ assert_or_panic(v[44] == 669);
+ assert_or_panic(v[45] == 670);
+ assert_or_panic(v[46] == 671);
+ assert_or_panic(v[47] == 672);
+ assert_or_panic(v[48] == 673);
+ assert_or_panic(v[49] == 674);
+ assert_or_panic(v[50] == 675);
+ assert_or_panic(v[51] == 676);
+ assert_or_panic(v[52] == 677);
+ assert_or_panic(v[53] == 678);
+ assert_or_panic(v[54] == 679);
+ assert_or_panic(v[55] == 680);
+ assert_or_panic(v[56] == 681);
+ assert_or_panic(v[57] == 682);
+ assert_or_panic(v[58] == 683);
+ assert_or_panic(v[59] == 684);
+ assert_or_panic(v[60] == 685);
+ assert_or_panic(v[61] == 686);
+ assert_or_panic(v[62] == 687);
+ assert_or_panic(v[63] == 688);
+ zig_vector_64_u16((Vector_64_u16){
+ 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704,
+ 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720,
+ 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736,
+ 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752,
+ }, 64);
+}
+
+typedef uint16_t Vector_96_u16 __attribute__((vector_size(96 * sizeof(uint16_t))));
+
+Vector_96_u16 zig_ret_vector_96_u16(void);
+void zig_vector_96_u16(Vector_96_u16, size_t);
+
+Vector_96_u16 c_ret_vector_96_u16(void) {
+ return (Vector_96_u16){
+ 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097,
+ 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113,
+ 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129,
+ 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145,
+ 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161,
+ 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177,
+ };
+}
+void c_vector_96_u16(Vector_96_u16 v, size_t i) {
+ assert_or_panic(v[0] == 1178);
+ assert_or_panic(v[1] == 1179);
+ assert_or_panic(v[2] == 1180);
+ assert_or_panic(v[3] == 1181);
+ assert_or_panic(v[4] == 1182);
+ assert_or_panic(v[5] == 1183);
+ assert_or_panic(v[6] == 1184);
+ assert_or_panic(v[7] == 1185);
+ assert_or_panic(v[8] == 1186);
+ assert_or_panic(v[9] == 1187);
+ assert_or_panic(v[10] == 1188);
+ assert_or_panic(v[11] == 1189);
+ assert_or_panic(v[12] == 1190);
+ assert_or_panic(v[13] == 1191);
+ assert_or_panic(v[14] == 1192);
+ assert_or_panic(v[15] == 1193);
+ assert_or_panic(v[16] == 1194);
+ assert_or_panic(v[17] == 1195);
+ assert_or_panic(v[18] == 1196);
+ assert_or_panic(v[19] == 1197);
+ assert_or_panic(v[20] == 1198);
+ assert_or_panic(v[21] == 1199);
+ assert_or_panic(v[22] == 1200);
+ assert_or_panic(v[23] == 1201);
+ assert_or_panic(v[24] == 1202);
+ assert_or_panic(v[25] == 1203);
+ assert_or_panic(v[26] == 1204);
+ assert_or_panic(v[27] == 1205);
+ assert_or_panic(v[28] == 1206);
+ assert_or_panic(v[29] == 1207);
+ assert_or_panic(v[30] == 1208);
+ assert_or_panic(v[31] == 1209);
+ assert_or_panic(v[32] == 1210);
+ assert_or_panic(v[33] == 1211);
+ assert_or_panic(v[34] == 1212);
+ assert_or_panic(v[35] == 1213);
+ assert_or_panic(v[36] == 1214);
+ assert_or_panic(v[37] == 1215);
+ assert_or_panic(v[38] == 1216);
+ assert_or_panic(v[39] == 1217);
+ assert_or_panic(v[40] == 1218);
+ assert_or_panic(v[41] == 1219);
+ assert_or_panic(v[42] == 1220);
+ assert_or_panic(v[43] == 1221);
+ assert_or_panic(v[44] == 1222);
+ assert_or_panic(v[45] == 1223);
+ assert_or_panic(v[46] == 1224);
+ assert_or_panic(v[47] == 1225);
+ assert_or_panic(v[48] == 1226);
+ assert_or_panic(v[49] == 1227);
+ assert_or_panic(v[50] == 1228);
+ assert_or_panic(v[51] == 1229);
+ assert_or_panic(v[52] == 1230);
+ assert_or_panic(v[53] == 1231);
+ assert_or_panic(v[54] == 1232);
+ assert_or_panic(v[55] == 1233);
+ assert_or_panic(v[56] == 1234);
+ assert_or_panic(v[57] == 1235);
+ assert_or_panic(v[58] == 1236);
+ assert_or_panic(v[59] == 1237);
+ assert_or_panic(v[60] == 1238);
+ assert_or_panic(v[61] == 1239);
+ assert_or_panic(v[62] == 1240);
+ assert_or_panic(v[63] == 1241);
+ assert_or_panic(v[64] == 1242);
+ assert_or_panic(v[65] == 1243);
+ assert_or_panic(v[66] == 1244);
+ assert_or_panic(v[67] == 1245);
+ assert_or_panic(v[68] == 1246);
+ assert_or_panic(v[69] == 1247);
+ assert_or_panic(v[70] == 1248);
+ assert_or_panic(v[71] == 1249);
+ assert_or_panic(v[72] == 1250);
+ assert_or_panic(v[73] == 1251);
+ assert_or_panic(v[74] == 1252);
+ assert_or_panic(v[75] == 1253);
+ assert_or_panic(v[76] == 1254);
+ assert_or_panic(v[77] == 1255);
+ assert_or_panic(v[80] == 1258);
+ assert_or_panic(v[81] == 1259);
+ assert_or_panic(v[82] == 1260);
+ assert_or_panic(v[83] == 1261);
+ assert_or_panic(v[84] == 1262);
+ assert_or_panic(v[85] == 1263);
+ assert_or_panic(v[86] == 1264);
+ assert_or_panic(v[87] == 1265);
+ assert_or_panic(v[88] == 1266);
+ assert_or_panic(v[89] == 1267);
+ assert_or_panic(v[90] == 1268);
+ assert_or_panic(v[91] == 1269);
+ assert_or_panic(v[92] == 1270);
+ assert_or_panic(v[93] == 1271);
+ assert_or_panic(v[94] == 1272);
+ assert_or_panic(v[95] == 1273);
+ assert_or_panic(i == 96);
+}
+void c_test_vector_96_u16(void) {
+ Vector_96_u16 v = zig_ret_vector_96_u16();
+ assert_or_panic(v[0] == 890);
+ assert_or_panic(v[1] == 891);
+ assert_or_panic(v[2] == 892);
+ assert_or_panic(v[3] == 893);
+ assert_or_panic(v[4] == 894);
+ assert_or_panic(v[5] == 895);
+ assert_or_panic(v[6] == 896);
+ assert_or_panic(v[7] == 897);
+ assert_or_panic(v[8] == 898);
+ assert_or_panic(v[9] == 899);
+ assert_or_panic(v[10] == 900);
+ assert_or_panic(v[11] == 901);
+ assert_or_panic(v[12] == 902);
+ assert_or_panic(v[13] == 903);
+ assert_or_panic(v[14] == 904);
+ assert_or_panic(v[15] == 905);
+ assert_or_panic(v[16] == 906);
+ assert_or_panic(v[17] == 907);
+ assert_or_panic(v[18] == 908);
+ assert_or_panic(v[19] == 909);
+ assert_or_panic(v[20] == 910);
+ assert_or_panic(v[21] == 911);
+ assert_or_panic(v[22] == 912);
+ assert_or_panic(v[23] == 913);
+ assert_or_panic(v[24] == 914);
+ assert_or_panic(v[25] == 915);
+ assert_or_panic(v[26] == 916);
+ assert_or_panic(v[27] == 917);
+ assert_or_panic(v[28] == 918);
+ assert_or_panic(v[29] == 919);
+ assert_or_panic(v[30] == 920);
+ assert_or_panic(v[31] == 921);
+ assert_or_panic(v[32] == 922);
+ assert_or_panic(v[33] == 923);
+ assert_or_panic(v[34] == 924);
+ assert_or_panic(v[35] == 925);
+ assert_or_panic(v[36] == 926);
+ assert_or_panic(v[37] == 927);
+ assert_or_panic(v[38] == 928);
+ assert_or_panic(v[39] == 929);
+ assert_or_panic(v[40] == 930);
+ assert_or_panic(v[41] == 931);
+ assert_or_panic(v[42] == 932);
+ assert_or_panic(v[43] == 933);
+ assert_or_panic(v[44] == 934);
+ assert_or_panic(v[45] == 935);
+ assert_or_panic(v[46] == 936);
+ assert_or_panic(v[47] == 937);
+ assert_or_panic(v[48] == 938);
+ assert_or_panic(v[49] == 939);
+ assert_or_panic(v[50] == 940);
+ assert_or_panic(v[51] == 941);
+ assert_or_panic(v[52] == 942);
+ assert_or_panic(v[53] == 943);
+ assert_or_panic(v[54] == 944);
+ assert_or_panic(v[55] == 945);
+ assert_or_panic(v[56] == 946);
+ assert_or_panic(v[57] == 947);
+ assert_or_panic(v[58] == 948);
+ assert_or_panic(v[59] == 949);
+ assert_or_panic(v[60] == 950);
+ assert_or_panic(v[61] == 951);
+ assert_or_panic(v[62] == 952);
+ assert_or_panic(v[63] == 953);
+ assert_or_panic(v[64] == 954);
+ assert_or_panic(v[65] == 955);
+ assert_or_panic(v[66] == 956);
+ assert_or_panic(v[67] == 957);
+ assert_or_panic(v[68] == 958);
+ assert_or_panic(v[69] == 959);
+ assert_or_panic(v[70] == 960);
+ assert_or_panic(v[71] == 961);
+ assert_or_panic(v[72] == 962);
+ assert_or_panic(v[73] == 963);
+ assert_or_panic(v[74] == 964);
+ assert_or_panic(v[75] == 965);
+ assert_or_panic(v[76] == 966);
+ assert_or_panic(v[77] == 967);
+ assert_or_panic(v[78] == 968);
+ assert_or_panic(v[79] == 969);
+ assert_or_panic(v[80] == 970);
+ assert_or_panic(v[81] == 971);
+ assert_or_panic(v[82] == 972);
+ assert_or_panic(v[83] == 973);
+ assert_or_panic(v[84] == 974);
+ assert_or_panic(v[85] == 975);
+ assert_or_panic(v[86] == 976);
+ assert_or_panic(v[87] == 977);
+ assert_or_panic(v[88] == 978);
+ assert_or_panic(v[89] == 979);
+ assert_or_panic(v[90] == 980);
+ assert_or_panic(v[91] == 981);
+ assert_or_panic(v[92] == 982);
+ assert_or_panic(v[93] == 983);
+ assert_or_panic(v[94] == 984);
+ assert_or_panic(v[95] == 985);
+ zig_vector_96_u16((Vector_96_u16){
+ 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001,
+ 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017,
+ 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033,
+ 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049,
+ 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065,
+ 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081,
+ }, 96);
+}
+
+typedef uint16_t Vector_128_u16 __attribute__((vector_size(128 * sizeof(uint16_t))));
+
+Vector_128_u16 zig_ret_vector_128_u16(void);
+void zig_vector_128_u16(Vector_128_u16, size_t);
+
+Vector_128_u16 c_ret_vector_128_u16(void) {
+ return (Vector_128_u16){
+ 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545,
+ 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561,
+ 1562, 1563, 1564, 1565, 1566, 1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577,
+ 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593,
+ 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609,
+ 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625,
+ 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641,
+ 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657,
+ };
+}
+void c_vector_128_u16(Vector_128_u16 v, size_t i) {
+ assert_or_panic(v[0] == 1658);
+ assert_or_panic(v[1] == 1659);
+ assert_or_panic(v[2] == 1660);
+ assert_or_panic(v[3] == 1661);
+ assert_or_panic(v[4] == 1662);
+ assert_or_panic(v[5] == 1663);
+ assert_or_panic(v[6] == 1664);
+ assert_or_panic(v[7] == 1665);
+ assert_or_panic(v[8] == 1666);
+ assert_or_panic(v[9] == 1667);
+ assert_or_panic(v[10] == 1668);
+ assert_or_panic(v[11] == 1669);
+ assert_or_panic(v[12] == 1670);
+ assert_or_panic(v[13] == 1671);
+ assert_or_panic(v[14] == 1672);
+ assert_or_panic(v[15] == 1673);
+ assert_or_panic(v[16] == 1674);
+ assert_or_panic(v[17] == 1675);
+ assert_or_panic(v[18] == 1676);
+ assert_or_panic(v[19] == 1677);
+ assert_or_panic(v[20] == 1678);
+ assert_or_panic(v[21] == 1679);
+ assert_or_panic(v[22] == 1680);
+ assert_or_panic(v[23] == 1681);
+ assert_or_panic(v[24] == 1682);
+ assert_or_panic(v[25] == 1683);
+ assert_or_panic(v[26] == 1684);
+ assert_or_panic(v[27] == 1685);
+ assert_or_panic(v[28] == 1686);
+ assert_or_panic(v[29] == 1687);
+ assert_or_panic(v[30] == 1688);
+ assert_or_panic(v[31] == 1689);
+ assert_or_panic(v[32] == 1690);
+ assert_or_panic(v[33] == 1691);
+ assert_or_panic(v[34] == 1692);
+ assert_or_panic(v[35] == 1693);
+ assert_or_panic(v[36] == 1694);
+ assert_or_panic(v[37] == 1695);
+ assert_or_panic(v[38] == 1696);
+ assert_or_panic(v[39] == 1697);
+ assert_or_panic(v[40] == 1698);
+ assert_or_panic(v[41] == 1699);
+ assert_or_panic(v[42] == 1700);
+ assert_or_panic(v[43] == 1701);
+ assert_or_panic(v[44] == 1702);
+ assert_or_panic(v[45] == 1703);
+ assert_or_panic(v[46] == 1704);
+ assert_or_panic(v[47] == 1705);
+ assert_or_panic(v[48] == 1706);
+ assert_or_panic(v[49] == 1707);
+ assert_or_panic(v[50] == 1708);
+ assert_or_panic(v[51] == 1709);
+ assert_or_panic(v[52] == 1710);
+ assert_or_panic(v[53] == 1711);
+ assert_or_panic(v[54] == 1712);
+ assert_or_panic(v[55] == 1713);
+ assert_or_panic(v[56] == 1714);
+ assert_or_panic(v[57] == 1715);
+ assert_or_panic(v[58] == 1716);
+ assert_or_panic(v[59] == 1717);
+ assert_or_panic(v[60] == 1718);
+ assert_or_panic(v[61] == 1719);
+ assert_or_panic(v[62] == 1720);
+ assert_or_panic(v[63] == 1721);
+ assert_or_panic(v[64] == 1722);
+ assert_or_panic(v[65] == 1723);
+ assert_or_panic(v[66] == 1724);
+ assert_or_panic(v[67] == 1725);
+ assert_or_panic(v[68] == 1726);
+ assert_or_panic(v[69] == 1727);
+ assert_or_panic(v[70] == 1728);
+ assert_or_panic(v[71] == 1729);
+ assert_or_panic(v[72] == 1730);
+ assert_or_panic(v[73] == 1731);
+ assert_or_panic(v[74] == 1732);
+ assert_or_panic(v[75] == 1733);
+ assert_or_panic(v[76] == 1734);
+ assert_or_panic(v[77] == 1735);
+ assert_or_panic(v[78] == 1736);
+ assert_or_panic(v[79] == 1737);
+ assert_or_panic(v[80] == 1738);
+ assert_or_panic(v[81] == 1739);
+ assert_or_panic(v[82] == 1740);
+ assert_or_panic(v[83] == 1741);
+ assert_or_panic(v[84] == 1742);
+ assert_or_panic(v[85] == 1743);
+ assert_or_panic(v[86] == 1744);
+ assert_or_panic(v[87] == 1745);
+ assert_or_panic(v[88] == 1746);
+ assert_or_panic(v[89] == 1747);
+ assert_or_panic(v[90] == 1748);
+ assert_or_panic(v[91] == 1749);
+ assert_or_panic(v[92] == 1750);
+ assert_or_panic(v[93] == 1751);
+ assert_or_panic(v[94] == 1752);
+ assert_or_panic(v[95] == 1753);
+ assert_or_panic(v[96] == 1754);
+ assert_or_panic(v[97] == 1755);
+ assert_or_panic(v[98] == 1756);
+ assert_or_panic(v[99] == 1757);
+ assert_or_panic(v[100] == 1758);
+ assert_or_panic(v[101] == 1759);
+ assert_or_panic(v[102] == 1760);
+ assert_or_panic(v[103] == 1761);
+ assert_or_panic(v[104] == 1762);
+ assert_or_panic(v[105] == 1763);
+ assert_or_panic(v[106] == 1764);
+ assert_or_panic(v[107] == 1765);
+ assert_or_panic(v[108] == 1766);
+ assert_or_panic(v[109] == 1767);
+ assert_or_panic(v[110] == 1768);
+ assert_or_panic(v[111] == 1769);
+ assert_or_panic(v[112] == 1770);
+ assert_or_panic(v[113] == 1771);
+ assert_or_panic(v[114] == 1772);
+ assert_or_panic(v[115] == 1773);
+ assert_or_panic(v[116] == 1774);
+ assert_or_panic(v[117] == 1775);
+ assert_or_panic(v[118] == 1776);
+ assert_or_panic(v[119] == 1777);
+ assert_or_panic(v[120] == 1778);
+ assert_or_panic(v[121] == 1779);
+ assert_or_panic(v[122] == 1780);
+ assert_or_panic(v[123] == 1781);
+ assert_or_panic(v[124] == 1782);
+ assert_or_panic(v[125] == 1783);
+ assert_or_panic(v[126] == 1784);
+ assert_or_panic(v[127] == 1785);
+ assert_or_panic(i == 128);
+}
+void c_test_vector_128_u16(void) {
+ Vector_128_u16 v = zig_ret_vector_128_u16();
+ assert_or_panic(v[0] == 1274);
+ assert_or_panic(v[1] == 1275);
+ assert_or_panic(v[2] == 1276);
+ assert_or_panic(v[3] == 1277);
+ assert_or_panic(v[4] == 1278);
+ assert_or_panic(v[5] == 1279);
+ assert_or_panic(v[6] == 1280);
+ assert_or_panic(v[7] == 1281);
+ assert_or_panic(v[8] == 1282);
+ assert_or_panic(v[9] == 1283);
+ assert_or_panic(v[10] == 1284);
+ assert_or_panic(v[11] == 1285);
+ assert_or_panic(v[12] == 1286);
+ assert_or_panic(v[13] == 1287);
+ assert_or_panic(v[14] == 1288);
+ assert_or_panic(v[15] == 1289);
+ assert_or_panic(v[16] == 1290);
+ assert_or_panic(v[17] == 1291);
+ assert_or_panic(v[18] == 1292);
+ assert_or_panic(v[19] == 1293);
+ assert_or_panic(v[20] == 1294);
+ assert_or_panic(v[21] == 1295);
+ assert_or_panic(v[22] == 1296);
+ assert_or_panic(v[23] == 1297);
+ assert_or_panic(v[24] == 1298);
+ assert_or_panic(v[25] == 1299);
+ assert_or_panic(v[26] == 1300);
+ assert_or_panic(v[27] == 1301);
+ assert_or_panic(v[28] == 1302);
+ assert_or_panic(v[29] == 1303);
+ assert_or_panic(v[30] == 1304);
+ assert_or_panic(v[31] == 1305);
+ assert_or_panic(v[32] == 1306);
+ assert_or_panic(v[33] == 1307);
+ assert_or_panic(v[34] == 1308);
+ assert_or_panic(v[35] == 1309);
+ assert_or_panic(v[36] == 1310);
+ assert_or_panic(v[37] == 1311);
+ assert_or_panic(v[38] == 1312);
+ assert_or_panic(v[39] == 1313);
+ assert_or_panic(v[40] == 1314);
+ assert_or_panic(v[41] == 1315);
+ assert_or_panic(v[42] == 1316);
+ assert_or_panic(v[43] == 1317);
+ assert_or_panic(v[44] == 1318);
+ assert_or_panic(v[45] == 1319);
+ assert_or_panic(v[46] == 1320);
+ assert_or_panic(v[47] == 1321);
+ assert_or_panic(v[48] == 1322);
+ assert_or_panic(v[49] == 1323);
+ assert_or_panic(v[50] == 1324);
+ assert_or_panic(v[51] == 1325);
+ assert_or_panic(v[52] == 1326);
+ assert_or_panic(v[53] == 1327);
+ assert_or_panic(v[54] == 1328);
+ assert_or_panic(v[55] == 1329);
+ assert_or_panic(v[56] == 1330);
+ assert_or_panic(v[57] == 1331);
+ assert_or_panic(v[58] == 1332);
+ assert_or_panic(v[59] == 1333);
+ assert_or_panic(v[60] == 1334);
+ assert_or_panic(v[61] == 1335);
+ assert_or_panic(v[62] == 1336);
+ assert_or_panic(v[63] == 1337);
+ assert_or_panic(v[64] == 1338);
+ assert_or_panic(v[65] == 1339);
+ assert_or_panic(v[66] == 1340);
+ assert_or_panic(v[67] == 1341);
+ assert_or_panic(v[68] == 1342);
+ assert_or_panic(v[69] == 1343);
+ assert_or_panic(v[70] == 1344);
+ assert_or_panic(v[71] == 1345);
+ assert_or_panic(v[72] == 1346);
+ assert_or_panic(v[73] == 1347);
+ assert_or_panic(v[74] == 1348);
+ assert_or_panic(v[75] == 1349);
+ assert_or_panic(v[76] == 1350);
+ assert_or_panic(v[77] == 1351);
+ assert_or_panic(v[78] == 1352);
+ assert_or_panic(v[79] == 1353);
+ assert_or_panic(v[80] == 1354);
+ assert_or_panic(v[81] == 1355);
+ assert_or_panic(v[82] == 1356);
+ assert_or_panic(v[83] == 1357);
+ assert_or_panic(v[84] == 1358);
+ assert_or_panic(v[85] == 1359);
+ assert_or_panic(v[86] == 1360);
+ assert_or_panic(v[87] == 1361);
+ assert_or_panic(v[88] == 1362);
+ assert_or_panic(v[89] == 1363);
+ assert_or_panic(v[90] == 1364);
+ assert_or_panic(v[91] == 1365);
+ assert_or_panic(v[92] == 1366);
+ assert_or_panic(v[93] == 1367);
+ assert_or_panic(v[94] == 1368);
+ assert_or_panic(v[95] == 1369);
+ assert_or_panic(v[96] == 1370);
+ assert_or_panic(v[97] == 1371);
+ assert_or_panic(v[98] == 1372);
+ assert_or_panic(v[99] == 1373);
+ assert_or_panic(v[100] == 1374);
+ assert_or_panic(v[101] == 1375);
+ assert_or_panic(v[102] == 1376);
+ assert_or_panic(v[103] == 1377);
+ assert_or_panic(v[104] == 1378);
+ assert_or_panic(v[105] == 1379);
+ assert_or_panic(v[106] == 1380);
+ assert_or_panic(v[107] == 1381);
+ assert_or_panic(v[108] == 1382);
+ assert_or_panic(v[109] == 1383);
+ assert_or_panic(v[110] == 1384);
+ assert_or_panic(v[111] == 1385);
+ assert_or_panic(v[112] == 1386);
+ assert_or_panic(v[113] == 1387);
+ assert_or_panic(v[114] == 1388);
+ assert_or_panic(v[115] == 1389);
+ assert_or_panic(v[116] == 1390);
+ assert_or_panic(v[117] == 1391);
+ assert_or_panic(v[118] == 1392);
+ assert_or_panic(v[119] == 1393);
+ assert_or_panic(v[120] == 1394);
+ assert_or_panic(v[121] == 1395);
+ assert_or_panic(v[122] == 1396);
+ assert_or_panic(v[123] == 1397);
+ assert_or_panic(v[124] == 1398);
+ assert_or_panic(v[125] == 1399);
+ assert_or_panic(v[126] == 1400);
+ assert_or_panic(v[127] == 1401);
+ zig_vector_128_u16((Vector_128_u16){
+ 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417,
+ 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1433,
+ 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449,
+ 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465,
+ 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481,
+ 1482, 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497,
+ 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513,
+ 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529,
+ }, 128);
+}
+
+typedef uint16_t Vector_192_u16 __attribute__((vector_size(192 * sizeof(uint16_t))));
+
+Vector_192_u16 zig_ret_vector_192_u16(void);
+void zig_vector_192_u16(Vector_192_u16, size_t);
+
+Vector_192_u16 c_ret_vector_192_u16(void) {
+ return (Vector_192_u16){
+ 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, 2184, 2185,
+ 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196, 2197, 2198, 2199, 2200, 2201,
+ 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, 2217,
+ 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, 2227, 2228, 2229, 2230, 2231, 2232, 2233,
+ 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249,
+ 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265,
+ 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281,
+ 2282, 2283, 2284, 2285, 2286, 2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297,
+ 2298, 2299, 2300, 2301, 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313,
+ 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329,
+ 2330, 2331, 2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345,
+ 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2360, 2361,
+ };
+}
+void c_vector_192_u16(Vector_192_u16 v, size_t i) {
+ assert_or_panic(v[0] == 2362);
+ assert_or_panic(v[1] == 2363);
+ assert_or_panic(v[2] == 2364);
+ assert_or_panic(v[3] == 2365);
+ assert_or_panic(v[4] == 2366);
+ assert_or_panic(v[5] == 2367);
+ assert_or_panic(v[6] == 2368);
+ assert_or_panic(v[7] == 2369);
+ assert_or_panic(v[8] == 2370);
+ assert_or_panic(v[9] == 2371);
+ assert_or_panic(v[10] == 2372);
+ assert_or_panic(v[11] == 2373);
+ assert_or_panic(v[12] == 2374);
+ assert_or_panic(v[13] == 2375);
+ assert_or_panic(v[14] == 2376);
+ assert_or_panic(v[15] == 2377);
+ assert_or_panic(v[16] == 2378);
+ assert_or_panic(v[17] == 2379);
+ assert_or_panic(v[18] == 2380);
+ assert_or_panic(v[19] == 2381);
+ assert_or_panic(v[20] == 2382);
+ assert_or_panic(v[21] == 2383);
+ assert_or_panic(v[22] == 2384);
+ assert_or_panic(v[23] == 2385);
+ assert_or_panic(v[24] == 2386);
+ assert_or_panic(v[25] == 2387);
+ assert_or_panic(v[26] == 2388);
+ assert_or_panic(v[27] == 2389);
+ assert_or_panic(v[28] == 2390);
+ assert_or_panic(v[29] == 2391);
+ assert_or_panic(v[30] == 2392);
+ assert_or_panic(v[31] == 2393);
+ assert_or_panic(v[32] == 2394);
+ assert_or_panic(v[33] == 2395);
+ assert_or_panic(v[34] == 2396);
+ assert_or_panic(v[35] == 2397);
+ assert_or_panic(v[36] == 2398);
+ assert_or_panic(v[37] == 2399);
+ assert_or_panic(v[38] == 2400);
+ assert_or_panic(v[39] == 2401);
+ assert_or_panic(v[40] == 2402);
+ assert_or_panic(v[41] == 2403);
+ assert_or_panic(v[42] == 2404);
+ assert_or_panic(v[43] == 2405);
+ assert_or_panic(v[44] == 2406);
+ assert_or_panic(v[45] == 2407);
+ assert_or_panic(v[46] == 2408);
+ assert_or_panic(v[47] == 2409);
+ assert_or_panic(v[48] == 2410);
+ assert_or_panic(v[49] == 2411);
+ assert_or_panic(v[50] == 2412);
+ assert_or_panic(v[51] == 2413);
+ assert_or_panic(v[52] == 2414);
+ assert_or_panic(v[53] == 2415);
+ assert_or_panic(v[54] == 2416);
+ assert_or_panic(v[55] == 2417);
+ assert_or_panic(v[56] == 2418);
+ assert_or_panic(v[57] == 2419);
+ assert_or_panic(v[58] == 2420);
+ assert_or_panic(v[59] == 2421);
+ assert_or_panic(v[60] == 2422);
+ assert_or_panic(v[61] == 2423);
+ assert_or_panic(v[62] == 2424);
+ assert_or_panic(v[63] == 2425);
+ assert_or_panic(v[64] == 2426);
+ assert_or_panic(v[65] == 2427);
+ assert_or_panic(v[66] == 2428);
+ assert_or_panic(v[67] == 2429);
+ assert_or_panic(v[68] == 2430);
+ assert_or_panic(v[69] == 2431);
+ assert_or_panic(v[70] == 2432);
+ assert_or_panic(v[71] == 2433);
+ assert_or_panic(v[72] == 2434);
+ assert_or_panic(v[73] == 2435);
+ assert_or_panic(v[74] == 2436);
+ assert_or_panic(v[75] == 2437);
+ assert_or_panic(v[76] == 2438);
+ assert_or_panic(v[77] == 2439);
+ assert_or_panic(v[78] == 2440);
+ assert_or_panic(v[79] == 2441);
+ assert_or_panic(v[80] == 2442);
+ assert_or_panic(v[81] == 2443);
+ assert_or_panic(v[82] == 2444);
+ assert_or_panic(v[83] == 2445);
+ assert_or_panic(v[84] == 2446);
+ assert_or_panic(v[85] == 2447);
+ assert_or_panic(v[86] == 2448);
+ assert_or_panic(v[87] == 2449);
+ assert_or_panic(v[88] == 2450);
+ assert_or_panic(v[89] == 2451);
+ assert_or_panic(v[90] == 2452);
+ assert_or_panic(v[91] == 2453);
+ assert_or_panic(v[92] == 2454);
+ assert_or_panic(v[93] == 2455);
+ assert_or_panic(v[94] == 2456);
+ assert_or_panic(v[95] == 2457);
+ assert_or_panic(v[96] == 2458);
+ assert_or_panic(v[97] == 2459);
+ assert_or_panic(v[98] == 2460);
+ assert_or_panic(v[99] == 2461);
+ assert_or_panic(v[100] == 2462);
+ assert_or_panic(v[101] == 2463);
+ assert_or_panic(v[102] == 2464);
+ assert_or_panic(v[103] == 2465);
+ assert_or_panic(v[104] == 2466);
+ assert_or_panic(v[105] == 2467);
+ assert_or_panic(v[106] == 2468);
+ assert_or_panic(v[107] == 2469);
+ assert_or_panic(v[108] == 2470);
+ assert_or_panic(v[109] == 2471);
+ assert_or_panic(v[110] == 2472);
+ assert_or_panic(v[111] == 2473);
+ assert_or_panic(v[112] == 2474);
+ assert_or_panic(v[113] == 2475);
+ assert_or_panic(v[114] == 2476);
+ assert_or_panic(v[115] == 2477);
+ assert_or_panic(v[116] == 2478);
+ assert_or_panic(v[117] == 2479);
+ assert_or_panic(v[118] == 2480);
+ assert_or_panic(v[119] == 2481);
+ assert_or_panic(v[120] == 2482);
+ assert_or_panic(v[121] == 2483);
+ assert_or_panic(v[122] == 2484);
+ assert_or_panic(v[123] == 2485);
+ assert_or_panic(v[124] == 2486);
+ assert_or_panic(v[125] == 2487);
+ assert_or_panic(v[126] == 2488);
+ assert_or_panic(v[127] == 2489);
+ assert_or_panic(v[128] == 2490);
+ assert_or_panic(v[129] == 2491);
+ assert_or_panic(v[130] == 2492);
+ assert_or_panic(v[131] == 2493);
+ assert_or_panic(v[132] == 2494);
+ assert_or_panic(v[133] == 2495);
+ assert_or_panic(v[134] == 2496);
+ assert_or_panic(v[135] == 2497);
+ assert_or_panic(v[136] == 2498);
+ assert_or_panic(v[137] == 2499);
+ assert_or_panic(v[138] == 2500);
+ assert_or_panic(v[139] == 2501);
+ assert_or_panic(v[140] == 2502);
+ assert_or_panic(v[141] == 2503);
+ assert_or_panic(v[142] == 2504);
+ assert_or_panic(v[143] == 2505);
+ assert_or_panic(v[144] == 2506);
+ assert_or_panic(v[145] == 2507);
+ assert_or_panic(v[146] == 2508);
+ assert_or_panic(v[147] == 2509);
+ assert_or_panic(v[148] == 2510);
+ assert_or_panic(v[149] == 2511);
+ assert_or_panic(v[150] == 2512);
+ assert_or_panic(v[151] == 2513);
+ assert_or_panic(v[152] == 2514);
+ assert_or_panic(v[153] == 2515);
+ assert_or_panic(v[154] == 2516);
+ assert_or_panic(v[155] == 2517);
+ assert_or_panic(v[156] == 2518);
+ assert_or_panic(v[157] == 2519);
+ assert_or_panic(v[158] == 2520);
+ assert_or_panic(v[159] == 2521);
+ assert_or_panic(v[160] == 2522);
+ assert_or_panic(v[161] == 2523);
+ assert_or_panic(v[162] == 2524);
+ assert_or_panic(v[163] == 2525);
+ assert_or_panic(v[164] == 2526);
+ assert_or_panic(v[165] == 2527);
+ assert_or_panic(v[166] == 2528);
+ assert_or_panic(v[167] == 2529);
+ assert_or_panic(v[168] == 2530);
+ assert_or_panic(v[169] == 2531);
+ assert_or_panic(v[170] == 2532);
+ assert_or_panic(v[171] == 2533);
+ assert_or_panic(v[172] == 2534);
+ assert_or_panic(v[173] == 2535);
+ assert_or_panic(v[174] == 2536);
+ assert_or_panic(v[175] == 2537);
+ assert_or_panic(v[176] == 2538);
+ assert_or_panic(v[177] == 2539);
+ assert_or_panic(v[178] == 2540);
+ assert_or_panic(v[179] == 2541);
+ assert_or_panic(v[180] == 2542);
+ assert_or_panic(v[181] == 2543);
+ assert_or_panic(v[182] == 2544);
+ assert_or_panic(v[183] == 2545);
+ assert_or_panic(v[184] == 2546);
+ assert_or_panic(v[185] == 2547);
+ assert_or_panic(v[186] == 2548);
+ assert_or_panic(v[187] == 2549);
+ assert_or_panic(v[188] == 2550);
+ assert_or_panic(v[189] == 2551);
+ assert_or_panic(v[190] == 2552);
+ assert_or_panic(v[191] == 2553);
+ assert_or_panic(i == 192);
+}
+void c_test_vector_192_u16(void) {
+ Vector_192_u16 v = zig_ret_vector_192_u16();
+ assert_or_panic(v[0] == 1786);
+ assert_or_panic(v[1] == 1787);
+ assert_or_panic(v[2] == 1788);
+ assert_or_panic(v[3] == 1789);
+ assert_or_panic(v[4] == 1790);
+ assert_or_panic(v[5] == 1791);
+ assert_or_panic(v[6] == 1792);
+ assert_or_panic(v[7] == 1793);
+ assert_or_panic(v[8] == 1794);
+ assert_or_panic(v[9] == 1795);
+ assert_or_panic(v[10] == 1796);
+ assert_or_panic(v[11] == 1797);
+ assert_or_panic(v[12] == 1798);
+ assert_or_panic(v[13] == 1799);
+ assert_or_panic(v[14] == 1800);
+ assert_or_panic(v[15] == 1801);
+ assert_or_panic(v[16] == 1802);
+ assert_or_panic(v[17] == 1803);
+ assert_or_panic(v[18] == 1804);
+ assert_or_panic(v[19] == 1805);
+ assert_or_panic(v[20] == 1806);
+ assert_or_panic(v[21] == 1807);
+ assert_or_panic(v[22] == 1808);
+ assert_or_panic(v[23] == 1809);
+ assert_or_panic(v[24] == 1810);
+ assert_or_panic(v[25] == 1811);
+ assert_or_panic(v[26] == 1812);
+ assert_or_panic(v[27] == 1813);
+ assert_or_panic(v[28] == 1814);
+ assert_or_panic(v[29] == 1815);
+ assert_or_panic(v[30] == 1816);
+ assert_or_panic(v[31] == 1817);
+ assert_or_panic(v[32] == 1818);
+ assert_or_panic(v[33] == 1819);
+ assert_or_panic(v[34] == 1820);
+ assert_or_panic(v[35] == 1821);
+ assert_or_panic(v[36] == 1822);
+ assert_or_panic(v[37] == 1823);
+ assert_or_panic(v[38] == 1824);
+ assert_or_panic(v[39] == 1825);
+ assert_or_panic(v[40] == 1826);
+ assert_or_panic(v[41] == 1827);
+ assert_or_panic(v[42] == 1828);
+ assert_or_panic(v[43] == 1829);
+ assert_or_panic(v[44] == 1830);
+ assert_or_panic(v[45] == 1831);
+ assert_or_panic(v[46] == 1832);
+ assert_or_panic(v[47] == 1833);
+ assert_or_panic(v[48] == 1834);
+ assert_or_panic(v[49] == 1835);
+ assert_or_panic(v[50] == 1836);
+ assert_or_panic(v[51] == 1837);
+ assert_or_panic(v[52] == 1838);
+ assert_or_panic(v[53] == 1839);
+ assert_or_panic(v[54] == 1840);
+ assert_or_panic(v[55] == 1841);
+ assert_or_panic(v[56] == 1842);
+ assert_or_panic(v[57] == 1843);
+ assert_or_panic(v[58] == 1844);
+ assert_or_panic(v[59] == 1845);
+ assert_or_panic(v[60] == 1846);
+ assert_or_panic(v[61] == 1847);
+ assert_or_panic(v[62] == 1848);
+ assert_or_panic(v[63] == 1849);
+ assert_or_panic(v[64] == 1850);
+ assert_or_panic(v[65] == 1851);
+ assert_or_panic(v[66] == 1852);
+ assert_or_panic(v[67] == 1853);
+ assert_or_panic(v[68] == 1854);
+ assert_or_panic(v[69] == 1855);
+ assert_or_panic(v[70] == 1856);
+ assert_or_panic(v[71] == 1857);
+ assert_or_panic(v[72] == 1858);
+ assert_or_panic(v[73] == 1859);
+ assert_or_panic(v[74] == 1860);
+ assert_or_panic(v[75] == 1861);
+ assert_or_panic(v[76] == 1862);
+ assert_or_panic(v[77] == 1863);
+ assert_or_panic(v[78] == 1864);
+ assert_or_panic(v[79] == 1865);
+ assert_or_panic(v[80] == 1866);
+ assert_or_panic(v[81] == 1867);
+ assert_or_panic(v[82] == 1868);
+ assert_or_panic(v[83] == 1869);
+ assert_or_panic(v[84] == 1870);
+ assert_or_panic(v[85] == 1871);
+ assert_or_panic(v[86] == 1872);
+ assert_or_panic(v[87] == 1873);
+ assert_or_panic(v[88] == 1874);
+ assert_or_panic(v[89] == 1875);
+ assert_or_panic(v[90] == 1876);
+ assert_or_panic(v[91] == 1877);
+ assert_or_panic(v[92] == 1878);
+ assert_or_panic(v[93] == 1879);
+ assert_or_panic(v[94] == 1880);
+ assert_or_panic(v[95] == 1881);
+ assert_or_panic(v[96] == 1882);
+ assert_or_panic(v[97] == 1883);
+ assert_or_panic(v[98] == 1884);
+ assert_or_panic(v[99] == 1885);
+ assert_or_panic(v[100] == 1886);
+ assert_or_panic(v[101] == 1887);
+ assert_or_panic(v[102] == 1888);
+ assert_or_panic(v[103] == 1889);
+ assert_or_panic(v[104] == 1890);
+ assert_or_panic(v[105] == 1891);
+ assert_or_panic(v[106] == 1892);
+ assert_or_panic(v[107] == 1893);
+ assert_or_panic(v[108] == 1894);
+ assert_or_panic(v[109] == 1895);
+ assert_or_panic(v[110] == 1896);
+ assert_or_panic(v[111] == 1897);
+ assert_or_panic(v[112] == 1898);
+ assert_or_panic(v[113] == 1899);
+ assert_or_panic(v[114] == 1900);
+ assert_or_panic(v[115] == 1901);
+ assert_or_panic(v[116] == 1902);
+ assert_or_panic(v[117] == 1903);
+ assert_or_panic(v[118] == 1904);
+ assert_or_panic(v[119] == 1905);
+ assert_or_panic(v[120] == 1906);
+ assert_or_panic(v[121] == 1907);
+ assert_or_panic(v[122] == 1908);
+ assert_or_panic(v[123] == 1909);
+ assert_or_panic(v[124] == 1910);
+ assert_or_panic(v[125] == 1911);
+ assert_or_panic(v[126] == 1912);
+ assert_or_panic(v[127] == 1913);
+ assert_or_panic(v[128] == 1914);
+ assert_or_panic(v[129] == 1915);
+ assert_or_panic(v[130] == 1916);
+ assert_or_panic(v[131] == 1917);
+ assert_or_panic(v[132] == 1918);
+ assert_or_panic(v[133] == 1919);
+ assert_or_panic(v[134] == 1920);
+ assert_or_panic(v[135] == 1921);
+ assert_or_panic(v[136] == 1922);
+ assert_or_panic(v[137] == 1923);
+ assert_or_panic(v[138] == 1924);
+ assert_or_panic(v[139] == 1925);
+ assert_or_panic(v[140] == 1926);
+ assert_or_panic(v[141] == 1927);
+ assert_or_panic(v[142] == 1928);
+ assert_or_panic(v[143] == 1929);
+ assert_or_panic(v[144] == 1930);
+ assert_or_panic(v[145] == 1931);
+ assert_or_panic(v[146] == 1932);
+ assert_or_panic(v[147] == 1933);
+ assert_or_panic(v[148] == 1934);
+ assert_or_panic(v[149] == 1935);
+ assert_or_panic(v[150] == 1936);
+ assert_or_panic(v[151] == 1937);
+ assert_or_panic(v[152] == 1938);
+ assert_or_panic(v[153] == 1939);
+ assert_or_panic(v[154] == 1940);
+ assert_or_panic(v[155] == 1941);
+ assert_or_panic(v[156] == 1942);
+ assert_or_panic(v[157] == 1943);
+ assert_or_panic(v[158] == 1944);
+ assert_or_panic(v[159] == 1945);
+ assert_or_panic(v[160] == 1946);
+ assert_or_panic(v[161] == 1947);
+ assert_or_panic(v[162] == 1948);
+ assert_or_panic(v[163] == 1949);
+ assert_or_panic(v[164] == 1950);
+ assert_or_panic(v[165] == 1951);
+ assert_or_panic(v[166] == 1952);
+ assert_or_panic(v[167] == 1953);
+ assert_or_panic(v[168] == 1954);
+ assert_or_panic(v[169] == 1955);
+ assert_or_panic(v[170] == 1956);
+ assert_or_panic(v[171] == 1957);
+ assert_or_panic(v[172] == 1958);
+ assert_or_panic(v[173] == 1959);
+ assert_or_panic(v[174] == 1960);
+ assert_or_panic(v[175] == 1961);
+ assert_or_panic(v[176] == 1962);
+ assert_or_panic(v[177] == 1963);
+ assert_or_panic(v[178] == 1964);
+ assert_or_panic(v[179] == 1965);
+ assert_or_panic(v[180] == 1966);
+ assert_or_panic(v[181] == 1967);
+ assert_or_panic(v[182] == 1968);
+ assert_or_panic(v[183] == 1969);
+ assert_or_panic(v[184] == 1970);
+ assert_or_panic(v[185] == 1971);
+ assert_or_panic(v[186] == 1972);
+ assert_or_panic(v[187] == 1973);
+ assert_or_panic(v[188] == 1974);
+ assert_or_panic(v[189] == 1975);
+ assert_or_panic(v[190] == 1976);
+ assert_or_panic(v[191] == 1977);
+ zig_vector_192_u16((Vector_192_u16){
+ 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993,
+ 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+ 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025,
+ 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041,
+ 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057,
+ 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073,
+ 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089,
+ 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105,
+ 2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121,
+ 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137,
+ 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, 2152, 2153,
+ 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169,
+ }, 192);
+}
+
+typedef uint16_t Vector_256_u16 __attribute__((vector_size(256 * sizeof(uint16_t))));
+
+Vector_256_u16 zig_ret_vector_256_u16(void);
+void zig_vector_256_u16(Vector_256_u16, size_t);
+
+Vector_256_u16 c_ret_vector_256_u16(void) {
+ return (Vector_256_u16){
+ 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, 3079, 3080, 3081,
+ 3082, 3083, 3084, 3085, 3086, 3087, 3088, 3089, 3090, 3091, 3092, 3093, 3094, 3095, 3096, 3097,
+ 3098, 3099, 3100, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111, 3112, 3113,
+ 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126, 3127, 3128, 3129,
+ 3130, 3131, 3132, 3133, 3134, 3135, 3136, 3137, 3138, 3139, 3140, 3141, 3142, 3143, 3144, 3145,
+ 3146, 3147, 3148, 3149, 3150, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161,
+ 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176, 3177,
+ 3178, 3179, 3180, 3181, 3182, 3183, 3184, 3185, 3186, 3187, 3188, 3189, 3190, 3191, 3192, 3193,
+ 3194, 3195, 3196, 3197, 3198, 3199, 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209,
+ 3210, 3211, 3212, 3213, 3214, 3215, 3216, 3217, 3218, 3219, 3220, 3221, 3222, 3223, 3224, 3225,
+ 3226, 3227, 3228, 3229, 3230, 3231, 3232, 3233, 3234, 3235, 3236, 3237, 3238, 3239, 3240, 3241,
+ 3242, 3243, 3244, 3245, 3246, 3247, 3248, 3249, 3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257,
+ 3258, 3259, 3260, 3261, 3262, 3263, 3264, 3265, 3266, 3267, 3268, 3269, 3270, 3271, 3272, 3273,
+ 3274, 3275, 3276, 3277, 3278, 3279, 3280, 3281, 3282, 3283, 3284, 3285, 3286, 3287, 3288, 3289,
+ 3290, 3291, 3292, 3293, 3294, 3295, 3296, 3297, 3298, 3299, 3300, 3301, 3302, 3303, 3304, 3305,
+ 3306, 3307, 3308, 3309, 3310, 3311, 3312, 3313, 3314, 3315, 3316, 3317, 3318, 3319, 3320, 3321,
+ };
+}
+void c_vector_256_u16(Vector_256_u16 v, size_t i) {
+ assert_or_panic(v[0] == 3322);
+ assert_or_panic(v[1] == 3323);
+ assert_or_panic(v[2] == 3324);
+ assert_or_panic(v[3] == 3325);
+ assert_or_panic(v[4] == 3326);
+ assert_or_panic(v[5] == 3327);
+ assert_or_panic(v[6] == 3328);
+ assert_or_panic(v[7] == 3329);
+ assert_or_panic(v[8] == 3330);
+ assert_or_panic(v[9] == 3331);
+ assert_or_panic(v[10] == 3332);
+ assert_or_panic(v[11] == 3333);
+ assert_or_panic(v[12] == 3334);
+ assert_or_panic(v[13] == 3335);
+ assert_or_panic(v[14] == 3336);
+ assert_or_panic(v[15] == 3337);
+ assert_or_panic(v[16] == 3338);
+ assert_or_panic(v[17] == 3339);
+ assert_or_panic(v[18] == 3340);
+ assert_or_panic(v[19] == 3341);
+ assert_or_panic(v[20] == 3342);
+ assert_or_panic(v[21] == 3343);
+ assert_or_panic(v[22] == 3344);
+ assert_or_panic(v[23] == 3345);
+ assert_or_panic(v[24] == 3346);
+ assert_or_panic(v[25] == 3347);
+ assert_or_panic(v[26] == 3348);
+ assert_or_panic(v[27] == 3349);
+ assert_or_panic(v[28] == 3350);
+ assert_or_panic(v[29] == 3351);
+ assert_or_panic(v[30] == 3352);
+ assert_or_panic(v[31] == 3353);
+ assert_or_panic(v[32] == 3354);
+ assert_or_panic(v[33] == 3355);
+ assert_or_panic(v[34] == 3356);
+ assert_or_panic(v[35] == 3357);
+ assert_or_panic(v[36] == 3358);
+ assert_or_panic(v[37] == 3359);
+ assert_or_panic(v[38] == 3360);
+ assert_or_panic(v[39] == 3361);
+ assert_or_panic(v[40] == 3362);
+ assert_or_panic(v[41] == 3363);
+ assert_or_panic(v[42] == 3364);
+ assert_or_panic(v[43] == 3365);
+ assert_or_panic(v[44] == 3366);
+ assert_or_panic(v[45] == 3367);
+ assert_or_panic(v[46] == 3368);
+ assert_or_panic(v[47] == 3369);
+ assert_or_panic(v[48] == 3370);
+ assert_or_panic(v[49] == 3371);
+ assert_or_panic(v[50] == 3372);
+ assert_or_panic(v[51] == 3373);
+ assert_or_panic(v[52] == 3374);
+ assert_or_panic(v[53] == 3375);
+ assert_or_panic(v[54] == 3376);
+ assert_or_panic(v[55] == 3377);
+ assert_or_panic(v[56] == 3378);
+ assert_or_panic(v[57] == 3379);
+ assert_or_panic(v[58] == 3380);
+ assert_or_panic(v[59] == 3381);
+ assert_or_panic(v[60] == 3382);
+ assert_or_panic(v[61] == 3383);
+ assert_or_panic(v[62] == 3384);
+ assert_or_panic(v[63] == 3385);
+ assert_or_panic(v[64] == 3386);
+ assert_or_panic(v[65] == 3387);
+ assert_or_panic(v[66] == 3388);
+ assert_or_panic(v[67] == 3389);
+ assert_or_panic(v[68] == 3390);
+ assert_or_panic(v[69] == 3391);
+ assert_or_panic(v[70] == 3392);
+ assert_or_panic(v[71] == 3393);
+ assert_or_panic(v[72] == 3394);
+ assert_or_panic(v[73] == 3395);
+ assert_or_panic(v[74] == 3396);
+ assert_or_panic(v[75] == 3397);
+ assert_or_panic(v[76] == 3398);
+ assert_or_panic(v[77] == 3399);
+ assert_or_panic(v[78] == 3400);
+ assert_or_panic(v[79] == 3401);
+ assert_or_panic(v[80] == 3402);
+ assert_or_panic(v[81] == 3403);
+ assert_or_panic(v[82] == 3404);
+ assert_or_panic(v[83] == 3405);
+ assert_or_panic(v[84] == 3406);
+ assert_or_panic(v[85] == 3407);
+ assert_or_panic(v[86] == 3408);
+ assert_or_panic(v[87] == 3409);
+ assert_or_panic(v[88] == 3410);
+ assert_or_panic(v[89] == 3411);
+ assert_or_panic(v[90] == 3412);
+ assert_or_panic(v[91] == 3413);
+ assert_or_panic(v[92] == 3414);
+ assert_or_panic(v[93] == 3415);
+ assert_or_panic(v[94] == 3416);
+ assert_or_panic(v[95] == 3417);
+ assert_or_panic(v[96] == 3418);
+ assert_or_panic(v[97] == 3419);
+ assert_or_panic(v[98] == 3420);
+ assert_or_panic(v[99] == 3421);
+ assert_or_panic(v[100] == 3422);
+ assert_or_panic(v[101] == 3423);
+ assert_or_panic(v[102] == 3424);
+ assert_or_panic(v[103] == 3425);
+ assert_or_panic(v[104] == 3426);
+ assert_or_panic(v[105] == 3427);
+ assert_or_panic(v[106] == 3428);
+ assert_or_panic(v[107] == 3429);
+ assert_or_panic(v[108] == 3430);
+ assert_or_panic(v[109] == 3431);
+ assert_or_panic(v[110] == 3432);
+ assert_or_panic(v[111] == 3433);
+ assert_or_panic(v[112] == 3434);
+ assert_or_panic(v[113] == 3435);
+ assert_or_panic(v[114] == 3436);
+ assert_or_panic(v[115] == 3437);
+ assert_or_panic(v[116] == 3438);
+ assert_or_panic(v[117] == 3439);
+ assert_or_panic(v[118] == 3440);
+ assert_or_panic(v[119] == 3441);
+ assert_or_panic(v[120] == 3442);
+ assert_or_panic(v[121] == 3443);
+ assert_or_panic(v[122] == 3444);
+ assert_or_panic(v[123] == 3445);
+ assert_or_panic(v[124] == 3446);
+ assert_or_panic(v[125] == 3447);
+ assert_or_panic(v[126] == 3448);
+ assert_or_panic(v[127] == 3449);
+ assert_or_panic(v[128] == 3450);
+ assert_or_panic(v[129] == 3451);
+ assert_or_panic(v[130] == 3452);
+ assert_or_panic(v[131] == 3453);
+ assert_or_panic(v[132] == 3454);
+ assert_or_panic(v[133] == 3455);
+ assert_or_panic(v[134] == 3456);
+ assert_or_panic(v[135] == 3457);
+ assert_or_panic(v[136] == 3458);
+ assert_or_panic(v[137] == 3459);
+ assert_or_panic(v[138] == 3460);
+ assert_or_panic(v[139] == 3461);
+ assert_or_panic(v[140] == 3462);
+ assert_or_panic(v[141] == 3463);
+ assert_or_panic(v[142] == 3464);
+ assert_or_panic(v[143] == 3465);
+ assert_or_panic(v[144] == 3466);
+ assert_or_panic(v[145] == 3467);
+ assert_or_panic(v[146] == 3468);
+ assert_or_panic(v[147] == 3469);
+ assert_or_panic(v[148] == 3470);
+ assert_or_panic(v[149] == 3471);
+ assert_or_panic(v[150] == 3472);
+ assert_or_panic(v[151] == 3473);
+ assert_or_panic(v[152] == 3474);
+ assert_or_panic(v[153] == 3475);
+ assert_or_panic(v[154] == 3476);
+ assert_or_panic(v[155] == 3477);
+ assert_or_panic(v[156] == 3478);
+ assert_or_panic(v[157] == 3479);
+ assert_or_panic(v[158] == 3480);
+ assert_or_panic(v[159] == 3481);
+ assert_or_panic(v[160] == 3482);
+ assert_or_panic(v[161] == 3483);
+ assert_or_panic(v[162] == 3484);
+ assert_or_panic(v[163] == 3485);
+ assert_or_panic(v[164] == 3486);
+ assert_or_panic(v[165] == 3487);
+ assert_or_panic(v[166] == 3488);
+ assert_or_panic(v[167] == 3489);
+ assert_or_panic(v[168] == 3490);
+ assert_or_panic(v[169] == 3491);
+ assert_or_panic(v[170] == 3492);
+ assert_or_panic(v[171] == 3493);
+ assert_or_panic(v[172] == 3494);
+ assert_or_panic(v[173] == 3495);
+ assert_or_panic(v[174] == 3496);
+ assert_or_panic(v[175] == 3497);
+ assert_or_panic(v[176] == 3498);
+ assert_or_panic(v[177] == 3499);
+ assert_or_panic(v[178] == 3500);
+ assert_or_panic(v[179] == 3501);
+ assert_or_panic(v[180] == 3502);
+ assert_or_panic(v[181] == 3503);
+ assert_or_panic(v[182] == 3504);
+ assert_or_panic(v[183] == 3505);
+ assert_or_panic(v[184] == 3506);
+ assert_or_panic(v[185] == 3507);
+ assert_or_panic(v[186] == 3508);
+ assert_or_panic(v[187] == 3509);
+ assert_or_panic(v[188] == 3510);
+ assert_or_panic(v[189] == 3511);
+ assert_or_panic(v[190] == 3512);
+ assert_or_panic(v[191] == 3513);
+ assert_or_panic(v[192] == 3514);
+ assert_or_panic(v[193] == 3515);
+ assert_or_panic(v[194] == 3516);
+ assert_or_panic(v[195] == 3517);
+ assert_or_panic(v[196] == 3518);
+ assert_or_panic(v[197] == 3519);
+ assert_or_panic(v[198] == 3520);
+ assert_or_panic(v[199] == 3521);
+ assert_or_panic(v[200] == 3522);
+ assert_or_panic(v[201] == 3523);
+ assert_or_panic(v[202] == 3524);
+ assert_or_panic(v[203] == 3525);
+ assert_or_panic(v[204] == 3526);
+ assert_or_panic(v[205] == 3527);
+ assert_or_panic(v[206] == 3528);
+ assert_or_panic(v[207] == 3529);
+ assert_or_panic(v[208] == 3530);
+ assert_or_panic(v[209] == 3531);
+ assert_or_panic(v[210] == 3532);
+ assert_or_panic(v[211] == 3533);
+ assert_or_panic(v[212] == 3534);
+ assert_or_panic(v[213] == 3535);
+ assert_or_panic(v[214] == 3536);
+ assert_or_panic(v[215] == 3537);
+ assert_or_panic(v[216] == 3538);
+ assert_or_panic(v[217] == 3539);
+ assert_or_panic(v[218] == 3540);
+ assert_or_panic(v[219] == 3541);
+ assert_or_panic(v[220] == 3542);
+ assert_or_panic(v[221] == 3543);
+ assert_or_panic(v[222] == 3544);
+ assert_or_panic(v[223] == 3545);
+ assert_or_panic(v[224] == 3546);
+ assert_or_panic(v[225] == 3547);
+ assert_or_panic(v[226] == 3548);
+ assert_or_panic(v[227] == 3549);
+ assert_or_panic(v[228] == 3550);
+ assert_or_panic(v[229] == 3551);
+ assert_or_panic(v[230] == 3552);
+ assert_or_panic(v[231] == 3553);
+ assert_or_panic(v[232] == 3554);
+ assert_or_panic(v[233] == 3555);
+ assert_or_panic(v[234] == 3556);
+ assert_or_panic(v[235] == 3557);
+ assert_or_panic(v[236] == 3558);
+ assert_or_panic(v[237] == 3559);
+ assert_or_panic(v[238] == 3560);
+ assert_or_panic(v[239] == 3561);
+ assert_or_panic(v[240] == 3562);
+ assert_or_panic(v[241] == 3563);
+ assert_or_panic(v[242] == 3564);
+ assert_or_panic(v[243] == 3565);
+ assert_or_panic(v[244] == 3566);
+ assert_or_panic(v[245] == 3567);
+ assert_or_panic(v[246] == 3568);
+ assert_or_panic(v[247] == 3569);
+ assert_or_panic(v[248] == 3570);
+ assert_or_panic(v[249] == 3571);
+ assert_or_panic(v[250] == 3572);
+ assert_or_panic(v[251] == 3573);
+ assert_or_panic(v[252] == 3574);
+ assert_or_panic(v[253] == 3575);
+ assert_or_panic(v[254] == 3576);
+ assert_or_panic(v[255] == 3577);
+ assert_or_panic(i == 256);
+}
+void c_test_vector_256_u16(void) {
+ Vector_256_u16 v = zig_ret_vector_256_u16();
+ assert_or_panic(v[0] == 2554);
+ assert_or_panic(v[1] == 2555);
+ assert_or_panic(v[2] == 2556);
+ assert_or_panic(v[3] == 2557);
+ assert_or_panic(v[4] == 2558);
+ assert_or_panic(v[5] == 2559);
+ assert_or_panic(v[6] == 2560);
+ assert_or_panic(v[7] == 2561);
+ assert_or_panic(v[8] == 2562);
+ assert_or_panic(v[9] == 2563);
+ assert_or_panic(v[10] == 2564);
+ assert_or_panic(v[11] == 2565);
+ assert_or_panic(v[12] == 2566);
+ assert_or_panic(v[13] == 2567);
+ assert_or_panic(v[14] == 2568);
+ assert_or_panic(v[15] == 2569);
+ assert_or_panic(v[16] == 2570);
+ assert_or_panic(v[17] == 2571);
+ assert_or_panic(v[18] == 2572);
+ assert_or_panic(v[19] == 2573);
+ assert_or_panic(v[20] == 2574);
+ assert_or_panic(v[21] == 2575);
+ assert_or_panic(v[22] == 2576);
+ assert_or_panic(v[23] == 2577);
+ assert_or_panic(v[24] == 2578);
+ assert_or_panic(v[25] == 2579);
+ assert_or_panic(v[26] == 2580);
+ assert_or_panic(v[27] == 2581);
+ assert_or_panic(v[28] == 2582);
+ assert_or_panic(v[29] == 2583);
+ assert_or_panic(v[30] == 2584);
+ assert_or_panic(v[31] == 2585);
+ assert_or_panic(v[32] == 2586);
+ assert_or_panic(v[33] == 2587);
+ assert_or_panic(v[34] == 2588);
+ assert_or_panic(v[35] == 2589);
+ assert_or_panic(v[36] == 2590);
+ assert_or_panic(v[37] == 2591);
+ assert_or_panic(v[38] == 2592);
+ assert_or_panic(v[39] == 2593);
+ assert_or_panic(v[40] == 2594);
+ assert_or_panic(v[41] == 2595);
+ assert_or_panic(v[42] == 2596);
+ assert_or_panic(v[43] == 2597);
+ assert_or_panic(v[44] == 2598);
+ assert_or_panic(v[45] == 2599);
+ assert_or_panic(v[46] == 2600);
+ assert_or_panic(v[47] == 2601);
+ assert_or_panic(v[48] == 2602);
+ assert_or_panic(v[49] == 2603);
+ assert_or_panic(v[50] == 2604);
+ assert_or_panic(v[51] == 2605);
+ assert_or_panic(v[52] == 2606);
+ assert_or_panic(v[53] == 2607);
+ assert_or_panic(v[54] == 2608);
+ assert_or_panic(v[55] == 2609);
+ assert_or_panic(v[56] == 2610);
+ assert_or_panic(v[57] == 2611);
+ assert_or_panic(v[58] == 2612);
+ assert_or_panic(v[59] == 2613);
+ assert_or_panic(v[60] == 2614);
+ assert_or_panic(v[61] == 2615);
+ assert_or_panic(v[62] == 2616);
+ assert_or_panic(v[63] == 2617);
+ assert_or_panic(v[64] == 2618);
+ assert_or_panic(v[65] == 2619);
+ assert_or_panic(v[66] == 2620);
+ assert_or_panic(v[67] == 2621);
+ assert_or_panic(v[68] == 2622);
+ assert_or_panic(v[69] == 2623);
+ assert_or_panic(v[70] == 2624);
+ assert_or_panic(v[71] == 2625);
+ assert_or_panic(v[72] == 2626);
+ assert_or_panic(v[73] == 2627);
+ assert_or_panic(v[74] == 2628);
+ assert_or_panic(v[75] == 2629);
+ assert_or_panic(v[76] == 2630);
+ assert_or_panic(v[77] == 2631);
+ assert_or_panic(v[78] == 2632);
+ assert_or_panic(v[79] == 2633);
+ assert_or_panic(v[80] == 2634);
+ assert_or_panic(v[81] == 2635);
+ assert_or_panic(v[82] == 2636);
+ assert_or_panic(v[83] == 2637);
+ assert_or_panic(v[84] == 2638);
+ assert_or_panic(v[85] == 2639);
+ assert_or_panic(v[86] == 2640);
+ assert_or_panic(v[87] == 2641);
+ assert_or_panic(v[88] == 2642);
+ assert_or_panic(v[89] == 2643);
+ assert_or_panic(v[90] == 2644);
+ assert_or_panic(v[91] == 2645);
+ assert_or_panic(v[92] == 2646);
+ assert_or_panic(v[93] == 2647);
+ assert_or_panic(v[94] == 2648);
+ assert_or_panic(v[95] == 2649);
+ assert_or_panic(v[96] == 2650);
+ assert_or_panic(v[97] == 2651);
+ assert_or_panic(v[98] == 2652);
+ assert_or_panic(v[99] == 2653);
+ assert_or_panic(v[100] == 2654);
+ assert_or_panic(v[101] == 2655);
+ assert_or_panic(v[102] == 2656);
+ assert_or_panic(v[103] == 2657);
+ assert_or_panic(v[104] == 2658);
+ assert_or_panic(v[105] == 2659);
+ assert_or_panic(v[106] == 2660);
+ assert_or_panic(v[107] == 2661);
+ assert_or_panic(v[108] == 2662);
+ assert_or_panic(v[109] == 2663);
+ assert_or_panic(v[110] == 2664);
+ assert_or_panic(v[111] == 2665);
+ assert_or_panic(v[112] == 2666);
+ assert_or_panic(v[113] == 2667);
+ assert_or_panic(v[114] == 2668);
+ assert_or_panic(v[115] == 2669);
+ assert_or_panic(v[116] == 2670);
+ assert_or_panic(v[117] == 2671);
+ assert_or_panic(v[118] == 2672);
+ assert_or_panic(v[119] == 2673);
+ assert_or_panic(v[120] == 2674);
+ assert_or_panic(v[121] == 2675);
+ assert_or_panic(v[122] == 2676);
+ assert_or_panic(v[123] == 2677);
+ assert_or_panic(v[124] == 2678);
+ assert_or_panic(v[125] == 2679);
+ assert_or_panic(v[126] == 2680);
+ assert_or_panic(v[127] == 2681);
+ assert_or_panic(v[128] == 2682);
+ assert_or_panic(v[129] == 2683);
+ assert_or_panic(v[130] == 2684);
+ assert_or_panic(v[131] == 2685);
+ assert_or_panic(v[132] == 2686);
+ assert_or_panic(v[133] == 2687);
+ assert_or_panic(v[134] == 2688);
+ assert_or_panic(v[135] == 2689);
+ assert_or_panic(v[136] == 2690);
+ assert_or_panic(v[137] == 2691);
+ assert_or_panic(v[138] == 2692);
+ assert_or_panic(v[139] == 2693);
+ assert_or_panic(v[140] == 2694);
+ assert_or_panic(v[141] == 2695);
+ assert_or_panic(v[142] == 2696);
+ assert_or_panic(v[143] == 2697);
+ assert_or_panic(v[144] == 2698);
+ assert_or_panic(v[145] == 2699);
+ assert_or_panic(v[146] == 2700);
+ assert_or_panic(v[147] == 2701);
+ assert_or_panic(v[148] == 2702);
+ assert_or_panic(v[149] == 2703);
+ assert_or_panic(v[150] == 2704);
+ assert_or_panic(v[151] == 2705);
+ assert_or_panic(v[152] == 2706);
+ assert_or_panic(v[153] == 2707);
+ assert_or_panic(v[154] == 2708);
+ assert_or_panic(v[155] == 2709);
+ assert_or_panic(v[156] == 2710);
+ assert_or_panic(v[157] == 2711);
+ assert_or_panic(v[158] == 2712);
+ assert_or_panic(v[159] == 2713);
+ assert_or_panic(v[160] == 2714);
+ assert_or_panic(v[161] == 2715);
+ assert_or_panic(v[162] == 2716);
+ assert_or_panic(v[163] == 2717);
+ assert_or_panic(v[164] == 2718);
+ assert_or_panic(v[165] == 2719);
+ assert_or_panic(v[166] == 2720);
+ assert_or_panic(v[167] == 2721);
+ assert_or_panic(v[168] == 2722);
+ assert_or_panic(v[169] == 2723);
+ assert_or_panic(v[170] == 2724);
+ assert_or_panic(v[171] == 2725);
+ assert_or_panic(v[172] == 2726);
+ assert_or_panic(v[173] == 2727);
+ assert_or_panic(v[174] == 2728);
+ assert_or_panic(v[175] == 2729);
+ assert_or_panic(v[176] == 2730);
+ assert_or_panic(v[177] == 2731);
+ assert_or_panic(v[178] == 2732);
+ assert_or_panic(v[179] == 2733);
+ assert_or_panic(v[180] == 2734);
+ assert_or_panic(v[181] == 2735);
+ assert_or_panic(v[182] == 2736);
+ assert_or_panic(v[183] == 2737);
+ assert_or_panic(v[184] == 2738);
+ assert_or_panic(v[185] == 2739);
+ assert_or_panic(v[186] == 2740);
+ assert_or_panic(v[187] == 2741);
+ assert_or_panic(v[188] == 2742);
+ assert_or_panic(v[189] == 2743);
+ assert_or_panic(v[190] == 2744);
+ assert_or_panic(v[191] == 2745);
+ assert_or_panic(v[192] == 2746);
+ assert_or_panic(v[193] == 2747);
+ assert_or_panic(v[194] == 2748);
+ assert_or_panic(v[195] == 2749);
+ assert_or_panic(v[196] == 2750);
+ assert_or_panic(v[197] == 2751);
+ assert_or_panic(v[198] == 2752);
+ assert_or_panic(v[199] == 2753);
+ assert_or_panic(v[200] == 2754);
+ assert_or_panic(v[201] == 2755);
+ assert_or_panic(v[202] == 2756);
+ assert_or_panic(v[203] == 2757);
+ assert_or_panic(v[204] == 2758);
+ assert_or_panic(v[205] == 2759);
+ assert_or_panic(v[206] == 2760);
+ assert_or_panic(v[207] == 2761);
+ assert_or_panic(v[208] == 2762);
+ assert_or_panic(v[209] == 2763);
+ assert_or_panic(v[210] == 2764);
+ assert_or_panic(v[211] == 2765);
+ assert_or_panic(v[212] == 2766);
+ assert_or_panic(v[213] == 2767);
+ assert_or_panic(v[214] == 2768);
+ assert_or_panic(v[215] == 2769);
+ assert_or_panic(v[216] == 2770);
+ assert_or_panic(v[217] == 2771);
+ assert_or_panic(v[218] == 2772);
+ assert_or_panic(v[219] == 2773);
+ assert_or_panic(v[220] == 2774);
+ assert_or_panic(v[221] == 2775);
+ assert_or_panic(v[222] == 2776);
+ assert_or_panic(v[223] == 2777);
+ assert_or_panic(v[224] == 2778);
+ assert_or_panic(v[225] == 2779);
+ assert_or_panic(v[226] == 2780);
+ assert_or_panic(v[227] == 2781);
+ assert_or_panic(v[228] == 2782);
+ assert_or_panic(v[229] == 2783);
+ assert_or_panic(v[230] == 2784);
+ assert_or_panic(v[231] == 2785);
+ assert_or_panic(v[232] == 2786);
+ assert_or_panic(v[233] == 2787);
+ assert_or_panic(v[234] == 2788);
+ assert_or_panic(v[235] == 2789);
+ assert_or_panic(v[236] == 2790);
+ assert_or_panic(v[237] == 2791);
+ assert_or_panic(v[238] == 2792);
+ assert_or_panic(v[239] == 2793);
+ assert_or_panic(v[240] == 2794);
+ assert_or_panic(v[241] == 2795);
+ assert_or_panic(v[242] == 2796);
+ assert_or_panic(v[243] == 2797);
+ assert_or_panic(v[244] == 2798);
+ assert_or_panic(v[245] == 2799);
+ assert_or_panic(v[246] == 2800);
+ assert_or_panic(v[247] == 2801);
+ assert_or_panic(v[248] == 2802);
+ assert_or_panic(v[249] == 2803);
+ assert_or_panic(v[250] == 2804);
+ assert_or_panic(v[251] == 2805);
+ assert_or_panic(v[252] == 2806);
+ assert_or_panic(v[253] == 2807);
+ assert_or_panic(v[254] == 2808);
+ assert_or_panic(v[255] == 2809);
+ zig_vector_256_u16((Vector_256_u16){
+ 2810, 2811, 2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825,
+ 2826, 2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, 2841,
+ 2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856, 2857,
+ 2858, 2859, 2860, 2861, 2862, 2863, 2864, 2865, 2866, 2867, 2868, 2869, 2870, 2871, 2872, 2873,
+ 2874, 2875, 2876, 2877, 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2885, 2886, 2887, 2888, 2889,
+ 2890, 2891, 2892, 2893, 2894, 2895, 2896, 2897, 2898, 2899, 2900, 2901, 2902, 2903, 2904, 2905,
+ 2906, 2907, 2908, 2909, 2910, 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921,
+ 2922, 2923, 2924, 2925, 2926, 2927, 2928, 2929, 2930, 2931, 2932, 2933, 2934, 2935, 2936, 2937,
+ 2938, 2939, 2940, 2941, 2942, 2943, 2944, 2945, 2946, 2947, 2948, 2949, 2950, 2951, 2952, 2953,
+ 2954, 2955, 2956, 2957, 2958, 2959, 2960, 2961, 2962, 2963, 2964, 2965, 2966, 2967, 2968, 2969,
+ 2970, 2971, 2972, 2973, 2974, 2975, 2976, 2977, 2978, 2979, 2980, 2981, 2982, 2983, 2984, 2985,
+ 2986, 2987, 2988, 2989, 2990, 2991, 2992, 2993, 2994, 2995, 2996, 2997, 2998, 2999, 3000, 3001,
+ 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017,
+ 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 3027, 3028, 3029, 3030, 3031, 3032, 3033,
+ 3034, 3035, 3036, 3037, 3038, 3039, 3040, 3041, 3042, 3043, 3044, 3045, 3046, 3047, 3048, 3049,
+ 3050, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063, 3064, 3065,
+ }, 256);
+}
+
+typedef uint32_t Vector_1_u32 __attribute__((vector_size(1 * sizeof(uint32_t))));
+
+Vector_1_u32 zig_ret_vector_1_u32(void);
+void zig_vector_1_u32(Vector_1_u32, size_t);
+
+Vector_1_u32 c_ret_vector_1_u32(void) {
+ return (Vector_1_u32){ 3 };
+}
+void c_vector_1_u32(Vector_1_u32 v, size_t i) {
+ assert_or_panic(v[0] == 4);
+ assert_or_panic(i == 1);
+}
+void c_test_vector_1_u32(void) {
+ Vector_1_u32 v = zig_ret_vector_1_u32();
+ assert_or_panic(v[0] == 1);
+ zig_vector_1_u32((Vector_1_u32){ 2 }, 1);
+}
+
+typedef uint32_t Vector_2_u32 __attribute__((vector_size(2 * sizeof(uint32_t))));
+
+Vector_2_u32 zig_ret_vector_2_u32(void);
+void zig_vector_2_u32(Vector_2_u32, size_t);
+
+Vector_2_u32 c_ret_vector_2_u32(void) {
+ return (Vector_2_u32){ 9, 10 };
+}
+void c_vector_2_u32(Vector_2_u32 v, size_t i) {
+ assert_or_panic(v[0] == 11);
+ assert_or_panic(v[1] == 12);
+ assert_or_panic(i == 2);
+}
+void c_test_vector_2_u32(void) {
+ Vector_2_u32 v = zig_ret_vector_2_u32();
+ assert_or_panic(v[0] == 5);
+ assert_or_panic(v[1] == 6);
+ zig_vector_2_u32((Vector_2_u32){ 7, 8 }, 2);
+}
+
+typedef uint32_t Vector_3_u32 __attribute__((vector_size(3 * sizeof(uint32_t))));
+
+Vector_3_u32 zig_ret_vector_3_u32(void);
+void zig_vector_3_u32(Vector_3_u32, size_t);
+
+Vector_3_u32 c_ret_vector_3_u32(void) {
+ return (Vector_3_u32){ 19, 20, 21 };
+}
+void c_vector_3_u32(Vector_3_u32 v, size_t i) {
+ assert_or_panic(v[0] == 22);
+ assert_or_panic(v[1] == 23);
+ assert_or_panic(v[2] == 24);
+ assert_or_panic(i == 3);
+}
+void c_test_vector_3_u32(void) {
+ Vector_3_u32 v = zig_ret_vector_3_u32();
+ assert_or_panic(v[0] == 13);
+ assert_or_panic(v[1] == 14);
+ assert_or_panic(v[2] == 15);
+ zig_vector_3_u32((Vector_3_u32){ 16, 17, 18 }, 3);
+}
+
+typedef uint32_t Vector_4_u32 __attribute__((vector_size(4 * sizeof(uint32_t))));
+
+Vector_4_u32 zig_ret_vector_4_u32(void);
+
+void zig_vector_4_u32(Vector_4_u32, size_t);
+void zig_vector_4_u32_vector_4_u32(Vector_4_u32, Vector_4_u32, size_t);
+
+Vector_4_u32 c_ret_vector_4_u32(void) {
+ return (Vector_4_u32){ 41, 42, 43, 44 };
+}
+void c_vector_4_u32(Vector_4_u32 v, size_t i) {
+ assert_or_panic(v[0] == 45);
+ assert_or_panic(v[1] == 46);
+ assert_or_panic(v[2] == 47);
+ assert_or_panic(v[3] == 48);
+ assert_or_panic(i == 4);
+}
+void c_vector_4_u32_vector_4_u32(Vector_4_u32 v0, Vector_4_u32 v1, size_t i) {
+ assert_or_panic(v0[0] == 49);
+ assert_or_panic(v0[1] == 50);
+ assert_or_panic(v0[2] == 51);
+ assert_or_panic(v0[3] == 52);
+ assert_or_panic(v1[0] == 53);
+ assert_or_panic(v1[1] == 54);
+ assert_or_panic(v1[2] == 55);
+ assert_or_panic(v1[3] == 56);
+ assert_or_panic(i == 8);
+}
+void c_test_vector_4_u32(void) {
+ Vector_4_u32 v = zig_ret_vector_4_u32();
+ assert_or_panic(v[0] == 25);
+ assert_or_panic(v[1] == 26);
+ assert_or_panic(v[2] == 27);
+ assert_or_panic(v[3] == 28);
+ zig_vector_4_u32((Vector_4_u32){ 29, 30, 31, 32 }, 4);
+ zig_vector_4_u32_vector_4_u32((Vector_4_u32){ 33, 34, 35, 36 }, (Vector_4_u32){ 37, 38, 39, 40 }, 8);
+}
+
+typedef uint32_t Vector_6_u32 __attribute__((vector_size(6 * sizeof(uint32_t))));
+
+Vector_6_u32 zig_ret_vector_6_u32(void);
+void zig_vector_6_u32(Vector_6_u32, size_t);
+
+Vector_6_u32 c_ret_vector_6_u32(void) {
+ return (Vector_6_u32){ 53, 54, 55, 56, 57, 58 };
+}
+void c_vector_6_u32(Vector_6_u32 v, size_t i) {
+ assert_or_panic(v[0] == 59);
+ assert_or_panic(v[1] == 60);
+ assert_or_panic(v[2] == 61);
+ assert_or_panic(v[3] == 62);
+ assert_or_panic(v[4] == 63);
+ assert_or_panic(v[5] == 64);
+ assert_or_panic(i == 6);
+}
+void c_test_vector_6_u32(void) {
+ Vector_6_u32 v = zig_ret_vector_6_u32();
+ assert_or_panic(v[0] == 41);
+ assert_or_panic(v[1] == 42);
+ assert_or_panic(v[2] == 43);
+ assert_or_panic(v[3] == 44);
+ assert_or_panic(v[4] == 45);
+ assert_or_panic(v[5] == 46);
+ zig_vector_6_u32((Vector_6_u32){ 47, 48, 49, 50, 51, 52 }, 6);
+}
+
+typedef uint32_t Vector_8_u32 __attribute__((vector_size(8 * sizeof(uint32_t))));
+
+Vector_8_u32 zig_ret_vector_8_u32(void);
+void zig_vector_8_u32(Vector_8_u32, size_t);
+
+Vector_8_u32 c_ret_vector_8_u32(void) {
+ return (Vector_8_u32){ 81, 82, 83, 84, 85, 86, 87, 88 };
+}
+void c_vector_8_u32(Vector_8_u32 v, size_t i) {
+ assert_or_panic(v[0] == 89);
+ assert_or_panic(v[1] == 90);
+ assert_or_panic(v[2] == 91);
+ assert_or_panic(v[3] == 92);
+ assert_or_panic(v[4] == 93);
+ assert_or_panic(v[5] == 94);
+ assert_or_panic(v[6] == 95);
+ assert_or_panic(v[7] == 96);
+ assert_or_panic(i == 8);
+}
+void c_test_vector_8_u32(void) {
+ Vector_8_u32 v = zig_ret_vector_8_u32();
+ assert_or_panic(v[0] == 65);
+ assert_or_panic(v[1] == 66);
+ assert_or_panic(v[2] == 67);
+ assert_or_panic(v[3] == 68);
+ assert_or_panic(v[4] == 69);
+ assert_or_panic(v[5] == 70);
+ assert_or_panic(v[6] == 71);
+ assert_or_panic(v[7] == 72);
+ zig_vector_8_u32((Vector_8_u32){ 73, 74, 75, 76, 77, 78, 79, 80 }, 8);
+}
+
+typedef uint32_t Vector_12_u32 __attribute__((vector_size(12 * sizeof(uint32_t))));
+
+Vector_12_u32 zig_ret_vector_12_u32(void);
+void zig_vector_12_u32(Vector_12_u32, size_t);
+
+Vector_12_u32 c_ret_vector_12_u32(void) {
+ return (Vector_12_u32){ 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132 };
+}
+void c_vector_12_u32(Vector_12_u32 v, size_t i) {
+ assert_or_panic(v[0] == 133);
+ assert_or_panic(v[1] == 134);
+ assert_or_panic(v[2] == 135);
+ assert_or_panic(v[3] == 136);
+ assert_or_panic(v[4] == 137);
+ assert_or_panic(v[5] == 138);
+ assert_or_panic(v[6] == 139);
+ assert_or_panic(v[7] == 140);
+ assert_or_panic(v[8] == 141);
+ assert_or_panic(v[9] == 142);
+ assert_or_panic(v[10] == 143);
+ assert_or_panic(v[11] == 144);
+ assert_or_panic(i == 12);
+}
+void c_test_vector_12_u32(void) {
+ Vector_12_u32 v = zig_ret_vector_12_u32();
+ assert_or_panic(v[0] == 97);
+ assert_or_panic(v[1] == 98);
+ assert_or_panic(v[2] == 99);
+ assert_or_panic(v[3] == 100);
+ assert_or_panic(v[4] == 101);
+ assert_or_panic(v[5] == 102);
+ assert_or_panic(v[6] == 103);
+ assert_or_panic(v[7] == 104);
+ assert_or_panic(v[8] == 105);
+ assert_or_panic(v[9] == 106);
+ assert_or_panic(v[10] == 107);
+ assert_or_panic(v[11] == 108);
+ zig_vector_12_u32((Vector_12_u32){ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120 }, 12);
+}
+
+typedef uint32_t Vector_16_u32 __attribute__((vector_size(16 * sizeof(uint32_t))));
+
+Vector_16_u32 zig_ret_vector_16_u32(void);
+void zig_vector_16_u32(Vector_16_u32, size_t);
+
+Vector_16_u32 c_ret_vector_16_u32(void) {
+ return (Vector_16_u32){ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192 };
+}
+void c_vector_16_u32(Vector_16_u32 v, size_t i) {
+ assert_or_panic(v[0] == 193);
+ assert_or_panic(v[1] == 194);
+ assert_or_panic(v[2] == 195);
+ assert_or_panic(v[3] == 196);
+ assert_or_panic(v[4] == 197);
+ assert_or_panic(v[5] == 198);
+ assert_or_panic(v[6] == 199);
+ assert_or_panic(v[7] == 200);
+ assert_or_panic(v[8] == 201);
+ assert_or_panic(v[9] == 202);
+ assert_or_panic(v[10] == 203);
+ assert_or_panic(v[11] == 204);
+ assert_or_panic(v[12] == 205);
+ assert_or_panic(v[13] == 206);
+ assert_or_panic(v[14] == 207);
+ assert_or_panic(v[15] == 208);
+ assert_or_panic(i == 16);
+}
+void c_test_vector_16_u32(void) {
+ Vector_16_u32 v = zig_ret_vector_16_u32();
+ assert_or_panic(v[0] == 145);
+ assert_or_panic(v[1] == 146);
+ assert_or_panic(v[2] == 147);
+ assert_or_panic(v[3] == 148);
+ assert_or_panic(v[4] == 149);
+ assert_or_panic(v[5] == 150);
+ assert_or_panic(v[6] == 151);
+ assert_or_panic(v[7] == 152);
+ assert_or_panic(v[8] == 153);
+ assert_or_panic(v[9] == 154);
+ assert_or_panic(v[10] == 155);
+ assert_or_panic(v[11] == 156);
+ assert_or_panic(v[12] == 157);
+ assert_or_panic(v[13] == 158);
+ assert_or_panic(v[14] == 159);
+ assert_or_panic(v[15] == 160);
+ zig_vector_16_u32((Vector_16_u32){ 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176 }, 16);
+}
+
+typedef uint32_t Vector_24_u32 __attribute__((vector_size(24 * sizeof(uint32_t))));
+
+Vector_24_u32 zig_ret_vector_24_u32(void);
+void zig_vector_24_u32(Vector_24_u32, size_t);
+
+Vector_24_u32 c_ret_vector_24_u32(void) {
+ return (Vector_24_u32){
+ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
+ 273, 274, 275, 276, 277, 278, 279, 280,
+ };
+}
+void c_vector_24_u32(Vector_24_u32 v, size_t i) {
+ assert_or_panic(v[0] == 281);
+ assert_or_panic(v[1] == 282);
+ assert_or_panic(v[2] == 283);
+ assert_or_panic(v[3] == 284);
+ assert_or_panic(v[4] == 285);
+ assert_or_panic(v[5] == 286);
+ assert_or_panic(v[6] == 287);
+ assert_or_panic(v[7] == 288);
+ assert_or_panic(v[8] == 289);
+ assert_or_panic(v[9] == 290);
+ assert_or_panic(v[10] == 291);
+ assert_or_panic(v[11] == 292);
+ assert_or_panic(v[12] == 293);
+ assert_or_panic(v[13] == 294);
+ assert_or_panic(v[14] == 295);
+ assert_or_panic(v[15] == 296);
+ assert_or_panic(v[16] == 297);
+ assert_or_panic(v[17] == 298);
+ assert_or_panic(v[18] == 299);
+ assert_or_panic(v[19] == 300);
+ assert_or_panic(v[20] == 301);
+ assert_or_panic(v[21] == 302);
+ assert_or_panic(v[22] == 303);
+ assert_or_panic(v[23] == 304);
+ assert_or_panic(i == 24);
+}
+void c_test_vector_24_u32(void) {
+ Vector_24_u32 v = zig_ret_vector_24_u32();
+ assert_or_panic(v[0] == 209);
+ assert_or_panic(v[1] == 210);
+ assert_or_panic(v[2] == 211);
+ assert_or_panic(v[3] == 212);
+ assert_or_panic(v[4] == 213);
+ assert_or_panic(v[5] == 214);
+ assert_or_panic(v[6] == 215);
+ assert_or_panic(v[7] == 216);
+ assert_or_panic(v[8] == 217);
+ assert_or_panic(v[9] == 218);
+ assert_or_panic(v[10] == 219);
+ assert_or_panic(v[11] == 220);
+ assert_or_panic(v[12] == 221);
+ assert_or_panic(v[13] == 222);
+ assert_or_panic(v[14] == 223);
+ assert_or_panic(v[15] == 224);
+ assert_or_panic(v[16] == 225);
+ assert_or_panic(v[17] == 226);
+ assert_or_panic(v[18] == 227);
+ assert_or_panic(v[19] == 228);
+ assert_or_panic(v[20] == 229);
+ assert_or_panic(v[21] == 230);
+ assert_or_panic(v[22] == 231);
+ assert_or_panic(v[23] == 232);
+ zig_vector_24_u32((Vector_24_u32){
+ 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255, 256,
+ }, 24);
+}
+
+typedef uint32_t Vector_32_u32 __attribute__((vector_size(32 * sizeof(uint32_t))));
+
+Vector_32_u32 zig_ret_vector_32_u32(void);
+void zig_vector_32_u32(Vector_32_u32, size_t);
+
+Vector_32_u32 c_ret_vector_32_u32(void) {
+ return (Vector_32_u32){
+ 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384,
+ 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400,
+ };
+}
+void c_vector_32_u32(Vector_32_u32 v, size_t i) {
+ assert_or_panic(v[0] == 401);
+ assert_or_panic(v[1] == 402);
+ assert_or_panic(v[2] == 403);
+ assert_or_panic(v[3] == 404);
+ assert_or_panic(v[4] == 405);
+ assert_or_panic(v[5] == 406);
+ assert_or_panic(v[6] == 407);
+ assert_or_panic(v[7] == 408);
+ assert_or_panic(v[8] == 409);
+ assert_or_panic(v[9] == 410);
+ assert_or_panic(v[10] == 411);
+ assert_or_panic(v[11] == 412);
+ assert_or_panic(v[12] == 413);
+ assert_or_panic(v[13] == 414);
+ assert_or_panic(v[14] == 415);
+ assert_or_panic(v[15] == 416);
+ assert_or_panic(v[16] == 417);
+ assert_or_panic(v[17] == 418);
+ assert_or_panic(v[18] == 419);
+ assert_or_panic(v[19] == 420);
+ assert_or_panic(v[20] == 421);
+ assert_or_panic(v[21] == 422);
+ assert_or_panic(v[22] == 423);
+ assert_or_panic(v[23] == 424);
+ assert_or_panic(v[24] == 425);
+ assert_or_panic(v[25] == 426);
+ assert_or_panic(v[26] == 427);
+ assert_or_panic(v[27] == 428);
+ assert_or_panic(v[28] == 429);
+ assert_or_panic(v[29] == 430);
+ assert_or_panic(v[30] == 431);
+ assert_or_panic(v[31] == 432);
+ assert_or_panic(i == 32);
+}
+void c_test_vector_32_u32(void) {
+ Vector_32_u32 v = zig_ret_vector_32_u32();
+ assert_or_panic(v[0] == 305);
+ assert_or_panic(v[1] == 306);
+ assert_or_panic(v[2] == 307);
+ assert_or_panic(v[3] == 308);
+ assert_or_panic(v[4] == 309);
+ assert_or_panic(v[5] == 310);
+ assert_or_panic(v[6] == 311);
+ assert_or_panic(v[7] == 312);
+ assert_or_panic(v[8] == 313);
+ assert_or_panic(v[9] == 314);
+ assert_or_panic(v[10] == 315);
+ assert_or_panic(v[11] == 316);
+ assert_or_panic(v[12] == 317);
+ assert_or_panic(v[13] == 318);
+ assert_or_panic(v[14] == 319);
+ assert_or_panic(v[15] == 320);
+ assert_or_panic(v[16] == 321);
+ assert_or_panic(v[17] == 322);
+ assert_or_panic(v[18] == 323);
+ assert_or_panic(v[19] == 324);
+ assert_or_panic(v[20] == 325);
+ assert_or_panic(v[21] == 326);
+ assert_or_panic(v[22] == 327);
+ assert_or_panic(v[23] == 328);
+ assert_or_panic(v[24] == 329);
+ assert_or_panic(v[25] == 330);
+ assert_or_panic(v[26] == 331);
+ assert_or_panic(v[27] == 332);
+ assert_or_panic(v[28] == 333);
+ assert_or_panic(v[29] == 334);
+ assert_or_panic(v[30] == 335);
+ assert_or_panic(v[31] == 336);
+ zig_vector_32_u32((Vector_32_u32){
+ 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352,
+ 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368,
+ }, 32);
+}
+
+typedef uint32_t Vector_48_u32 __attribute__((vector_size(48 * sizeof(uint32_t))));
+
+Vector_48_u32 zig_ret_vector_48_u32(void);
+void zig_vector_48_u32(Vector_48_u32, size_t);
+
+Vector_48_u32 c_ret_vector_48_u32(void) {
+ return (Vector_48_u32){
+ 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544,
+ 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560,
+ 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576,
+ };
+}
+void c_vector_48_u32(Vector_48_u32 v, size_t i) {
+ assert_or_panic(v[0] == 577);
+ assert_or_panic(v[1] == 578);
+ assert_or_panic(v[2] == 579);
+ assert_or_panic(v[3] == 580);
+ assert_or_panic(v[4] == 581);
+ assert_or_panic(v[5] == 582);
+ assert_or_panic(v[6] == 583);
+ assert_or_panic(v[7] == 584);
+ assert_or_panic(v[8] == 585);
+ assert_or_panic(v[9] == 586);
+ assert_or_panic(v[10] == 587);
+ assert_or_panic(v[11] == 588);
+ assert_or_panic(v[12] == 589);
+ assert_or_panic(v[13] == 590);
+ assert_or_panic(v[14] == 591);
+ assert_or_panic(v[15] == 592);
+ assert_or_panic(v[16] == 593);
+ assert_or_panic(v[17] == 594);
+ assert_or_panic(v[18] == 595);
+ assert_or_panic(v[19] == 596);
+ assert_or_panic(v[20] == 597);
+ assert_or_panic(v[21] == 598);
+ assert_or_panic(v[22] == 599);
+ assert_or_panic(v[23] == 600);
+ assert_or_panic(v[24] == 601);
+ assert_or_panic(v[25] == 602);
+ assert_or_panic(v[26] == 603);
+ assert_or_panic(v[27] == 604);
+ assert_or_panic(v[28] == 605);
+ assert_or_panic(v[29] == 606);
+ assert_or_panic(v[30] == 607);
+ assert_or_panic(v[31] == 608);
+ assert_or_panic(v[32] == 609);
+ assert_or_panic(v[33] == 610);
+ assert_or_panic(v[34] == 611);
+ assert_or_panic(v[35] == 612);
+ assert_or_panic(v[36] == 613);
+ assert_or_panic(v[37] == 614);
+ assert_or_panic(v[38] == 615);
+ assert_or_panic(v[39] == 616);
+ assert_or_panic(v[40] == 617);
+ assert_or_panic(v[41] == 618);
+ assert_or_panic(v[42] == 619);
+ assert_or_panic(v[43] == 620);
+ assert_or_panic(v[44] == 621);
+ assert_or_panic(v[45] == 622);
+ assert_or_panic(v[46] == 623);
+ assert_or_panic(v[47] == 624);
+ assert_or_panic(i == 48);
+}
+void c_test_vector_48_u32(void) {
+ Vector_48_u32 v = zig_ret_vector_48_u32();
+ assert_or_panic(v[0] == 433);
+ assert_or_panic(v[1] == 434);
+ assert_or_panic(v[2] == 435);
+ assert_or_panic(v[3] == 436);
+ assert_or_panic(v[4] == 437);
+ assert_or_panic(v[5] == 438);
+ assert_or_panic(v[6] == 439);
+ assert_or_panic(v[7] == 440);
+ assert_or_panic(v[8] == 441);
+ assert_or_panic(v[9] == 442);
+ assert_or_panic(v[10] == 443);
+ assert_or_panic(v[11] == 444);
+ assert_or_panic(v[12] == 445);
+ assert_or_panic(v[13] == 446);
+ assert_or_panic(v[14] == 447);
+ assert_or_panic(v[15] == 448);
+ assert_or_panic(v[16] == 449);
+ assert_or_panic(v[17] == 450);
+ assert_or_panic(v[18] == 451);
+ assert_or_panic(v[19] == 452);
+ assert_or_panic(v[20] == 453);
+ assert_or_panic(v[21] == 454);
+ assert_or_panic(v[22] == 455);
+ assert_or_panic(v[23] == 456);
+ assert_or_panic(v[24] == 457);
+ assert_or_panic(v[25] == 458);
+ assert_or_panic(v[26] == 459);
+ assert_or_panic(v[27] == 460);
+ assert_or_panic(v[28] == 461);
+ assert_or_panic(v[29] == 462);
+ assert_or_panic(v[30] == 463);
+ assert_or_panic(v[31] == 464);
+ assert_or_panic(v[32] == 465);
+ assert_or_panic(v[33] == 466);
+ assert_or_panic(v[34] == 467);
+ assert_or_panic(v[35] == 468);
+ assert_or_panic(v[36] == 469);
+ assert_or_panic(v[37] == 470);
+ assert_or_panic(v[38] == 471);
+ assert_or_panic(v[39] == 472);
+ assert_or_panic(v[40] == 473);
+ assert_or_panic(v[41] == 474);
+ assert_or_panic(v[42] == 475);
+ assert_or_panic(v[43] == 476);
+ assert_or_panic(v[44] == 477);
+ assert_or_panic(v[45] == 478);
+ assert_or_panic(v[46] == 479);
+ assert_or_panic(v[47] == 480);
+ zig_vector_48_u32((Vector_48_u32){
+ 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496,
+ 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512,
+ 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528,
+ }, 48);
+}
+
+typedef uint32_t Vector_64_u32 __attribute__((vector_size(64 * sizeof(uint32_t))));
+
+Vector_64_u32 zig_ret_vector_64_u32(void);
+void zig_vector_64_u32(Vector_64_u32, size_t);
+
+Vector_64_u32 c_ret_vector_64_u32(void) {
+ return (Vector_64_u32){
+ 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768,
+ 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784,
+ 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800,
+ 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816,
+ };
+}
+void c_vector_64_u32(Vector_64_u32 v, size_t i) {
+ assert_or_panic(v[0] == 817);
+ assert_or_panic(v[1] == 818);
+ assert_or_panic(v[2] == 819);
+ assert_or_panic(v[3] == 820);
+ assert_or_panic(v[4] == 821);
+ assert_or_panic(v[5] == 822);
+ assert_or_panic(v[6] == 823);
+ assert_or_panic(v[7] == 824);
+ assert_or_panic(v[8] == 825);
+ assert_or_panic(v[9] == 826);
+ assert_or_panic(v[10] == 827);
+ assert_or_panic(v[11] == 828);
+ assert_or_panic(v[12] == 829);
+ assert_or_panic(v[13] == 830);
+ assert_or_panic(v[14] == 831);
+ assert_or_panic(v[15] == 832);
+ assert_or_panic(v[16] == 833);
+ assert_or_panic(v[17] == 834);
+ assert_or_panic(v[18] == 835);
+ assert_or_panic(v[19] == 836);
+ assert_or_panic(v[20] == 837);
+ assert_or_panic(v[21] == 838);
+ assert_or_panic(v[22] == 839);
+ assert_or_panic(v[23] == 840);
+ assert_or_panic(v[24] == 841);
+ assert_or_panic(v[25] == 842);
+ assert_or_panic(v[26] == 843);
+ assert_or_panic(v[27] == 844);
+ assert_or_panic(v[28] == 845);
+ assert_or_panic(v[29] == 846);
+ assert_or_panic(v[30] == 847);
+ assert_or_panic(v[31] == 848);
+ assert_or_panic(v[32] == 849);
+ assert_or_panic(v[33] == 850);
+ assert_or_panic(v[34] == 851);
+ assert_or_panic(v[35] == 852);
+ assert_or_panic(v[36] == 853);
+ assert_or_panic(v[37] == 854);
+ assert_or_panic(v[38] == 855);
+ assert_or_panic(v[39] == 856);
+ assert_or_panic(v[40] == 857);
+ assert_or_panic(v[41] == 858);
+ assert_or_panic(v[42] == 859);
+ assert_or_panic(v[43] == 860);
+ assert_or_panic(v[44] == 861);
+ assert_or_panic(v[45] == 862);
+ assert_or_panic(v[46] == 863);
+ assert_or_panic(v[47] == 864);
+ assert_or_panic(v[48] == 865);
+ assert_or_panic(v[49] == 866);
+ assert_or_panic(v[50] == 867);
+ assert_or_panic(v[51] == 868);
+ assert_or_panic(v[52] == 869);
+ assert_or_panic(v[53] == 870);
+ assert_or_panic(v[54] == 871);
+ assert_or_panic(v[55] == 872);
+ assert_or_panic(v[56] == 873);
+ assert_or_panic(v[57] == 874);
+ assert_or_panic(v[58] == 875);
+ assert_or_panic(v[59] == 876);
+ assert_or_panic(v[60] == 877);
+ assert_or_panic(v[61] == 878);
+ assert_or_panic(v[62] == 879);
+ assert_or_panic(v[63] == 880);
+ assert_or_panic(i == 64);
+}
+void c_test_vector_64_u32(void) {
+ Vector_64_u32 v = zig_ret_vector_64_u32();
+ assert_or_panic(v[0] == 625);
+ assert_or_panic(v[1] == 626);
+ assert_or_panic(v[2] == 627);
+ assert_or_panic(v[3] == 628);
+ assert_or_panic(v[4] == 629);
+ assert_or_panic(v[5] == 630);
+ assert_or_panic(v[6] == 631);
+ assert_or_panic(v[7] == 632);
+ assert_or_panic(v[8] == 633);
+ assert_or_panic(v[9] == 634);
+ assert_or_panic(v[10] == 635);
+ assert_or_panic(v[11] == 636);
+ assert_or_panic(v[12] == 637);
+ assert_or_panic(v[13] == 638);
+ assert_or_panic(v[14] == 639);
+ assert_or_panic(v[15] == 640);
+ assert_or_panic(v[16] == 641);
+ assert_or_panic(v[17] == 642);
+ assert_or_panic(v[18] == 643);
+ assert_or_panic(v[19] == 644);
+ assert_or_panic(v[20] == 645);
+ assert_or_panic(v[21] == 646);
+ assert_or_panic(v[22] == 647);
+ assert_or_panic(v[23] == 648);
+ assert_or_panic(v[24] == 649);
+ assert_or_panic(v[25] == 650);
+ assert_or_panic(v[26] == 651);
+ assert_or_panic(v[27] == 652);
+ assert_or_panic(v[28] == 653);
+ assert_or_panic(v[29] == 654);
+ assert_or_panic(v[30] == 655);
+ assert_or_panic(v[31] == 656);
+ assert_or_panic(v[32] == 657);
+ assert_or_panic(v[33] == 658);
+ assert_or_panic(v[34] == 659);
+ assert_or_panic(v[35] == 660);
+ assert_or_panic(v[36] == 661);
+ assert_or_panic(v[37] == 662);
+ assert_or_panic(v[38] == 663);
+ assert_or_panic(v[39] == 664);
+ assert_or_panic(v[40] == 665);
+ assert_or_panic(v[41] == 666);
+ assert_or_panic(v[42] == 667);
+ assert_or_panic(v[43] == 668);
+ assert_or_panic(v[44] == 669);
+ assert_or_panic(v[45] == 670);
+ assert_or_panic(v[46] == 671);
+ assert_or_panic(v[47] == 672);
+ assert_or_panic(v[48] == 673);
+ assert_or_panic(v[49] == 674);
+ assert_or_panic(v[50] == 675);
+ assert_or_panic(v[51] == 676);
+ assert_or_panic(v[52] == 677);
+ assert_or_panic(v[53] == 678);
+ assert_or_panic(v[54] == 679);
+ assert_or_panic(v[55] == 680);
+ assert_or_panic(v[56] == 681);
+ assert_or_panic(v[57] == 682);
+ assert_or_panic(v[58] == 683);
+ assert_or_panic(v[59] == 684);
+ assert_or_panic(v[60] == 685);
+ assert_or_panic(v[61] == 686);
+ assert_or_panic(v[62] == 687);
+ assert_or_panic(v[63] == 688);
+ zig_vector_64_u32((Vector_64_u32){
+ 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704,
+ 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720,
+ 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736,
+ 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752,
+ }, 64);
+}
+
+typedef uint32_t Vector_96_u32 __attribute__((vector_size(96 * sizeof(uint32_t))));
+
+Vector_96_u32 zig_ret_vector_96_u32(void);
+void zig_vector_96_u32(Vector_96_u32, size_t);
+
+Vector_96_u32 c_ret_vector_96_u32(void) {
+ return (Vector_96_u32){
+ 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097,
+ 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113,
+ 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129,
+ 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145,
+ 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161,
+ 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177,
+ };
+}
+void c_vector_96_u32(Vector_96_u32 v, size_t i) {
+ assert_or_panic(v[0] == 1178);
+ assert_or_panic(v[1] == 1179);
+ assert_or_panic(v[2] == 1180);
+ assert_or_panic(v[3] == 1181);
+ assert_or_panic(v[4] == 1182);
+ assert_or_panic(v[5] == 1183);
+ assert_or_panic(v[6] == 1184);
+ assert_or_panic(v[7] == 1185);
+ assert_or_panic(v[8] == 1186);
+ assert_or_panic(v[9] == 1187);
+ assert_or_panic(v[10] == 1188);
+ assert_or_panic(v[11] == 1189);
+ assert_or_panic(v[12] == 1190);
+ assert_or_panic(v[13] == 1191);
+ assert_or_panic(v[14] == 1192);
+ assert_or_panic(v[15] == 1193);
+ assert_or_panic(v[16] == 1194);
+ assert_or_panic(v[17] == 1195);
+ assert_or_panic(v[18] == 1196);
+ assert_or_panic(v[19] == 1197);
+ assert_or_panic(v[20] == 1198);
+ assert_or_panic(v[21] == 1199);
+ assert_or_panic(v[22] == 1200);
+ assert_or_panic(v[23] == 1201);
+ assert_or_panic(v[24] == 1202);
+ assert_or_panic(v[25] == 1203);
+ assert_or_panic(v[26] == 1204);
+ assert_or_panic(v[27] == 1205);
+ assert_or_panic(v[28] == 1206);
+ assert_or_panic(v[29] == 1207);
+ assert_or_panic(v[30] == 1208);
+ assert_or_panic(v[31] == 1209);
+ assert_or_panic(v[32] == 1210);
+ assert_or_panic(v[33] == 1211);
+ assert_or_panic(v[34] == 1212);
+ assert_or_panic(v[35] == 1213);
+ assert_or_panic(v[36] == 1214);
+ assert_or_panic(v[37] == 1215);
+ assert_or_panic(v[38] == 1216);
+ assert_or_panic(v[39] == 1217);
+ assert_or_panic(v[40] == 1218);
+ assert_or_panic(v[41] == 1219);
+ assert_or_panic(v[42] == 1220);
+ assert_or_panic(v[43] == 1221);
+ assert_or_panic(v[44] == 1222);
+ assert_or_panic(v[45] == 1223);
+ assert_or_panic(v[46] == 1224);
+ assert_or_panic(v[47] == 1225);
+ assert_or_panic(v[48] == 1226);
+ assert_or_panic(v[49] == 1227);
+ assert_or_panic(v[50] == 1228);
+ assert_or_panic(v[51] == 1229);
+ assert_or_panic(v[52] == 1230);
+ assert_or_panic(v[53] == 1231);
+ assert_or_panic(v[54] == 1232);
+ assert_or_panic(v[55] == 1233);
+ assert_or_panic(v[56] == 1234);
+ assert_or_panic(v[57] == 1235);
+ assert_or_panic(v[58] == 1236);
+ assert_or_panic(v[59] == 1237);
+ assert_or_panic(v[60] == 1238);
+ assert_or_panic(v[61] == 1239);
+ assert_or_panic(v[62] == 1240);
+ assert_or_panic(v[63] == 1241);
+ assert_or_panic(v[64] == 1242);
+ assert_or_panic(v[65] == 1243);
+ assert_or_panic(v[66] == 1244);
+ assert_or_panic(v[67] == 1245);
+ assert_or_panic(v[68] == 1246);
+ assert_or_panic(v[69] == 1247);
+ assert_or_panic(v[70] == 1248);
+ assert_or_panic(v[71] == 1249);
+ assert_or_panic(v[72] == 1250);
+ assert_or_panic(v[73] == 1251);
+ assert_or_panic(v[74] == 1252);
+ assert_or_panic(v[75] == 1253);
+ assert_or_panic(v[76] == 1254);
+ assert_or_panic(v[77] == 1255);
+ assert_or_panic(v[80] == 1258);
+ assert_or_panic(v[81] == 1259);
+ assert_or_panic(v[82] == 1260);
+ assert_or_panic(v[83] == 1261);
+ assert_or_panic(v[84] == 1262);
+ assert_or_panic(v[85] == 1263);
+ assert_or_panic(v[86] == 1264);
+ assert_or_panic(v[87] == 1265);
+ assert_or_panic(v[88] == 1266);
+ assert_or_panic(v[89] == 1267);
+ assert_or_panic(v[90] == 1268);
+ assert_or_panic(v[91] == 1269);
+ assert_or_panic(v[92] == 1270);
+ assert_or_panic(v[93] == 1271);
+ assert_or_panic(v[94] == 1272);
+ assert_or_panic(v[95] == 1273);
+ assert_or_panic(i == 96);
+}
+void c_test_vector_96_u32(void) {
+ Vector_96_u32 v = zig_ret_vector_96_u32();
+ assert_or_panic(v[0] == 890);
+ assert_or_panic(v[1] == 891);
+ assert_or_panic(v[2] == 892);
+ assert_or_panic(v[3] == 893);
+ assert_or_panic(v[4] == 894);
+ assert_or_panic(v[5] == 895);
+ assert_or_panic(v[6] == 896);
+ assert_or_panic(v[7] == 897);
+ assert_or_panic(v[8] == 898);
+ assert_or_panic(v[9] == 899);
+ assert_or_panic(v[10] == 900);
+ assert_or_panic(v[11] == 901);
+ assert_or_panic(v[12] == 902);
+ assert_or_panic(v[13] == 903);
+ assert_or_panic(v[14] == 904);
+ assert_or_panic(v[15] == 905);
+ assert_or_panic(v[16] == 906);
+ assert_or_panic(v[17] == 907);
+ assert_or_panic(v[18] == 908);
+ assert_or_panic(v[19] == 909);
+ assert_or_panic(v[20] == 910);
+ assert_or_panic(v[21] == 911);
+ assert_or_panic(v[22] == 912);
+ assert_or_panic(v[23] == 913);
+ assert_or_panic(v[24] == 914);
+ assert_or_panic(v[25] == 915);
+ assert_or_panic(v[26] == 916);
+ assert_or_panic(v[27] == 917);
+ assert_or_panic(v[28] == 918);
+ assert_or_panic(v[29] == 919);
+ assert_or_panic(v[30] == 920);
+ assert_or_panic(v[31] == 921);
+ assert_or_panic(v[32] == 922);
+ assert_or_panic(v[33] == 923);
+ assert_or_panic(v[34] == 924);
+ assert_or_panic(v[35] == 925);
+ assert_or_panic(v[36] == 926);
+ assert_or_panic(v[37] == 927);
+ assert_or_panic(v[38] == 928);
+ assert_or_panic(v[39] == 929);
+ assert_or_panic(v[40] == 930);
+ assert_or_panic(v[41] == 931);
+ assert_or_panic(v[42] == 932);
+ assert_or_panic(v[43] == 933);
+ assert_or_panic(v[44] == 934);
+ assert_or_panic(v[45] == 935);
+ assert_or_panic(v[46] == 936);
+ assert_or_panic(v[47] == 937);
+ assert_or_panic(v[48] == 938);
+ assert_or_panic(v[49] == 939);
+ assert_or_panic(v[50] == 940);
+ assert_or_panic(v[51] == 941);
+ assert_or_panic(v[52] == 942);
+ assert_or_panic(v[53] == 943);
+ assert_or_panic(v[54] == 944);
+ assert_or_panic(v[55] == 945);
+ assert_or_panic(v[56] == 946);
+ assert_or_panic(v[57] == 947);
+ assert_or_panic(v[58] == 948);
+ assert_or_panic(v[59] == 949);
+ assert_or_panic(v[60] == 950);
+ assert_or_panic(v[61] == 951);
+ assert_or_panic(v[62] == 952);
+ assert_or_panic(v[63] == 953);
+ assert_or_panic(v[64] == 954);
+ assert_or_panic(v[65] == 955);
+ assert_or_panic(v[66] == 956);
+ assert_or_panic(v[67] == 957);
+ assert_or_panic(v[68] == 958);
+ assert_or_panic(v[69] == 959);
+ assert_or_panic(v[70] == 960);
+ assert_or_panic(v[71] == 961);
+ assert_or_panic(v[72] == 962);
+ assert_or_panic(v[73] == 963);
+ assert_or_panic(v[74] == 964);
+ assert_or_panic(v[75] == 965);
+ assert_or_panic(v[76] == 966);
+ assert_or_panic(v[77] == 967);
+ assert_or_panic(v[78] == 968);
+ assert_or_panic(v[79] == 969);
+ assert_or_panic(v[80] == 970);
+ assert_or_panic(v[81] == 971);
+ assert_or_panic(v[82] == 972);
+ assert_or_panic(v[83] == 973);
+ assert_or_panic(v[84] == 974);
+ assert_or_panic(v[85] == 975);
+ assert_or_panic(v[86] == 976);
+ assert_or_panic(v[87] == 977);
+ assert_or_panic(v[88] == 978);
+ assert_or_panic(v[89] == 979);
+ assert_or_panic(v[90] == 980);
+ assert_or_panic(v[91] == 981);
+ assert_or_panic(v[92] == 982);
+ assert_or_panic(v[93] == 983);
+ assert_or_panic(v[94] == 984);
+ assert_or_panic(v[95] == 985);
+ zig_vector_96_u32((Vector_96_u32){
+ 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001,
+ 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017,
+ 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033,
+ 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049,
+ 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065,
+ 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081,
+ }, 96);
+}
+
+typedef uint32_t Vector_128_u32 __attribute__((vector_size(128 * sizeof(uint32_t))));
+
+Vector_128_u32 zig_ret_vector_128_u32(void);
+void zig_vector_128_u32(Vector_128_u32, size_t);
+
+Vector_128_u32 c_ret_vector_128_u32(void) {
+ return (Vector_128_u32){
+ 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545,
+ 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561,
+ 1562, 1563, 1564, 1565, 1566, 1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577,
+ 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593,
+ 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609,
+ 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625,
+ 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641,
+ 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657,
+ };
+}
+void c_vector_128_u32(Vector_128_u32 v, size_t i) {
+ assert_or_panic(v[0] == 1658);
+ assert_or_panic(v[1] == 1659);
+ assert_or_panic(v[2] == 1660);
+ assert_or_panic(v[3] == 1661);
+ assert_or_panic(v[4] == 1662);
+ assert_or_panic(v[5] == 1663);
+ assert_or_panic(v[6] == 1664);
+ assert_or_panic(v[7] == 1665);
+ assert_or_panic(v[8] == 1666);
+ assert_or_panic(v[9] == 1667);
+ assert_or_panic(v[10] == 1668);
+ assert_or_panic(v[11] == 1669);
+ assert_or_panic(v[12] == 1670);
+ assert_or_panic(v[13] == 1671);
+ assert_or_panic(v[14] == 1672);
+ assert_or_panic(v[15] == 1673);
+ assert_or_panic(v[16] == 1674);
+ assert_or_panic(v[17] == 1675);
+ assert_or_panic(v[18] == 1676);
+ assert_or_panic(v[19] == 1677);
+ assert_or_panic(v[20] == 1678);
+ assert_or_panic(v[21] == 1679);
+ assert_or_panic(v[22] == 1680);
+ assert_or_panic(v[23] == 1681);
+ assert_or_panic(v[24] == 1682);
+ assert_or_panic(v[25] == 1683);
+ assert_or_panic(v[26] == 1684);
+ assert_or_panic(v[27] == 1685);
+ assert_or_panic(v[28] == 1686);
+ assert_or_panic(v[29] == 1687);
+ assert_or_panic(v[30] == 1688);
+ assert_or_panic(v[31] == 1689);
+ assert_or_panic(v[32] == 1690);
+ assert_or_panic(v[33] == 1691);
+ assert_or_panic(v[34] == 1692);
+ assert_or_panic(v[35] == 1693);
+ assert_or_panic(v[36] == 1694);
+ assert_or_panic(v[37] == 1695);
+ assert_or_panic(v[38] == 1696);
+ assert_or_panic(v[39] == 1697);
+ assert_or_panic(v[40] == 1698);
+ assert_or_panic(v[41] == 1699);
+ assert_or_panic(v[42] == 1700);
+ assert_or_panic(v[43] == 1701);
+ assert_or_panic(v[44] == 1702);
+ assert_or_panic(v[45] == 1703);
+ assert_or_panic(v[46] == 1704);
+ assert_or_panic(v[47] == 1705);
+ assert_or_panic(v[48] == 1706);
+ assert_or_panic(v[49] == 1707);
+ assert_or_panic(v[50] == 1708);
+ assert_or_panic(v[51] == 1709);
+ assert_or_panic(v[52] == 1710);
+ assert_or_panic(v[53] == 1711);
+ assert_or_panic(v[54] == 1712);
+ assert_or_panic(v[55] == 1713);
+ assert_or_panic(v[56] == 1714);
+ assert_or_panic(v[57] == 1715);
+ assert_or_panic(v[58] == 1716);
+ assert_or_panic(v[59] == 1717);
+ assert_or_panic(v[60] == 1718);
+ assert_or_panic(v[61] == 1719);
+ assert_or_panic(v[62] == 1720);
+ assert_or_panic(v[63] == 1721);
+ assert_or_panic(v[64] == 1722);
+ assert_or_panic(v[65] == 1723);
+ assert_or_panic(v[66] == 1724);
+ assert_or_panic(v[67] == 1725);
+ assert_or_panic(v[68] == 1726);
+ assert_or_panic(v[69] == 1727);
+ assert_or_panic(v[70] == 1728);
+ assert_or_panic(v[71] == 1729);
+ assert_or_panic(v[72] == 1730);
+ assert_or_panic(v[73] == 1731);
+ assert_or_panic(v[74] == 1732);
+ assert_or_panic(v[75] == 1733);
+ assert_or_panic(v[76] == 1734);
+ assert_or_panic(v[77] == 1735);
+ assert_or_panic(v[78] == 1736);
+ assert_or_panic(v[79] == 1737);
+ assert_or_panic(v[80] == 1738);
+ assert_or_panic(v[81] == 1739);
+ assert_or_panic(v[82] == 1740);
+ assert_or_panic(v[83] == 1741);
+ assert_or_panic(v[84] == 1742);
+ assert_or_panic(v[85] == 1743);
+ assert_or_panic(v[86] == 1744);
+ assert_or_panic(v[87] == 1745);
+ assert_or_panic(v[88] == 1746);
+ assert_or_panic(v[89] == 1747);
+ assert_or_panic(v[90] == 1748);
+ assert_or_panic(v[91] == 1749);
+ assert_or_panic(v[92] == 1750);
+ assert_or_panic(v[93] == 1751);
+ assert_or_panic(v[94] == 1752);
+ assert_or_panic(v[95] == 1753);
+ assert_or_panic(v[96] == 1754);
+ assert_or_panic(v[97] == 1755);
+ assert_or_panic(v[98] == 1756);
+ assert_or_panic(v[99] == 1757);
+ assert_or_panic(v[100] == 1758);
+ assert_or_panic(v[101] == 1759);
+ assert_or_panic(v[102] == 1760);
+ assert_or_panic(v[103] == 1761);
+ assert_or_panic(v[104] == 1762);
+ assert_or_panic(v[105] == 1763);
+ assert_or_panic(v[106] == 1764);
+ assert_or_panic(v[107] == 1765);
+ assert_or_panic(v[108] == 1766);
+ assert_or_panic(v[109] == 1767);
+ assert_or_panic(v[110] == 1768);
+ assert_or_panic(v[111] == 1769);
+ assert_or_panic(v[112] == 1770);
+ assert_or_panic(v[113] == 1771);
+ assert_or_panic(v[114] == 1772);
+ assert_or_panic(v[115] == 1773);
+ assert_or_panic(v[116] == 1774);
+ assert_or_panic(v[117] == 1775);
+ assert_or_panic(v[118] == 1776);
+ assert_or_panic(v[119] == 1777);
+ assert_or_panic(v[120] == 1778);
+ assert_or_panic(v[121] == 1779);
+ assert_or_panic(v[122] == 1780);
+ assert_or_panic(v[123] == 1781);
+ assert_or_panic(v[124] == 1782);
+ assert_or_panic(v[125] == 1783);
+ assert_or_panic(v[126] == 1784);
+ assert_or_panic(v[127] == 1785);
+ assert_or_panic(i == 128);
+}
+void c_test_vector_128_u32(void) {
+ Vector_128_u32 v = zig_ret_vector_128_u32();
+ assert_or_panic(v[0] == 1274);
+ assert_or_panic(v[1] == 1275);
+ assert_or_panic(v[2] == 1276);
+ assert_or_panic(v[3] == 1277);
+ assert_or_panic(v[4] == 1278);
+ assert_or_panic(v[5] == 1279);
+ assert_or_panic(v[6] == 1280);
+ assert_or_panic(v[7] == 1281);
+ assert_or_panic(v[8] == 1282);
+ assert_or_panic(v[9] == 1283);
+ assert_or_panic(v[10] == 1284);
+ assert_or_panic(v[11] == 1285);
+ assert_or_panic(v[12] == 1286);
+ assert_or_panic(v[13] == 1287);
+ assert_or_panic(v[14] == 1288);
+ assert_or_panic(v[15] == 1289);
+ assert_or_panic(v[16] == 1290);
+ assert_or_panic(v[17] == 1291);
+ assert_or_panic(v[18] == 1292);
+ assert_or_panic(v[19] == 1293);
+ assert_or_panic(v[20] == 1294);
+ assert_or_panic(v[21] == 1295);
+ assert_or_panic(v[22] == 1296);
+ assert_or_panic(v[23] == 1297);
+ assert_or_panic(v[24] == 1298);
+ assert_or_panic(v[25] == 1299);
+ assert_or_panic(v[26] == 1300);
+ assert_or_panic(v[27] == 1301);
+ assert_or_panic(v[28] == 1302);
+ assert_or_panic(v[29] == 1303);
+ assert_or_panic(v[30] == 1304);
+ assert_or_panic(v[31] == 1305);
+ assert_or_panic(v[32] == 1306);
+ assert_or_panic(v[33] == 1307);
+ assert_or_panic(v[34] == 1308);
+ assert_or_panic(v[35] == 1309);
+ assert_or_panic(v[36] == 1310);
+ assert_or_panic(v[37] == 1311);
+ assert_or_panic(v[38] == 1312);
+ assert_or_panic(v[39] == 1313);
+ assert_or_panic(v[40] == 1314);
+ assert_or_panic(v[41] == 1315);
+ assert_or_panic(v[42] == 1316);
+ assert_or_panic(v[43] == 1317);
+ assert_or_panic(v[44] == 1318);
+ assert_or_panic(v[45] == 1319);
+ assert_or_panic(v[46] == 1320);
+ assert_or_panic(v[47] == 1321);
+ assert_or_panic(v[48] == 1322);
+ assert_or_panic(v[49] == 1323);
+ assert_or_panic(v[50] == 1324);
+ assert_or_panic(v[51] == 1325);
+ assert_or_panic(v[52] == 1326);
+ assert_or_panic(v[53] == 1327);
+ assert_or_panic(v[54] == 1328);
+ assert_or_panic(v[55] == 1329);
+ assert_or_panic(v[56] == 1330);
+ assert_or_panic(v[57] == 1331);
+ assert_or_panic(v[58] == 1332);
+ assert_or_panic(v[59] == 1333);
+ assert_or_panic(v[60] == 1334);
+ assert_or_panic(v[61] == 1335);
+ assert_or_panic(v[62] == 1336);
+ assert_or_panic(v[63] == 1337);
+ assert_or_panic(v[64] == 1338);
+ assert_or_panic(v[65] == 1339);
+ assert_or_panic(v[66] == 1340);
+ assert_or_panic(v[67] == 1341);
+ assert_or_panic(v[68] == 1342);
+ assert_or_panic(v[69] == 1343);
+ assert_or_panic(v[70] == 1344);
+ assert_or_panic(v[71] == 1345);
+ assert_or_panic(v[72] == 1346);
+ assert_or_panic(v[73] == 1347);
+ assert_or_panic(v[74] == 1348);
+ assert_or_panic(v[75] == 1349);
+ assert_or_panic(v[76] == 1350);
+ assert_or_panic(v[77] == 1351);
+ assert_or_panic(v[78] == 1352);
+ assert_or_panic(v[79] == 1353);
+ assert_or_panic(v[80] == 1354);
+ assert_or_panic(v[81] == 1355);
+ assert_or_panic(v[82] == 1356);
+ assert_or_panic(v[83] == 1357);
+ assert_or_panic(v[84] == 1358);
+ assert_or_panic(v[85] == 1359);
+ assert_or_panic(v[86] == 1360);
+ assert_or_panic(v[87] == 1361);
+ assert_or_panic(v[88] == 1362);
+ assert_or_panic(v[89] == 1363);
+ assert_or_panic(v[90] == 1364);
+ assert_or_panic(v[91] == 1365);
+ assert_or_panic(v[92] == 1366);
+ assert_or_panic(v[93] == 1367);
+ assert_or_panic(v[94] == 1368);
+ assert_or_panic(v[95] == 1369);
+ assert_or_panic(v[96] == 1370);
+ assert_or_panic(v[97] == 1371);
+ assert_or_panic(v[98] == 1372);
+ assert_or_panic(v[99] == 1373);
+ assert_or_panic(v[100] == 1374);
+ assert_or_panic(v[101] == 1375);
+ assert_or_panic(v[102] == 1376);
+ assert_or_panic(v[103] == 1377);
+ assert_or_panic(v[104] == 1378);
+ assert_or_panic(v[105] == 1379);
+ assert_or_panic(v[106] == 1380);
+ assert_or_panic(v[107] == 1381);
+ assert_or_panic(v[108] == 1382);
+ assert_or_panic(v[109] == 1383);
+ assert_or_panic(v[110] == 1384);
+ assert_or_panic(v[111] == 1385);
+ assert_or_panic(v[112] == 1386);
+ assert_or_panic(v[113] == 1387);
+ assert_or_panic(v[114] == 1388);
+ assert_or_panic(v[115] == 1389);
+ assert_or_panic(v[116] == 1390);
+ assert_or_panic(v[117] == 1391);
+ assert_or_panic(v[118] == 1392);
+ assert_or_panic(v[119] == 1393);
+ assert_or_panic(v[120] == 1394);
+ assert_or_panic(v[121] == 1395);
+ assert_or_panic(v[122] == 1396);
+ assert_or_panic(v[123] == 1397);
+ assert_or_panic(v[124] == 1398);
+ assert_or_panic(v[125] == 1399);
+ assert_or_panic(v[126] == 1400);
+ assert_or_panic(v[127] == 1401);
+ zig_vector_128_u32((Vector_128_u32){
+ 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417,
+ 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1433,
+ 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449,
+ 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465,
+ 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481,
+ 1482, 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497,
+ 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513,
+ 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529,
+ }, 128);
+}
+
+typedef uint64_t Vector_1_u64 __attribute__((vector_size(1 * sizeof(uint64_t))));
+
+Vector_1_u64 zig_ret_vector_1_u64(void);
+void zig_vector_1_u64(Vector_1_u64, size_t);
+
+Vector_1_u64 c_ret_vector_1_u64(void) {
+ return (Vector_1_u64){ 3 };
+}
+void c_vector_1_u64(Vector_1_u64 v, size_t i) {
+ assert_or_panic(v[0] == 4);
+ assert_or_panic(i == 1);
+}
+void c_test_vector_1_u64(void) {
+ Vector_1_u64 v = zig_ret_vector_1_u64();
+ assert_or_panic(v[0] == 1);
+ zig_vector_1_u64((Vector_1_u64){ 2 }, 1);
+}
+
+typedef uint64_t Vector_2_u64 __attribute__((vector_size(2 * sizeof(uint64_t))));
+
+Vector_2_u64 zig_ret_vector_2_u64(void);
+void zig_vector_2_u64(Vector_2_u64, size_t);
+
+Vector_2_u64 c_ret_vector_2_u64(void) {
+ return (Vector_2_u64){ 9, 10 };
+}
+void c_vector_2_u64(Vector_2_u64 v, size_t i) {
+ assert_or_panic(v[0] == 11);
+ assert_or_panic(v[1] == 12);
+ assert_or_panic(i == 2);
+}
+void c_test_vector_2_u64(void) {
+ Vector_2_u64 v = zig_ret_vector_2_u64();
+ assert_or_panic(v[0] == 5);
+ assert_or_panic(v[1] == 6);
+ zig_vector_2_u64((Vector_2_u64){ 7, 8 }, 2);
+}
+
+typedef uint64_t Vector_3_u64 __attribute__((vector_size(3 * sizeof(uint64_t))));
+
+Vector_3_u64 zig_ret_vector_3_u64(void);
+void zig_vector_3_u64(Vector_3_u64, size_t);
+
+Vector_3_u64 c_ret_vector_3_u64(void) {
+ return (Vector_3_u64){ 19, 20, 21 };
+}
+void c_vector_3_u64(Vector_3_u64 v, size_t i) {
+ assert_or_panic(v[0] == 22);
+ assert_or_panic(v[1] == 23);
+ assert_or_panic(v[2] == 24);
+ assert_or_panic(i == 3);
+}
+void c_test_vector_3_u64(void) {
+ Vector_3_u64 v = zig_ret_vector_3_u64();
+ assert_or_panic(v[0] == 13);
+ assert_or_panic(v[1] == 14);
+ assert_or_panic(v[2] == 15);
+ zig_vector_3_u64((Vector_3_u64){ 16, 17, 18 }, 3);
+}
+
+typedef uint64_t Vector_4_u64 __attribute__((vector_size(4 * sizeof(uint64_t))));
+
+Vector_4_u64 zig_ret_vector_4_u64(void);
+void zig_vector_4_u64(Vector_4_u64, size_t);
+
+Vector_4_u64 c_ret_vector_4_u64(void) {
+ return (Vector_4_u64){ 33, 34, 35, 36 };
+}
+void c_vector_4_u64(Vector_4_u64 v, size_t i) {
+ assert_or_panic(v[0] == 37);
+ assert_or_panic(v[1] == 38);
+ assert_or_panic(v[2] == 39);
+ assert_or_panic(v[3] == 40);
+ assert_or_panic(i == 4);
+}
+void c_test_vector_4_u64(void) {
+ Vector_4_u64 v = zig_ret_vector_4_u64();
+ assert_or_panic(v[0] == 25);
+ assert_or_panic(v[1] == 26);
+ assert_or_panic(v[2] == 27);
+ assert_or_panic(v[3] == 28);
+ zig_vector_4_u64((Vector_4_u64){ 29, 30, 31, 32 }, 4);
+}
+
+typedef uint64_t Vector_6_u64 __attribute__((vector_size(6 * sizeof(uint64_t))));
+
+Vector_6_u64 zig_ret_vector_6_u64(void);
+void zig_vector_6_u64(Vector_6_u64, size_t);
+
+Vector_6_u64 c_ret_vector_6_u64(void) {
+ return (Vector_6_u64){ 53, 54, 55, 56, 57, 58 };
+}
+void c_vector_6_u64(Vector_6_u64 v, size_t i) {
+ assert_or_panic(v[0] == 59);
+ assert_or_panic(v[1] == 60);
+ assert_or_panic(v[2] == 61);
+ assert_or_panic(v[3] == 62);
+ assert_or_panic(v[4] == 63);
+ assert_or_panic(v[5] == 64);
+ assert_or_panic(i == 6);
+}
+void c_test_vector_6_u64(void) {
+ Vector_6_u64 v = zig_ret_vector_6_u64();
+ assert_or_panic(v[0] == 41);
+ assert_or_panic(v[1] == 42);
+ assert_or_panic(v[2] == 43);
+ assert_or_panic(v[3] == 44);
+ assert_or_panic(v[4] == 45);
+ assert_or_panic(v[5] == 46);
+ zig_vector_6_u64((Vector_6_u64){ 47, 48, 49, 50, 51, 52 }, 6);
+}
+
+typedef uint64_t Vector_8_u64 __attribute__((vector_size(8 * sizeof(uint64_t))));
+
+Vector_8_u64 zig_ret_vector_8_u64(void);
+void zig_vector_8_u64(Vector_8_u64, size_t);
+
+Vector_8_u64 c_ret_vector_8_u64(void) {
+ return (Vector_8_u64){ 81, 82, 83, 84, 85, 86, 87, 88 };
+}
+void c_vector_8_u64(Vector_8_u64 v, size_t i) {
+ assert_or_panic(v[0] == 89);
+ assert_or_panic(v[1] == 90);
+ assert_or_panic(v[2] == 91);
+ assert_or_panic(v[3] == 92);
+ assert_or_panic(v[4] == 93);
+ assert_or_panic(v[5] == 94);
+ assert_or_panic(v[6] == 95);
+ assert_or_panic(v[7] == 96);
+ assert_or_panic(i == 8);
+}
+void c_test_vector_8_u64(void) {
+ Vector_8_u64 v = zig_ret_vector_8_u64();
+ assert_or_panic(v[0] == 65);
+ assert_or_panic(v[1] == 66);
+ assert_or_panic(v[2] == 67);
+ assert_or_panic(v[3] == 68);
+ assert_or_panic(v[4] == 69);
+ assert_or_panic(v[5] == 70);
+ assert_or_panic(v[6] == 71);
+ assert_or_panic(v[7] == 72);
+ zig_vector_8_u64((Vector_8_u64){ 73, 74, 75, 76, 77, 78, 79, 80 }, 8);
+}
+
+typedef uint64_t Vector_12_u64 __attribute__((vector_size(12 * sizeof(uint64_t))));
+
+Vector_12_u64 zig_ret_vector_12_u64(void);
+void zig_vector_12_u64(Vector_12_u64, size_t);
+
+Vector_12_u64 c_ret_vector_12_u64(void) {
+ return (Vector_12_u64){ 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132 };
+}
+void c_vector_12_u64(Vector_12_u64 v, size_t i) {
+ assert_or_panic(v[0] == 133);
+ assert_or_panic(v[1] == 134);
+ assert_or_panic(v[2] == 135);
+ assert_or_panic(v[3] == 136);
+ assert_or_panic(v[4] == 137);
+ assert_or_panic(v[5] == 138);
+ assert_or_panic(v[6] == 139);
+ assert_or_panic(v[7] == 140);
+ assert_or_panic(v[8] == 141);
+ assert_or_panic(v[9] == 142);
+ assert_or_panic(v[10] == 143);
+ assert_or_panic(v[11] == 144);
+ assert_or_panic(i == 12);
+}
+void c_test_vector_12_u64(void) {
+ Vector_12_u64 v = zig_ret_vector_12_u64();
+ assert_or_panic(v[0] == 97);
+ assert_or_panic(v[1] == 98);
+ assert_or_panic(v[2] == 99);
+ assert_or_panic(v[3] == 100);
+ assert_or_panic(v[4] == 101);
+ assert_or_panic(v[5] == 102);
+ assert_or_panic(v[6] == 103);
+ assert_or_panic(v[7] == 104);
+ assert_or_panic(v[8] == 105);
+ assert_or_panic(v[9] == 106);
+ assert_or_panic(v[10] == 107);
+ assert_or_panic(v[11] == 108);
+ zig_vector_12_u64((Vector_12_u64){ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120 }, 12);
+}
+
+typedef uint64_t Vector_16_u64 __attribute__((vector_size(16 * sizeof(uint64_t))));
+
+Vector_16_u64 zig_ret_vector_16_u64(void);
+void zig_vector_16_u64(Vector_16_u64, size_t);
+
+Vector_16_u64 c_ret_vector_16_u64(void) {
+ return (Vector_16_u64){ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192 };
+}
+void c_vector_16_u64(Vector_16_u64 v, size_t i) {
+ assert_or_panic(v[0] == 193);
+ assert_or_panic(v[1] == 194);
+ assert_or_panic(v[2] == 195);
+ assert_or_panic(v[3] == 196);
+ assert_or_panic(v[4] == 197);
+ assert_or_panic(v[5] == 198);
+ assert_or_panic(v[6] == 199);
+ assert_or_panic(v[7] == 200);
+ assert_or_panic(v[8] == 201);
+ assert_or_panic(v[9] == 202);
+ assert_or_panic(v[10] == 203);
+ assert_or_panic(v[11] == 204);
+ assert_or_panic(v[12] == 205);
+ assert_or_panic(v[13] == 206);
+ assert_or_panic(v[14] == 207);
+ assert_or_panic(v[15] == 208);
+ assert_or_panic(i == 16);
+}
+void c_test_vector_16_u64(void) {
+ Vector_16_u64 v = zig_ret_vector_16_u64();
+ assert_or_panic(v[0] == 145);
+ assert_or_panic(v[1] == 146);
+ assert_or_panic(v[2] == 147);
+ assert_or_panic(v[3] == 148);
+ assert_or_panic(v[4] == 149);
+ assert_or_panic(v[5] == 150);
+ assert_or_panic(v[6] == 151);
+ assert_or_panic(v[7] == 152);
+ assert_or_panic(v[8] == 153);
+ assert_or_panic(v[9] == 154);
+ assert_or_panic(v[10] == 155);
+ assert_or_panic(v[11] == 156);
+ assert_or_panic(v[12] == 157);
+ assert_or_panic(v[13] == 158);
+ assert_or_panic(v[14] == 159);
+ assert_or_panic(v[15] == 160);
+ zig_vector_16_u64((Vector_16_u64){ 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176 }, 16);
+}
+
+typedef uint64_t Vector_24_u64 __attribute__((vector_size(24 * sizeof(uint64_t))));
+
+Vector_24_u64 zig_ret_vector_24_u64(void);
+void zig_vector_24_u64(Vector_24_u64, size_t);
+
+Vector_24_u64 c_ret_vector_24_u64(void) {
+ return (Vector_24_u64){
+ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
+ 273, 274, 275, 276, 277, 278, 279, 280,
+ };
+}
+void c_vector_24_u64(Vector_24_u64 v, size_t i) {
+ assert_or_panic(v[0] == 281);
+ assert_or_panic(v[1] == 282);
+ assert_or_panic(v[2] == 283);
+ assert_or_panic(v[3] == 284);
+ assert_or_panic(v[4] == 285);
+ assert_or_panic(v[5] == 286);
+ assert_or_panic(v[6] == 287);
+ assert_or_panic(v[7] == 288);
+ assert_or_panic(v[8] == 289);
+ assert_or_panic(v[9] == 290);
+ assert_or_panic(v[10] == 291);
+ assert_or_panic(v[11] == 292);
+ assert_or_panic(v[12] == 293);
+ assert_or_panic(v[13] == 294);
+ assert_or_panic(v[14] == 295);
+ assert_or_panic(v[15] == 296);
+ assert_or_panic(v[16] == 297);
+ assert_or_panic(v[17] == 298);
+ assert_or_panic(v[18] == 299);
+ assert_or_panic(v[19] == 300);
+ assert_or_panic(v[20] == 301);
+ assert_or_panic(v[21] == 302);
+ assert_or_panic(v[22] == 303);
+ assert_or_panic(v[23] == 304);
+ assert_or_panic(i == 24);
+}
+void c_test_vector_24_u64(void) {
+ Vector_24_u64 v = zig_ret_vector_24_u64();
+ assert_or_panic(v[0] == 209);
+ assert_or_panic(v[1] == 210);
+ assert_or_panic(v[2] == 211);
+ assert_or_panic(v[3] == 212);
+ assert_or_panic(v[4] == 213);
+ assert_or_panic(v[5] == 214);
+ assert_or_panic(v[6] == 215);
+ assert_or_panic(v[7] == 216);
+ assert_or_panic(v[8] == 217);
+ assert_or_panic(v[9] == 218);
+ assert_or_panic(v[10] == 219);
+ assert_or_panic(v[11] == 220);
+ assert_or_panic(v[12] == 221);
+ assert_or_panic(v[13] == 222);
+ assert_or_panic(v[14] == 223);
+ assert_or_panic(v[15] == 224);
+ assert_or_panic(v[16] == 225);
+ assert_or_panic(v[17] == 226);
+ assert_or_panic(v[18] == 227);
+ assert_or_panic(v[19] == 228);
+ assert_or_panic(v[20] == 229);
+ assert_or_panic(v[21] == 230);
+ assert_or_panic(v[22] == 231);
+ assert_or_panic(v[23] == 232);
+ zig_vector_24_u64((Vector_24_u64){
+ 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255, 256,
+ }, 24);
+}
+
+typedef uint64_t Vector_32_u64 __attribute__((vector_size(32 * sizeof(uint64_t))));
+
+Vector_32_u64 zig_ret_vector_32_u64(void);
+void zig_vector_32_u64(Vector_32_u64, size_t);
+
+Vector_32_u64 c_ret_vector_32_u64(void) {
+ return (Vector_32_u64){
+ 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384,
+ 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400,
+ };
+}
+void c_vector_32_u64(Vector_32_u64 v, size_t i) {
+ assert_or_panic(v[0] == 401);
+ assert_or_panic(v[1] == 402);
+ assert_or_panic(v[2] == 403);
+ assert_or_panic(v[3] == 404);
+ assert_or_panic(v[4] == 405);
+ assert_or_panic(v[5] == 406);
+ assert_or_panic(v[6] == 407);
+ assert_or_panic(v[7] == 408);
+ assert_or_panic(v[8] == 409);
+ assert_or_panic(v[9] == 410);
+ assert_or_panic(v[10] == 411);
+ assert_or_panic(v[11] == 412);
+ assert_or_panic(v[12] == 413);
+ assert_or_panic(v[13] == 414);
+ assert_or_panic(v[14] == 415);
+ assert_or_panic(v[15] == 416);
+ assert_or_panic(v[16] == 417);
+ assert_or_panic(v[17] == 418);
+ assert_or_panic(v[18] == 419);
+ assert_or_panic(v[19] == 420);
+ assert_or_panic(v[20] == 421);
+ assert_or_panic(v[21] == 422);
+ assert_or_panic(v[22] == 423);
+ assert_or_panic(v[23] == 424);
+ assert_or_panic(v[24] == 425);
+ assert_or_panic(v[25] == 426);
+ assert_or_panic(v[26] == 427);
+ assert_or_panic(v[27] == 428);
+ assert_or_panic(v[28] == 429);
+ assert_or_panic(v[29] == 430);
+ assert_or_panic(v[30] == 431);
+ assert_or_panic(v[31] == 432);
+ assert_or_panic(i == 32);
+}
+void c_test_vector_32_u64(void) {
+ Vector_32_u64 v = zig_ret_vector_32_u64();
+ assert_or_panic(v[0] == 305);
+ assert_or_panic(v[1] == 306);
+ assert_or_panic(v[2] == 307);
+ assert_or_panic(v[3] == 308);
+ assert_or_panic(v[4] == 309);
+ assert_or_panic(v[5] == 310);
+ assert_or_panic(v[6] == 311);
+ assert_or_panic(v[7] == 312);
+ assert_or_panic(v[8] == 313);
+ assert_or_panic(v[9] == 314);
+ assert_or_panic(v[10] == 315);
+ assert_or_panic(v[11] == 316);
+ assert_or_panic(v[12] == 317);
+ assert_or_panic(v[13] == 318);
+ assert_or_panic(v[14] == 319);
+ assert_or_panic(v[15] == 320);
+ assert_or_panic(v[16] == 321);
+ assert_or_panic(v[17] == 322);
+ assert_or_panic(v[18] == 323);
+ assert_or_panic(v[19] == 324);
+ assert_or_panic(v[20] == 325);
+ assert_or_panic(v[21] == 326);
+ assert_or_panic(v[22] == 327);
+ assert_or_panic(v[23] == 328);
+ assert_or_panic(v[24] == 329);
+ assert_or_panic(v[25] == 330);
+ assert_or_panic(v[26] == 331);
+ assert_or_panic(v[27] == 332);
+ assert_or_panic(v[28] == 333);
+ assert_or_panic(v[29] == 334);
+ assert_or_panic(v[30] == 335);
+ assert_or_panic(v[31] == 336);
+ zig_vector_32_u64((Vector_32_u64){
+ 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352,
+ 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368,
+ }, 32);
+}
+
+typedef uint64_t Vector_48_u64 __attribute__((vector_size(48 * sizeof(uint64_t))));
+
+Vector_48_u64 zig_ret_vector_48_u64(void);
+void zig_vector_48_u64(Vector_48_u64, size_t);
+
+Vector_48_u64 c_ret_vector_48_u64(void) {
+ return (Vector_48_u64){
+ 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544,
+ 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560,
+ 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576,
+ };
+}
+void c_vector_48_u64(Vector_48_u64 v, size_t i) {
+ assert_or_panic(v[0] == 577);
+ assert_or_panic(v[1] == 578);
+ assert_or_panic(v[2] == 579);
+ assert_or_panic(v[3] == 580);
+ assert_or_panic(v[4] == 581);
+ assert_or_panic(v[5] == 582);
+ assert_or_panic(v[6] == 583);
+ assert_or_panic(v[7] == 584);
+ assert_or_panic(v[8] == 585);
+ assert_or_panic(v[9] == 586);
+ assert_or_panic(v[10] == 587);
+ assert_or_panic(v[11] == 588);
+ assert_or_panic(v[12] == 589);
+ assert_or_panic(v[13] == 590);
+ assert_or_panic(v[14] == 591);
+ assert_or_panic(v[15] == 592);
+ assert_or_panic(v[16] == 593);
+ assert_or_panic(v[17] == 594);
+ assert_or_panic(v[18] == 595);
+ assert_or_panic(v[19] == 596);
+ assert_or_panic(v[20] == 597);
+ assert_or_panic(v[21] == 598);
+ assert_or_panic(v[22] == 599);
+ assert_or_panic(v[23] == 600);
+ assert_or_panic(v[24] == 601);
+ assert_or_panic(v[25] == 602);
+ assert_or_panic(v[26] == 603);
+ assert_or_panic(v[27] == 604);
+ assert_or_panic(v[28] == 605);
+ assert_or_panic(v[29] == 606);
+ assert_or_panic(v[30] == 607);
+ assert_or_panic(v[31] == 608);
+ assert_or_panic(v[32] == 609);
+ assert_or_panic(v[33] == 610);
+ assert_or_panic(v[34] == 611);
+ assert_or_panic(v[35] == 612);
+ assert_or_panic(v[36] == 613);
+ assert_or_panic(v[37] == 614);
+ assert_or_panic(v[38] == 615);
+ assert_or_panic(v[39] == 616);
+ assert_or_panic(v[40] == 617);
+ assert_or_panic(v[41] == 618);
+ assert_or_panic(v[42] == 619);
+ assert_or_panic(v[43] == 620);
+ assert_or_panic(v[44] == 621);
+ assert_or_panic(v[45] == 622);
+ assert_or_panic(v[46] == 623);
+ assert_or_panic(v[47] == 624);
+ assert_or_panic(i == 48);
+}
+void c_test_vector_48_u64(void) {
+ Vector_48_u64 v = zig_ret_vector_48_u64();
+ assert_or_panic(v[0] == 433);
+ assert_or_panic(v[1] == 434);
+ assert_or_panic(v[2] == 435);
+ assert_or_panic(v[3] == 436);
+ assert_or_panic(v[4] == 437);
+ assert_or_panic(v[5] == 438);
+ assert_or_panic(v[6] == 439);
+ assert_or_panic(v[7] == 440);
+ assert_or_panic(v[8] == 441);
+ assert_or_panic(v[9] == 442);
+ assert_or_panic(v[10] == 443);
+ assert_or_panic(v[11] == 444);
+ assert_or_panic(v[12] == 445);
+ assert_or_panic(v[13] == 446);
+ assert_or_panic(v[14] == 447);
+ assert_or_panic(v[15] == 448);
+ assert_or_panic(v[16] == 449);
+ assert_or_panic(v[17] == 450);
+ assert_or_panic(v[18] == 451);
+ assert_or_panic(v[19] == 452);
+ assert_or_panic(v[20] == 453);
+ assert_or_panic(v[21] == 454);
+ assert_or_panic(v[22] == 455);
+ assert_or_panic(v[23] == 456);
+ assert_or_panic(v[24] == 457);
+ assert_or_panic(v[25] == 458);
+ assert_or_panic(v[26] == 459);
+ assert_or_panic(v[27] == 460);
+ assert_or_panic(v[28] == 461);
+ assert_or_panic(v[29] == 462);
+ assert_or_panic(v[30] == 463);
+ assert_or_panic(v[31] == 464);
+ assert_or_panic(v[32] == 465);
+ assert_or_panic(v[33] == 466);
+ assert_or_panic(v[34] == 467);
+ assert_or_panic(v[35] == 468);
+ assert_or_panic(v[36] == 469);
+ assert_or_panic(v[37] == 470);
+ assert_or_panic(v[38] == 471);
+ assert_or_panic(v[39] == 472);
+ assert_or_panic(v[40] == 473);
+ assert_or_panic(v[41] == 474);
+ assert_or_panic(v[42] == 475);
+ assert_or_panic(v[43] == 476);
+ assert_or_panic(v[44] == 477);
+ assert_or_panic(v[45] == 478);
+ assert_or_panic(v[46] == 479);
+ assert_or_panic(v[47] == 480);
+ zig_vector_48_u64((Vector_48_u64){
+ 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496,
+ 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512,
+ 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528,
+ }, 48);
+}
+
+typedef uint64_t Vector_64_u64 __attribute__((vector_size(64 * sizeof(uint64_t))));
+
+Vector_64_u64 zig_ret_vector_64_u64(void);
+void zig_vector_64_u64(Vector_64_u64, size_t);
+
+Vector_64_u64 c_ret_vector_64_u64(void) {
+ return (Vector_64_u64){
+ 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768,
+ 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784,
+ 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800,
+ 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816,
+ };
+}
+void c_vector_64_u64(Vector_64_u64 v, size_t i) {
+ assert_or_panic(v[0] == 817);
+ assert_or_panic(v[1] == 818);
+ assert_or_panic(v[2] == 819);
+ assert_or_panic(v[3] == 820);
+ assert_or_panic(v[4] == 821);
+ assert_or_panic(v[5] == 822);
+ assert_or_panic(v[6] == 823);
+ assert_or_panic(v[7] == 824);
+ assert_or_panic(v[8] == 825);
+ assert_or_panic(v[9] == 826);
+ assert_or_panic(v[10] == 827);
+ assert_or_panic(v[11] == 828);
+ assert_or_panic(v[12] == 829);
+ assert_or_panic(v[13] == 830);
+ assert_or_panic(v[14] == 831);
+ assert_or_panic(v[15] == 832);
+ assert_or_panic(v[16] == 833);
+ assert_or_panic(v[17] == 834);
+ assert_or_panic(v[18] == 835);
+ assert_or_panic(v[19] == 836);
+ assert_or_panic(v[20] == 837);
+ assert_or_panic(v[21] == 838);
+ assert_or_panic(v[22] == 839);
+ assert_or_panic(v[23] == 840);
+ assert_or_panic(v[24] == 841);
+ assert_or_panic(v[25] == 842);
+ assert_or_panic(v[26] == 843);
+ assert_or_panic(v[27] == 844);
+ assert_or_panic(v[28] == 845);
+ assert_or_panic(v[29] == 846);
+ assert_or_panic(v[30] == 847);
+ assert_or_panic(v[31] == 848);
+ assert_or_panic(v[32] == 849);
+ assert_or_panic(v[33] == 850);
+ assert_or_panic(v[34] == 851);
+ assert_or_panic(v[35] == 852);
+ assert_or_panic(v[36] == 853);
+ assert_or_panic(v[37] == 854);
+ assert_or_panic(v[38] == 855);
+ assert_or_panic(v[39] == 856);
+ assert_or_panic(v[40] == 857);
+ assert_or_panic(v[41] == 858);
+ assert_or_panic(v[42] == 859);
+ assert_or_panic(v[43] == 860);
+ assert_or_panic(v[44] == 861);
+ assert_or_panic(v[45] == 862);
+ assert_or_panic(v[46] == 863);
+ assert_or_panic(v[47] == 864);
+ assert_or_panic(v[48] == 865);
+ assert_or_panic(v[49] == 866);
+ assert_or_panic(v[50] == 867);
+ assert_or_panic(v[51] == 868);
+ assert_or_panic(v[52] == 869);
+ assert_or_panic(v[53] == 870);
+ assert_or_panic(v[54] == 871);
+ assert_or_panic(v[55] == 872);
+ assert_or_panic(v[56] == 873);
+ assert_or_panic(v[57] == 874);
+ assert_or_panic(v[58] == 875);
+ assert_or_panic(v[59] == 876);
+ assert_or_panic(v[60] == 877);
+ assert_or_panic(v[61] == 878);
+ assert_or_panic(v[62] == 879);
+ assert_or_panic(v[63] == 880);
+ assert_or_panic(i == 64);
+}
+void c_test_vector_64_u64(void) {
+ Vector_64_u64 v = zig_ret_vector_64_u64();
+ assert_or_panic(v[0] == 625);
+ assert_or_panic(v[1] == 626);
+ assert_or_panic(v[2] == 627);
+ assert_or_panic(v[3] == 628);
+ assert_or_panic(v[4] == 629);
+ assert_or_panic(v[5] == 630);
+ assert_or_panic(v[6] == 631);
+ assert_or_panic(v[7] == 632);
+ assert_or_panic(v[8] == 633);
+ assert_or_panic(v[9] == 634);
+ assert_or_panic(v[10] == 635);
+ assert_or_panic(v[11] == 636);
+ assert_or_panic(v[12] == 637);
+ assert_or_panic(v[13] == 638);
+ assert_or_panic(v[14] == 639);
+ assert_or_panic(v[15] == 640);
+ assert_or_panic(v[16] == 641);
+ assert_or_panic(v[17] == 642);
+ assert_or_panic(v[18] == 643);
+ assert_or_panic(v[19] == 644);
+ assert_or_panic(v[20] == 645);
+ assert_or_panic(v[21] == 646);
+ assert_or_panic(v[22] == 647);
+ assert_or_panic(v[23] == 648);
+ assert_or_panic(v[24] == 649);
+ assert_or_panic(v[25] == 650);
+ assert_or_panic(v[26] == 651);
+ assert_or_panic(v[27] == 652);
+ assert_or_panic(v[28] == 653);
+ assert_or_panic(v[29] == 654);
+ assert_or_panic(v[30] == 655);
+ assert_or_panic(v[31] == 656);
+ assert_or_panic(v[32] == 657);
+ assert_or_panic(v[33] == 658);
+ assert_or_panic(v[34] == 659);
+ assert_or_panic(v[35] == 660);
+ assert_or_panic(v[36] == 661);
+ assert_or_panic(v[37] == 662);
+ assert_or_panic(v[38] == 663);
+ assert_or_panic(v[39] == 664);
+ assert_or_panic(v[40] == 665);
+ assert_or_panic(v[41] == 666);
+ assert_or_panic(v[42] == 667);
+ assert_or_panic(v[43] == 668);
+ assert_or_panic(v[44] == 669);
+ assert_or_panic(v[45] == 670);
+ assert_or_panic(v[46] == 671);
+ assert_or_panic(v[47] == 672);
+ assert_or_panic(v[48] == 673);
+ assert_or_panic(v[49] == 674);
+ assert_or_panic(v[50] == 675);
+ assert_or_panic(v[51] == 676);
+ assert_or_panic(v[52] == 677);
+ assert_or_panic(v[53] == 678);
+ assert_or_panic(v[54] == 679);
+ assert_or_panic(v[55] == 680);
+ assert_or_panic(v[56] == 681);
+ assert_or_panic(v[57] == 682);
+ assert_or_panic(v[58] == 683);
+ assert_or_panic(v[59] == 684);
+ assert_or_panic(v[60] == 685);
+ assert_or_panic(v[61] == 686);
+ assert_or_panic(v[62] == 687);
+ assert_or_panic(v[63] == 688);
+ zig_vector_64_u64((Vector_64_u64){
+ 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704,
+ 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720,
+ 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736,
+ 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752,
+ }, 64);
+}
+
+typedef float Vector_1_f32 __attribute__((vector_size(1 * sizeof(float))));
+
+Vector_1_f32 zig_ret_vector_1_f32(void);
+void zig_vector_1_f32(Vector_1_f32, size_t);
+
+Vector_1_f32 c_ret_vector_1_f32(void) {
+ return (Vector_1_f32){ 3 };
+}
+void c_vector_1_f32(Vector_1_f32 v, size_t i) {
+ assert_or_panic(v[0] == 4);
+ assert_or_panic(i == 1);
+}
+void c_test_vector_1_f32(void) {
+ Vector_1_f32 v = zig_ret_vector_1_f32();
+ assert_or_panic(v[0] == 1);
+ zig_vector_1_f32((Vector_1_f32){ 2 }, 1);
+}
+
+typedef float Vector_2_f32 __attribute__((vector_size(2 * sizeof(float))));
+
+Vector_2_f32 zig_ret_vector_2_f32(void);
+void zig_vector_2_f32(Vector_2_f32, size_t);
+
+Vector_2_f32 c_ret_vector_2_f32(void) {
+ return (Vector_2_f32){ 9, 10 };
+}
+void c_vector_2_f32(Vector_2_f32 v, size_t i) {
+ assert_or_panic(v[0] == 11);
+ assert_or_panic(v[1] == 12);
+ assert_or_panic(i == 2);
+}
+void c_test_vector_2_f32(void) {
+ Vector_2_f32 v = zig_ret_vector_2_f32();
+ assert_or_panic(v[0] == 5);
+ assert_or_panic(v[1] == 6);
+ zig_vector_2_f32((Vector_2_f32){ 7, 8 }, 2);
+}
+
+typedef float Vector_3_f32 __attribute__((vector_size(3 * sizeof(float))));
+
+Vector_3_f32 zig_ret_vector_3_f32(void);
+void zig_vector_3_f32(Vector_3_f32, size_t);
+
+Vector_3_f32 c_ret_vector_3_f32(void) {
+ return (Vector_3_f32){ 19, 20, 21 };
+}
+void c_vector_3_f32(Vector_3_f32 v, size_t i) {
+ assert_or_panic(v[0] == 22);
+ assert_or_panic(v[1] == 23);
+ assert_or_panic(v[2] == 24);
+ assert_or_panic(i == 32);
+}
+void c_test_vector_3_f32(void) {
+ Vector_3_f32 v = zig_ret_vector_3_f32();
+ assert_or_panic(v[0] == 13);
+ assert_or_panic(v[1] == 14);
+ assert_or_panic(v[2] == 15);
+ zig_vector_3_f32((Vector_3_f32){ 16, 17, 18 }, 3);
+}
+
+typedef float Vector_4_f32 __attribute__((vector_size(4 * sizeof(float))));
+
+Vector_4_f32 zig_ret_vector_4_f32(void);
+void zig_vector_4_f32(Vector_4_f32, size_t);
+void zig_vector_4_f32_vector_4_f32(Vector_4_f32, Vector_4_f32, size_t);
+
+Vector_4_f32 c_ret_vector_4_f32(void) {
+ return (Vector_4_f32){ 41, 42, 43, 44 };
+}
+void c_vector_4_f32(Vector_4_f32 v, size_t i) {
+ assert_or_panic(v[0] == 45);
+ assert_or_panic(v[1] == 46);
+ assert_or_panic(v[2] == 47);
+ assert_or_panic(v[3] == 48);
+ assert_or_panic(i == 4);
+}
+void c_vector_4_f32_vector_4_f32(Vector_4_f32 v0, Vector_4_f32 v1, size_t i) {
+ assert_or_panic(v0[0] == 49);
+ assert_or_panic(v0[1] == 50);
+ assert_or_panic(v0[2] == 51);
+ assert_or_panic(v0[3] == 52);
+ assert_or_panic(v1[0] == 53);
+ assert_or_panic(v1[1] == 54);
+ assert_or_panic(v1[2] == 55);
+ assert_or_panic(v1[3] == 56);
+ assert_or_panic(i == 8);
+}
+void c_test_vector_4_f32(void) {
+ Vector_4_f32 v = zig_ret_vector_4_f32();
+ assert_or_panic(v[0] == 25);
+ assert_or_panic(v[1] == 26);
+ assert_or_panic(v[2] == 27);
+ assert_or_panic(v[3] == 28);
+ zig_vector_4_f32((Vector_4_f32){ 29, 30, 31, 32 }, 4);
+ zig_vector_4_f32_vector_4_f32((Vector_4_f32){ 33, 34, 35, 36 }, (Vector_4_f32){ 37, 38, 39, 40 }, 8);
+}
+
+typedef float Vector_6_f32 __attribute__((vector_size(6 * sizeof(float))));
+
+Vector_6_f32 zig_ret_vector_6_f32(void);
+void zig_vector_6_f32(Vector_6_f32, size_t);
+
+Vector_6_f32 c_ret_vector_6_f32(void) {
+ return (Vector_6_f32){ 53, 54, 55, 56, 57, 58 };
+}
+void c_vector_6_f32(Vector_6_f32 v, size_t i) {
+ assert_or_panic(v[0] == 59);
+ assert_or_panic(v[1] == 60);
+ assert_or_panic(v[2] == 61);
+ assert_or_panic(v[3] == 62);
+ assert_or_panic(v[4] == 63);
+ assert_or_panic(v[5] == 64);
+ assert_or_panic(i == 6);
+}
+void c_test_vector_6_f32(void) {
+ Vector_6_f32 v = zig_ret_vector_6_f32();
+ assert_or_panic(v[0] == 41);
+ assert_or_panic(v[1] == 42);
+ assert_or_panic(v[2] == 43);
+ assert_or_panic(v[3] == 44);
+ assert_or_panic(v[4] == 45);
+ assert_or_panic(v[5] == 46);
+ zig_vector_6_f32((Vector_6_f32){ 47, 48, 49, 50, 51, 52 }, 6);
+}
+
+typedef float Vector_8_f32 __attribute__((vector_size(8 * sizeof(float))));
+
+Vector_8_f32 zig_ret_vector_8_f32(void);
+void zig_vector_8_f32(Vector_8_f32, size_t);
+
+Vector_8_f32 c_ret_vector_8_f32(void) {
+ return (Vector_8_f32){ 81, 82, 83, 84, 85, 86, 87, 88 };
+}
+void c_vector_8_f32(Vector_8_f32 v, size_t i) {
+ assert_or_panic(v[0] == 89);
+ assert_or_panic(v[1] == 90);
+ assert_or_panic(v[2] == 91);
+ assert_or_panic(v[3] == 92);
+ assert_or_panic(v[4] == 93);
+ assert_or_panic(v[5] == 94);
+ assert_or_panic(v[6] == 95);
+ assert_or_panic(v[7] == 96);
+ assert_or_panic(i == 8);
+}
+void c_test_vector_8_f32(void) {
+ Vector_8_f32 v = zig_ret_vector_8_f32();
+ assert_or_panic(v[0] == 65);
+ assert_or_panic(v[1] == 66);
+ assert_or_panic(v[2] == 67);
+ assert_or_panic(v[3] == 68);
+ assert_or_panic(v[4] == 69);
+ assert_or_panic(v[5] == 70);
+ assert_or_panic(v[6] == 71);
+ assert_or_panic(v[7] == 72);
+ zig_vector_8_f32((Vector_8_f32){ 73, 74, 75, 76, 77, 78, 79, 80 }, 8);
+}
+
+typedef float Vector_12_f32 __attribute__((vector_size(12 * sizeof(float))));
+
+Vector_12_f32 zig_ret_vector_12_f32(void);
+void zig_vector_12_f32(Vector_12_f32, size_t);
+
+Vector_12_f32 c_ret_vector_12_f32(void) {
+ return (Vector_12_f32){ 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132 };
+}
+void c_vector_12_f32(Vector_12_f32 v, size_t i) {
+ assert_or_panic(v[0] == 133);
+ assert_or_panic(v[1] == 134);
+ assert_or_panic(v[2] == 135);
+ assert_or_panic(v[3] == 136);
+ assert_or_panic(v[4] == 137);
+ assert_or_panic(v[5] == 138);
+ assert_or_panic(v[6] == 139);
+ assert_or_panic(v[7] == 140);
+ assert_or_panic(v[8] == 141);
+ assert_or_panic(v[9] == 142);
+ assert_or_panic(v[10] == 143);
+ assert_or_panic(v[11] == 144);
+ assert_or_panic(i == 12);
+}
+void c_test_vector_12_f32(void) {
+ Vector_12_f32 v = zig_ret_vector_12_f32();
+ assert_or_panic(v[0] == 97);
+ assert_or_panic(v[1] == 98);
+ assert_or_panic(v[2] == 99);
+ assert_or_panic(v[3] == 100);
+ assert_or_panic(v[4] == 101);
+ assert_or_panic(v[5] == 102);
+ assert_or_panic(v[6] == 103);
+ assert_or_panic(v[7] == 104);
+ assert_or_panic(v[8] == 105);
+ assert_or_panic(v[9] == 106);
+ assert_or_panic(v[10] == 107);
+ assert_or_panic(v[11] == 108);
+ zig_vector_12_f32((Vector_12_f32){ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120 }, 12);
+}
+
+typedef float Vector_16_f32 __attribute__((vector_size(16 * sizeof(float))));
+
+Vector_16_f32 zig_ret_vector_16_f32(void);
+void zig_vector_16_f32(Vector_16_f32, size_t);
+
+Vector_16_f32 c_ret_vector_16_f32(void) {
+ return (Vector_16_f32){ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192 };
+}
+void c_vector_16_f32(Vector_16_f32 v, size_t i) {
+ assert_or_panic(v[0] == 193);
+ assert_or_panic(v[1] == 194);
+ assert_or_panic(v[2] == 195);
+ assert_or_panic(v[3] == 196);
+ assert_or_panic(v[4] == 197);
+ assert_or_panic(v[5] == 198);
+ assert_or_panic(v[6] == 199);
+ assert_or_panic(v[7] == 200);
+ assert_or_panic(v[8] == 201);
+ assert_or_panic(v[9] == 202);
+ assert_or_panic(v[10] == 203);
+ assert_or_panic(v[11] == 204);
+ assert_or_panic(v[12] == 205);
+ assert_or_panic(v[13] == 206);
+ assert_or_panic(v[14] == 207);
+ assert_or_panic(v[15] == 208);
+ assert_or_panic(i == 16);
+}
+void c_test_vector_16_f32(void) {
+ Vector_16_f32 v = zig_ret_vector_16_f32();
+ assert_or_panic(v[0] == 145);
+ assert_or_panic(v[1] == 146);
+ assert_or_panic(v[2] == 147);
+ assert_or_panic(v[3] == 148);
+ assert_or_panic(v[4] == 149);
+ assert_or_panic(v[5] == 150);
+ assert_or_panic(v[6] == 151);
+ assert_or_panic(v[7] == 152);
+ assert_or_panic(v[8] == 153);
+ assert_or_panic(v[9] == 154);
+ assert_or_panic(v[10] == 155);
+ assert_or_panic(v[11] == 156);
+ assert_or_panic(v[12] == 157);
+ assert_or_panic(v[13] == 158);
+ assert_or_panic(v[14] == 159);
+ assert_or_panic(v[15] == 160);
+ zig_vector_16_f32((Vector_16_f32){ 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176 }, 16);
+}
+
+typedef float Vector_24_f32 __attribute__((vector_size(24 * sizeof(float))));
+
+Vector_24_f32 zig_ret_vector_24_f32(void);
+void zig_vector_24_f32(Vector_24_f32, size_t);
+
+Vector_24_f32 c_ret_vector_24_f32(void) {
+ return (Vector_24_f32){
+ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
+ 273, 274, 275, 276, 277, 278, 279, 280,
+ };
+}
+void c_vector_24_f32(Vector_24_f32 v, size_t i) {
+ assert_or_panic(v[0] == 281);
+ assert_or_panic(v[1] == 282);
+ assert_or_panic(v[2] == 283);
+ assert_or_panic(v[3] == 284);
+ assert_or_panic(v[4] == 285);
+ assert_or_panic(v[5] == 286);
+ assert_or_panic(v[6] == 287);
+ assert_or_panic(v[7] == 288);
+ assert_or_panic(v[8] == 289);
+ assert_or_panic(v[9] == 290);
+ assert_or_panic(v[10] == 291);
+ assert_or_panic(v[11] == 292);
+ assert_or_panic(v[12] == 293);
+ assert_or_panic(v[13] == 294);
+ assert_or_panic(v[14] == 295);
+ assert_or_panic(v[15] == 296);
+ assert_or_panic(v[16] == 297);
+ assert_or_panic(v[17] == 298);
+ assert_or_panic(v[18] == 299);
+ assert_or_panic(v[19] == 300);
+ assert_or_panic(v[20] == 301);
+ assert_or_panic(v[21] == 302);
+ assert_or_panic(v[22] == 303);
+ assert_or_panic(v[23] == 304);
+ assert_or_panic(i == 24);
+}
+void c_test_vector_24_f32(void) {
+ Vector_24_f32 v = zig_ret_vector_24_f32();
+ assert_or_panic(v[0] == 209);
+ assert_or_panic(v[1] == 210);
+ assert_or_panic(v[2] == 211);
+ assert_or_panic(v[3] == 212);
+ assert_or_panic(v[4] == 213);
+ assert_or_panic(v[5] == 214);
+ assert_or_panic(v[6] == 215);
+ assert_or_panic(v[7] == 216);
+ assert_or_panic(v[8] == 217);
+ assert_or_panic(v[9] == 218);
+ assert_or_panic(v[10] == 219);
+ assert_or_panic(v[11] == 220);
+ assert_or_panic(v[12] == 221);
+ assert_or_panic(v[13] == 222);
+ assert_or_panic(v[14] == 223);
+ assert_or_panic(v[15] == 224);
+ assert_or_panic(v[16] == 225);
+ assert_or_panic(v[17] == 226);
+ assert_or_panic(v[18] == 227);
+ assert_or_panic(v[19] == 228);
+ assert_or_panic(v[20] == 229);
+ assert_or_panic(v[21] == 230);
+ assert_or_panic(v[22] == 231);
+ assert_or_panic(v[23] == 232);
+ zig_vector_24_f32((Vector_24_f32){
+ 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255, 256,
+ }, 24);
+}
+
+typedef float Vector_32_f32 __attribute__((vector_size(32 * sizeof(float))));
+
+Vector_32_f32 zig_ret_vector_32_f32(void);
+void zig_vector_32_f32(Vector_32_f32, size_t);
+
+Vector_32_f32 c_ret_vector_32_f32(void) {
+ return (Vector_32_f32){
+ 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384,
+ 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400,
+ };
+}
+void c_vector_32_f32(Vector_32_f32 v, size_t i) {
+ assert_or_panic(v[0] == 401);
+ assert_or_panic(v[1] == 402);
+ assert_or_panic(v[2] == 403);
+ assert_or_panic(v[3] == 404);
+ assert_or_panic(v[4] == 405);
+ assert_or_panic(v[5] == 406);
+ assert_or_panic(v[6] == 407);
+ assert_or_panic(v[7] == 408);
+ assert_or_panic(v[8] == 409);
+ assert_or_panic(v[9] == 410);
+ assert_or_panic(v[10] == 411);
+ assert_or_panic(v[11] == 412);
+ assert_or_panic(v[12] == 413);
+ assert_or_panic(v[13] == 414);
+ assert_or_panic(v[14] == 415);
+ assert_or_panic(v[15] == 416);
+ assert_or_panic(v[16] == 417);
+ assert_or_panic(v[17] == 418);
+ assert_or_panic(v[18] == 419);
+ assert_or_panic(v[19] == 420);
+ assert_or_panic(v[20] == 421);
+ assert_or_panic(v[21] == 422);
+ assert_or_panic(v[22] == 423);
+ assert_or_panic(v[23] == 424);
+ assert_or_panic(v[24] == 425);
+ assert_or_panic(v[25] == 426);
+ assert_or_panic(v[26] == 427);
+ assert_or_panic(v[27] == 428);
+ assert_or_panic(v[28] == 429);
+ assert_or_panic(v[29] == 430);
+ assert_or_panic(v[30] == 431);
+ assert_or_panic(v[31] == 432);
+ assert_or_panic(i == 32);
+}
+void c_test_vector_32_f32(void) {
+ Vector_32_f32 v = zig_ret_vector_32_f32();
+ assert_or_panic(v[0] == 305);
+ assert_or_panic(v[1] == 306);
+ assert_or_panic(v[2] == 307);
+ assert_or_panic(v[3] == 308);
+ assert_or_panic(v[4] == 309);
+ assert_or_panic(v[5] == 310);
+ assert_or_panic(v[6] == 311);
+ assert_or_panic(v[7] == 312);
+ assert_or_panic(v[8] == 313);
+ assert_or_panic(v[9] == 314);
+ assert_or_panic(v[10] == 315);
+ assert_or_panic(v[11] == 316);
+ assert_or_panic(v[12] == 317);
+ assert_or_panic(v[13] == 318);
+ assert_or_panic(v[14] == 319);
+ assert_or_panic(v[15] == 320);
+ assert_or_panic(v[16] == 321);
+ assert_or_panic(v[17] == 322);
+ assert_or_panic(v[18] == 323);
+ assert_or_panic(v[19] == 324);
+ assert_or_panic(v[20] == 325);
+ assert_or_panic(v[21] == 326);
+ assert_or_panic(v[22] == 327);
+ assert_or_panic(v[23] == 328);
+ assert_or_panic(v[24] == 329);
+ assert_or_panic(v[25] == 330);
+ assert_or_panic(v[26] == 331);
+ assert_or_panic(v[27] == 332);
+ assert_or_panic(v[28] == 333);
+ assert_or_panic(v[29] == 334);
+ assert_or_panic(v[30] == 335);
+ assert_or_panic(v[31] == 336);
+ zig_vector_32_f32((Vector_32_f32){
+ 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352,
+ 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368,
+ }, 32);
+}
+
+typedef float Vector_48_f32 __attribute__((vector_size(48 * sizeof(float))));
+
+Vector_48_f32 zig_ret_vector_48_f32(void);
+void zig_vector_48_f32(Vector_48_f32, size_t);
+
+Vector_48_f32 c_ret_vector_48_f32(void) {
+ return (Vector_48_f32){
+ 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544,
+ 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560,
+ 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576,
+ };
+}
+void c_vector_48_f32(Vector_48_f32 v, size_t i) {
+ assert_or_panic(v[0] == 577);
+ assert_or_panic(v[1] == 578);
+ assert_or_panic(v[2] == 579);
+ assert_or_panic(v[3] == 580);
+ assert_or_panic(v[4] == 581);
+ assert_or_panic(v[5] == 582);
+ assert_or_panic(v[6] == 583);
+ assert_or_panic(v[7] == 584);
+ assert_or_panic(v[8] == 585);
+ assert_or_panic(v[9] == 586);
+ assert_or_panic(v[10] == 587);
+ assert_or_panic(v[11] == 588);
+ assert_or_panic(v[12] == 589);
+ assert_or_panic(v[13] == 590);
+ assert_or_panic(v[14] == 591);
+ assert_or_panic(v[15] == 592);
+ assert_or_panic(v[16] == 593);
+ assert_or_panic(v[17] == 594);
+ assert_or_panic(v[18] == 595);
+ assert_or_panic(v[19] == 596);
+ assert_or_panic(v[20] == 597);
+ assert_or_panic(v[21] == 598);
+ assert_or_panic(v[22] == 599);
+ assert_or_panic(v[23] == 600);
+ assert_or_panic(v[24] == 601);
+ assert_or_panic(v[25] == 602);
+ assert_or_panic(v[26] == 603);
+ assert_or_panic(v[27] == 604);
+ assert_or_panic(v[28] == 605);
+ assert_or_panic(v[29] == 606);
+ assert_or_panic(v[30] == 607);
+ assert_or_panic(v[31] == 608);
+ assert_or_panic(v[32] == 609);
+ assert_or_panic(v[33] == 610);
+ assert_or_panic(v[34] == 611);
+ assert_or_panic(v[35] == 612);
+ assert_or_panic(v[36] == 613);
+ assert_or_panic(v[37] == 614);
+ assert_or_panic(v[38] == 615);
+ assert_or_panic(v[39] == 616);
+ assert_or_panic(v[40] == 617);
+ assert_or_panic(v[41] == 618);
+ assert_or_panic(v[42] == 619);
+ assert_or_panic(v[43] == 620);
+ assert_or_panic(v[44] == 621);
+ assert_or_panic(v[45] == 622);
+ assert_or_panic(v[46] == 623);
+ assert_or_panic(v[47] == 624);
+ assert_or_panic(i == 48);
+}
+void c_test_vector_48_f32(void) {
+ Vector_48_f32 v = zig_ret_vector_48_f32();
+ assert_or_panic(v[0] == 433);
+ assert_or_panic(v[1] == 434);
+ assert_or_panic(v[2] == 435);
+ assert_or_panic(v[3] == 436);
+ assert_or_panic(v[4] == 437);
+ assert_or_panic(v[5] == 438);
+ assert_or_panic(v[6] == 439);
+ assert_or_panic(v[7] == 440);
+ assert_or_panic(v[8] == 441);
+ assert_or_panic(v[9] == 442);
+ assert_or_panic(v[10] == 443);
+ assert_or_panic(v[11] == 444);
+ assert_or_panic(v[12] == 445);
+ assert_or_panic(v[13] == 446);
+ assert_or_panic(v[14] == 447);
+ assert_or_panic(v[15] == 448);
+ assert_or_panic(v[16] == 449);
+ assert_or_panic(v[17] == 450);
+ assert_or_panic(v[18] == 451);
+ assert_or_panic(v[19] == 452);
+ assert_or_panic(v[20] == 453);
+ assert_or_panic(v[21] == 454);
+ assert_or_panic(v[22] == 455);
+ assert_or_panic(v[23] == 456);
+ assert_or_panic(v[24] == 457);
+ assert_or_panic(v[25] == 458);
+ assert_or_panic(v[26] == 459);
+ assert_or_panic(v[27] == 460);
+ assert_or_panic(v[28] == 461);
+ assert_or_panic(v[29] == 462);
+ assert_or_panic(v[30] == 463);
+ assert_or_panic(v[31] == 464);
+ assert_or_panic(v[32] == 465);
+ assert_or_panic(v[33] == 466);
+ assert_or_panic(v[34] == 467);
+ assert_or_panic(v[35] == 468);
+ assert_or_panic(v[36] == 469);
+ assert_or_panic(v[37] == 470);
+ assert_or_panic(v[38] == 471);
+ assert_or_panic(v[39] == 472);
+ assert_or_panic(v[40] == 473);
+ assert_or_panic(v[41] == 474);
+ assert_or_panic(v[42] == 475);
+ assert_or_panic(v[43] == 476);
+ assert_or_panic(v[44] == 477);
+ assert_or_panic(v[45] == 478);
+ assert_or_panic(v[46] == 479);
+ assert_or_panic(v[47] == 480);
+ zig_vector_48_f32((Vector_48_f32){
+ 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496,
+ 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512,
+ 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528,
+ }, 48);
+}
+
+typedef float Vector_64_f32 __attribute__((vector_size(64 * sizeof(float))));
+
+Vector_64_f32 zig_ret_vector_64_f32(void);
+void zig_vector_64_f32(Vector_64_f32, size_t);
+
+Vector_64_f32 c_ret_vector_64_f32(void) {
+ return (Vector_64_f32){
+ 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768,
+ 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784,
+ 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800,
+ 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816,
+ };
+}
+void c_vector_64_f32(Vector_64_f32 v, size_t i) {
+ assert_or_panic(v[0] == 817);
+ assert_or_panic(v[1] == 818);
+ assert_or_panic(v[2] == 819);
+ assert_or_panic(v[3] == 820);
+ assert_or_panic(v[4] == 821);
+ assert_or_panic(v[5] == 822);
+ assert_or_panic(v[6] == 823);
+ assert_or_panic(v[7] == 824);
+ assert_or_panic(v[8] == 825);
+ assert_or_panic(v[9] == 826);
+ assert_or_panic(v[10] == 827);
+ assert_or_panic(v[11] == 828);
+ assert_or_panic(v[12] == 829);
+ assert_or_panic(v[13] == 830);
+ assert_or_panic(v[14] == 831);
+ assert_or_panic(v[15] == 832);
+ assert_or_panic(v[16] == 833);
+ assert_or_panic(v[17] == 834);
+ assert_or_panic(v[18] == 835);
+ assert_or_panic(v[19] == 836);
+ assert_or_panic(v[20] == 837);
+ assert_or_panic(v[21] == 838);
+ assert_or_panic(v[22] == 839);
+ assert_or_panic(v[23] == 840);
+ assert_or_panic(v[24] == 841);
+ assert_or_panic(v[25] == 842);
+ assert_or_panic(v[26] == 843);
+ assert_or_panic(v[27] == 844);
+ assert_or_panic(v[28] == 845);
+ assert_or_panic(v[29] == 846);
+ assert_or_panic(v[30] == 847);
+ assert_or_panic(v[31] == 848);
+ assert_or_panic(v[32] == 849);
+ assert_or_panic(v[33] == 850);
+ assert_or_panic(v[34] == 851);
+ assert_or_panic(v[35] == 852);
+ assert_or_panic(v[36] == 853);
+ assert_or_panic(v[37] == 854);
+ assert_or_panic(v[38] == 855);
+ assert_or_panic(v[39] == 856);
+ assert_or_panic(v[40] == 857);
+ assert_or_panic(v[41] == 858);
+ assert_or_panic(v[42] == 859);
+ assert_or_panic(v[43] == 860);
+ assert_or_panic(v[44] == 861);
+ assert_or_panic(v[45] == 862);
+ assert_or_panic(v[46] == 863);
+ assert_or_panic(v[47] == 864);
+ assert_or_panic(v[48] == 865);
+ assert_or_panic(v[49] == 866);
+ assert_or_panic(v[50] == 867);
+ assert_or_panic(v[51] == 868);
+ assert_or_panic(v[52] == 869);
+ assert_or_panic(v[53] == 870);
+ assert_or_panic(v[54] == 871);
+ assert_or_panic(v[55] == 872);
+ assert_or_panic(v[56] == 873);
+ assert_or_panic(v[57] == 874);
+ assert_or_panic(v[58] == 875);
+ assert_or_panic(v[59] == 876);
+ assert_or_panic(v[60] == 877);
+ assert_or_panic(v[61] == 878);
+ assert_or_panic(v[62] == 879);
+ assert_or_panic(v[63] == 880);
+ assert_or_panic(i == 64);
+}
+void c_test_vector_64_f32(void) {
+ Vector_64_f32 v = zig_ret_vector_64_f32();
+ assert_or_panic(v[0] == 625);
+ assert_or_panic(v[1] == 626);
+ assert_or_panic(v[2] == 627);
+ assert_or_panic(v[3] == 628);
+ assert_or_panic(v[4] == 629);
+ assert_or_panic(v[5] == 630);
+ assert_or_panic(v[6] == 631);
+ assert_or_panic(v[7] == 632);
+ assert_or_panic(v[8] == 633);
+ assert_or_panic(v[9] == 634);
+ assert_or_panic(v[10] == 635);
+ assert_or_panic(v[11] == 636);
+ assert_or_panic(v[12] == 637);
+ assert_or_panic(v[13] == 638);
+ assert_or_panic(v[14] == 639);
+ assert_or_panic(v[15] == 640);
+ assert_or_panic(v[16] == 641);
+ assert_or_panic(v[17] == 642);
+ assert_or_panic(v[18] == 643);
+ assert_or_panic(v[19] == 644);
+ assert_or_panic(v[20] == 645);
+ assert_or_panic(v[21] == 646);
+ assert_or_panic(v[22] == 647);
+ assert_or_panic(v[23] == 648);
+ assert_or_panic(v[24] == 649);
+ assert_or_panic(v[25] == 650);
+ assert_or_panic(v[26] == 651);
+ assert_or_panic(v[27] == 652);
+ assert_or_panic(v[28] == 653);
+ assert_or_panic(v[29] == 654);
+ assert_or_panic(v[30] == 655);
+ assert_or_panic(v[31] == 656);
+ assert_or_panic(v[32] == 657);
+ assert_or_panic(v[33] == 658);
+ assert_or_panic(v[34] == 659);
+ assert_or_panic(v[35] == 660);
+ assert_or_panic(v[36] == 661);
+ assert_or_panic(v[37] == 662);
+ assert_or_panic(v[38] == 663);
+ assert_or_panic(v[39] == 664);
+ assert_or_panic(v[40] == 665);
+ assert_or_panic(v[41] == 666);
+ assert_or_panic(v[42] == 667);
+ assert_or_panic(v[43] == 668);
+ assert_or_panic(v[44] == 669);
+ assert_or_panic(v[45] == 670);
+ assert_or_panic(v[46] == 671);
+ assert_or_panic(v[47] == 672);
+ assert_or_panic(v[48] == 673);
+ assert_or_panic(v[49] == 674);
+ assert_or_panic(v[50] == 675);
+ assert_or_panic(v[51] == 676);
+ assert_or_panic(v[52] == 677);
+ assert_or_panic(v[53] == 678);
+ assert_or_panic(v[54] == 679);
+ assert_or_panic(v[55] == 680);
+ assert_or_panic(v[56] == 681);
+ assert_or_panic(v[57] == 682);
+ assert_or_panic(v[58] == 683);
+ assert_or_panic(v[59] == 684);
+ assert_or_panic(v[60] == 685);
+ assert_or_panic(v[61] == 686);
+ assert_or_panic(v[62] == 687);
+ assert_or_panic(v[63] == 688);
+ zig_vector_64_f32((Vector_64_f32){
+ 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704,
+ 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720,
+ 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736,
+ 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752,
+ }, 64);
+}
+
+typedef float Vector_96_f32 __attribute__((vector_size(96 * sizeof(float))));
+
+Vector_96_f32 zig_ret_vector_96_f32(void);
+void zig_vector_96_f32(Vector_96_f32, size_t);
+
+Vector_96_f32 c_ret_vector_96_f32(void) {
+ return (Vector_96_f32){
+ 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097,
+ 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113,
+ 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129,
+ 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145,
+ 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161,
+ 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177,
+ };
+}
+void c_vector_96_f32(Vector_96_f32 v, size_t i) {
+ assert_or_panic(v[0] == 1178);
+ assert_or_panic(v[1] == 1179);
+ assert_or_panic(v[2] == 1180);
+ assert_or_panic(v[3] == 1181);
+ assert_or_panic(v[4] == 1182);
+ assert_or_panic(v[5] == 1183);
+ assert_or_panic(v[6] == 1184);
+ assert_or_panic(v[7] == 1185);
+ assert_or_panic(v[8] == 1186);
+ assert_or_panic(v[9] == 1187);
+ assert_or_panic(v[10] == 1188);
+ assert_or_panic(v[11] == 1189);
+ assert_or_panic(v[12] == 1190);
+ assert_or_panic(v[13] == 1191);
+ assert_or_panic(v[14] == 1192);
+ assert_or_panic(v[15] == 1193);
+ assert_or_panic(v[16] == 1194);
+ assert_or_panic(v[17] == 1195);
+ assert_or_panic(v[18] == 1196);
+ assert_or_panic(v[19] == 1197);
+ assert_or_panic(v[20] == 1198);
+ assert_or_panic(v[21] == 1199);
+ assert_or_panic(v[22] == 1200);
+ assert_or_panic(v[23] == 1201);
+ assert_or_panic(v[24] == 1202);
+ assert_or_panic(v[25] == 1203);
+ assert_or_panic(v[26] == 1204);
+ assert_or_panic(v[27] == 1205);
+ assert_or_panic(v[28] == 1206);
+ assert_or_panic(v[29] == 1207);
+ assert_or_panic(v[30] == 1208);
+ assert_or_panic(v[31] == 1209);
+ assert_or_panic(v[32] == 1210);
+ assert_or_panic(v[33] == 1211);
+ assert_or_panic(v[34] == 1212);
+ assert_or_panic(v[35] == 1213);
+ assert_or_panic(v[36] == 1214);
+ assert_or_panic(v[37] == 1215);
+ assert_or_panic(v[38] == 1216);
+ assert_or_panic(v[39] == 1217);
+ assert_or_panic(v[40] == 1218);
+ assert_or_panic(v[41] == 1219);
+ assert_or_panic(v[42] == 1220);
+ assert_or_panic(v[43] == 1221);
+ assert_or_panic(v[44] == 1222);
+ assert_or_panic(v[45] == 1223);
+ assert_or_panic(v[46] == 1224);
+ assert_or_panic(v[47] == 1225);
+ assert_or_panic(v[48] == 1226);
+ assert_or_panic(v[49] == 1227);
+ assert_or_panic(v[50] == 1228);
+ assert_or_panic(v[51] == 1229);
+ assert_or_panic(v[52] == 1230);
+ assert_or_panic(v[53] == 1231);
+ assert_or_panic(v[54] == 1232);
+ assert_or_panic(v[55] == 1233);
+ assert_or_panic(v[56] == 1234);
+ assert_or_panic(v[57] == 1235);
+ assert_or_panic(v[58] == 1236);
+ assert_or_panic(v[59] == 1237);
+ assert_or_panic(v[60] == 1238);
+ assert_or_panic(v[61] == 1239);
+ assert_or_panic(v[62] == 1240);
+ assert_or_panic(v[63] == 1241);
+ assert_or_panic(v[64] == 1242);
+ assert_or_panic(v[65] == 1243);
+ assert_or_panic(v[66] == 1244);
+ assert_or_panic(v[67] == 1245);
+ assert_or_panic(v[68] == 1246);
+ assert_or_panic(v[69] == 1247);
+ assert_or_panic(v[70] == 1248);
+ assert_or_panic(v[71] == 1249);
+ assert_or_panic(v[72] == 1250);
+ assert_or_panic(v[73] == 1251);
+ assert_or_panic(v[74] == 1252);
+ assert_or_panic(v[75] == 1253);
+ assert_or_panic(v[76] == 1254);
+ assert_or_panic(v[77] == 1255);
+ assert_or_panic(v[80] == 1258);
+ assert_or_panic(v[81] == 1259);
+ assert_or_panic(v[82] == 1260);
+ assert_or_panic(v[83] == 1261);
+ assert_or_panic(v[84] == 1262);
+ assert_or_panic(v[85] == 1263);
+ assert_or_panic(v[86] == 1264);
+ assert_or_panic(v[87] == 1265);
+ assert_or_panic(v[88] == 1266);
+ assert_or_panic(v[89] == 1267);
+ assert_or_panic(v[90] == 1268);
+ assert_or_panic(v[91] == 1269);
+ assert_or_panic(v[92] == 1270);
+ assert_or_panic(v[93] == 1271);
+ assert_or_panic(v[94] == 1272);
+ assert_or_panic(v[95] == 1273);
+ assert_or_panic(i == 96);
+}
+void c_test_vector_96_f32(void) {
+ Vector_96_f32 v = zig_ret_vector_96_f32();
+ assert_or_panic(v[0] == 890);
+ assert_or_panic(v[1] == 891);
+ assert_or_panic(v[2] == 892);
+ assert_or_panic(v[3] == 893);
+ assert_or_panic(v[4] == 894);
+ assert_or_panic(v[5] == 895);
+ assert_or_panic(v[6] == 896);
+ assert_or_panic(v[7] == 897);
+ assert_or_panic(v[8] == 898);
+ assert_or_panic(v[9] == 899);
+ assert_or_panic(v[10] == 900);
+ assert_or_panic(v[11] == 901);
+ assert_or_panic(v[12] == 902);
+ assert_or_panic(v[13] == 903);
+ assert_or_panic(v[14] == 904);
+ assert_or_panic(v[15] == 905);
+ assert_or_panic(v[16] == 906);
+ assert_or_panic(v[17] == 907);
+ assert_or_panic(v[18] == 908);
+ assert_or_panic(v[19] == 909);
+ assert_or_panic(v[20] == 910);
+ assert_or_panic(v[21] == 911);
+ assert_or_panic(v[22] == 912);
+ assert_or_panic(v[23] == 913);
+ assert_or_panic(v[24] == 914);
+ assert_or_panic(v[25] == 915);
+ assert_or_panic(v[26] == 916);
+ assert_or_panic(v[27] == 917);
+ assert_or_panic(v[28] == 918);
+ assert_or_panic(v[29] == 919);
+ assert_or_panic(v[30] == 920);
+ assert_or_panic(v[31] == 921);
+ assert_or_panic(v[32] == 922);
+ assert_or_panic(v[33] == 923);
+ assert_or_panic(v[34] == 924);
+ assert_or_panic(v[35] == 925);
+ assert_or_panic(v[36] == 926);
+ assert_or_panic(v[37] == 927);
+ assert_or_panic(v[38] == 928);
+ assert_or_panic(v[39] == 929);
+ assert_or_panic(v[40] == 930);
+ assert_or_panic(v[41] == 931);
+ assert_or_panic(v[42] == 932);
+ assert_or_panic(v[43] == 933);
+ assert_or_panic(v[44] == 934);
+ assert_or_panic(v[45] == 935);
+ assert_or_panic(v[46] == 936);
+ assert_or_panic(v[47] == 937);
+ assert_or_panic(v[48] == 938);
+ assert_or_panic(v[49] == 939);
+ assert_or_panic(v[50] == 940);
+ assert_or_panic(v[51] == 941);
+ assert_or_panic(v[52] == 942);
+ assert_or_panic(v[53] == 943);
+ assert_or_panic(v[54] == 944);
+ assert_or_panic(v[55] == 945);
+ assert_or_panic(v[56] == 946);
+ assert_or_panic(v[57] == 947);
+ assert_or_panic(v[58] == 948);
+ assert_or_panic(v[59] == 949);
+ assert_or_panic(v[60] == 950);
+ assert_or_panic(v[61] == 951);
+ assert_or_panic(v[62] == 952);
+ assert_or_panic(v[63] == 953);
+ assert_or_panic(v[64] == 954);
+ assert_or_panic(v[65] == 955);
+ assert_or_panic(v[66] == 956);
+ assert_or_panic(v[67] == 957);
+ assert_or_panic(v[68] == 958);
+ assert_or_panic(v[69] == 959);
+ assert_or_panic(v[70] == 960);
+ assert_or_panic(v[71] == 961);
+ assert_or_panic(v[72] == 962);
+ assert_or_panic(v[73] == 963);
+ assert_or_panic(v[74] == 964);
+ assert_or_panic(v[75] == 965);
+ assert_or_panic(v[76] == 966);
+ assert_or_panic(v[77] == 967);
+ assert_or_panic(v[78] == 968);
+ assert_or_panic(v[79] == 969);
+ assert_or_panic(v[80] == 970);
+ assert_or_panic(v[81] == 971);
+ assert_or_panic(v[82] == 972);
+ assert_or_panic(v[83] == 973);
+ assert_or_panic(v[84] == 974);
+ assert_or_panic(v[85] == 975);
+ assert_or_panic(v[86] == 976);
+ assert_or_panic(v[87] == 977);
+ assert_or_panic(v[88] == 978);
+ assert_or_panic(v[89] == 979);
+ assert_or_panic(v[90] == 980);
+ assert_or_panic(v[91] == 981);
+ assert_or_panic(v[92] == 982);
+ assert_or_panic(v[93] == 983);
+ assert_or_panic(v[94] == 984);
+ assert_or_panic(v[95] == 985);
+ zig_vector_96_f32((Vector_96_f32){
+ 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001,
+ 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017,
+ 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033,
+ 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049,
+ 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065,
+ 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081,
+ }, 96);
+}
+
+typedef float Vector_128_f32 __attribute__((vector_size(128 * sizeof(float))));
+
+Vector_128_f32 zig_ret_vector_128_f32(void);
+void zig_vector_128_f32(Vector_128_f32, size_t);
+
+Vector_128_f32 c_ret_vector_128_f32(void) {
+ return (Vector_128_f32){
+ 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545,
+ 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561,
+ 1562, 1563, 1564, 1565, 1566, 1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577,
+ 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593,
+ 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609,
+ 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625,
+ 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641,
+ 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657,
+ };
+}
+void c_vector_128_f32(Vector_128_f32 v, size_t i) {
+ assert_or_panic(v[0] == 1658);
+ assert_or_panic(v[1] == 1659);
+ assert_or_panic(v[2] == 1660);
+ assert_or_panic(v[3] == 1661);
+ assert_or_panic(v[4] == 1662);
+ assert_or_panic(v[5] == 1663);
+ assert_or_panic(v[6] == 1664);
+ assert_or_panic(v[7] == 1665);
+ assert_or_panic(v[8] == 1666);
+ assert_or_panic(v[9] == 1667);
+ assert_or_panic(v[10] == 1668);
+ assert_or_panic(v[11] == 1669);
+ assert_or_panic(v[12] == 1670);
+ assert_or_panic(v[13] == 1671);
+ assert_or_panic(v[14] == 1672);
+ assert_or_panic(v[15] == 1673);
+ assert_or_panic(v[16] == 1674);
+ assert_or_panic(v[17] == 1675);
+ assert_or_panic(v[18] == 1676);
+ assert_or_panic(v[19] == 1677);
+ assert_or_panic(v[20] == 1678);
+ assert_or_panic(v[21] == 1679);
+ assert_or_panic(v[22] == 1680);
+ assert_or_panic(v[23] == 1681);
+ assert_or_panic(v[24] == 1682);
+ assert_or_panic(v[25] == 1683);
+ assert_or_panic(v[26] == 1684);
+ assert_or_panic(v[27] == 1685);
+ assert_or_panic(v[28] == 1686);
+ assert_or_panic(v[29] == 1687);
+ assert_or_panic(v[30] == 1688);
+ assert_or_panic(v[31] == 1689);
+ assert_or_panic(v[32] == 1690);
+ assert_or_panic(v[33] == 1691);
+ assert_or_panic(v[34] == 1692);
+ assert_or_panic(v[35] == 1693);
+ assert_or_panic(v[36] == 1694);
+ assert_or_panic(v[37] == 1695);
+ assert_or_panic(v[38] == 1696);
+ assert_or_panic(v[39] == 1697);
+ assert_or_panic(v[40] == 1698);
+ assert_or_panic(v[41] == 1699);
+ assert_or_panic(v[42] == 1700);
+ assert_or_panic(v[43] == 1701);
+ assert_or_panic(v[44] == 1702);
+ assert_or_panic(v[45] == 1703);
+ assert_or_panic(v[46] == 1704);
+ assert_or_panic(v[47] == 1705);
+ assert_or_panic(v[48] == 1706);
+ assert_or_panic(v[49] == 1707);
+ assert_or_panic(v[50] == 1708);
+ assert_or_panic(v[51] == 1709);
+ assert_or_panic(v[52] == 1710);
+ assert_or_panic(v[53] == 1711);
+ assert_or_panic(v[54] == 1712);
+ assert_or_panic(v[55] == 1713);
+ assert_or_panic(v[56] == 1714);
+ assert_or_panic(v[57] == 1715);
+ assert_or_panic(v[58] == 1716);
+ assert_or_panic(v[59] == 1717);
+ assert_or_panic(v[60] == 1718);
+ assert_or_panic(v[61] == 1719);
+ assert_or_panic(v[62] == 1720);
+ assert_or_panic(v[63] == 1721);
+ assert_or_panic(v[64] == 1722);
+ assert_or_panic(v[65] == 1723);
+ assert_or_panic(v[66] == 1724);
+ assert_or_panic(v[67] == 1725);
+ assert_or_panic(v[68] == 1726);
+ assert_or_panic(v[69] == 1727);
+ assert_or_panic(v[70] == 1728);
+ assert_or_panic(v[71] == 1729);
+ assert_or_panic(v[72] == 1730);
+ assert_or_panic(v[73] == 1731);
+ assert_or_panic(v[74] == 1732);
+ assert_or_panic(v[75] == 1733);
+ assert_or_panic(v[76] == 1734);
+ assert_or_panic(v[77] == 1735);
+ assert_or_panic(v[78] == 1736);
+ assert_or_panic(v[79] == 1737);
+ assert_or_panic(v[80] == 1738);
+ assert_or_panic(v[81] == 1739);
+ assert_or_panic(v[82] == 1740);
+ assert_or_panic(v[83] == 1741);
+ assert_or_panic(v[84] == 1742);
+ assert_or_panic(v[85] == 1743);
+ assert_or_panic(v[86] == 1744);
+ assert_or_panic(v[87] == 1745);
+ assert_or_panic(v[88] == 1746);
+ assert_or_panic(v[89] == 1747);
+ assert_or_panic(v[90] == 1748);
+ assert_or_panic(v[91] == 1749);
+ assert_or_panic(v[92] == 1750);
+ assert_or_panic(v[93] == 1751);
+ assert_or_panic(v[94] == 1752);
+ assert_or_panic(v[95] == 1753);
+ assert_or_panic(v[96] == 1754);
+ assert_or_panic(v[97] == 1755);
+ assert_or_panic(v[98] == 1756);
+ assert_or_panic(v[99] == 1757);
+ assert_or_panic(v[100] == 1758);
+ assert_or_panic(v[101] == 1759);
+ assert_or_panic(v[102] == 1760);
+ assert_or_panic(v[103] == 1761);
+ assert_or_panic(v[104] == 1762);
+ assert_or_panic(v[105] == 1763);
+ assert_or_panic(v[106] == 1764);
+ assert_or_panic(v[107] == 1765);
+ assert_or_panic(v[108] == 1766);
+ assert_or_panic(v[109] == 1767);
+ assert_or_panic(v[110] == 1768);
+ assert_or_panic(v[111] == 1769);
+ assert_or_panic(v[112] == 1770);
+ assert_or_panic(v[113] == 1771);
+ assert_or_panic(v[114] == 1772);
+ assert_or_panic(v[115] == 1773);
+ assert_or_panic(v[116] == 1774);
+ assert_or_panic(v[117] == 1775);
+ assert_or_panic(v[118] == 1776);
+ assert_or_panic(v[119] == 1777);
+ assert_or_panic(v[120] == 1778);
+ assert_or_panic(v[121] == 1779);
+ assert_or_panic(v[122] == 1780);
+ assert_or_panic(v[123] == 1781);
+ assert_or_panic(v[124] == 1782);
+ assert_or_panic(v[125] == 1783);
+ assert_or_panic(v[126] == 1784);
+ assert_or_panic(v[127] == 1785);
+ assert_or_panic(i == 128);
+}
+void c_test_vector_128_f32(void) {
+ Vector_128_f32 v = zig_ret_vector_128_f32();
+ assert_or_panic(v[0] == 1274);
+ assert_or_panic(v[1] == 1275);
+ assert_or_panic(v[2] == 1276);
+ assert_or_panic(v[3] == 1277);
+ assert_or_panic(v[4] == 1278);
+ assert_or_panic(v[5] == 1279);
+ assert_or_panic(v[6] == 1280);
+ assert_or_panic(v[7] == 1281);
+ assert_or_panic(v[8] == 1282);
+ assert_or_panic(v[9] == 1283);
+ assert_or_panic(v[10] == 1284);
+ assert_or_panic(v[11] == 1285);
+ assert_or_panic(v[12] == 1286);
+ assert_or_panic(v[13] == 1287);
+ assert_or_panic(v[14] == 1288);
+ assert_or_panic(v[15] == 1289);
+ assert_or_panic(v[16] == 1290);
+ assert_or_panic(v[17] == 1291);
+ assert_or_panic(v[18] == 1292);
+ assert_or_panic(v[19] == 1293);
+ assert_or_panic(v[20] == 1294);
+ assert_or_panic(v[21] == 1295);
+ assert_or_panic(v[22] == 1296);
+ assert_or_panic(v[23] == 1297);
+ assert_or_panic(v[24] == 1298);
+ assert_or_panic(v[25] == 1299);
+ assert_or_panic(v[26] == 1300);
+ assert_or_panic(v[27] == 1301);
+ assert_or_panic(v[28] == 1302);
+ assert_or_panic(v[29] == 1303);
+ assert_or_panic(v[30] == 1304);
+ assert_or_panic(v[31] == 1305);
+ assert_or_panic(v[32] == 1306);
+ assert_or_panic(v[33] == 1307);
+ assert_or_panic(v[34] == 1308);
+ assert_or_panic(v[35] == 1309);
+ assert_or_panic(v[36] == 1310);
+ assert_or_panic(v[37] == 1311);
+ assert_or_panic(v[38] == 1312);
+ assert_or_panic(v[39] == 1313);
+ assert_or_panic(v[40] == 1314);
+ assert_or_panic(v[41] == 1315);
+ assert_or_panic(v[42] == 1316);
+ assert_or_panic(v[43] == 1317);
+ assert_or_panic(v[44] == 1318);
+ assert_or_panic(v[45] == 1319);
+ assert_or_panic(v[46] == 1320);
+ assert_or_panic(v[47] == 1321);
+ assert_or_panic(v[48] == 1322);
+ assert_or_panic(v[49] == 1323);
+ assert_or_panic(v[50] == 1324);
+ assert_or_panic(v[51] == 1325);
+ assert_or_panic(v[52] == 1326);
+ assert_or_panic(v[53] == 1327);
+ assert_or_panic(v[54] == 1328);
+ assert_or_panic(v[55] == 1329);
+ assert_or_panic(v[56] == 1330);
+ assert_or_panic(v[57] == 1331);
+ assert_or_panic(v[58] == 1332);
+ assert_or_panic(v[59] == 1333);
+ assert_or_panic(v[60] == 1334);
+ assert_or_panic(v[61] == 1335);
+ assert_or_panic(v[62] == 1336);
+ assert_or_panic(v[63] == 1337);
+ assert_or_panic(v[64] == 1338);
+ assert_or_panic(v[65] == 1339);
+ assert_or_panic(v[66] == 1340);
+ assert_or_panic(v[67] == 1341);
+ assert_or_panic(v[68] == 1342);
+ assert_or_panic(v[69] == 1343);
+ assert_or_panic(v[70] == 1344);
+ assert_or_panic(v[71] == 1345);
+ assert_or_panic(v[72] == 1346);
+ assert_or_panic(v[73] == 1347);
+ assert_or_panic(v[74] == 1348);
+ assert_or_panic(v[75] == 1349);
+ assert_or_panic(v[76] == 1350);
+ assert_or_panic(v[77] == 1351);
+ assert_or_panic(v[78] == 1352);
+ assert_or_panic(v[79] == 1353);
+ assert_or_panic(v[80] == 1354);
+ assert_or_panic(v[81] == 1355);
+ assert_or_panic(v[82] == 1356);
+ assert_or_panic(v[83] == 1357);
+ assert_or_panic(v[84] == 1358);
+ assert_or_panic(v[85] == 1359);
+ assert_or_panic(v[86] == 1360);
+ assert_or_panic(v[87] == 1361);
+ assert_or_panic(v[88] == 1362);
+ assert_or_panic(v[89] == 1363);
+ assert_or_panic(v[90] == 1364);
+ assert_or_panic(v[91] == 1365);
+ assert_or_panic(v[92] == 1366);
+ assert_or_panic(v[93] == 1367);
+ assert_or_panic(v[94] == 1368);
+ assert_or_panic(v[95] == 1369);
+ assert_or_panic(v[96] == 1370);
+ assert_or_panic(v[97] == 1371);
+ assert_or_panic(v[98] == 1372);
+ assert_or_panic(v[99] == 1373);
+ assert_or_panic(v[100] == 1374);
+ assert_or_panic(v[101] == 1375);
+ assert_or_panic(v[102] == 1376);
+ assert_or_panic(v[103] == 1377);
+ assert_or_panic(v[104] == 1378);
+ assert_or_panic(v[105] == 1379);
+ assert_or_panic(v[106] == 1380);
+ assert_or_panic(v[107] == 1381);
+ assert_or_panic(v[108] == 1382);
+ assert_or_panic(v[109] == 1383);
+ assert_or_panic(v[110] == 1384);
+ assert_or_panic(v[111] == 1385);
+ assert_or_panic(v[112] == 1386);
+ assert_or_panic(v[113] == 1387);
+ assert_or_panic(v[114] == 1388);
+ assert_or_panic(v[115] == 1389);
+ assert_or_panic(v[116] == 1390);
+ assert_or_panic(v[117] == 1391);
+ assert_or_panic(v[118] == 1392);
+ assert_or_panic(v[119] == 1393);
+ assert_or_panic(v[120] == 1394);
+ assert_or_panic(v[121] == 1395);
+ assert_or_panic(v[122] == 1396);
+ assert_or_panic(v[123] == 1397);
+ assert_or_panic(v[124] == 1398);
+ assert_or_panic(v[125] == 1399);
+ assert_or_panic(v[126] == 1400);
+ assert_or_panic(v[127] == 1401);
+ zig_vector_128_f32((Vector_128_f32){
+ 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417,
+ 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1433,
+ 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449,
+ 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465,
+ 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481,
+ 1482, 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497,
+ 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513,
+ 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529,
+ }, 128);
+}
+
+typedef double Vector_1_f64 __attribute__((vector_size(1 * sizeof(double))));
+
+Vector_1_f64 zig_ret_vector_1_f64(void);
+void zig_vector_1_f64(Vector_1_f64, size_t);
+
+Vector_1_f64 c_ret_vector_1_f64(void) {
+ return (Vector_1_f64){ 3 };
+}
+void c_vector_1_f64(Vector_1_f64 v, size_t i) {
+ assert_or_panic(v[0] == 4);
+ assert_or_panic(i == 1);
+}
+void c_test_vector_1_f64(void) {
+ Vector_1_f64 v = zig_ret_vector_1_f64();
+ assert_or_panic(v[0] == 1);
+ zig_vector_1_f64((Vector_1_f64){ 2 }, 1);
+}
+
+typedef double Vector_2_f64 __attribute__((vector_size(2 * sizeof(double))));
+
+Vector_2_f64 zig_ret_vector_2_f64(void);
+void zig_vector_2_f64(Vector_2_f64, size_t);
+
+Vector_2_f64 c_ret_vector_2_f64(void) {
+ return (Vector_2_f64){ 9, 10 };
+}
+void c_vector_2_f64(Vector_2_f64 v, size_t i) {
+ assert_or_panic(v[0] == 11);
+ assert_or_panic(v[1] == 12);
+ assert_or_panic(i == 2);
+}
+void c_test_vector_2_f64(void) {
+ Vector_2_f64 v = zig_ret_vector_2_f64();
+ assert_or_panic(v[0] == 5);
+ assert_or_panic(v[1] == 6);
+ zig_vector_2_f64((Vector_2_f64){ 7, 8 }, 2);
+}
+
+typedef double Vector_3_f64 __attribute__((vector_size(3 * sizeof(double))));
+
+Vector_3_f64 zig_ret_vector_3_f64(void);
+void zig_vector_3_f64(Vector_3_f64, size_t);
+
+Vector_3_f64 c_ret_vector_3_f64(void) {
+ return (Vector_3_f64){ 19, 20, 21 };
+}
+void c_vector_3_f64(Vector_3_f64 v, size_t i) {
+ assert_or_panic(v[0] == 22);
+ assert_or_panic(v[1] == 23);
+ assert_or_panic(v[2] == 24);
+ assert_or_panic(i == 3);
+}
+void c_test_vector_3_f64(void) {
+ Vector_3_f64 v = zig_ret_vector_3_f64();
+ assert_or_panic(v[0] == 13);
+ assert_or_panic(v[1] == 14);
+ assert_or_panic(v[2] == 15);
+ zig_vector_3_f64((Vector_3_f64){ 16, 17, 18 }, 3);
+}
+
+typedef double Vector_4_f64 __attribute__((vector_size(4 * sizeof(double))));
+
+Vector_4_f64 zig_ret_vector_4_f64(void);
+void zig_vector_4_f64(Vector_4_f64, size_t);
+
+Vector_4_f64 c_ret_vector_4_f64(void) {
+ return (Vector_4_f64){ 33, 34, 35, 36 };
+}
+void c_vector_4_f64(Vector_4_f64 v, size_t i) {
+ assert_or_panic(v[0] == 37);
+ assert_or_panic(v[1] == 38);
+ assert_or_panic(v[2] == 39);
+ assert_or_panic(v[3] == 40);
+ assert_or_panic(i == 4);
+}
+void c_test_vector_4_f64(void) {
+ Vector_4_f64 v = zig_ret_vector_4_f64();
+ assert_or_panic(v[0] == 25);
+ assert_or_panic(v[1] == 26);
+ assert_or_panic(v[2] == 27);
+ assert_or_panic(v[3] == 28);
+ zig_vector_4_f64((Vector_4_f64){ 29, 30, 31, 32 }, 4);
+}
+
+typedef double Vector_6_f64 __attribute__((vector_size(6 * sizeof(double))));
+
+Vector_6_f64 zig_ret_vector_6_f64(void);
+void zig_vector_6_f64(Vector_6_f64, size_t);
+
+Vector_6_f64 c_ret_vector_6_f64(void) {
+ return (Vector_6_f64){ 53, 54, 55, 56, 57, 58 };
+}
+void c_vector_6_f64(Vector_6_f64 v, size_t i) {
+ assert_or_panic(v[0] == 59);
+ assert_or_panic(v[1] == 60);
+ assert_or_panic(v[2] == 61);
+ assert_or_panic(v[3] == 62);
+ assert_or_panic(v[4] == 63);
+ assert_or_panic(v[5] == 64);
+ assert_or_panic(i == 6);
+}
+void c_test_vector_6_f64(void) {
+ Vector_6_f64 v = zig_ret_vector_6_f64();
+ assert_or_panic(v[0] == 41);
+ assert_or_panic(v[1] == 42);
+ assert_or_panic(v[2] == 43);
+ assert_or_panic(v[3] == 44);
+ assert_or_panic(v[4] == 45);
+ assert_or_panic(v[5] == 46);
+ zig_vector_6_f64((Vector_6_f64){ 47, 48, 49, 50, 51, 52 }, 6);
+}
+
+typedef double Vector_8_f64 __attribute__((vector_size(8 * sizeof(double))));
+
+Vector_8_f64 zig_ret_vector_8_f64(void);
+void zig_vector_8_f64(Vector_8_f64, size_t);
+
+Vector_8_f64 c_ret_vector_8_f64(void) {
+ return (Vector_8_f64){ 81, 82, 83, 84, 85, 86, 87, 88 };
+}
+void c_vector_8_f64(Vector_8_f64 v, size_t i) {
+ assert_or_panic(v[0] == 89);
+ assert_or_panic(v[1] == 90);
+ assert_or_panic(v[2] == 91);
+ assert_or_panic(v[3] == 92);
+ assert_or_panic(v[4] == 93);
+ assert_or_panic(v[5] == 94);
+ assert_or_panic(v[6] == 95);
+ assert_or_panic(v[7] == 96);
+ assert_or_panic(i == 8);
+}
+void c_test_vector_8_f64(void) {
+ Vector_8_f64 v = zig_ret_vector_8_f64();
+ assert_or_panic(v[0] == 65);
+ assert_or_panic(v[1] == 66);
+ assert_or_panic(v[2] == 67);
+ assert_or_panic(v[3] == 68);
+ assert_or_panic(v[4] == 69);
+ assert_or_panic(v[5] == 70);
+ assert_or_panic(v[6] == 71);
+ assert_or_panic(v[7] == 72);
+ zig_vector_8_f64((Vector_8_f64){ 73, 74, 75, 76, 77, 78, 79, 80 }, 8);
+}
+
+typedef double Vector_12_f64 __attribute__((vector_size(12 * sizeof(double))));
+
+Vector_12_f64 zig_ret_vector_12_f64(void);
+void zig_vector_12_f64(Vector_12_f64, size_t);
+
+Vector_12_f64 c_ret_vector_12_f64(void) {
+ return (Vector_12_f64){ 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132 };
+}
+void c_vector_12_f64(Vector_12_f64 v, size_t i) {
+ assert_or_panic(v[0] == 133);
+ assert_or_panic(v[1] == 134);
+ assert_or_panic(v[2] == 135);
+ assert_or_panic(v[3] == 136);
+ assert_or_panic(v[4] == 137);
+ assert_or_panic(v[5] == 138);
+ assert_or_panic(v[6] == 139);
+ assert_or_panic(v[7] == 140);
+ assert_or_panic(v[8] == 141);
+ assert_or_panic(v[9] == 142);
+ assert_or_panic(v[10] == 143);
+ assert_or_panic(v[11] == 144);
+ assert_or_panic(i == 12);
+}
+void c_test_vector_12_f64(void) {
+ Vector_12_f64 v = zig_ret_vector_12_f64();
+ assert_or_panic(v[0] == 97);
+ assert_or_panic(v[1] == 98);
+ assert_or_panic(v[2] == 99);
+ assert_or_panic(v[3] == 100);
+ assert_or_panic(v[4] == 101);
+ assert_or_panic(v[5] == 102);
+ assert_or_panic(v[6] == 103);
+ assert_or_panic(v[7] == 104);
+ assert_or_panic(v[8] == 105);
+ assert_or_panic(v[9] == 106);
+ assert_or_panic(v[10] == 107);
+ assert_or_panic(v[11] == 108);
+ zig_vector_12_f64((Vector_12_f64){ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120 }, 12);
+}
+
+typedef double Vector_16_f64 __attribute__((vector_size(16 * sizeof(double))));
+
+Vector_16_f64 zig_ret_vector_16_f64(void);
+void zig_vector_16_f64(Vector_16_f64, size_t);
+
+Vector_16_f64 c_ret_vector_16_f64(void) {
+ return (Vector_16_f64){ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192 };
+}
+void c_vector_16_f64(Vector_16_f64 v, size_t i) {
+ assert_or_panic(v[0] == 193);
+ assert_or_panic(v[1] == 194);
+ assert_or_panic(v[2] == 195);
+ assert_or_panic(v[3] == 196);
+ assert_or_panic(v[4] == 197);
+ assert_or_panic(v[5] == 198);
+ assert_or_panic(v[6] == 199);
+ assert_or_panic(v[7] == 200);
+ assert_or_panic(v[8] == 201);
+ assert_or_panic(v[9] == 202);
+ assert_or_panic(v[10] == 203);
+ assert_or_panic(v[11] == 204);
+ assert_or_panic(v[12] == 205);
+ assert_or_panic(v[13] == 206);
+ assert_or_panic(v[14] == 207);
+ assert_or_panic(v[15] == 208);
+ assert_or_panic(i == 16);
+}
+void c_test_vector_16_f64(void) {
+ Vector_16_f64 v = zig_ret_vector_16_f64();
+ assert_or_panic(v[0] == 145);
+ assert_or_panic(v[1] == 146);
+ assert_or_panic(v[2] == 147);
+ assert_or_panic(v[3] == 148);
+ assert_or_panic(v[4] == 149);
+ assert_or_panic(v[5] == 150);
+ assert_or_panic(v[6] == 151);
+ assert_or_panic(v[7] == 152);
+ assert_or_panic(v[8] == 153);
+ assert_or_panic(v[9] == 154);
+ assert_or_panic(v[10] == 155);
+ assert_or_panic(v[11] == 156);
+ assert_or_panic(v[12] == 157);
+ assert_or_panic(v[13] == 158);
+ assert_or_panic(v[14] == 159);
+ assert_or_panic(v[15] == 160);
+ zig_vector_16_f64((Vector_16_f64){ 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176 }, 16);
+}
+
+typedef double Vector_24_f64 __attribute__((vector_size(24 * sizeof(double))));
+
+Vector_24_f64 zig_ret_vector_24_f64(void);
+void zig_vector_24_f64(Vector_24_f64, size_t);
+
+Vector_24_f64 c_ret_vector_24_f64(void) {
+ return (Vector_24_f64){
+ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
+ 273, 274, 275, 276, 277, 278, 279, 280,
+ };
+}
+void c_vector_24_f64(Vector_24_f64 v, size_t i) {
+ assert_or_panic(v[0] == 281);
+ assert_or_panic(v[1] == 282);
+ assert_or_panic(v[2] == 283);
+ assert_or_panic(v[3] == 284);
+ assert_or_panic(v[4] == 285);
+ assert_or_panic(v[5] == 286);
+ assert_or_panic(v[6] == 287);
+ assert_or_panic(v[7] == 288);
+ assert_or_panic(v[8] == 289);
+ assert_or_panic(v[9] == 290);
+ assert_or_panic(v[10] == 291);
+ assert_or_panic(v[11] == 292);
+ assert_or_panic(v[12] == 293);
+ assert_or_panic(v[13] == 294);
+ assert_or_panic(v[14] == 295);
+ assert_or_panic(v[15] == 296);
+ assert_or_panic(v[16] == 297);
+ assert_or_panic(v[17] == 298);
+ assert_or_panic(v[18] == 299);
+ assert_or_panic(v[19] == 300);
+ assert_or_panic(v[20] == 301);
+ assert_or_panic(v[21] == 302);
+ assert_or_panic(v[22] == 303);
+ assert_or_panic(v[23] == 304);
+ assert_or_panic(i == 24);
+}
+void c_test_vector_24_f64(void) {
+ Vector_24_f64 v = zig_ret_vector_24_f64();
+ assert_or_panic(v[0] == 209);
+ assert_or_panic(v[1] == 210);
+ assert_or_panic(v[2] == 211);
+ assert_or_panic(v[3] == 212);
+ assert_or_panic(v[4] == 213);
+ assert_or_panic(v[5] == 214);
+ assert_or_panic(v[6] == 215);
+ assert_or_panic(v[7] == 216);
+ assert_or_panic(v[8] == 217);
+ assert_or_panic(v[9] == 218);
+ assert_or_panic(v[10] == 219);
+ assert_or_panic(v[11] == 220);
+ assert_or_panic(v[12] == 221);
+ assert_or_panic(v[13] == 222);
+ assert_or_panic(v[14] == 223);
+ assert_or_panic(v[15] == 224);
+ assert_or_panic(v[16] == 225);
+ assert_or_panic(v[17] == 226);
+ assert_or_panic(v[18] == 227);
+ assert_or_panic(v[19] == 228);
+ assert_or_panic(v[20] == 229);
+ assert_or_panic(v[21] == 230);
+ assert_or_panic(v[22] == 231);
+ assert_or_panic(v[23] == 232);
+ zig_vector_24_f64((Vector_24_f64){
+ 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255, 256,
+ }, 24);
+}
+
+typedef double Vector_32_f64 __attribute__((vector_size(32 * sizeof(double))));
+
+Vector_32_f64 zig_ret_vector_32_f64(void);
+void zig_vector_32_f64(Vector_32_f64, size_t);
+
+Vector_32_f64 c_ret_vector_32_f64(void) {
+ return (Vector_32_f64){
+ 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384,
+ 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400,
+ };
+}
+void c_vector_32_f64(Vector_32_f64 v, size_t i) {
+ assert_or_panic(v[0] == 401);
+ assert_or_panic(v[1] == 402);
+ assert_or_panic(v[2] == 403);
+ assert_or_panic(v[3] == 404);
+ assert_or_panic(v[4] == 405);
+ assert_or_panic(v[5] == 406);
+ assert_or_panic(v[6] == 407);
+ assert_or_panic(v[7] == 408);
+ assert_or_panic(v[8] == 409);
+ assert_or_panic(v[9] == 410);
+ assert_or_panic(v[10] == 411);
+ assert_or_panic(v[11] == 412);
+ assert_or_panic(v[12] == 413);
+ assert_or_panic(v[13] == 414);
+ assert_or_panic(v[14] == 415);
+ assert_or_panic(v[15] == 416);
+ assert_or_panic(v[16] == 417);
+ assert_or_panic(v[17] == 418);
+ assert_or_panic(v[18] == 419);
+ assert_or_panic(v[19] == 420);
+ assert_or_panic(v[20] == 421);
+ assert_or_panic(v[21] == 422);
+ assert_or_panic(v[22] == 423);
+ assert_or_panic(v[23] == 424);
+ assert_or_panic(v[24] == 425);
+ assert_or_panic(v[25] == 426);
+ assert_or_panic(v[26] == 427);
+ assert_or_panic(v[27] == 428);
+ assert_or_panic(v[28] == 429);
+ assert_or_panic(v[29] == 430);
+ assert_or_panic(v[30] == 431);
+ assert_or_panic(v[31] == 432);
+ assert_or_panic(i == 32);
+}
+void c_test_vector_32_f64(void) {
+ Vector_32_f64 v = zig_ret_vector_32_f64();
+ assert_or_panic(v[0] == 305);
+ assert_or_panic(v[1] == 306);
+ assert_or_panic(v[2] == 307);
+ assert_or_panic(v[3] == 308);
+ assert_or_panic(v[4] == 309);
+ assert_or_panic(v[5] == 310);
+ assert_or_panic(v[6] == 311);
+ assert_or_panic(v[7] == 312);
+ assert_or_panic(v[8] == 313);
+ assert_or_panic(v[9] == 314);
+ assert_or_panic(v[10] == 315);
+ assert_or_panic(v[11] == 316);
+ assert_or_panic(v[12] == 317);
+ assert_or_panic(v[13] == 318);
+ assert_or_panic(v[14] == 319);
+ assert_or_panic(v[15] == 320);
+ assert_or_panic(v[16] == 321);
+ assert_or_panic(v[17] == 322);
+ assert_or_panic(v[18] == 323);
+ assert_or_panic(v[19] == 324);
+ assert_or_panic(v[20] == 325);
+ assert_or_panic(v[21] == 326);
+ assert_or_panic(v[22] == 327);
+ assert_or_panic(v[23] == 328);
+ assert_or_panic(v[24] == 329);
+ assert_or_panic(v[25] == 330);
+ assert_or_panic(v[26] == 331);
+ assert_or_panic(v[27] == 332);
+ assert_or_panic(v[28] == 333);
+ assert_or_panic(v[29] == 334);
+ assert_or_panic(v[30] == 335);
+ assert_or_panic(v[31] == 336);
+ zig_vector_32_f64((Vector_32_f64){
+ 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352,
+ 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368,
+ }, 32);
+}
+
+typedef double Vector_48_f64 __attribute__((vector_size(48 * sizeof(double))));
+
+Vector_48_f64 zig_ret_vector_48_f64(void);
+void zig_vector_48_f64(Vector_48_f64, size_t);
+
+Vector_48_f64 c_ret_vector_48_f64(void) {
+ return (Vector_48_f64){
+ 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544,
+ 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560,
+ 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576,
+ };
+}
+void c_vector_48_f64(Vector_48_f64 v, size_t i) {
+ assert_or_panic(v[0] == 577);
+ assert_or_panic(v[1] == 578);
+ assert_or_panic(v[2] == 579);
+ assert_or_panic(v[3] == 580);
+ assert_or_panic(v[4] == 581);
+ assert_or_panic(v[5] == 582);
+ assert_or_panic(v[6] == 583);
+ assert_or_panic(v[7] == 584);
+ assert_or_panic(v[8] == 585);
+ assert_or_panic(v[9] == 586);
+ assert_or_panic(v[10] == 587);
+ assert_or_panic(v[11] == 588);
+ assert_or_panic(v[12] == 589);
+ assert_or_panic(v[13] == 590);
+ assert_or_panic(v[14] == 591);
+ assert_or_panic(v[15] == 592);
+ assert_or_panic(v[16] == 593);
+ assert_or_panic(v[17] == 594);
+ assert_or_panic(v[18] == 595);
+ assert_or_panic(v[19] == 596);
+ assert_or_panic(v[20] == 597);
+ assert_or_panic(v[21] == 598);
+ assert_or_panic(v[22] == 599);
+ assert_or_panic(v[23] == 600);
+ assert_or_panic(v[24] == 601);
+ assert_or_panic(v[25] == 602);
+ assert_or_panic(v[26] == 603);
+ assert_or_panic(v[27] == 604);
+ assert_or_panic(v[28] == 605);
+ assert_or_panic(v[29] == 606);
+ assert_or_panic(v[30] == 607);
+ assert_or_panic(v[31] == 608);
+ assert_or_panic(v[32] == 609);
+ assert_or_panic(v[33] == 610);
+ assert_or_panic(v[34] == 611);
+ assert_or_panic(v[35] == 612);
+ assert_or_panic(v[36] == 613);
+ assert_or_panic(v[37] == 614);
+ assert_or_panic(v[38] == 615);
+ assert_or_panic(v[39] == 616);
+ assert_or_panic(v[40] == 617);
+ assert_or_panic(v[41] == 618);
+ assert_or_panic(v[42] == 619);
+ assert_or_panic(v[43] == 620);
+ assert_or_panic(v[44] == 621);
+ assert_or_panic(v[45] == 622);
+ assert_or_panic(v[46] == 623);
+ assert_or_panic(v[47] == 624);
+ assert_or_panic(i == 48);
+}
+void c_test_vector_48_f64(void) {
+ Vector_48_f64 v = zig_ret_vector_48_f64();
+ assert_or_panic(v[0] == 433);
+ assert_or_panic(v[1] == 434);
+ assert_or_panic(v[2] == 435);
+ assert_or_panic(v[3] == 436);
+ assert_or_panic(v[4] == 437);
+ assert_or_panic(v[5] == 438);
+ assert_or_panic(v[6] == 439);
+ assert_or_panic(v[7] == 440);
+ assert_or_panic(v[8] == 441);
+ assert_or_panic(v[9] == 442);
+ assert_or_panic(v[10] == 443);
+ assert_or_panic(v[11] == 444);
+ assert_or_panic(v[12] == 445);
+ assert_or_panic(v[13] == 446);
+ assert_or_panic(v[14] == 447);
+ assert_or_panic(v[15] == 448);
+ assert_or_panic(v[16] == 449);
+ assert_or_panic(v[17] == 450);
+ assert_or_panic(v[18] == 451);
+ assert_or_panic(v[19] == 452);
+ assert_or_panic(v[20] == 453);
+ assert_or_panic(v[21] == 454);
+ assert_or_panic(v[22] == 455);
+ assert_or_panic(v[23] == 456);
+ assert_or_panic(v[24] == 457);
+ assert_or_panic(v[25] == 458);
+ assert_or_panic(v[26] == 459);
+ assert_or_panic(v[27] == 460);
+ assert_or_panic(v[28] == 461);
+ assert_or_panic(v[29] == 462);
+ assert_or_panic(v[30] == 463);
+ assert_or_panic(v[31] == 464);
+ assert_or_panic(v[32] == 465);
+ assert_or_panic(v[33] == 466);
+ assert_or_panic(v[34] == 467);
+ assert_or_panic(v[35] == 468);
+ assert_or_panic(v[36] == 469);
+ assert_or_panic(v[37] == 470);
+ assert_or_panic(v[38] == 471);
+ assert_or_panic(v[39] == 472);
+ assert_or_panic(v[40] == 473);
+ assert_or_panic(v[41] == 474);
+ assert_or_panic(v[42] == 475);
+ assert_or_panic(v[43] == 476);
+ assert_or_panic(v[44] == 477);
+ assert_or_panic(v[45] == 478);
+ assert_or_panic(v[46] == 479);
+ assert_or_panic(v[47] == 480);
+ zig_vector_48_f64((Vector_48_f64){
+ 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496,
+ 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512,
+ 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528,
+ }, 48);
+}
+
+typedef double Vector_64_f64 __attribute__((vector_size(64 * sizeof(double))));
+
+Vector_64_f64 zig_ret_vector_64_f64(void);
+void zig_vector_64_f64(Vector_64_f64, size_t);
+
+Vector_64_f64 c_ret_vector_64_f64(void) {
+ return (Vector_64_f64){
+ 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768,
+ 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784,
+ 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800,
+ 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816,
};
}
+void c_vector_64_f64(Vector_64_f64 v, size_t i) {
+ assert_or_panic(v[0] == 817);
+ assert_or_panic(v[1] == 818);
+ assert_or_panic(v[2] == 819);
+ assert_or_panic(v[3] == 820);
+ assert_or_panic(v[4] == 821);
+ assert_or_panic(v[5] == 822);
+ assert_or_panic(v[6] == 823);
+ assert_or_panic(v[7] == 824);
+ assert_or_panic(v[8] == 825);
+ assert_or_panic(v[9] == 826);
+ assert_or_panic(v[10] == 827);
+ assert_or_panic(v[11] == 828);
+ assert_or_panic(v[12] == 829);
+ assert_or_panic(v[13] == 830);
+ assert_or_panic(v[14] == 831);
+ assert_or_panic(v[15] == 832);
+ assert_or_panic(v[16] == 833);
+ assert_or_panic(v[17] == 834);
+ assert_or_panic(v[18] == 835);
+ assert_or_panic(v[19] == 836);
+ assert_or_panic(v[20] == 837);
+ assert_or_panic(v[21] == 838);
+ assert_or_panic(v[22] == 839);
+ assert_or_panic(v[23] == 840);
+ assert_or_panic(v[24] == 841);
+ assert_or_panic(v[25] == 842);
+ assert_or_panic(v[26] == 843);
+ assert_or_panic(v[27] == 844);
+ assert_or_panic(v[28] == 845);
+ assert_or_panic(v[29] == 846);
+ assert_or_panic(v[30] == 847);
+ assert_or_panic(v[31] == 848);
+ assert_or_panic(v[32] == 849);
+ assert_or_panic(v[33] == 850);
+ assert_or_panic(v[34] == 851);
+ assert_or_panic(v[35] == 852);
+ assert_or_panic(v[36] == 853);
+ assert_or_panic(v[37] == 854);
+ assert_or_panic(v[38] == 855);
+ assert_or_panic(v[39] == 856);
+ assert_or_panic(v[40] == 857);
+ assert_or_panic(v[41] == 858);
+ assert_or_panic(v[42] == 859);
+ assert_or_panic(v[43] == 860);
+ assert_or_panic(v[44] == 861);
+ assert_or_panic(v[45] == 862);
+ assert_or_panic(v[46] == 863);
+ assert_or_panic(v[47] == 864);
+ assert_or_panic(v[48] == 865);
+ assert_or_panic(v[49] == 866);
+ assert_or_panic(v[50] == 867);
+ assert_or_panic(v[51] == 868);
+ assert_or_panic(v[52] == 869);
+ assert_or_panic(v[53] == 870);
+ assert_or_panic(v[54] == 871);
+ assert_or_panic(v[55] == 872);
+ assert_or_panic(v[56] == 873);
+ assert_or_panic(v[57] == 874);
+ assert_or_panic(v[58] == 875);
+ assert_or_panic(v[59] == 876);
+ assert_or_panic(v[60] == 877);
+ assert_or_panic(v[61] == 878);
+ assert_or_panic(v[62] == 879);
+ assert_or_panic(v[63] == 880);
+ assert_or_panic(i == 64);
+}
+void c_test_vector_64_f64(void) {
+ Vector_64_f64 v = zig_ret_vector_64_f64();
+ assert_or_panic(v[0] == 625);
+ assert_or_panic(v[1] == 626);
+ assert_or_panic(v[2] == 627);
+ assert_or_panic(v[3] == 628);
+ assert_or_panic(v[4] == 629);
+ assert_or_panic(v[5] == 630);
+ assert_or_panic(v[6] == 631);
+ assert_or_panic(v[7] == 632);
+ assert_or_panic(v[8] == 633);
+ assert_or_panic(v[9] == 634);
+ assert_or_panic(v[10] == 635);
+ assert_or_panic(v[11] == 636);
+ assert_or_panic(v[12] == 637);
+ assert_or_panic(v[13] == 638);
+ assert_or_panic(v[14] == 639);
+ assert_or_panic(v[15] == 640);
+ assert_or_panic(v[16] == 641);
+ assert_or_panic(v[17] == 642);
+ assert_or_panic(v[18] == 643);
+ assert_or_panic(v[19] == 644);
+ assert_or_panic(v[20] == 645);
+ assert_or_panic(v[21] == 646);
+ assert_or_panic(v[22] == 647);
+ assert_or_panic(v[23] == 648);
+ assert_or_panic(v[24] == 649);
+ assert_or_panic(v[25] == 650);
+ assert_or_panic(v[26] == 651);
+ assert_or_panic(v[27] == 652);
+ assert_or_panic(v[28] == 653);
+ assert_or_panic(v[29] == 654);
+ assert_or_panic(v[30] == 655);
+ assert_or_panic(v[31] == 656);
+ assert_or_panic(v[32] == 657);
+ assert_or_panic(v[33] == 658);
+ assert_or_panic(v[34] == 659);
+ assert_or_panic(v[35] == 660);
+ assert_or_panic(v[36] == 661);
+ assert_or_panic(v[37] == 662);
+ assert_or_panic(v[38] == 663);
+ assert_or_panic(v[39] == 664);
+ assert_or_panic(v[40] == 665);
+ assert_or_panic(v[41] == 666);
+ assert_or_panic(v[42] == 667);
+ assert_or_panic(v[43] == 668);
+ assert_or_panic(v[44] == 669);
+ assert_or_panic(v[45] == 670);
+ assert_or_panic(v[46] == 671);
+ assert_or_panic(v[47] == 672);
+ assert_or_panic(v[48] == 673);
+ assert_or_panic(v[49] == 674);
+ assert_or_panic(v[50] == 675);
+ assert_or_panic(v[51] == 676);
+ assert_or_panic(v[52] == 677);
+ assert_or_panic(v[53] == 678);
+ assert_or_panic(v[54] == 679);
+ assert_or_panic(v[55] == 680);
+ assert_or_panic(v[56] == 681);
+ assert_or_panic(v[57] == 682);
+ assert_or_panic(v[58] == 683);
+ assert_or_panic(v[59] == 684);
+ assert_or_panic(v[60] == 685);
+ assert_or_panic(v[61] == 686);
+ assert_or_panic(v[62] == 687);
+ assert_or_panic(v[63] == 688);
+ zig_vector_64_f64((Vector_64_f64){
+ 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704,
+ 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720,
+ 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736,
+ 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752,
+ }, 64);
+}
+
+struct Struct_u8 {
+ uint8_t a;
+};
+
+struct Struct_u8 zig_ret_struct_u8(void);
+void zig_struct_u8(struct Struct_u8, size_t);
+
+struct Struct_u8 c_ret_struct_u8(void) {
+ return (struct Struct_u8){ .a = 4 };
+}
+void c_struct_u8(struct Struct_u8 s, size_t i) {
+ assert_or_panic(s.a == 5);
+ assert_or_panic(i == 6);
+}
+void c_test_struct_u8(void) {
+ struct Struct_u8 s = zig_ret_struct_u8();
+ assert_or_panic(s.a == 1);
+ zig_struct_u8((struct Struct_u8){ .a = 2 }, 3);
+}
+
+struct Struct_u8_u8 {
+ uint8_t a, b;
+};
+
+struct Struct_u8_u8 zig_ret_struct_u8_u8(void);
+void zig_struct_u8_u8(struct Struct_u8_u8, size_t);
+
+struct Struct_u8_u8 c_ret_struct_u8_u8(void) {
+ return (struct Struct_u8_u8){ .a = 6, .b = 7 };
+}
+void c_struct_u8_u8(struct Struct_u8_u8 s, size_t i) {
+ assert_or_panic(s.a == 8);
+ assert_or_panic(s.b == 9);
+ assert_or_panic(i == 10);
+}
+void c_test_struct_u8_u8(void) {
+ struct Struct_u8_u8 s = zig_ret_struct_u8_u8();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ zig_struct_u8_u8((struct Struct_u8_u8){ .a = 3, .b = 4 }, 5);
+}
+
+struct Struct_u8_u8_u8 {
+ uint8_t a, b, c;
+};
+
+struct Struct_u8_u8_u8 zig_ret_struct_u8_u8_u8(void);
+void zig_struct_u8_u8_u8(struct Struct_u8_u8_u8, size_t);
+
+struct Struct_u8_u8_u8 c_ret_struct_u8_u8_u8(void) {
+ return (struct Struct_u8_u8_u8){ .a = 8, .b = 9, .c = 10 };
+}
+void c_struct_u8_u8_u8(struct Struct_u8_u8_u8 s, size_t i) {
+ assert_or_panic(s.a == 11);
+ assert_or_panic(s.b == 12);
+ assert_or_panic(s.c == 13);
+ assert_or_panic(i == 14);
+}
+void c_test_struct_u8_u8_u8(void) {
+ struct Struct_u8_u8_u8 s = zig_ret_struct_u8_u8_u8();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ assert_or_panic(s.c == 3);
+ zig_struct_u8_u8_u8((struct Struct_u8_u8_u8){ .a = 4, .b = 5, .c = 6 }, 7);
+}
+
+struct Struct_u8_u8_u8_u8 {
+ uint8_t a, b, c, d;
+};
+
+struct Struct_u8_u8_u8_u8 zig_ret_struct_u8_u8_u8_u8(void);
+void zig_struct_u8_u8_u8_u8(struct Struct_u8_u8_u8_u8, size_t);
+
+struct Struct_u8_u8_u8_u8 c_ret_struct_u8_u8_u8_u8(void) {
+ return (struct Struct_u8_u8_u8_u8){ .a = 10, .b = 11, .c = 12, .d = 13 };
+}
+void c_struct_u8_u8_u8_u8(struct Struct_u8_u8_u8_u8 s, size_t i) {
+ assert_or_panic(s.a == 14);
+ assert_or_panic(s.b == 15);
+ assert_or_panic(s.c == 16);
+ assert_or_panic(s.d == 17);
+ assert_or_panic(i == 18);
+}
+void c_test_struct_u8_u8_u8_u8(void) {
+ struct Struct_u8_u8_u8_u8 s = zig_ret_struct_u8_u8_u8_u8();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ assert_or_panic(s.c == 3);
+ assert_or_panic(s.d == 4);
+ zig_struct_u8_u8_u8_u8((struct Struct_u8_u8_u8_u8){ .a = 5, .b = 6, .c = 7, .d = 8 }, 9);
+}
+
+struct Struct_u16 {
+ uint16_t a;
+};
+
+struct Struct_u16 zig_ret_struct_u16(void);
+void zig_struct_u16(struct Struct_u16, size_t);
+
+struct Struct_u16 c_ret_struct_u16(void) {
+ return (struct Struct_u16){ .a = 4 };
+}
+void c_struct_u16(struct Struct_u16 s, size_t i) {
+ assert_or_panic(s.a == 5);
+ assert_or_panic(i == 6);
+}
+void c_test_struct_u16(void) {
+ struct Struct_u16 s = zig_ret_struct_u16();
+ assert_or_panic(s.a == 1);
+ zig_struct_u16((struct Struct_u16){ .a = 2 }, 3);
+}
+
+struct Struct_u16_u16 {
+ uint16_t a, b;
+};
+
+struct Struct_u16_u16 zig_ret_struct_u16_u16(void);
+void zig_struct_u16_u16(struct Struct_u16_u16, size_t);
+
+struct Struct_u16_u16 c_ret_struct_u16_u16(void) {
+ return (struct Struct_u16_u16){ .a = 6, .b = 7 };
+}
+void c_struct_u16_u16(struct Struct_u16_u16 s, size_t i) {
+ assert_or_panic(s.a == 8);
+ assert_or_panic(s.b == 9);
+ assert_or_panic(i == 10);
+}
+void c_test_struct_u16_u16(void) {
+ struct Struct_u16_u16 s = zig_ret_struct_u16_u16();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ zig_struct_u16_u16((struct Struct_u16_u16){ .a = 3, .b = 4 }, 5);
+}
+
+struct Struct_u16_u16_u16 {
+ uint16_t a, b, c;
+};
+
+struct Struct_u16_u16_u16 zig_ret_struct_u16_u16_u16(void);
+void zig_struct_u16_u16_u16(struct Struct_u16_u16_u16, size_t);
+
+struct Struct_u16_u16_u16 c_ret_struct_u16_u16_u16(void) {
+ return (struct Struct_u16_u16_u16){ .a = 8, .b = 9, .c = 10 };
+}
+void c_struct_u16_u16_u16(struct Struct_u16_u16_u16 s, size_t i) {
+ assert_or_panic(s.a == 11);
+ assert_or_panic(s.b == 12);
+ assert_or_panic(s.c == 13);
+ assert_or_panic(i == 14);
+}
+void c_test_struct_u16_u16_u16(void) {
+ struct Struct_u16_u16_u16 s = zig_ret_struct_u16_u16_u16();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ assert_or_panic(s.c == 3);
+ zig_struct_u16_u16_u16((struct Struct_u16_u16_u16){ .a = 4, .b = 5, .c = 6 }, 7);
+}
+
+struct Struct_u16_u16_u16_u16 {
+ uint16_t a, b, c, d;
+};
+
+struct Struct_u16_u16_u16_u16 zig_ret_struct_u16_u16_u16_u16(void);
+void zig_struct_u16_u16_u16_u16(struct Struct_u16_u16_u16_u16, size_t);
+
+struct Struct_u16_u16_u16_u16 c_ret_struct_u16_u16_u16_u16(void) {
+ return (struct Struct_u16_u16_u16_u16){ .a = 10, .b = 11, .c = 12, .d = 13 };
+}
+void c_struct_u16_u16_u16_u16(struct Struct_u16_u16_u16_u16 s, size_t i) {
+ assert_or_panic(s.a == 14);
+ assert_or_panic(s.b == 15);
+ assert_or_panic(s.c == 16);
+ assert_or_panic(s.d == 17);
+ assert_or_panic(i == 18);
+}
+void c_test_struct_u16_u16_u16_u16(void) {
+ struct Struct_u16_u16_u16_u16 s = zig_ret_struct_u16_u16_u16_u16();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ assert_or_panic(s.c == 3);
+ assert_or_panic(s.d == 4);
+ zig_struct_u16_u16_u16_u16((struct Struct_u16_u16_u16_u16){ .a = 5, .b = 6, .c = 7, .d = 8 }, 9);
+}
+
+struct Struct_u32 {
+ uint32_t a;
+};
+
+struct Struct_u32 zig_ret_struct_u32(void);
+void zig_struct_u32(struct Struct_u32, size_t);
+
+struct Struct_u32 c_ret_struct_u32(void) {
+ return (struct Struct_u32){ .a = 4 };
+}
+void c_struct_u32(struct Struct_u32 s, size_t i) {
+ assert_or_panic(s.a == 5);
+ assert_or_panic(i == 6);
+}
+void c_test_struct_u32(void) {
+ struct Struct_u32 s = zig_ret_struct_u32();
+ assert_or_panic(s.a == 1);
+ zig_struct_u32((struct Struct_u32){ .a = 2 }, 3);
+}
+
+struct Struct_u32_u32 {
+ uint32_t a, b;
+};
+
+struct Struct_u32_u32 zig_ret_struct_u32_u32(void);
+void zig_struct_u32_u32(struct Struct_u32_u32, size_t);
+
+struct Struct_u32_u32 c_ret_struct_u32_u32(void) {
+ return (struct Struct_u32_u32){ .a = 6, .b = 7 };
+}
+void c_struct_u32_u32(struct Struct_u32_u32 s, size_t i) {
+ assert_or_panic(s.a == 8);
+ assert_or_panic(s.b == 9);
+ assert_or_panic(i == 10);
+}
+void c_test_struct_u32_u32(void) {
+ struct Struct_u32_u32 s = zig_ret_struct_u32_u32();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ zig_struct_u32_u32((struct Struct_u32_u32){ .a = 3, .b = 4 }, 5);
+}
+
+struct Struct_u32_u32_u32 {
+ uint32_t a, b, c;
+};
+
+struct Struct_u32_u32_u32 zig_ret_struct_u32_u32_u32(void);
+void zig_struct_u32_u32_u32(struct Struct_u32_u32_u32, size_t);
+
+struct Struct_u32_u32_u32 c_ret_struct_u32_u32_u32(void) {
+ return (struct Struct_u32_u32_u32){ .a = 8, .b = 9, .c = 10 };
+}
+void c_struct_u32_u32_u32(struct Struct_u32_u32_u32 s, size_t i) {
+ assert_or_panic(s.a == 11);
+ assert_or_panic(s.b == 12);
+ assert_or_panic(s.c == 13);
+ assert_or_panic(i == 14);
+}
+void c_test_struct_u32_u32_u32(void) {
+ struct Struct_u32_u32_u32 s = zig_ret_struct_u32_u32_u32();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ assert_or_panic(s.c == 3);
+ zig_struct_u32_u32_u32((struct Struct_u32_u32_u32){ .a = 4, .b = 5, .c = 6 }, 7);
+}
+
+struct Struct_u32_u32_u32_u32 {
+ uint32_t a, b, c, d;
+};
+
+struct Struct_u32_u32_u32_u32 zig_ret_struct_u32_u32_u32_u32(void);
+void zig_struct_u32_u32_u32_u32(struct Struct_u32_u32_u32_u32, size_t);
+
+struct Struct_u32_u32_u32_u32 c_ret_struct_u32_u32_u32_u32(void) {
+ return (struct Struct_u32_u32_u32_u32){ .a = 10, .b = 11, .c = 12, .d = 13 };
+}
+void c_struct_u32_u32_u32_u32(struct Struct_u32_u32_u32_u32 s, size_t i) {
+ assert_or_panic(s.a == 14);
+ assert_or_panic(s.b == 15);
+ assert_or_panic(s.c == 16);
+ assert_or_panic(s.d == 17);
+ assert_or_panic(i == 18);
+}
+void c_test_struct_u32_u32_u32_u32(void) {
+ struct Struct_u32_u32_u32_u32 s = zig_ret_struct_u32_u32_u32_u32();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ assert_or_panic(s.c == 3);
+ assert_or_panic(s.d == 4);
+ zig_struct_u32_u32_u32_u32((struct Struct_u32_u32_u32_u32){ .a = 5, .b = 6, .c = 7, .d = 8 }, 9);
+}
+
+struct Struct_u64 {
+ uint64_t a;
+};
+
+struct Struct_u64 zig_ret_struct_u64(void);
+void zig_struct_u64(struct Struct_u64, size_t);
+
+struct Struct_u64 c_ret_struct_u64(void) {
+ return (struct Struct_u64){ .a = 4 };
+}
+void c_struct_u64(struct Struct_u64 s, size_t i) {
+ assert_or_panic(s.a == 5);
+ assert_or_panic(i == 6);
+}
+void c_test_struct_u64(void) {
+ struct Struct_u64 s = zig_ret_struct_u64();
+ assert_or_panic(s.a == 1);
+ zig_struct_u64((struct Struct_u64){ .a = 2 }, 3);
+}
+
+struct Struct_u64_u64 {
+ uint64_t a;
+ uint64_t b;
+};
+
+struct Struct_u64_u64 zig_ret_struct_u64_u64(void);
+void zig_struct_u64_u64(struct Struct_u64_u64, size_t);
+void zig_1_struct_u64_u64(size_t, struct Struct_u64_u64, size_t);
+void zig_2_struct_u64_u64(size_t, size_t, struct Struct_u64_u64, size_t);
+void zig_3_struct_u64_u64(size_t, size_t, size_t, struct Struct_u64_u64, size_t);
+void zig_4_struct_u64_u64(size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t);
+void zig_5_struct_u64_u64(size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t);
+void zig_6_struct_u64_u64(size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t);
+void zig_7_struct_u64_u64(size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t);
+void zig_8_struct_u64_u64(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t);
+
+struct Struct_u64_u64 c_ret_struct_u64_u64(void) {
+ return (struct Struct_u64_u64){ .a = 21, .b = 22 };
+}
+void c_struct_u64_u64(struct Struct_u64_u64 s, size_t i) {
+ assert_or_panic(s.a == 23);
+ assert_or_panic(s.b == 24);
+ assert_or_panic(i == 1);
+}
+void c_1_struct_u64_u64(size_t a0, struct Struct_u64_u64 s, size_t i) {
+ assert_or_panic(s.a == 25);
+ assert_or_panic(s.b == 26);
+ assert_or_panic(i == 2);
+}
+void c_2_struct_u64_u64(size_t a0, size_t a1, struct Struct_u64_u64 s, size_t i) {
+ assert_or_panic(s.a == 27);
+ assert_or_panic(s.b == 28);
+ assert_or_panic(i == 3);
+}
+void c_3_struct_u64_u64(size_t a0, size_t a1, size_t a2, struct Struct_u64_u64 s, size_t i) {
+ assert_or_panic(s.a == 29);
+ assert_or_panic(s.b == 30);
+ assert_or_panic(i == 4);
+}
+void c_4_struct_u64_u64(size_t a0, size_t a1, size_t a2, size_t a3, struct Struct_u64_u64 s, size_t i) {
+ assert_or_panic(s.a == 31);
+ assert_or_panic(s.b == 32);
+ assert_or_panic(i == 5);
+}
+void c_5_struct_u64_u64(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, struct Struct_u64_u64 s, size_t i) {
+ assert_or_panic(s.a == 33);
+ assert_or_panic(s.b == 34);
+ assert_or_panic(i == 6);
+}
+void c_6_struct_u64_u64(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, struct Struct_u64_u64 s, size_t i) {
+ assert_or_panic(s.a == 35);
+ assert_or_panic(s.b == 36);
+ assert_or_panic(i == 7);
+}
+void c_7_struct_u64_u64(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, size_t a6, struct Struct_u64_u64 s, size_t i) {
+ assert_or_panic(s.a == 37);
+ assert_or_panic(s.b == 38);
+ assert_or_panic(i == 8);
+}
+void c_8_struct_u64_u64(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, size_t a6, size_t a7, struct Struct_u64_u64 s, size_t i) {
+ assert_or_panic(s.a == 39);
+ assert_or_panic(s.b == 40);
+ assert_or_panic(i == 9);
+}
+void c_test_struct_u64_u64(void) {
+ struct Struct_u64_u64 s = zig_ret_struct_u64_u64();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ zig_struct_u64_u64((struct Struct_u64_u64){ .a = 3, .b = 4 }, 1);
+ zig_1_struct_u64_u64(0, (struct Struct_u64_u64){ .a = 5, .b = 6 }, 2);
+ zig_2_struct_u64_u64(0, 1, (struct Struct_u64_u64){ .a = 7, .b = 8 }, 3);
+ zig_3_struct_u64_u64(0, 1, 2, (struct Struct_u64_u64){ .a = 9, .b = 10 }, 4);
+ zig_4_struct_u64_u64(0, 1, 2, 3, (struct Struct_u64_u64){ .a = 11, .b = 12 }, 5);
+ zig_5_struct_u64_u64(0, 1, 2, 3, 4, (struct Struct_u64_u64){ .a = 13, .b = 14 }, 6);
+ zig_6_struct_u64_u64(0, 1, 2, 3, 4, 5, (struct Struct_u64_u64){ .a = 15, .b = 16 }, 7);
+ zig_7_struct_u64_u64(0, 1, 2, 3, 4, 5, 6, (struct Struct_u64_u64){ .a = 17, .b = 18 }, 8);
+ zig_8_struct_u64_u64(0, 1, 2, 3, 4, 5, 6, 7, (struct Struct_u64_u64){ .a = 19, .b = 20 }, 9);
+}
+
+struct Struct_u64_u64_u64 {
+ uint64_t a, b, c;
+};
+
+struct Struct_u64_u64_u64 zig_ret_struct_u64_u64_u64(void);
+void zig_struct_u64_u64_u64(struct Struct_u64_u64_u64, size_t);
+
+struct Struct_u64_u64_u64 c_ret_struct_u64_u64_u64(void) {
+ return (struct Struct_u64_u64_u64){ .a = 8, .b = 9, .c = 10 };
+}
+void c_struct_u64_u64_u64(struct Struct_u64_u64_u64 s, size_t i) {
+ assert_or_panic(s.a == 11);
+ assert_or_panic(s.b == 12);
+ assert_or_panic(s.c == 13);
+ assert_or_panic(i == 14);
+}
+void c_test_struct_u64_u64_u64(void) {
+ struct Struct_u64_u64_u64 s = zig_ret_struct_u64_u64_u64();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ assert_or_panic(s.c == 3);
+ zig_struct_u64_u64_u64((struct Struct_u64_u64_u64){ .a = 4, .b = 5, .c = 6 }, 7);
+}
+
+struct Struct_u64_u64_u64_u64 {
+ uint64_t a, b, c, d;
+};
+
+struct Struct_u64_u64_u64_u64 zig_ret_struct_u64_u64_u64_u64(void);
+void zig_struct_u64_u64_u64_u64(struct Struct_u64_u64_u64_u64, size_t);
+
+struct Struct_u64_u64_u64_u64 c_ret_struct_u64_u64_u64_u64(void) {
+ return (struct Struct_u64_u64_u64_u64){ .a = 10, .b = 11, .c = 12, .d = 13 };
+}
+void c_struct_u64_u64_u64_u64(struct Struct_u64_u64_u64_u64 s, size_t i) {
+ assert_or_panic(s.a == 14);
+ assert_or_panic(s.b == 15);
+ assert_or_panic(s.c == 16);
+ assert_or_panic(s.d == 17);
+ assert_or_panic(i == 18);
+}
+void c_test_struct_u64_u64_u64_u64(void) {
+ struct Struct_u64_u64_u64_u64 s = zig_ret_struct_u64_u64_u64_u64();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ assert_or_panic(s.c == 3);
+ assert_or_panic(s.d == 4);
+ zig_struct_u64_u64_u64_u64((struct Struct_u64_u64_u64_u64){ .a = 5, .b = 6, .c = 7, .d = 8 }, 9);
+}
+
+struct Struct_f32 {
+ float a;
+};
+
+struct Struct_f32 zig_ret_struct_f32(void);
+void zig_struct_f32(struct Struct_f32, size_t);
+
+struct Struct_f32 c_ret_struct_f32(void) {
+ return (struct Struct_f32){ .a = 4 };
+}
+void c_struct_f32(struct Struct_f32 s, size_t i) {
+ assert_or_panic(s.a == 5);
+ assert_or_panic(i == 6);
+}
+void c_test_struct_f32(void) {
+ struct Struct_f32 s = zig_ret_struct_f32();
+ assert_or_panic(s.a == 1);
+ zig_struct_f32((struct Struct_f32){ .a = 2 }, 3);
+}
+
+struct Struct_f32_f32 {
+ float a, b;
+};
+
+struct Struct_f32_f32 zig_ret_struct_f32_f32(void);
+void zig_struct_f32_f32(struct Struct_f32_f32, size_t);
+
+struct Struct_f32_f32 c_ret_struct_f32_f32(void) {
+ return (struct Struct_f32_f32){ .a = 6, .b = 7 };
+}
+void c_struct_f32_f32(struct Struct_f32_f32 s, size_t i) {
+ assert_or_panic(s.a == 8);
+ assert_or_panic(s.b == 9);
+ assert_or_panic(i == 10);
+}
+void c_test_struct_f32_f32(void) {
+ struct Struct_f32_f32 s = zig_ret_struct_f32_f32();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ zig_struct_f32_f32((struct Struct_f32_f32){ .a = 3, .b = 4 }, 5);
+}
+
+struct Struct_f32_f32_f32 {
+ float a, b, c;
+};
+
+struct Struct_f32_f32_f32 zig_ret_struct_f32_f32_f32(void);
+void zig_struct_f32_f32_f32(struct Struct_f32_f32_f32, size_t);
+
+struct Struct_f32_f32_f32 c_ret_struct_f32_f32_f32(void) {
+ return (struct Struct_f32_f32_f32){ .a = 8, .b = 9, .c = 10 };
+}
+void c_struct_f32_f32_f32(struct Struct_f32_f32_f32 s, size_t i) {
+ assert_or_panic(s.a == 11);
+ assert_or_panic(s.b == 12);
+ assert_or_panic(s.c == 13);
+ assert_or_panic(i == 14);
+}
+void c_test_struct_f32_f32_f32(void) {
+ struct Struct_f32_f32_f32 s = zig_ret_struct_f32_f32_f32();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ assert_or_panic(s.c == 3);
+ zig_struct_f32_f32_f32((struct Struct_f32_f32_f32){ .a = 4, .b = 5, .c = 6 }, 7);
+}
+
+struct Struct_f32_f32_f32_f32 {
+ float a, b, c, d;
+};
+
+struct Struct_f32_f32_f32_f32 zig_ret_struct_f32_f32_f32_f32(void);
+void zig_struct_f32_f32_f32_f32(struct Struct_f32_f32_f32_f32, size_t);
+
+struct Struct_f32_f32_f32_f32 c_ret_struct_f32_f32_f32_f32(void) {
+ return (struct Struct_f32_f32_f32_f32){ .a = 10, .b = 11, .c = 12, .d = 13 };
+}
+void c_struct_f32_f32_f32_f32(struct Struct_f32_f32_f32_f32 s, size_t i) {
+ assert_or_panic(s.a == 14);
+ assert_or_panic(s.b == 15);
+ assert_or_panic(s.c == 16);
+ assert_or_panic(s.d == 17);
+ assert_or_panic(i == 18);
+}
+void c_test_struct_f32_f32_f32_f32(void) {
+ struct Struct_f32_f32_f32_f32 s = zig_ret_struct_f32_f32_f32_f32();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ assert_or_panic(s.c == 3);
+ assert_or_panic(s.d == 4);
+ zig_struct_f32_f32_f32_f32((struct Struct_f32_f32_f32_f32){ .a = 5, .b = 6, .c = 7, .d = 8 }, 9);
+}
+
+struct Struct_f32_f32_f32_f32_f32 {
+ float a, b, c, d, e;
+};
+
+struct Struct_f32_f32_f32_f32_f32 zig_ret_struct_f32_f32_f32_f32_f32(void);
+void zig_struct_f32_f32_f32_f32_f32(struct Struct_f32_f32_f32_f32_f32, size_t);
+
+struct Struct_f32_f32_f32_f32_f32 c_ret_struct_f32_f32_f32_f32_f32(void) {
+ return (struct Struct_f32_f32_f32_f32_f32){ .a = 12, .b = 13, .c = 14, .d = 15, .e = 16 };
+}
+void c_struct_f32_f32_f32_f32_f32(struct Struct_f32_f32_f32_f32_f32 s, size_t i) {
+ assert_or_panic(s.a == 17);
+ assert_or_panic(s.b == 18);
+ assert_or_panic(s.c == 19);
+ assert_or_panic(s.d == 20);
+ assert_or_panic(s.e == 21);
+ assert_or_panic(i == 22);
+}
+void c_test_struct_f32_f32_f32_f32_f32(void) {
+ struct Struct_f32_f32_f32_f32_f32 s = zig_ret_struct_f32_f32_f32_f32_f32();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ assert_or_panic(s.c == 3);
+ assert_or_panic(s.d == 4);
+ assert_or_panic(s.e == 5);
+ zig_struct_f32_f32_f32_f32_f32((struct Struct_f32_f32_f32_f32_f32){ .a = 6, .b = 7, .c = 8, .d = 9, .e = 10 }, 11);
+}
+
+struct Struct_f32a8 {
+ alignas(8) float a;
+};
+
+struct Struct_f32a8 zig_ret_struct_f32a8(void);
+void zig_struct_f32a8(struct Struct_f32a8, float);
+
+struct Struct_f32a8 c_ret_struct_f32a8(void) {
+ return (struct Struct_f32a8){ .a = 4.125f };
+}
+void c_struct_f32a8(struct Struct_f32a8 s, float f) {
+ assert_or_panic(s.a == 5.375f);
+ assert_or_panic(f == 6.5f);
+}
+void c_test_struct_f32a8(void) {
+ struct Struct_f32a8 s = zig_ret_struct_f32a8();
+ assert_or_panic(s.a == 1.25f);
+ zig_struct_f32a8((struct Struct_f32a8){ .a = 2.75f }, 3.5f);
+}
+
+struct Struct_f32a8_f32a8 {
+ alignas(8) float a;
+ alignas(8) float b;
+};
+
+struct Struct_f32a8_f32a8 zig_ret_struct_f32a8_f32a8(void);
+void zig_struct_f32a8_f32a8(struct Struct_f32a8_f32a8, float);
+
+struct Struct_f32a8_f32a8 c_ret_struct_f32a8_f32a8(void) {
+ return (struct Struct_f32a8_f32a8){ .a = 6.625f, .b = 7.875f };
+}
+void c_struct_f32a8_f32a8(struct Struct_f32a8_f32a8 s, float f) {
+ assert_or_panic(s.a == 8.0625f);
+ assert_or_panic(s.b == 9.1875f);
+ assert_or_panic(f == 10.5f);
+}
+void c_test_struct_f32a8_f32a8(void) {
+ struct Struct_f32a8_f32a8 s = zig_ret_struct_f32a8_f32a8();
+ assert_or_panic(s.a == 1.25f);
+ assert_or_panic(s.b == 2.75f);
+ zig_struct_f32a8_f32a8((struct Struct_f32a8_f32a8){ .a = 3.125f, .b = 4.375f }, 5.5f);
+}
+
+struct Struct_f32f32_f32 {
+ struct {
+ float b, c;
+ } a;
+ float d;
+};
+
+struct Struct_f32f32_f32 zig_ret_struct_f32f32_f32(void);
+void zig_struct_f32f32_f32(struct Struct_f32f32_f32);
+
+struct Struct_f32f32_f32 c_ret_struct_f32f32_f32(void) {
+ return (struct Struct_f32f32_f32){ .a = { .b = 1.0f, .c = 2.0f }, .d = 3.0f };
+}
+void c_struct_f32f32_f32(struct Struct_f32f32_f32 s) {
+ assert_or_panic(s.a.b == 1.0f);
+ assert_or_panic(s.a.c == 2.0f);
+ assert_or_panic(s.d == 3.0f);
+}
+void c_test_struct_f32f32_f32(void) {
+ struct Struct_f32f32_f32 s = zig_ret_struct_f32f32_f32();
+ assert_or_panic(s.a.b == 1.0f);
+ assert_or_panic(s.a.c == 2.0f);
+ assert_or_panic(s.d == 3.0f);
+ zig_struct_f32f32_f32((struct Struct_f32f32_f32){ .a = { .b = 1.0f, .c = 2.0f }, .d = 3.0f });
+}
+
+struct Struct_f32_f32f32 {
+ float a;
+ struct {
+ float c, d;
+ } b;
+};
+
+struct Struct_f32_f32f32 zig_ret_struct_f32_f32f32(void);
+void zig_struct_f32_f32f32(struct Struct_f32_f32f32);
+
+struct Struct_f32_f32f32 c_ret_struct_f32_f32f32(void) {
+ return (struct Struct_f32_f32f32){ .a = 1.0f, .b = { .c = 2.0f, .d = 3.0f } };
+}
+void c_struct_f32_f32f32(struct Struct_f32_f32f32 s) {
+ assert_or_panic(s.a == 1.0f);
+ assert_or_panic(s.b.c == 2.0f);
+ assert_or_panic(s.b.d == 3.0f);
+}
+void c_test_struct_f32_f32f32(void) {
+ struct Struct_f32_f32f32 s = zig_ret_struct_f32_f32f32();
+ assert_or_panic(s.a == 1.0f);
+ assert_or_panic(s.b.c == 2.0f);
+ assert_or_panic(s.b.d == 3.0f);
+ zig_struct_f32_f32f32((struct Struct_f32_f32f32){ .a = 1.0f, .b = { .c = 2.0f, .d = 3.0f } });
+}
+
+struct Struct_f64 {
+ double a;
+};
+
+struct Struct_f64 zig_ret_struct_f64(void);
+void zig_struct_f64(struct Struct_f64, size_t);
+
+struct Struct_f64 c_ret_struct_f64(void) {
+ return (struct Struct_f64){ .a = 4 };
+}
+void c_struct_f64(struct Struct_f64 s, size_t i) {
+ assert_or_panic(s.a == 5);
+ assert_or_panic(i == 6);
+}
+void c_test_struct_f64(void) {
+ struct Struct_f64 s = zig_ret_struct_f64();
+ assert_or_panic(s.a == 1);
+ zig_struct_f64((struct Struct_f64){ .a = 2 }, 3);
+}
+
+struct Struct_f64_f64 {
+ double a, b;
+};
+
+struct Struct_f64_f64 zig_ret_struct_f64_f64(void);
+void zig_struct_f64_f64(struct Struct_f64_f64, size_t);
+
+struct Struct_f64_f64 c_ret_struct_f64_f64(void) {
+ return (struct Struct_f64_f64){ .a = 6, .b = 7 };
+}
+void c_struct_f64_f64(struct Struct_f64_f64 s, size_t i) {
+ assert_or_panic(s.a == 8);
+ assert_or_panic(s.b == 9);
+ assert_or_panic(i == 10);
+}
+void c_test_struct_f64_f64(void) {
+ struct Struct_f64_f64 s = zig_ret_struct_f64_f64();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ zig_struct_f64_f64((struct Struct_f64_f64){ .a = 3, .b = 4 }, 5);
+}
+
+struct Struct_f64_f64_f64 {
+ double a, b, c;
+};
-void zig_vector_2_bool(Vector2Bool vec);
-void zig_vector_4_bool(Vector4Bool vec);
-void zig_vector_8_bool(Vector8Bool vec);
-void zig_vector_16_bool(Vector16Bool vec);
-void zig_vector_32_bool(Vector32Bool vec);
-void zig_vector_64_bool(Vector64Bool vec);
-void zig_vector_128_bool(Vector128Bool vec);
-void zig_vector_256_bool(Vector256Bool vec);
-void zig_vector_512_bool(Vector512Bool vec);
-
-Vector2Bool zig_ret_vector_2_bool(void);
-Vector4Bool zig_ret_vector_4_bool(void);
-Vector8Bool zig_ret_vector_8_bool(void);
-Vector16Bool zig_ret_vector_16_bool(void);
-Vector32Bool zig_ret_vector_32_bool(void);
-Vector64Bool zig_ret_vector_64_bool(void);
-Vector128Bool zig_ret_vector_128_bool(void);
-Vector256Bool zig_ret_vector_256_bool(void);
-Vector512Bool zig_ret_vector_512_bool(void);
+struct Struct_f64_f64_f64 zig_ret_struct_f64_f64_f64(void);
+void zig_struct_f64_f64_f64(struct Struct_f64_f64_f64, size_t);
+struct Struct_f64_f64_f64 c_ret_struct_f64_f64_f64(void) {
+ return (struct Struct_f64_f64_f64){ .a = 8, .b = 9, .c = 10 };
+}
+void c_struct_f64_f64_f64(struct Struct_f64_f64_f64 s, size_t i) {
+ assert_or_panic(s.a == 11);
+ assert_or_panic(s.b == 12);
+ assert_or_panic(s.c == 13);
+ assert_or_panic(i == 14);
+}
+void c_test_struct_f64_f64_f64(void) {
+ struct Struct_f64_f64_f64 s = zig_ret_struct_f64_f64_f64();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ assert_or_panic(s.c == 3);
+ zig_struct_f64_f64_f64((struct Struct_f64_f64_f64){ .a = 4, .b = 5, .c = 6 }, 7);
+}
+
+struct Struct_f64_f64_f64_f64 {
+ double a, b, c, d;
+};
+
+struct Struct_f64_f64_f64_f64 zig_ret_struct_f64_f64_f64_f64(void);
+void zig_struct_f64_f64_f64_f64(struct Struct_f64_f64_f64_f64, size_t);
+
+struct Struct_f64_f64_f64_f64 c_ret_struct_f64_f64_f64_f64(void) {
+ return (struct Struct_f64_f64_f64_f64){ .a = 10, .b = 11, .c = 12, .d = 13 };
+}
+void c_struct_f64_f64_f64_f64(struct Struct_f64_f64_f64_f64 s, size_t i) {
+ assert_or_panic(s.a == 14);
+ assert_or_panic(s.b == 15);
+ assert_or_panic(s.c == 16);
+ assert_or_panic(s.d == 17);
+ assert_or_panic(i == 18);
+}
+void c_test_struct_f64_f64_f64_f64(void) {
+ struct Struct_f64_f64_f64_f64 s = zig_ret_struct_f64_f64_f64_f64();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ assert_or_panic(s.c == 3);
+ assert_or_panic(s.d == 4);
+ zig_struct_f64_f64_f64_f64((struct Struct_f64_f64_f64_f64){ .a = 5, .b = 6, .c = 7, .d = 8 }, 9);
+}
+
+struct Struct_f64_f64_f64_f64_f64 {
+ double a, b, c, d, e;
+};
+
+struct Struct_f64_f64_f64_f64_f64 zig_ret_struct_f64_f64_f64_f64_f64(void);
+void zig_struct_f64_f64_f64_f64_f64(struct Struct_f64_f64_f64_f64_f64, size_t);
+
+struct Struct_f64_f64_f64_f64_f64 c_ret_struct_f64_f64_f64_f64_f64(void) {
+ return (struct Struct_f64_f64_f64_f64_f64){ .a = 12, .b = 13, .c = 14, .d = 15, .e = 16 };
+}
+void c_struct_f64_f64_f64_f64_f64(struct Struct_f64_f64_f64_f64_f64 s, size_t i) {
+ assert_or_panic(s.a == 17);
+ assert_or_panic(s.b == 18);
+ assert_or_panic(s.c == 19);
+ assert_or_panic(s.d == 20);
+ assert_or_panic(s.e == 21);
+ assert_or_panic(i == 22);
+}
+void c_test_struct_f64_f64_f64_f64_f64(void) {
+ struct Struct_f64_f64_f64_f64_f64 s = zig_ret_struct_f64_f64_f64_f64_f64();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ assert_or_panic(s.c == 3);
+ assert_or_panic(s.d == 4);
+ assert_or_panic(s.e == 5);
+ zig_struct_f64_f64_f64_f64_f64((struct Struct_f64_f64_f64_f64_f64){ .a = 6, .b = 7, .c = 8, .d = 9, .e = 10 }, 11);
+}
+
+struct Struct_u32_Union_u32_u32u32 {
+ uint32_t a;
+ union {
+ struct {
+ uint32_t d, e;
+ } c;
+ } b;
+};
+
+struct Struct_u32_Union_u32_u32u32 zig_ret_struct_u32_union_u32_u32u32(void);
+void zig_struct_u32_union_u32_u32u32(struct Struct_u32_Union_u32_u32u32);
+
+struct Struct_u32_Union_u32_u32u32 c_ret_struct_u32_union_u32_u32u32(void) {
+ struct Struct_u32_Union_u32_u32u32 s;
+ s.a = 1;
+ s.b.c.d = 2;
+ s.b.c.e = 3;
+ return s;
+}
+void c_struct_u32_union_u32_u32u32(struct Struct_u32_Union_u32_u32u32 s) {
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b.c.d == 2);
+ assert_or_panic(s.b.c.e == 3);
+}
+void c_test_struct_u32_union_u32_u32u32(void) {
+ struct Struct_u32_Union_u32_u32u32 s = zig_ret_struct_u32_union_u32_u32u32();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b.c.d == 2);
+ assert_or_panic(s.b.c.e == 3);
+ zig_struct_u32_union_u32_u32u32(s);
+}
+
+struct Struct_i32_i32 {
+ int32_t a;
+ int32_t b;
+};
+
+void zig_struct_i32_i32(struct Struct_i32_i32);
+
+struct BigStruct {
+ uint64_t a;
+ uint64_t b;
+ uint64_t c;
+ uint64_t d;
+ uint8_t e;
+};
+
+void zig_big_struct(struct BigStruct);
+
+union BigUnion {
+ struct BigStruct a;
+};
+
+void zig_big_union(union BigUnion);
+
+struct MedStructMixed {
+ uint32_t a;
+ float b;
+ float c;
+ uint32_t d;
+};
+
+void zig_med_struct_mixed(struct MedStructMixed);
+struct MedStructMixed zig_ret_med_struct_mixed();
+
+void zig_small_packed_struct(uint8_t);
+#ifndef ZIG_NO_I128
+void zig_big_packed_struct(__int128);
#endif
-typedef struct Vector3 {
- float x;
- float y;
- float z;
-} Vector3;
-
-typedef struct Vector5 {
- float x;
- float y;
- float z;
- float w;
- float q;
-} Vector5;
-
-typedef struct Rect {
- uint32_t left;
- uint32_t right;
- uint32_t top;
- uint32_t bottom;
-} Rect;
-
-void zig_multiple_struct_ints(struct Rect, struct Rect);
-
-typedef struct FloatRect {
- float left;
- float right;
- float top;
- float bottom;
-} FloatRect;
-
-void zig_multiple_struct_floats(struct FloatRect, struct FloatRect);
+struct SplitStructInts {
+ uint64_t a;
+ uint8_t b;
+ uint32_t c;
+};
+void zig_split_struct_ints(struct SplitStructInts);
+
+struct SplitStructMixed {
+ uint64_t a;
+ uint8_t b;
+ float c;
+};
+void zig_split_struct_mixed(struct SplitStructMixed);
+struct SplitStructMixed zig_ret_split_struct_mixed();
+
+struct BigStruct zig_big_struct_both(struct BigStruct);
void run_c_tests(void) {
zig_u8(0xff);
@@ -2843,202 +15374,34 @@ void run_c_tests(void) {
}
#endif
-#if !defined(__mips64)
-#if !defined(ZIG_PPC32)
-#if !defined(__s390x__)
-#if !(defined(_WIN32) && defined(__i386__))
- {
- struct Struct_u8 s = zig_ret_struct_u8();
- assert_or_panic(s.a == 1);
- zig_struct_u8((struct Struct_u8){ .a = 2 }, 3);
- }
-#endif
-#endif
-#endif
-#endif
-
-#if !defined(__mips64)
-#if !defined(ZIG_PPC32)
-#if !defined(__s390x__)
-#if !(defined(_WIN32) && defined(__i386__))
- {
- struct Struct_u16 s = zig_ret_struct_u16();
- assert_or_panic(s.a == 7);
- zig_struct_u16((struct Struct_u16){ .a = 8 }, 9);
- }
-#endif
-#endif
-#endif
-#endif
-
-#if !defined(__mips64)
-#if !defined(ZIG_PPC32)
-#if !defined(__s390x__)
-#if !(defined(_WIN32) && defined(__i386__))
- {
- struct Struct_u32 s = zig_ret_struct_u32();
- assert_or_panic(s.a == 13);
- zig_struct_u32((struct Struct_u32){ .a = 14 }, 15);
- }
-#endif
-#endif
-#endif
-#endif
-
-#if !defined(ZIG_PPC32)
-#if !defined(ZIG_RISCV32)
-#if !defined(__s390x__)
-#if !(defined(_WIN32) && defined(__i386__))
- {
- struct Struct_u64 s = zig_ret_struct_u64();
- assert_or_panic(s.a == 19);
- zig_struct_u64((struct Struct_u64){ .a = 20 }, 21);
- }
-#endif
-#endif
-#endif
-#endif
-
-#if !defined(ZIG_PPC32) && !defined(__hexagon__) && !defined(__s390x__)
- {
- struct Struct_u64_u64 s = zig_ret_struct_u64_u64();
- assert_or_panic(s.a == 1);
- assert_or_panic(s.b == 2);
- zig_struct_u64_u64_0((struct Struct_u64_u64){ .a = 3, .b = 4 }, 1);
- zig_struct_u64_u64_1(0, (struct Struct_u64_u64){ .a = 5, .b = 6 }, 2);
- zig_struct_u64_u64_2(0, 1, (struct Struct_u64_u64){ .a = 7, .b = 8 }, 3);
- zig_struct_u64_u64_3(0, 1, 2, (struct Struct_u64_u64){ .a = 9, .b = 10 }, 4);
- zig_struct_u64_u64_4(0, 1, 2, 3, (struct Struct_u64_u64){ .a = 11, .b = 12 }, 5);
- zig_struct_u64_u64_5(0, 1, 2, 3, 4, (struct Struct_u64_u64){ .a = 13, .b = 14 }, 6);
- zig_struct_u64_u64_6(0, 1, 2, 3, 4, 5, (struct Struct_u64_u64){ .a = 15, .b = 16 }, 7);
- zig_struct_u64_u64_7(0, 1, 2, 3, 4, 5, 6, (struct Struct_u64_u64){ .a = 17, .b = 18 }, 8);
- zig_struct_u64_u64_8(0, 1, 2, 3, 4, 5, 6, 7, (struct Struct_u64_u64){ .a = 19, .b = 20 }, 9);
- }
-
-#if !defined(__mips64__)
-#if !(defined(_WIN32) && defined(__i386__))
- {
- struct Struct_f32 s = zig_ret_struct_f32();
- assert_or_panic(s.a == 2.5f);
- zig_struct_f32((struct Struct_f32){ .a = 2.5f });
- }
-#endif
-#endif
-
-#if !(defined(__arm__) && defined(__SOFTFP__))
-#if !defined(ZIG_RISCV32)
-#if !(defined(_WIN32) && defined(__i386__))
- {
- struct Struct_f64 s = zig_ret_struct_f64();
- assert_or_panic(s.a == 2.5);
- zig_struct_f64((struct Struct_f64){ .a = 2.5 });
- }
-#endif
-#endif
-#endif
-
-#if !defined(__arm__)
-#if !defined(__loongarch__)
-#if !defined(__mips64__)
-#if !defined(__powerpc__)
-#if !defined(ZIG_RISCV32)
-#if !defined(__s390x__)
-#if !defined(__i386__)
- {
- struct Struct_f32a8 s = zig_ret_struct_f32a8();
- assert_or_panic(s.a == 1.25f);
- zig_struct_f32a8((struct Struct_f32a8){ .a = 2.75f }, 3.5f);
- }
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
-
-#if !defined(__arm__)
-#if !defined(__loongarch__)
-#if !defined(__mips64__)
-#if !defined(__powerpc__)
-#if !defined(__riscv)
-#if !defined(__s390x__)
-#if !defined(__i386__)
- {
- struct Struct_f32a8_f32a8 s = zig_ret_struct_f32a8_f32a8();
- assert_or_panic(s.a == 1.25f);
- assert_or_panic(s.b == 2.75f);
- zig_struct_f32a8_f32a8((struct Struct_f32a8_f32a8){ .a = 3.125f, .b = 4.375f }, 5.5f);
- }
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
-
-#if !(defined(__arm__) && defined(__SOFTFP__))
-#if !defined(__loongarch__) && !defined(__mips64__)
- {
- struct Struct_f32f32_f32 s = zig_ret_struct_f32f32_f32();
- assert_or_panic(s.a.b == 1.0f);
- assert_or_panic(s.a.c == 2.0f);
- assert_or_panic(s.d == 3.0f);
- zig_struct_f32f32_f32((struct Struct_f32f32_f32){ .a = { .b = 1.0f, .c = 2.0f }, .d = 3.0f });
- }
-
- {
- struct Struct_f32_f32f32 s = zig_ret_struct_f32_f32f32();
- assert_or_panic(s.a == 1.0f);
- assert_or_panic(s.b.c == 2.0f);
- assert_or_panic(s.b.d == 3.0f);
- zig_struct_f32_f32f32((struct Struct_f32_f32f32){ .a = 1.0f, .b = { .c = 2.0f, .d = 3.0f } });
- }
-#endif
-#endif
-
-#if !defined(__powerpc__) && !defined(__loongarch__) && !defined(__mips64__)
-#if !(defined(_WIN32) && defined(__i386__))
- {
- struct Struct_u32_Union_u32_u32u32 s = zig_ret_struct_u32_union_u32_u32u32();
- assert_or_panic(s.a == 1);
- assert_or_panic(s.b.c.d == 2);
- assert_or_panic(s.b.c.e == 3);
- zig_struct_u32_union_u32_u32u32(s);
- }
-
+#if !(defined(__i386__) && defined(_WIN32))
+#ifndef __loongarch__
+#ifndef ZIG_MIPS64
+#ifndef __powerpc__
+#ifndef __s390x__
{
struct Struct_i32_i32 s = {1, 2};
zig_struct_i32_i32(s);
}
#endif
#endif
+#endif
+#endif
+#endif
-#if !defined(__powerpc64__) && !defined(__loongarch__) && !defined(__mips64__)
+#ifndef __hexagon__
+#ifndef __loongarch__
+#ifndef ZIG_MIPS64
+#ifndef __powerpc__
+#ifndef __s390x__
{
struct BigStruct s = {1, 2, 3, 4, 5};
zig_big_struct(s);
}
#endif
#endif
-
-#if !defined __i386__ && !defined __arm__ && \
- !defined __powerpc__ && !defined(__loongarch__) && \
- !defined(__mips64__) && !defined(__hexagon__) && !defined(__s390x__)
- {
- struct SmallStructInts s = {1, 2, 3, 4};
- zig_small_struct_ints(s);
- }
#endif
-
-#if !defined __arm__ && \
- !defined __powerpc__ && !defined(__loongarch__) && \
- !defined(__mips64__) && !defined(__hexagon__) && !defined(__s390x__)
- {
- struct MedStructInts s = {1, 2, 3};
- zig_med_struct_ints(s);
- }
+#endif
#endif
#ifndef ZIG_NO_I128
@@ -3059,34 +15422,60 @@ void run_c_tests(void) {
zig_small_packed_struct(s);
}
-#if !defined __i386__ && !defined __arm__ && \
- !defined ZIG_PPC32 && !defined _ARCH_PPC64 && !defined(__loongarch__) && \
- !defined(__mips64__) && !defined(__hexagon__) && !defined(__s390x__)
+#ifndef __hexagon__
+#ifndef __i386__
+#ifndef __loongarch__
+#ifndef ZIG_MIPS64
+#ifndef __powerpc__
+#ifndef __s390x__
{
struct SplitStructInts s = {1234, 100, 1337};
zig_split_struct_ints(s);
}
#endif
+#endif
+#endif
+#endif
+#endif
+#endif
-#if !defined __arm__ && !defined ZIG_PPC32 && !defined _ARCH_PPC64 && !defined(__loongarch__) && \
- !defined(__mips64__) && !defined(__hexagon__) && !defined(__s390x__)
+#ifndef __hexagon__
+#ifndef __loongarch__
+#ifndef ZIG_MIPS64
+#ifndef __powerpc__
+#ifndef __s390x__
{
struct MedStructMixed s = {1234, 100.0f, 1337.0f};
zig_med_struct_mixed(s);
}
#endif
+#endif
+#endif
+#endif
+#endif
-#if !defined __i386__ && !defined __arm__ && \
- !defined ZIG_PPC32 && !defined _ARCH_PPC64 && !defined(__loongarch__) && \
- !defined(__mips64__) && !defined(__hexagon__) && !defined(__s390x__)
+#ifndef __hexagon__
+#ifndef __i386__
+#ifndef __loongarch__
+#ifndef ZIG_MIPS64
+#ifndef __powerpc__
+#ifndef __s390x__
{
struct SplitStructMixed s = {1234, 100, 1337.0f};
zig_split_struct_mixed(s);
}
#endif
+#endif
+#endif
+#endif
+#endif
+#endif
-#if !defined(__powerpc__) && !defined(__loongarch__) && !defined(__mips64__) && !defined(__hexagon__) && \
- !defined(__s390x__)
+#ifndef __hexagon__
+#ifndef __loongarch__
+#ifndef ZIG_MIPS64
+#ifndef __powerpc__
+#ifndef __s390x__
{
struct BigStruct s = {30, 31, 32, 33, 34};
struct BigStruct res = zig_big_struct_both(s);
@@ -3097,23 +15486,9 @@ void run_c_tests(void) {
assert_or_panic(res.e == 24);
}
#endif
-
-#if !defined ZIG_PPC32 && !defined _ARCH_PPC64 && !defined(__loongarch__) && !defined(__mips64__) && \
- !defined(__hexagon__) && !defined(__s390x__)
- {
- struct Rect r1 = {1, 21, 16, 4};
- struct Rect r2 = {178, 189, 21, 15};
- zig_multiple_struct_ints(r1, r2);
- }
#endif
-
-#if !defined ZIG_PPC32 && !defined(__loongarch__) && !defined(__mips64__) && !defined(__hexagon__) && \
- !defined(__s390x__)
- {
- struct FloatRect r1 = {1, 21, 16, 4};
- struct FloatRect r2 = {178, 189, 21, 15};
- zig_multiple_struct_floats(r1, r2);
- }
+#endif
+#endif
#endif
{
@@ -3129,2107 +15504,6 @@ void run_c_tests(void) {
assert_or_panic(zig_ret_i32() == -1);
assert_or_panic(zig_ret_i64() == -1);
}
-
-#if defined(ZIG_BACKEND_STAGE2_X86_64) || defined(ZIG_PPC32)
- {
- zig_vector_2_bool((Vector2Bool){
- false,
- true,
- });
-
- Vector2Bool vec = zig_ret_vector_2_bool();
- assert_or_panic(vec[0] == false);
- assert_or_panic(vec[1] == false);
- }
- {
- zig_vector_4_bool((Vector4Bool){
- false,
- false,
- false,
- false,
- });
-
- Vector4Bool vec = zig_ret_vector_4_bool();
- assert_or_panic(vec[0] == false);
- assert_or_panic(vec[1] == true);
- assert_or_panic(vec[2] == true);
- assert_or_panic(vec[3] == true);
- }
- {
- zig_vector_8_bool((Vector8Bool){
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- });
-
- Vector8Bool vec = zig_ret_vector_8_bool();
- assert_or_panic(vec[0] == false);
- assert_or_panic(vec[1] == false);
- assert_or_panic(vec[2] == false);
- assert_or_panic(vec[3] == false);
- assert_or_panic(vec[4] == true);
- assert_or_panic(vec[5] == false);
- assert_or_panic(vec[6] == false);
- assert_or_panic(vec[7] == false);
- }
- {
- zig_vector_16_bool((Vector16Bool){
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- });
-
- Vector16Bool vec = zig_ret_vector_16_bool();
- assert_or_panic(vec[0] == false);
- assert_or_panic(vec[1] == true);
- assert_or_panic(vec[2] == false);
- assert_or_panic(vec[3] == false);
- assert_or_panic(vec[4] == false);
- assert_or_panic(vec[5] == true);
- assert_or_panic(vec[6] == false);
- assert_or_panic(vec[7] == false);
- assert_or_panic(vec[8] == true);
- assert_or_panic(vec[9] == false);
- assert_or_panic(vec[10] == false);
- assert_or_panic(vec[11] == false);
- assert_or_panic(vec[12] == false);
- assert_or_panic(vec[13] == true);
- assert_or_panic(vec[14] == false);
- assert_or_panic(vec[15] == false);
- }
- {
- zig_vector_32_bool((Vector32Bool){
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- });
-
- Vector32Bool vec = zig_ret_vector_32_bool();
- assert_or_panic(vec[0] == false);
- assert_or_panic(vec[1] == true);
- assert_or_panic(vec[2] == false);
- assert_or_panic(vec[3] == false);
- assert_or_panic(vec[4] == true);
- assert_or_panic(vec[5] == false);
- assert_or_panic(vec[6] == true);
- assert_or_panic(vec[7] == true);
- assert_or_panic(vec[8] == true);
- assert_or_panic(vec[9] == true);
- assert_or_panic(vec[10] == true);
- assert_or_panic(vec[11] == true);
- assert_or_panic(vec[12] == false);
- assert_or_panic(vec[13] == false);
- assert_or_panic(vec[14] == false);
- assert_or_panic(vec[15] == false);
- assert_or_panic(vec[16] == false);
- assert_or_panic(vec[17] == false);
- assert_or_panic(vec[18] == true);
- assert_or_panic(vec[19] == true);
- assert_or_panic(vec[20] == true);
- assert_or_panic(vec[21] == false);
- assert_or_panic(vec[22] == true);
- assert_or_panic(vec[23] == false);
- assert_or_panic(vec[24] == true);
- assert_or_panic(vec[25] == false);
- assert_or_panic(vec[26] == false);
- assert_or_panic(vec[27] == true);
- assert_or_panic(vec[28] == false);
- assert_or_panic(vec[29] == false);
- assert_or_panic(vec[30] == true);
- assert_or_panic(vec[31] == true);
- }
- {
- zig_vector_64_bool((Vector64Bool){
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- });
-
- Vector64Bool vec = zig_ret_vector_64_bool();
- assert_or_panic(vec[0] == true);
- assert_or_panic(vec[1] == false);
- assert_or_panic(vec[2] == true);
- assert_or_panic(vec[3] == false);
- assert_or_panic(vec[4] == false);
- assert_or_panic(vec[5] == true);
- assert_or_panic(vec[6] == false);
- assert_or_panic(vec[7] == true);
- assert_or_panic(vec[8] == true);
- assert_or_panic(vec[9] == false);
- assert_or_panic(vec[10] == true);
- assert_or_panic(vec[11] == false);
- assert_or_panic(vec[12] == true);
- assert_or_panic(vec[13] == false);
- assert_or_panic(vec[14] == false);
- assert_or_panic(vec[15] == true);
- assert_or_panic(vec[16] == false);
- assert_or_panic(vec[17] == false);
- assert_or_panic(vec[18] == true);
- assert_or_panic(vec[19] == true);
- assert_or_panic(vec[20] == false);
- assert_or_panic(vec[21] == false);
- assert_or_panic(vec[22] == true);
- assert_or_panic(vec[23] == false);
- assert_or_panic(vec[24] == false);
- assert_or_panic(vec[25] == true);
- assert_or_panic(vec[26] == true);
- assert_or_panic(vec[27] == true);
- assert_or_panic(vec[28] == true);
- assert_or_panic(vec[29] == true);
- assert_or_panic(vec[30] == false);
- assert_or_panic(vec[31] == false);
- assert_or_panic(vec[32] == true);
- assert_or_panic(vec[33] == true);
- assert_or_panic(vec[34] == true);
- assert_or_panic(vec[35] == true);
- assert_or_panic(vec[36] == false);
- assert_or_panic(vec[37] == true);
- assert_or_panic(vec[38] == false);
- assert_or_panic(vec[39] == true);
- assert_or_panic(vec[40] == true);
- assert_or_panic(vec[41] == true);
- assert_or_panic(vec[42] == true);
- assert_or_panic(vec[43] == true);
- assert_or_panic(vec[44] == false);
- assert_or_panic(vec[45] == false);
- assert_or_panic(vec[46] == false);
- assert_or_panic(vec[47] == true);
- assert_or_panic(vec[48] == true);
- assert_or_panic(vec[49] == true);
- assert_or_panic(vec[50] == false);
- assert_or_panic(vec[51] == true);
- assert_or_panic(vec[52] == true);
- assert_or_panic(vec[53] == true);
- assert_or_panic(vec[54] == false);
- assert_or_panic(vec[55] == false);
- assert_or_panic(vec[56] == false);
- assert_or_panic(vec[57] == true);
- assert_or_panic(vec[58] == false);
- assert_or_panic(vec[59] == false);
- assert_or_panic(vec[60] == true);
- assert_or_panic(vec[61] == false);
- assert_or_panic(vec[62] == true);
- assert_or_panic(vec[63] == false);
- }
- {
- zig_vector_128_bool((Vector128Bool){
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- });
-
- Vector128Bool vec = zig_ret_vector_128_bool();
- assert_or_panic(vec[0] == true);
- assert_or_panic(vec[1] == true);
- assert_or_panic(vec[2] == false);
- assert_or_panic(vec[3] == false);
- assert_or_panic(vec[4] == false);
- assert_or_panic(vec[5] == true);
- assert_or_panic(vec[6] == true);
- assert_or_panic(vec[7] == false);
- assert_or_panic(vec[8] == false);
- assert_or_panic(vec[9] == true);
- assert_or_panic(vec[10] == false);
- assert_or_panic(vec[11] == false);
- assert_or_panic(vec[12] == false);
- assert_or_panic(vec[13] == true);
- assert_or_panic(vec[14] == false);
- assert_or_panic(vec[15] == true);
- assert_or_panic(vec[16] == true);
- assert_or_panic(vec[17] == false);
- assert_or_panic(vec[18] == false);
- assert_or_panic(vec[19] == true);
- assert_or_panic(vec[20] == true);
- assert_or_panic(vec[21] == true);
- assert_or_panic(vec[22] == true);
- assert_or_panic(vec[23] == true);
- assert_or_panic(vec[24] == false);
- assert_or_panic(vec[25] == false);
- assert_or_panic(vec[26] == true);
- assert_or_panic(vec[27] == true);
- assert_or_panic(vec[28] == true);
- assert_or_panic(vec[29] == false);
- assert_or_panic(vec[30] == false);
- assert_or_panic(vec[31] == true);
- assert_or_panic(vec[32] == true);
- assert_or_panic(vec[33] == false);
- assert_or_panic(vec[34] == true);
- assert_or_panic(vec[35] == true);
- assert_or_panic(vec[36] == true);
- assert_or_panic(vec[37] == false);
- assert_or_panic(vec[38] == true);
- assert_or_panic(vec[39] == true);
- assert_or_panic(vec[40] == true);
- assert_or_panic(vec[41] == false);
- assert_or_panic(vec[42] == true);
- assert_or_panic(vec[43] == true);
- assert_or_panic(vec[44] == false);
- assert_or_panic(vec[45] == false);
- assert_or_panic(vec[46] == false);
- assert_or_panic(vec[47] == true);
- assert_or_panic(vec[48] == false);
- assert_or_panic(vec[49] == false);
- assert_or_panic(vec[50] == false);
- assert_or_panic(vec[51] == false);
- assert_or_panic(vec[52] == true);
- assert_or_panic(vec[53] == false);
- assert_or_panic(vec[54] == true);
- assert_or_panic(vec[55] == false);
- assert_or_panic(vec[56] == true);
- assert_or_panic(vec[57] == false);
- assert_or_panic(vec[58] == false);
- assert_or_panic(vec[59] == true);
- assert_or_panic(vec[60] == true);
- assert_or_panic(vec[61] == true);
- assert_or_panic(vec[62] == true);
- assert_or_panic(vec[63] == true);
- assert_or_panic(vec[64] == false);
- assert_or_panic(vec[65] == false);
- assert_or_panic(vec[66] == false);
- assert_or_panic(vec[67] == true);
- assert_or_panic(vec[68] == true);
- assert_or_panic(vec[69] == false);
- assert_or_panic(vec[70] == true);
- assert_or_panic(vec[71] == true);
- assert_or_panic(vec[72] == false);
- assert_or_panic(vec[73] == true);
- assert_or_panic(vec[74] == true);
- assert_or_panic(vec[75] == false);
- assert_or_panic(vec[76] == false);
- assert_or_panic(vec[77] == true);
- assert_or_panic(vec[78] == false);
- assert_or_panic(vec[79] == true);
- assert_or_panic(vec[80] == false);
- assert_or_panic(vec[81] == false);
- assert_or_panic(vec[82] == true);
- assert_or_panic(vec[83] == true);
- assert_or_panic(vec[84] == false);
- assert_or_panic(vec[85] == true);
- assert_or_panic(vec[86] == false);
- assert_or_panic(vec[87] == false);
- assert_or_panic(vec[88] == true);
- assert_or_panic(vec[89] == true);
- assert_or_panic(vec[90] == true);
- assert_or_panic(vec[91] == true);
- assert_or_panic(vec[92] == true);
- assert_or_panic(vec[93] == false);
- assert_or_panic(vec[94] == false);
- assert_or_panic(vec[95] == true);
- assert_or_panic(vec[96] == false);
- assert_or_panic(vec[97] == false);
- assert_or_panic(vec[98] == true);
- assert_or_panic(vec[99] == true);
- assert_or_panic(vec[100] == true);
- assert_or_panic(vec[101] == true);
- assert_or_panic(vec[102] == true);
- assert_or_panic(vec[103] == true);
- assert_or_panic(vec[104] == true);
- assert_or_panic(vec[105] == false);
- assert_or_panic(vec[106] == false);
- assert_or_panic(vec[107] == true);
- assert_or_panic(vec[108] == false);
- assert_or_panic(vec[109] == false);
- assert_or_panic(vec[110] == true);
- assert_or_panic(vec[111] == false);
- assert_or_panic(vec[112] == false);
- assert_or_panic(vec[113] == true);
- assert_or_panic(vec[114] == false);
- assert_or_panic(vec[115] == false);
- assert_or_panic(vec[116] == false);
- assert_or_panic(vec[117] == false);
- assert_or_panic(vec[118] == false);
- assert_or_panic(vec[119] == false);
- assert_or_panic(vec[120] == true);
- assert_or_panic(vec[121] == true);
- assert_or_panic(vec[122] == true);
- assert_or_panic(vec[123] == false);
- assert_or_panic(vec[124] == true);
- assert_or_panic(vec[125] == false);
- assert_or_panic(vec[126] == false);
- assert_or_panic(vec[127] == true);
- }
- {
- zig_vector_256_bool((Vector256Bool){
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- });
-
- Vector256Bool vec = zig_ret_vector_256_bool();
- assert_or_panic(vec[0] == true);
- assert_or_panic(vec[1] == true);
- assert_or_panic(vec[2] == true);
- assert_or_panic(vec[3] == false);
- assert_or_panic(vec[4] == true);
- assert_or_panic(vec[5] == false);
- assert_or_panic(vec[6] == false);
- assert_or_panic(vec[7] == true);
- assert_or_panic(vec[8] == false);
- assert_or_panic(vec[9] == false);
- assert_or_panic(vec[10] == false);
- assert_or_panic(vec[11] == false);
- assert_or_panic(vec[12] == false);
- assert_or_panic(vec[13] == false);
- assert_or_panic(vec[14] == false);
- assert_or_panic(vec[15] == false);
- assert_or_panic(vec[16] == true);
- assert_or_panic(vec[17] == false);
- assert_or_panic(vec[18] == true);
- assert_or_panic(vec[19] == false);
- assert_or_panic(vec[20] == false);
- assert_or_panic(vec[21] == true);
- assert_or_panic(vec[22] == true);
- assert_or_panic(vec[23] == false);
- assert_or_panic(vec[24] == false);
- assert_or_panic(vec[25] == true);
- assert_or_panic(vec[26] == true);
- assert_or_panic(vec[27] == false);
- assert_or_panic(vec[28] == true);
- assert_or_panic(vec[29] == true);
- assert_or_panic(vec[30] == true);
- assert_or_panic(vec[31] == false);
- assert_or_panic(vec[32] == true);
- assert_or_panic(vec[33] == false);
- assert_or_panic(vec[34] == true);
- assert_or_panic(vec[35] == false);
- assert_or_panic(vec[36] == true);
- assert_or_panic(vec[37] == false);
- assert_or_panic(vec[38] == true);
- assert_or_panic(vec[39] == false);
- assert_or_panic(vec[40] == false);
- assert_or_panic(vec[41] == false);
- assert_or_panic(vec[42] == true);
- assert_or_panic(vec[43] == true);
- assert_or_panic(vec[44] == true);
- assert_or_panic(vec[45] == false);
- assert_or_panic(vec[46] == false);
- assert_or_panic(vec[47] == false);
- assert_or_panic(vec[48] == true);
- assert_or_panic(vec[49] == false);
- assert_or_panic(vec[50] == true);
- assert_or_panic(vec[51] == false);
- assert_or_panic(vec[52] == true);
- assert_or_panic(vec[53] == false);
- assert_or_panic(vec[54] == true);
- assert_or_panic(vec[55] == true);
- assert_or_panic(vec[56] == false);
- assert_or_panic(vec[57] == false);
- assert_or_panic(vec[58] == false);
- assert_or_panic(vec[59] == true);
- assert_or_panic(vec[60] == true);
- assert_or_panic(vec[61] == true);
- assert_or_panic(vec[62] == false);
- assert_or_panic(vec[63] == true);
- assert_or_panic(vec[64] == false);
- assert_or_panic(vec[65] == true);
- assert_or_panic(vec[66] == false);
- assert_or_panic(vec[67] == true);
- assert_or_panic(vec[68] == true);
- assert_or_panic(vec[69] == false);
- assert_or_panic(vec[70] == true);
- assert_or_panic(vec[71] == false);
- assert_or_panic(vec[72] == true);
- assert_or_panic(vec[73] == true);
- assert_or_panic(vec[74] == false);
- assert_or_panic(vec[75] == false);
- assert_or_panic(vec[76] == false);
- assert_or_panic(vec[77] == false);
- assert_or_panic(vec[78] == false);
- assert_or_panic(vec[79] == false);
- assert_or_panic(vec[80] == false);
- assert_or_panic(vec[81] == false);
- assert_or_panic(vec[82] == false);
- assert_or_panic(vec[83] == true);
- assert_or_panic(vec[84] == false);
- assert_or_panic(vec[85] == false);
- assert_or_panic(vec[86] == false);
- assert_or_panic(vec[87] == true);
- assert_or_panic(vec[88] == false);
- assert_or_panic(vec[89] == true);
- assert_or_panic(vec[90] == true);
- assert_or_panic(vec[91] == false);
- assert_or_panic(vec[92] == false);
- assert_or_panic(vec[93] == true);
- assert_or_panic(vec[94] == true);
- assert_or_panic(vec[95] == false);
- assert_or_panic(vec[96] == false);
- assert_or_panic(vec[97] == true);
- assert_or_panic(vec[98] == false);
- assert_or_panic(vec[99] == false);
- assert_or_panic(vec[100] == false);
- assert_or_panic(vec[101] == false);
- assert_or_panic(vec[102] == false);
- assert_or_panic(vec[103] == false);
- assert_or_panic(vec[104] == false);
- assert_or_panic(vec[105] == true);
- assert_or_panic(vec[106] == true);
- assert_or_panic(vec[107] == false);
- assert_or_panic(vec[108] == true);
- assert_or_panic(vec[109] == false);
- assert_or_panic(vec[110] == true);
- assert_or_panic(vec[111] == true);
- assert_or_panic(vec[112] == false);
- assert_or_panic(vec[113] == false);
- assert_or_panic(vec[114] == false);
- assert_or_panic(vec[115] == false);
- assert_or_panic(vec[116] == false);
- assert_or_panic(vec[117] == false);
- assert_or_panic(vec[118] == false);
- assert_or_panic(vec[119] == true);
- assert_or_panic(vec[120] == true);
- assert_or_panic(vec[121] == true);
- assert_or_panic(vec[122] == false);
- assert_or_panic(vec[123] == true);
- assert_or_panic(vec[124] == true);
- assert_or_panic(vec[125] == false);
- assert_or_panic(vec[126] == false);
- assert_or_panic(vec[127] == true);
- assert_or_panic(vec[128] == true);
- assert_or_panic(vec[129] == true);
- assert_or_panic(vec[130] == true);
- assert_or_panic(vec[131] == true);
- assert_or_panic(vec[132] == false);
- assert_or_panic(vec[133] == true);
- assert_or_panic(vec[134] == true);
- assert_or_panic(vec[135] == false);
- assert_or_panic(vec[136] == false);
- assert_or_panic(vec[137] == true);
- assert_or_panic(vec[138] == true);
- assert_or_panic(vec[139] == false);
- assert_or_panic(vec[140] == true);
- assert_or_panic(vec[141] == false);
- assert_or_panic(vec[142] == true);
- assert_or_panic(vec[143] == false);
- assert_or_panic(vec[144] == true);
- assert_or_panic(vec[145] == true);
- assert_or_panic(vec[146] == true);
- assert_or_panic(vec[147] == true);
- assert_or_panic(vec[148] == false);
- assert_or_panic(vec[149] == false);
- assert_or_panic(vec[150] == false);
- assert_or_panic(vec[151] == true);
- assert_or_panic(vec[152] == false);
- assert_or_panic(vec[153] == true);
- assert_or_panic(vec[154] == false);
- assert_or_panic(vec[155] == true);
- assert_or_panic(vec[156] == true);
- assert_or_panic(vec[157] == false);
- assert_or_panic(vec[158] == true);
- assert_or_panic(vec[159] == true);
- assert_or_panic(vec[160] == true);
- assert_or_panic(vec[161] == true);
- assert_or_panic(vec[162] == true);
- assert_or_panic(vec[163] == false);
- assert_or_panic(vec[164] == false);
- assert_or_panic(vec[165] == true);
- assert_or_panic(vec[166] == false);
- assert_or_panic(vec[167] == true);
- assert_or_panic(vec[168] == true);
- assert_or_panic(vec[169] == true);
- assert_or_panic(vec[170] == true);
- assert_or_panic(vec[171] == false);
- assert_or_panic(vec[172] == true);
- assert_or_panic(vec[173] == true);
- assert_or_panic(vec[174] == true);
- assert_or_panic(vec[175] == true);
- assert_or_panic(vec[176] == true);
- assert_or_panic(vec[177] == true);
- assert_or_panic(vec[178] == true);
- assert_or_panic(vec[179] == false);
- assert_or_panic(vec[180] == true);
- assert_or_panic(vec[181] == false);
- assert_or_panic(vec[182] == false);
- assert_or_panic(vec[183] == false);
- assert_or_panic(vec[184] == true);
- assert_or_panic(vec[185] == false);
- assert_or_panic(vec[186] == true);
- assert_or_panic(vec[187] == true);
- assert_or_panic(vec[188] == false);
- assert_or_panic(vec[189] == true);
- assert_or_panic(vec[190] == false);
- assert_or_panic(vec[191] == true);
- assert_or_panic(vec[192] == false);
- assert_or_panic(vec[193] == true);
- assert_or_panic(vec[194] == false);
- assert_or_panic(vec[195] == false);
- assert_or_panic(vec[196] == true);
- assert_or_panic(vec[197] == true);
- assert_or_panic(vec[198] == true);
- assert_or_panic(vec[199] == true);
- assert_or_panic(vec[200] == true);
- assert_or_panic(vec[201] == true);
- assert_or_panic(vec[202] == true);
- assert_or_panic(vec[203] == false);
- assert_or_panic(vec[204] == true);
- assert_or_panic(vec[205] == false);
- assert_or_panic(vec[206] == false);
- assert_or_panic(vec[207] == true);
- assert_or_panic(vec[208] == true);
- assert_or_panic(vec[209] == false);
- assert_or_panic(vec[210] == false);
- assert_or_panic(vec[211] == false);
- assert_or_panic(vec[212] == true);
- assert_or_panic(vec[213] == true);
- assert_or_panic(vec[214] == true);
- assert_or_panic(vec[215] == false);
- assert_or_panic(vec[216] == false);
- assert_or_panic(vec[217] == true);
- assert_or_panic(vec[218] == true);
- assert_or_panic(vec[219] == true);
- assert_or_panic(vec[220] == true);
- assert_or_panic(vec[221] == false);
- assert_or_panic(vec[222] == true);
- assert_or_panic(vec[223] == false);
- assert_or_panic(vec[224] == true);
- assert_or_panic(vec[225] == true);
- assert_or_panic(vec[226] == true);
- assert_or_panic(vec[227] == false);
- assert_or_panic(vec[228] == false);
- assert_or_panic(vec[229] == false);
- assert_or_panic(vec[230] == false);
- assert_or_panic(vec[231] == false);
- assert_or_panic(vec[232] == true);
- assert_or_panic(vec[233] == true);
- assert_or_panic(vec[234] == false);
- assert_or_panic(vec[235] == false);
- assert_or_panic(vec[236] == false);
- assert_or_panic(vec[237] == true);
- assert_or_panic(vec[238] == true);
- assert_or_panic(vec[239] == false);
- assert_or_panic(vec[240] == true);
- assert_or_panic(vec[241] == true);
- assert_or_panic(vec[242] == true);
- assert_or_panic(vec[243] == false);
- assert_or_panic(vec[244] == true);
- assert_or_panic(vec[245] == true);
- assert_or_panic(vec[246] == false);
- assert_or_panic(vec[247] == true);
- assert_or_panic(vec[248] == false);
- assert_or_panic(vec[249] == false);
- assert_or_panic(vec[250] == true);
- assert_or_panic(vec[251] == true);
- assert_or_panic(vec[252] == false);
- assert_or_panic(vec[253] == true);
- assert_or_panic(vec[254] == false);
- assert_or_panic(vec[255] == true);
- }
- {
- zig_vector_512_bool((Vector512Bool){
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- });
-
- Vector512Bool vec = zig_ret_vector_512_bool();
- assert_or_panic(vec[0] == true);
- assert_or_panic(vec[1] == true);
- assert_or_panic(vec[2] == true);
- assert_or_panic(vec[3] == true);
- assert_or_panic(vec[4] == false);
- assert_or_panic(vec[5] == true);
- assert_or_panic(vec[6] == false);
- assert_or_panic(vec[7] == true);
- assert_or_panic(vec[8] == true);
- assert_or_panic(vec[9] == true);
- assert_or_panic(vec[10] == false);
- assert_or_panic(vec[11] == true);
- assert_or_panic(vec[12] == false);
- assert_or_panic(vec[13] == false);
- assert_or_panic(vec[14] == false);
- assert_or_panic(vec[15] == true);
- assert_or_panic(vec[16] == true);
- assert_or_panic(vec[17] == false);
- assert_or_panic(vec[18] == false);
- assert_or_panic(vec[19] == false);
- assert_or_panic(vec[20] == true);
- assert_or_panic(vec[21] == true);
- assert_or_panic(vec[22] == false);
- assert_or_panic(vec[23] == false);
- assert_or_panic(vec[24] == false);
- assert_or_panic(vec[25] == false);
- assert_or_panic(vec[26] == true);
- assert_or_panic(vec[27] == false);
- assert_or_panic(vec[28] == false);
- assert_or_panic(vec[29] == false);
- assert_or_panic(vec[30] == true);
- assert_or_panic(vec[31] == true);
- assert_or_panic(vec[32] == true);
- assert_or_panic(vec[33] == true);
- assert_or_panic(vec[34] == false);
- assert_or_panic(vec[35] == false);
- assert_or_panic(vec[36] == false);
- assert_or_panic(vec[37] == true);
- assert_or_panic(vec[38] == true);
- assert_or_panic(vec[39] == true);
- assert_or_panic(vec[40] == false);
- assert_or_panic(vec[41] == false);
- assert_or_panic(vec[42] == true);
- assert_or_panic(vec[43] == false);
- assert_or_panic(vec[44] == false);
- assert_or_panic(vec[45] == true);
- assert_or_panic(vec[46] == false);
- assert_or_panic(vec[47] == false);
- assert_or_panic(vec[48] == true);
- assert_or_panic(vec[49] == true);
- assert_or_panic(vec[50] == true);
- assert_or_panic(vec[51] == true);
- assert_or_panic(vec[52] == false);
- assert_or_panic(vec[53] == false);
- assert_or_panic(vec[54] == false);
- assert_or_panic(vec[55] == true);
- assert_or_panic(vec[56] == false);
- assert_or_panic(vec[57] == true);
- assert_or_panic(vec[58] == false);
- assert_or_panic(vec[59] == true);
- assert_or_panic(vec[60] == true);
- assert_or_panic(vec[61] == false);
- assert_or_panic(vec[62] == false);
- assert_or_panic(vec[63] == true);
- assert_or_panic(vec[64] == true);
- assert_or_panic(vec[65] == false);
- assert_or_panic(vec[66] == true);
- assert_or_panic(vec[67] == false);
- assert_or_panic(vec[68] == false);
- assert_or_panic(vec[69] == false);
- assert_or_panic(vec[70] == true);
- assert_or_panic(vec[71] == true);
- assert_or_panic(vec[72] == true);
- assert_or_panic(vec[73] == true);
- assert_or_panic(vec[74] == true);
- assert_or_panic(vec[75] == false);
- assert_or_panic(vec[76] == true);
- assert_or_panic(vec[77] == false);
- assert_or_panic(vec[78] == true);
- assert_or_panic(vec[79] == true);
- assert_or_panic(vec[80] == true);
- assert_or_panic(vec[81] == true);
- assert_or_panic(vec[82] == true);
- assert_or_panic(vec[83] == false);
- assert_or_panic(vec[84] == true);
- assert_or_panic(vec[85] == true);
- assert_or_panic(vec[86] == false);
- assert_or_panic(vec[87] == true);
- assert_or_panic(vec[88] == false);
- assert_or_panic(vec[89] == false);
- assert_or_panic(vec[90] == true);
- assert_or_panic(vec[91] == false);
- assert_or_panic(vec[92] == true);
- assert_or_panic(vec[93] == false);
- assert_or_panic(vec[94] == false);
- assert_or_panic(vec[95] == false);
- assert_or_panic(vec[96] == true);
- assert_or_panic(vec[97] == true);
- assert_or_panic(vec[98] == false);
- assert_or_panic(vec[99] == true);
- assert_or_panic(vec[100] == true);
- assert_or_panic(vec[101] == false);
- assert_or_panic(vec[102] == true);
- assert_or_panic(vec[103] == false);
- assert_or_panic(vec[104] == true);
- assert_or_panic(vec[105] == false);
- assert_or_panic(vec[106] == true);
- assert_or_panic(vec[107] == false);
- assert_or_panic(vec[108] == false);
- assert_or_panic(vec[109] == true);
- assert_or_panic(vec[110] == false);
- assert_or_panic(vec[111] == false);
- assert_or_panic(vec[112] == true);
- assert_or_panic(vec[113] == false);
- assert_or_panic(vec[114] == true);
- assert_or_panic(vec[115] == false);
- assert_or_panic(vec[116] == true);
- assert_or_panic(vec[117] == false);
- assert_or_panic(vec[118] == false);
- assert_or_panic(vec[119] == true);
- assert_or_panic(vec[120] == true);
- assert_or_panic(vec[121] == true);
- assert_or_panic(vec[122] == false);
- assert_or_panic(vec[123] == true);
- assert_or_panic(vec[124] == false);
- assert_or_panic(vec[125] == false);
- assert_or_panic(vec[126] == true);
- assert_or_panic(vec[127] == true);
- assert_or_panic(vec[128] == false);
- assert_or_panic(vec[129] == true);
- assert_or_panic(vec[130] == true);
- assert_or_panic(vec[131] == false);
- assert_or_panic(vec[132] == true);
- assert_or_panic(vec[133] == true);
- assert_or_panic(vec[134] == false);
- assert_or_panic(vec[135] == true);
- assert_or_panic(vec[136] == true);
- assert_or_panic(vec[137] == false);
- assert_or_panic(vec[138] == false);
- assert_or_panic(vec[139] == false);
- assert_or_panic(vec[140] == true);
- assert_or_panic(vec[141] == false);
- assert_or_panic(vec[142] == true);
- assert_or_panic(vec[143] == false);
- assert_or_panic(vec[144] == false);
- assert_or_panic(vec[145] == false);
- assert_or_panic(vec[146] == true);
- assert_or_panic(vec[147] == false);
- assert_or_panic(vec[148] == true);
- assert_or_panic(vec[149] == false);
- assert_or_panic(vec[150] == false);
- assert_or_panic(vec[151] == true);
- assert_or_panic(vec[152] == false);
- assert_or_panic(vec[153] == true);
- assert_or_panic(vec[154] == true);
- assert_or_panic(vec[155] == false);
- assert_or_panic(vec[156] == true);
- assert_or_panic(vec[157] == true);
- assert_or_panic(vec[158] == false);
- assert_or_panic(vec[159] == true);
- assert_or_panic(vec[160] == true);
- assert_or_panic(vec[161] == false);
- assert_or_panic(vec[162] == false);
- assert_or_panic(vec[163] == false);
- assert_or_panic(vec[164] == true);
- assert_or_panic(vec[165] == false);
- assert_or_panic(vec[166] == true);
- assert_or_panic(vec[167] == true);
- assert_or_panic(vec[168] == true);
- assert_or_panic(vec[169] == true);
- assert_or_panic(vec[170] == false);
- assert_or_panic(vec[171] == true);
- assert_or_panic(vec[172] == false);
- assert_or_panic(vec[173] == false);
- assert_or_panic(vec[174] == true);
- assert_or_panic(vec[175] == true);
- assert_or_panic(vec[176] == true);
- assert_or_panic(vec[177] == false);
- assert_or_panic(vec[178] == false);
- assert_or_panic(vec[179] == false);
- assert_or_panic(vec[180] == true);
- assert_or_panic(vec[181] == false);
- assert_or_panic(vec[182] == false);
- assert_or_panic(vec[183] == true);
- assert_or_panic(vec[184] == true);
- assert_or_panic(vec[185] == false);
- assert_or_panic(vec[186] == true);
- assert_or_panic(vec[187] == false);
- assert_or_panic(vec[188] == true);
- assert_or_panic(vec[189] == true);
- assert_or_panic(vec[190] == true);
- assert_or_panic(vec[191] == true);
- assert_or_panic(vec[192] == true);
- assert_or_panic(vec[193] == true);
- assert_or_panic(vec[194] == true);
- assert_or_panic(vec[195] == false);
- assert_or_panic(vec[196] == false);
- assert_or_panic(vec[197] == false);
- assert_or_panic(vec[198] == false);
- assert_or_panic(vec[199] == false);
- assert_or_panic(vec[200] == true);
- assert_or_panic(vec[201] == false);
- assert_or_panic(vec[202] == true);
- assert_or_panic(vec[203] == false);
- assert_or_panic(vec[204] == true);
- assert_or_panic(vec[205] == true);
- assert_or_panic(vec[206] == false);
- assert_or_panic(vec[207] == false);
- assert_or_panic(vec[208] == false);
- assert_or_panic(vec[209] == true);
- assert_or_panic(vec[210] == true);
- assert_or_panic(vec[211] == true);
- assert_or_panic(vec[212] == false);
- assert_or_panic(vec[213] == false);
- assert_or_panic(vec[214] == true);
- assert_or_panic(vec[215] == true);
- assert_or_panic(vec[216] == true);
- assert_or_panic(vec[217] == false);
- assert_or_panic(vec[218] == false);
- assert_or_panic(vec[219] == true);
- assert_or_panic(vec[220] == false);
- assert_or_panic(vec[221] == true);
- assert_or_panic(vec[222] == true);
- assert_or_panic(vec[223] == false);
- assert_or_panic(vec[224] == true);
- assert_or_panic(vec[225] == false);
- assert_or_panic(vec[226] == false);
- assert_or_panic(vec[227] == true);
- assert_or_panic(vec[228] == false);
- assert_or_panic(vec[229] == false);
- assert_or_panic(vec[230] == true);
- assert_or_panic(vec[231] == true);
- assert_or_panic(vec[232] == false);
- assert_or_panic(vec[233] == true);
- assert_or_panic(vec[234] == true);
- assert_or_panic(vec[235] == true);
- assert_or_panic(vec[236] == true);
- assert_or_panic(vec[237] == true);
- assert_or_panic(vec[238] == false);
- assert_or_panic(vec[239] == true);
- assert_or_panic(vec[240] == false);
- assert_or_panic(vec[241] == false);
- assert_or_panic(vec[242] == true);
- assert_or_panic(vec[243] == false);
- assert_or_panic(vec[244] == true);
- assert_or_panic(vec[245] == false);
- assert_or_panic(vec[246] == true);
- assert_or_panic(vec[247] == false);
- assert_or_panic(vec[248] == true);
- assert_or_panic(vec[249] == true);
- assert_or_panic(vec[250] == true);
- assert_or_panic(vec[251] == true);
- assert_or_panic(vec[252] == true);
- assert_or_panic(vec[253] == false);
- assert_or_panic(vec[254] == false);
- assert_or_panic(vec[255] == false);
- assert_or_panic(vec[256] == false);
- assert_or_panic(vec[257] == false);
- assert_or_panic(vec[258] == false);
- assert_or_panic(vec[259] == true);
- assert_or_panic(vec[260] == true);
- assert_or_panic(vec[261] == true);
- assert_or_panic(vec[262] == true);
- assert_or_panic(vec[263] == false);
- assert_or_panic(vec[264] == false);
- assert_or_panic(vec[265] == false);
- assert_or_panic(vec[266] == true);
- assert_or_panic(vec[267] == false);
- assert_or_panic(vec[268] == true);
- assert_or_panic(vec[269] == false);
- assert_or_panic(vec[270] == true);
- assert_or_panic(vec[271] == true);
- assert_or_panic(vec[272] == true);
- assert_or_panic(vec[273] == true);
- assert_or_panic(vec[274] == true);
- assert_or_panic(vec[275] == true);
- assert_or_panic(vec[276] == false);
- assert_or_panic(vec[277] == false);
- assert_or_panic(vec[278] == true);
- assert_or_panic(vec[279] == true);
- assert_or_panic(vec[280] == false);
- assert_or_panic(vec[281] == false);
- assert_or_panic(vec[282] == false);
- assert_or_panic(vec[283] == false);
- assert_or_panic(vec[284] == true);
- assert_or_panic(vec[285] == true);
- assert_or_panic(vec[286] == true);
- assert_or_panic(vec[287] == false);
- assert_or_panic(vec[288] == false);
- assert_or_panic(vec[289] == false);
- assert_or_panic(vec[290] == true);
- assert_or_panic(vec[291] == false);
- assert_or_panic(vec[292] == true);
- assert_or_panic(vec[293] == true);
- assert_or_panic(vec[294] == false);
- assert_or_panic(vec[295] == true);
- assert_or_panic(vec[296] == true);
- assert_or_panic(vec[297] == true);
- assert_or_panic(vec[298] == false);
- assert_or_panic(vec[299] == true);
- assert_or_panic(vec[300] == true);
- assert_or_panic(vec[301] == false);
- assert_or_panic(vec[302] == false);
- assert_or_panic(vec[303] == true);
- assert_or_panic(vec[304] == false);
- assert_or_panic(vec[305] == false);
- assert_or_panic(vec[306] == true);
- assert_or_panic(vec[307] == true);
- assert_or_panic(vec[308] == true);
- assert_or_panic(vec[309] == true);
- assert_or_panic(vec[310] == false);
- assert_or_panic(vec[311] == false);
- assert_or_panic(vec[312] == false);
- assert_or_panic(vec[313] == false);
- assert_or_panic(vec[314] == false);
- assert_or_panic(vec[315] == true);
- assert_or_panic(vec[316] == false);
- assert_or_panic(vec[317] == false);
- assert_or_panic(vec[318] == true);
- assert_or_panic(vec[319] == false);
- assert_or_panic(vec[320] == false);
- assert_or_panic(vec[321] == true);
- assert_or_panic(vec[322] == true);
- assert_or_panic(vec[323] == true);
- assert_or_panic(vec[324] == true);
- assert_or_panic(vec[325] == false);
- assert_or_panic(vec[326] == false);
- assert_or_panic(vec[327] == false);
- assert_or_panic(vec[328] == true);
- assert_or_panic(vec[329] == true);
- assert_or_panic(vec[330] == false);
- assert_or_panic(vec[331] == true);
- assert_or_panic(vec[332] == true);
- assert_or_panic(vec[333] == false);
- assert_or_panic(vec[334] == false);
- assert_or_panic(vec[335] == true);
- assert_or_panic(vec[336] == true);
- assert_or_panic(vec[337] == false);
- assert_or_panic(vec[338] == true);
- assert_or_panic(vec[339] == true);
- assert_or_panic(vec[340] == true);
- assert_or_panic(vec[341] == false);
- assert_or_panic(vec[342] == false);
- assert_or_panic(vec[343] == false);
- assert_or_panic(vec[344] == true);
- assert_or_panic(vec[345] == true);
- assert_or_panic(vec[346] == false);
- assert_or_panic(vec[347] == true);
- assert_or_panic(vec[348] == false);
- assert_or_panic(vec[349] == true);
- assert_or_panic(vec[350] == false);
- assert_or_panic(vec[351] == false);
- assert_or_panic(vec[352] == true);
- assert_or_panic(vec[353] == false);
- assert_or_panic(vec[354] == true);
- assert_or_panic(vec[355] == false);
- assert_or_panic(vec[356] == false);
- assert_or_panic(vec[357] == false);
- assert_or_panic(vec[358] == false);
- assert_or_panic(vec[359] == false);
- assert_or_panic(vec[360] == true);
- assert_or_panic(vec[361] == true);
- assert_or_panic(vec[362] == false);
- assert_or_panic(vec[363] == false);
- assert_or_panic(vec[364] == false);
- assert_or_panic(vec[365] == false);
- assert_or_panic(vec[366] == true);
- assert_or_panic(vec[367] == false);
- assert_or_panic(vec[368] == true);
- assert_or_panic(vec[369] == false);
- assert_or_panic(vec[370] == true);
- assert_or_panic(vec[371] == true);
- assert_or_panic(vec[372] == false);
- assert_or_panic(vec[373] == true);
- assert_or_panic(vec[374] == true);
- assert_or_panic(vec[375] == true);
- assert_or_panic(vec[376] == true);
- assert_or_panic(vec[377] == true);
- assert_or_panic(vec[378] == false);
- assert_or_panic(vec[379] == true);
- assert_or_panic(vec[380] == false);
- assert_or_panic(vec[381] == true);
- assert_or_panic(vec[382] == true);
- assert_or_panic(vec[383] == true);
- assert_or_panic(vec[384] == true);
- assert_or_panic(vec[385] == true);
- assert_or_panic(vec[386] == false);
- assert_or_panic(vec[387] == true);
- assert_or_panic(vec[388] == true);
- assert_or_panic(vec[389] == false);
- assert_or_panic(vec[390] == true);
- assert_or_panic(vec[391] == false);
- assert_or_panic(vec[392] == true);
- assert_or_panic(vec[393] == false);
- assert_or_panic(vec[394] == true);
- assert_or_panic(vec[395] == false);
- assert_or_panic(vec[396] == true);
- assert_or_panic(vec[397] == false);
- assert_or_panic(vec[398] == false);
- assert_or_panic(vec[399] == true);
- assert_or_panic(vec[400] == true);
- assert_or_panic(vec[401] == true);
- assert_or_panic(vec[402] == true);
- assert_or_panic(vec[403] == false);
- assert_or_panic(vec[404] == false);
- assert_or_panic(vec[405] == true);
- assert_or_panic(vec[406] == false);
- assert_or_panic(vec[407] == false);
- assert_or_panic(vec[408] == false);
- assert_or_panic(vec[409] == true);
- assert_or_panic(vec[410] == false);
- assert_or_panic(vec[411] == true);
- assert_or_panic(vec[412] == true);
- assert_or_panic(vec[413] == false);
- assert_or_panic(vec[414] == true);
- assert_or_panic(vec[415] == true);
- assert_or_panic(vec[416] == false);
- assert_or_panic(vec[417] == true);
- assert_or_panic(vec[418] == true);
- assert_or_panic(vec[419] == false);
- assert_or_panic(vec[420] == false);
- assert_or_panic(vec[421] == true);
- assert_or_panic(vec[422] == false);
- assert_or_panic(vec[423] == false);
- assert_or_panic(vec[424] == true);
- assert_or_panic(vec[425] == false);
- assert_or_panic(vec[426] == true);
- assert_or_panic(vec[427] == false);
- assert_or_panic(vec[428] == false);
- assert_or_panic(vec[429] == true);
- assert_or_panic(vec[430] == false);
- assert_or_panic(vec[431] == true);
- assert_or_panic(vec[432] == true);
- assert_or_panic(vec[433] == false);
- assert_or_panic(vec[434] == true);
- assert_or_panic(vec[435] == false);
- assert_or_panic(vec[436] == true);
- assert_or_panic(vec[437] == false);
- assert_or_panic(vec[438] == true);
- assert_or_panic(vec[439] == false);
- assert_or_panic(vec[440] == false);
- assert_or_panic(vec[441] == true);
- assert_or_panic(vec[442] == true);
- assert_or_panic(vec[443] == false);
- assert_or_panic(vec[444] == true);
- assert_or_panic(vec[445] == true);
- assert_or_panic(vec[446] == false);
- assert_or_panic(vec[447] == true);
- assert_or_panic(vec[448] == true);
- assert_or_panic(vec[449] == false);
- assert_or_panic(vec[450] == false);
- assert_or_panic(vec[451] == false);
- assert_or_panic(vec[452] == false);
- assert_or_panic(vec[453] == false);
- assert_or_panic(vec[454] == true);
- assert_or_panic(vec[455] == false);
- assert_or_panic(vec[456] == false);
- assert_or_panic(vec[457] == true);
- assert_or_panic(vec[458] == false);
- assert_or_panic(vec[459] == true);
- assert_or_panic(vec[460] == false);
- assert_or_panic(vec[461] == false);
- assert_or_panic(vec[462] == false);
- assert_or_panic(vec[463] == true);
- assert_or_panic(vec[464] == false);
- assert_or_panic(vec[465] == true);
- assert_or_panic(vec[466] == false);
- assert_or_panic(vec[467] == false);
- assert_or_panic(vec[468] == false);
- assert_or_panic(vec[469] == false);
- assert_or_panic(vec[470] == true);
- assert_or_panic(vec[471] == true);
- assert_or_panic(vec[472] == false);
- assert_or_panic(vec[473] == true);
- assert_or_panic(vec[474] == true);
- assert_or_panic(vec[475] == false);
- assert_or_panic(vec[476] == false);
- assert_or_panic(vec[477] == true);
- assert_or_panic(vec[478] == true);
- assert_or_panic(vec[479] == true);
- assert_or_panic(vec[480] == false);
- assert_or_panic(vec[481] == false);
- assert_or_panic(vec[482] == true);
- assert_or_panic(vec[483] == false);
- assert_or_panic(vec[484] == false);
- assert_or_panic(vec[485] == false);
- assert_or_panic(vec[486] == true);
- assert_or_panic(vec[487] == true);
- assert_or_panic(vec[488] == false);
- assert_or_panic(vec[489] == false);
- assert_or_panic(vec[490] == false);
- assert_or_panic(vec[491] == false);
- assert_or_panic(vec[492] == false);
- assert_or_panic(vec[493] == true);
- assert_or_panic(vec[494] == true);
- assert_or_panic(vec[495] == true);
- assert_or_panic(vec[496] == true);
- assert_or_panic(vec[497] == false);
- assert_or_panic(vec[498] == false);
- assert_or_panic(vec[499] == false);
- assert_or_panic(vec[500] == true);
- assert_or_panic(vec[501] == false);
- assert_or_panic(vec[502] == true);
- assert_or_panic(vec[503] == true);
- assert_or_panic(vec[504] == true);
- assert_or_panic(vec[505] == true);
- assert_or_panic(vec[506] == false);
- assert_or_panic(vec[507] == false);
- assert_or_panic(vec[508] == true);
- assert_or_panic(vec[509] == true);
- assert_or_panic(vec[510] == false);
- assert_or_panic(vec[511] == false);
- }
-#endif
}
void c_u8(uint8_t x) {
@@ -5312,6 +15586,7 @@ void c_five_floats(float a, float b, float c, float d, float e) {
assert_or_panic(e == 5.0);
}
+#ifndef ZIG_NO_COMPLEX
float complex c_cmultf_comp(float a_r, float a_i, float b_r, float b_i) {
assert_or_panic(a_r == 1.25f);
assert_or_panic(a_i == 2.6f);
@@ -5347,6 +15622,7 @@ double complex c_cmultd(double complex a, double complex b) {
return 1.5 + I * 13.5;
}
+#endif
struct Struct_i32_i32 c_mut_struct_i32_i32(struct Struct_i32_i32 s) {
assert_or_panic(s.a == 1);
@@ -5378,51 +15654,6 @@ void c_big_union(union BigUnion x) {
assert_or_panic(x.a.d == 4);
}
-void c_small_struct_ints(struct SmallStructInts x) {
- assert_or_panic(x.a == 1);
- assert_or_panic(x.b == 2);
- assert_or_panic(x.c == 3);
- assert_or_panic(x.d == 4);
-
- struct SmallStructInts y = zig_ret_small_struct_ints();
-
- assert_or_panic(y.a == 1);
- assert_or_panic(y.b == 2);
- assert_or_panic(y.c == 3);
- assert_or_panic(y.d == 4);
-}
-
-struct SmallStructInts c_ret_small_struct_ints() {
- struct SmallStructInts s = {
- .a = 1,
- .b = 2,
- .c = 3,
- .d = 4,
- };
- return s;
-}
-
-void c_med_struct_ints(struct MedStructInts s) {
- assert_or_panic(s.x == 1);
- assert_or_panic(s.y == 2);
- assert_or_panic(s.z == 3);
-
- struct MedStructInts s2 = zig_ret_med_struct_ints();
-
- assert_or_panic(s2.x == 1);
- assert_or_panic(s2.y == 2);
- assert_or_panic(s2.z == 3);
-}
-
-struct MedStructInts c_ret_med_struct_ints() {
- struct MedStructInts s = {
- .x = 1,
- .y = 2,
- .z = 3,
- };
- return s;
-}
-
void c_med_struct_mixed(struct MedStructMixed x) {
assert_or_panic(x.a == 1234);
assert_or_panic(x.b == 100.0f);
@@ -5435,7 +15666,7 @@ void c_med_struct_mixed(struct MedStructMixed x) {
assert_or_panic(y.c == 1337.0f);
}
-struct MedStructMixed c_ret_med_struct_mixed() {
+struct MedStructMixed c_ret_med_struct_mixed(void) {
struct MedStructMixed s = {
.a = 1234,
.b = 100.0,
@@ -5461,7 +15692,7 @@ void c_split_struct_mixed(struct SplitStructMixed x) {
assert_or_panic(y.c == 1337.0f);
}
-uint8_t c_ret_small_packed_struct() {
+uint8_t c_ret_small_packed_struct(void) {
uint8_t s = 0;
s |= 0 << 0;
s |= 1 << 2;
@@ -5478,7 +15709,7 @@ void c_small_packed_struct(uint8_t x) {
}
#ifndef ZIG_NO_I128
-__int128 c_ret_big_packed_struct() {
+__int128 c_ret_big_packed_struct(void) {
__int128 s = 0;
s |= 1 << 0;
s |= (__int128)2 << 64;
@@ -5491,7 +15722,7 @@ void c_big_packed_struct(__int128 x) {
}
#endif
-struct SplitStructMixed c_ret_split_struct_mixed() {
+struct SplitStructMixed c_ret_split_struct_mixed(void) {
struct SplitStructMixed s = {
.a = 1234,
.b = 100,
@@ -5510,74 +15741,31 @@ struct BigStruct c_big_struct_both(struct BigStruct x) {
return y;
}
-void c_small_struct_floats(Vector3 vec) {
- assert_or_panic(vec.x == 3.0);
- assert_or_panic(vec.y == 6.0);
- assert_or_panic(vec.z == 12.0);
-}
-
-void c_small_struct_floats_extra(Vector3 vec, const char *str) {
- assert_or_panic(vec.x == 3.0);
- assert_or_panic(vec.y == 6.0);
- assert_or_panic(vec.z == 12.0);
- assert_or_panic(!strcmp(str, "hello"));
-}
-
-void c_big_struct_floats(Vector5 vec) {
- assert_or_panic(vec.x == 76.0);
- assert_or_panic(vec.y == -1.0);
- assert_or_panic(vec.z == -12.0);
- assert_or_panic(vec.w == 69);
- assert_or_panic(vec.q == 55);
-}
-
-void c_multiple_struct_ints(Rect x, Rect y) {
- assert_or_panic(x.left == 1);
- assert_or_panic(x.right == 21);
- assert_or_panic(x.top == 16);
- assert_or_panic(x.bottom == 4);
- assert_or_panic(y.left == 178);
- assert_or_panic(y.right == 189);
- assert_or_panic(y.top == 21);
- assert_or_panic(y.bottom == 15);
-}
-
-void c_multiple_struct_floats(FloatRect x, FloatRect y) {
- assert_or_panic(x.left == 1);
- assert_or_panic(x.right == 21);
- assert_or_panic(x.top == 16);
- assert_or_panic(x.bottom == 4);
- assert_or_panic(y.left == 178);
- assert_or_panic(y.right == 189);
- assert_or_panic(y.top == 21);
- assert_or_panic(y.bottom == 15);
-}
-
-bool c_ret_bool() {
+bool c_ret_bool(void) {
return 1;
}
-uint8_t c_ret_u8() {
+uint8_t c_ret_u8(void) {
return 0xff;
}
-uint16_t c_ret_u16() {
+uint16_t c_ret_u16(void) {
return 0xffff;
}
-uint32_t c_ret_u32() {
+uint32_t c_ret_u32(void) {
return 0xffffffff;
}
-uint64_t c_ret_u64() {
+uint64_t c_ret_u64(void) {
return 0xffffffffffffffff;
}
-int8_t c_ret_i8() {
+int8_t c_ret_i8(void) {
return -1;
}
-int16_t c_ret_i16() {
+int16_t c_ret_i16(void) {
return -1;
}
-int32_t c_ret_i32() {
+int32_t c_ret_i32(void) {
return -1;
}
-int64_t c_ret_i64() {
+int64_t c_ret_i64(void) {
return -1;
}
@@ -5592,7 +15780,7 @@ void c_struct_with_array(StructWithArray x) {
assert_or_panic(x.b == 2);
}
-StructWithArray c_ret_struct_with_array() {
+StructWithArray c_ret_struct_with_array(void) {
return (StructWithArray){4, {}, 155};
}
@@ -5614,7 +15802,7 @@ void c_float_array_struct(FloatArrayStruct x) {
assert_or_panic(x.size.height == 8);
}
-FloatArrayStruct c_ret_float_array_struct() {
+FloatArrayStruct c_ret_float_array_struct(void) {
FloatArrayStruct x;
x.origin.x = 1;
x.origin.y = 2;
@@ -5792,7 +15980,7 @@ f16_struct c_f16_struct(f16_struct a) {
return (f16_struct){34};
}
-#if defined __x86_64__ || defined __i386__
+#if (defined __x86_64__ || defined __i386__) && !defined _MSC_VER
typedef long double f80;
f80 c_f80(f80 a) {
assert_or_panic((double)a == 12.34);
@@ -5890,7 +16078,6 @@ struct ByRef __attribute__((sysv_abi)) c_explict_sys_v(struct ByRef in) {
}
#endif
-
struct byval_tail_callsite_attr_Point {
double x;
double y;
@@ -5907,7 +16094,7 @@ double c_byval_tail_callsite_attr(struct byval_tail_callsite_attr_Rect in) {
return in.size.width;
}
-#ifdef __i386__
+#if defined(__i386__) && defined(_WIN32) && !defined(_WIN64) && defined(_MSC_VER)
void __attribute__((fastcall)) zig_fastcall_check(int a, float b, void *c, double d, int e);
void __attribute__((fastcall)) c_fastcall_check(int a, float b, void *c, double d, int e) {
assert_or_panic(a == 1);
@@ -5915,7 +16102,98 @@ void __attribute__((fastcall)) c_fastcall_check(int a, float b, void *c, double
assert_or_panic((uintptr_t)c == 3);
assert_or_panic(d == 4.0);
assert_or_panic(e == 5);
- zig_fastcall_check(a, b, c, d, e);
+}
+
+typedef struct {
+ int a;
+ int b;
+ int c;
+} FastcallSRet;
+FastcallSRet __attribute__((fastcall)) zig_fastcall_sret(void);
+FastcallSRet __attribute__((fastcall)) c_fastcall_sret(void) {
+ return (FastcallSRet){
+ .a = 1,
+ .b = 2,
+ .c = 3
+ };
+}
+
+typedef struct {
+ char a;
+ short b;
+} FastcallNoSRet;
+FastcallNoSRet __attribute__((fastcall)) zig_fastcall_no_sret(void);
+FastcallNoSRet __attribute__((fastcall)) c_fastcall_no_sret(void) {
+ return (FastcallNoSRet){
+ .a = 1,
+ .b = 2
+ };
+}
+
+typedef struct {
+ float a;
+ float b;
+} FastcallNoSRetF32F32;
+FastcallNoSRetF32F32 __attribute__((fastcall)) zig_fastcall_no_sret_f32_f32(void);
+FastcallNoSRetF32F32 __attribute__((fastcall)) c_fastcall_no_sret_f32_f32(void) {
+ return (FastcallNoSRetF32F32){
+ .a = 1,
+ .b = 2
+ };
+}
+
+typedef struct {
+ double a;
+} FastcallNoSRetF64;
+FastcallNoSRetF64 __attribute__((fastcall)) zig_fastcall_no_sret_f64(void);
+FastcallNoSRetF64 __attribute__((fastcall)) c_fastcall_no_sret_f64(void) {
+ return (FastcallNoSRetF64){
+ .a = 1
+ };
+}
+
+float __attribute__((fastcall)) zig_fastcall_ret_f32(void);
+float __attribute__((fastcall)) c_fastcall_ret_f32(void) {
+ return 1;
+}
+
+double __attribute__((fastcall)) zig_fastcall_ret_f64(void);
+double __attribute__((fastcall)) c_fastcall_ret_f64(void) {
+ return 1;
+}
+
+void run_c_fastcall_tests(void) {
+ {
+ zig_fastcall_check(1, 2, (void*)3, 4, 5);
+ }
+ {
+ const FastcallSRet s = zig_fastcall_sret();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ assert_or_panic(s.c == 3);
+ }
+ {
+ const FastcallNoSRet s = zig_fastcall_no_sret();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ }
+ {
+ const FastcallNoSRetF32F32 s = zig_fastcall_no_sret_f32_f32();
+ assert_or_panic(s.a == 1);
+ assert_or_panic(s.b == 2);
+ }
+ {
+ const FastcallNoSRetF64 s = zig_fastcall_no_sret_f64();
+ assert_or_panic(s.a == 1);
+ }
+ {
+ const float s = zig_fastcall_ret_f32();
+ assert_or_panic(s == 1);
+ }
+ {
+ const double s = zig_fastcall_ret_f64();
+ assert_or_panic(s == 1);
+ }
}
void __attribute__((vectorcall)) zig_vectorcall_check(int a, float b, double c, void *d, float e, double f, double g, float h, float i, int j);
@@ -5933,3 +16211,18 @@ void __attribute__((vectorcall)) c_vectorcall_check(int a, float b, double c, vo
zig_vectorcall_check(a, b, c, d, e, f, g, h, i, j);
}
#endif
+
+#if defined(__x86_64__) && defined(_WIN64)
+void c_win64_varargs_u64_f64_u64_f64(uint64_t a, double b, uint64_t c, double d) {
+ assert_or_panic(a == UINT64_C(0x3ff0000000000000));
+ assert_or_panic(b == 2.0);
+ assert_or_panic(c == UINT64_C(0x4008000000000000));
+ assert_or_panic(d == 4.0);
+}
+void c_win64_varargs_f64_u64_f64_u64(double a, uint64_t b, double c, uint64_t d) {
+ assert_or_panic(a == 5.0);
+ assert_or_panic(b == UINT64_C(0x4018000000000000));
+ assert_or_panic(c == 7.0);
+ assert_or_panic(d == UINT64_C(0x4020000000000000));
+}
+#endif
diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig
index ff6ecbea9a4bd4a318fa8cbbd6cdcca73528b1ce..1fd570b4ed40b6a50d2085c8d65a32fa941b36fc 100644
--- a/test/c_abi/main.zig
+++ b/test/c_abi/main.zig
@@ -15,16 +15,15 @@ const have_i128 = builtin.cpu.arch != .x86 and !builtin.cpu.arch.isArm() and
builtin.cpu.arch != .hexagon and
builtin.cpu.arch != .s390x; // https://github.com/llvm/llvm-project/issues/168460
-const have_f128 = builtin.cpu.arch.isWasm() or (builtin.cpu.arch.isX86() and !builtin.os.tag.isDarwin());
-const have_f80 = builtin.cpu.arch.isX86();
-
-extern fn run_c_tests() void;
+const have_f128 = builtin.cpu.arch.isWasm() or (builtin.cpu.arch.isX86() and !builtin.os.tag.isDarwin() and builtin.abi != .msvc);
+const have_f80 = builtin.cpu.arch.isX86() and builtin.abi != .msvc;
export fn zig_panic() noreturn {
@panic("zig_panic called from C");
}
-test "C importing Zig ABI Tests" {
+extern fn run_c_tests() void;
+test run_c_tests {
run_c_tests();
}
@@ -50,7 +49,7 @@ export fn zig_five_integers(a: i32, b: i32, c: i32, d: i32, e: i32) void {
expect(e == 90) catch @panic("test failure: zig_five_integers 90");
}
-test "C ABI integers" {
+test "integers" {
if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
c_u8(0xff);
@@ -120,13 +119,13 @@ export fn zig_five_floats(a: f32, b: f32, c: f32, d: f32, e: f32) void {
expect(e == 5.0) catch @panic("test failure: zig_five_floats 5.0");
}
-test "C ABI floats" {
+test "floats" {
c_f32(12.34);
c_f64(56.78);
c_five_floats(1.0, 2.0, 3.0, 4.0, 5.0);
}
-test "C ABI long double" {
+test "long double" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
c_long_double(12.34);
@@ -145,7 +144,7 @@ export fn zig_longdouble(x: c_longdouble) void {
extern fn c_ptr(*anyopaque) void;
-test "C ABI pointer" {
+test "pointer" {
c_ptr(@as(*anyopaque, @ptrFromInt(0xdeadbeef)));
}
@@ -155,7 +154,7 @@ export fn zig_ptr(x: *anyopaque) void {
extern fn c_bool(bool) void;
-test "C ABI bool" {
+test "bool" {
c_bool(true);
}
@@ -190,7 +189,7 @@ const complex_abi_compatible = builtin.cpu.arch != .x86 and !builtin.cpu.arch.is
builtin.cpu.arch != .s390x and
!(builtin.cpu.arch.isLoongArch() and builtin.abi.float() == .soft);
-test "C ABI complex float" {
+test "complex float" {
if (!complex_abi_compatible) return error.SkipZigTest;
const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };
@@ -201,7 +200,7 @@ test "C ABI complex float" {
try expect(z.imag == 13.5);
}
-test "C ABI complex float by component" {
+test "complex float by component" {
if (!complex_abi_compatible) return error.SkipZigTest;
const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };
@@ -212,7 +211,7 @@ test "C ABI complex float by component" {
try expect(z2.imag == 13.5);
}
-test "C ABI complex double" {
+test "complex double" {
if (!complex_abi_compatible) return error.SkipZigTest;
const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };
@@ -223,7 +222,7 @@ test "C ABI complex double" {
try expect(z.imag == 13.5);
}
-test "C ABI complex double by component" {
+test "complex double by component" {
if (!complex_abi_compatible) return error.SkipZigTest;
const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };
@@ -270,3307 +269,107 @@ export fn zig_cmultd_comp(a_r: f64, a_i: f64, b_r: f64, b_i: f64) ComplexDouble
return .{ .real = 1.5, .imag = 13.5 };
}
-const Struct_u8 = extern struct {
- a: u8,
-};
-
-export fn zig_ret_struct_u8() Struct_u8 {
- return .{ .a = 1 };
-}
-
-export fn zig_struct_u8(s: Struct_u8, i: usize) void {
- expect(s.a == 2) catch @panic("test failure");
- expect(i == 3) catch @panic("test failure");
-}
-
-extern fn c_ret_struct_u8() Struct_u8;
-
-extern fn c_struct_u8(Struct_u8, usize) void;
-
-test "C ABI struct u8" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
- if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
-
- const s = c_ret_struct_u8();
- try expect(s.a == 4);
- c_struct_u8(.{ .a = 5 }, 6);
-}
-
-const Struct_u16 = extern struct {
- a: u16,
-};
-
-export fn zig_ret_struct_u16() Struct_u16 {
- return .{ .a = 7 };
-}
-
-export fn zig_struct_u16(s: Struct_u16, i: usize) void {
- expect(s.a == 8) catch @panic("test failure");
- expect(i == 9) catch @panic("test failure");
-}
-
-extern fn c_ret_struct_u16() Struct_u16;
-
-extern fn c_struct_u16(Struct_u16, usize) void;
-
-test "C ABI struct u16" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
- if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
-
- const s = c_ret_struct_u16();
- try expect(s.a == 10);
- c_struct_u16(.{ .a = 11 }, 12);
-}
-
-const Struct_u32 = extern struct {
- a: u32,
-};
-
-export fn zig_ret_struct_u32() Struct_u32 {
- return .{ .a = 13 };
-}
-
-export fn zig_struct_u32(s: Struct_u32, i: usize) void {
- expect(s.a == 14) catch @panic("test failure");
- expect(i == 15) catch @panic("test failure");
-}
-
-extern fn c_ret_struct_u32() Struct_u32;
-
-extern fn c_struct_u32(Struct_u32, usize) void;
-
-test "C ABI struct u32" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
- if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
-
- const s = c_ret_struct_u32();
- try expect(s.a == 16);
- c_struct_u32(.{ .a = 17 }, 18);
-}
-
-const Struct_u64 = extern struct {
- a: u64,
-};
-
-export fn zig_ret_struct_u64() Struct_u64 {
- return .{ .a = 19 };
-}
-
-export fn zig_struct_u64(s: Struct_u64, i: usize) void {
- expect(s.a == 20) catch @panic("test failure");
- expect(i == 21) catch @panic("test failure");
-}
-
-extern fn c_ret_struct_u64() Struct_u64;
-
-extern fn c_struct_u64(Struct_u64, usize) void;
-
-test "C ABI struct u64" {
- if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
- if (builtin.cpu.arch == .riscv32) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
- if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
-
- const s = c_ret_struct_u64();
- try expect(s.a == 22);
- c_struct_u64(.{ .a = 23 }, 24);
-}
-
-const Struct_u64_u64 = extern struct {
- a: u64,
- b: u64,
-};
-
-export fn zig_ret_struct_u64_u64() Struct_u64_u64 {
- return .{ .a = 1, .b = 2 };
-}
-
-export fn zig_struct_u64_u64_0(s: Struct_u64_u64, i: usize) void {
- expect(s.a == 3) catch @panic("test failure");
- expect(s.b == 4) catch @panic("test failure");
- expect(i == 1) catch @panic("test failure");
-}
-export fn zig_struct_u64_u64_1(_: usize, s: Struct_u64_u64, i: usize) void {
- expect(s.a == 5) catch @panic("test failure");
- expect(s.b == 6) catch @panic("test failure");
- expect(i == 2) catch @panic("test failure");
-}
-export fn zig_struct_u64_u64_2(_: usize, _: usize, s: Struct_u64_u64, i: usize) void {
- expect(s.a == 7) catch @panic("test failure");
- expect(s.b == 8) catch @panic("test failure");
- expect(i == 3) catch @panic("test failure");
-}
-export fn zig_struct_u64_u64_3(_: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
- expect(s.a == 9) catch @panic("test failure");
- expect(s.b == 10) catch @panic("test failure");
- expect(i == 4) catch @panic("test failure");
-}
-export fn zig_struct_u64_u64_4(_: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
- expect(s.a == 11) catch @panic("test failure");
- expect(s.b == 12) catch @panic("test failure");
- expect(i == 5) catch @panic("test failure");
-}
-export fn zig_struct_u64_u64_5(_: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
- expect(s.a == 13) catch @panic("test failure");
- expect(s.b == 14) catch @panic("test failure");
- expect(i == 6) catch @panic("test failure");
-}
-export fn zig_struct_u64_u64_6(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
- expect(s.a == 15) catch @panic("test failure");
- expect(s.b == 16) catch @panic("test failure");
- expect(i == 7) catch @panic("test failure");
-}
-export fn zig_struct_u64_u64_7(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
- expect(s.a == 17) catch @panic("test failure");
- expect(s.b == 18) catch @panic("test failure");
- expect(i == 8) catch @panic("test failure");
-}
-export fn zig_struct_u64_u64_8(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
- expect(s.a == 19) catch @panic("test failure");
- expect(s.b == 20) catch @panic("test failure");
- expect(i == 9) catch @panic("test failure");
-}
-
-extern fn c_ret_struct_u64_u64() Struct_u64_u64;
-
-extern fn c_struct_u64_u64_0(Struct_u64_u64, usize) void;
-extern fn c_struct_u64_u64_1(usize, Struct_u64_u64, usize) void;
-extern fn c_struct_u64_u64_2(usize, usize, Struct_u64_u64, usize) void;
-extern fn c_struct_u64_u64_3(usize, usize, usize, Struct_u64_u64, usize) void;
-extern fn c_struct_u64_u64_4(usize, usize, usize, usize, Struct_u64_u64, usize) void;
-extern fn c_struct_u64_u64_5(usize, usize, usize, usize, usize, Struct_u64_u64, usize) void;
-extern fn c_struct_u64_u64_6(usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void;
-extern fn c_struct_u64_u64_7(usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void;
-extern fn c_struct_u64_u64_8(usize, usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void;
-
-test "C ABI struct u64, u64" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- const s = c_ret_struct_u64_u64();
- try expect(s.a == 21);
- try expect(s.b == 22);
- c_struct_u64_u64_0(.{ .a = 23, .b = 24 }, 1);
- c_struct_u64_u64_1(0, .{ .a = 25, .b = 26 }, 2);
- c_struct_u64_u64_2(0, 1, .{ .a = 27, .b = 28 }, 3);
- c_struct_u64_u64_3(0, 1, 2, .{ .a = 29, .b = 30 }, 4);
- c_struct_u64_u64_4(0, 1, 2, 3, .{ .a = 31, .b = 32 }, 5);
- c_struct_u64_u64_5(0, 1, 2, 3, 4, .{ .a = 33, .b = 34 }, 6);
- c_struct_u64_u64_6(0, 1, 2, 3, 4, 5, .{ .a = 35, .b = 36 }, 7);
- c_struct_u64_u64_7(0, 1, 2, 3, 4, 5, 6, .{ .a = 37, .b = 38 }, 8);
- c_struct_u64_u64_8(0, 1, 2, 3, 4, 5, 6, 7, .{ .a = 39, .b = 40 }, 9);
-}
-
-const Struct_f32 = extern struct {
- a: f32,
-};
-
-export fn zig_ret_struct_f32() Struct_f32 {
- return .{ .a = 2.5 };
-}
-
-export fn zig_struct_f32(s: Struct_f32) void {
- expect(s.a == 2.5) catch @panic("test failure");
-}
-
-extern fn c_ret_struct_f32() Struct_f32;
-
-extern fn c_struct_f32(Struct_f32) void;
-
-test "C ABI struct f32" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
- if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
-
- const s = c_ret_struct_f32();
- try expect(s.a == 2.5);
- c_struct_f32(.{ .a = 2.5 });
-}
-
-const Struct_f64 = extern struct {
- a: f64,
-};
-
-export fn zig_ret_struct_f64() Struct_f64 {
- return .{ .a = 2.5 };
-}
-
-export fn zig_struct_f64(s: Struct_f64) void {
- expect(s.a == 2.5) catch @panic("test failure");
-}
-
-extern fn c_ret_struct_f64() Struct_f64;
-
-extern fn c_struct_f64(Struct_f64) void;
-
-test "C ABI struct f64" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
- if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
- if (builtin.cpu.arch == .riscv32) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
- if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
-
- const s = c_ret_struct_f64();
- try expect(s.a == 2.5);
- c_struct_f64(.{ .a = 2.5 });
-}
-
-const Struct_f32a8 = extern struct {
- a: f32 align(8),
-};
-
-export fn zig_ret_struct_f32a8() Struct_f32a8 {
- return .{ .a = 1.25 };
-}
-
-export fn zig_struct_f32a8(s: Struct_f32a8, f: f32) void {
- expect(s.a == 2.75) catch @panic("test failure");
- expect(f == 3.5) catch @panic("test failure");
-}
-
-extern fn c_ret_struct_f32a8() Struct_f32a8;
-
-extern fn c_struct_f32a8(Struct_f32a8, f32) void;
-
-test "C ABI struct f32 align(8)" {
- if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
- if (builtin.cpu.arch == .riscv32) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
- if (builtin.cpu.arch == .x86) return error.SkipZigTest;
-
- const s = c_ret_struct_f32a8();
- try expect(s.a == 4.125);
- c_struct_f32a8(.{ .a = 5.375 }, 6.5);
-}
-
-const Struct_f32a8_f32a8 = extern struct {
- a: f32 align(8),
- b: f32 align(8),
-};
-
-export fn zig_ret_struct_f32a8_f32a8() Struct_f32a8_f32a8 {
- return .{ .a = 1.25, .b = 2.75 };
-}
-
-export fn zig_struct_f32a8_f32a8(s: Struct_f32a8_f32a8, f: f32) void {
- expect(s.a == 3.125) catch @panic("test failure");
- expect(s.b == 4.375) catch @panic("test failure");
- expect(f == 5.5) catch @panic("test failure");
-}
-
-extern fn c_ret_struct_f32a8_f32a8() Struct_f32a8_f32a8;
-
-extern fn c_struct_f32a8_f32a8(Struct_f32a8_f32a8, f32) void;
-
-test "C ABI struct f32 align(8), f32 align(8)" {
- if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
- if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
- if (builtin.cpu.arch == .x86) return error.SkipZigTest;
-
- const s = c_ret_struct_f32a8_f32a8();
- try expect(s.a == 6.625);
- try expect(s.b == 7.875);
- c_struct_f32a8_f32a8(.{ .a = 8.0625, .b = 9.1875 }, 10.5);
-}
-
-const Struct_f32f32_f32 = extern struct {
- a: extern struct { b: f32, c: f32 },
- d: f32,
-};
-
-export fn zig_ret_struct_f32f32_f32() Struct_f32f32_f32 {
- return .{ .a = .{ .b = 1.0, .c = 2.0 }, .d = 3.0 };
-}
-
-export fn zig_struct_f32f32_f32(s: Struct_f32f32_f32) void {
- expect(s.a.b == 1.0) catch @panic("test failure");
- expect(s.a.c == 2.0) catch @panic("test failure");
- expect(s.d == 3.0) catch @panic("test failure");
-}
-
-extern fn c_ret_struct_f32f32_f32() Struct_f32f32_f32;
-
-extern fn c_struct_f32f32_f32(Struct_f32f32_f32) void;
-
-test "C ABI struct {f32, f32}, f32" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
- if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- const s = c_ret_struct_f32f32_f32();
- try expect(s.a.b == 1.0);
- try expect(s.a.c == 2.0);
- try expect(s.d == 3.0);
- c_struct_f32f32_f32(.{ .a = .{ .b = 1.0, .c = 2.0 }, .d = 3.0 });
-}
-
-const Struct_f32_f32f32 = extern struct {
- a: f32,
- b: extern struct { c: f32, d: f32 },
-};
-
-export fn zig_ret_struct_f32_f32f32() Struct_f32_f32f32 {
- return .{ .a = 1.0, .b = .{ .c = 2.0, .d = 3.0 } };
-}
-
-export fn zig_struct_f32_f32f32(s: Struct_f32_f32f32) void {
- expect(s.a == 1.0) catch @panic("test failure");
- expect(s.b.c == 2.0) catch @panic("test failure");
- expect(s.b.d == 3.0) catch @panic("test failure");
-}
-
-extern fn c_ret_struct_f32_f32f32() Struct_f32_f32f32;
-
-extern fn c_struct_f32_f32f32(Struct_f32_f32f32) void;
-
-test "C ABI struct f32 {f32,f32}" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
- if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- const s = c_ret_struct_f32_f32f32();
- try expect(s.a == 1.0);
- try expect(s.b.c == 2.0);
- try expect(s.b.d == 3.0);
- c_struct_f32_f32f32(.{ .a = 1.0, .b = .{ .c = 2.0, .d = 3.0 } });
-}
-
-const Struct_u32_Union_u32_u32u32 = extern struct {
- a: u32,
- b: extern union {
- c: extern struct {
- d: u32,
- e: u32,
- },
- },
-};
-
-export fn zig_ret_struct_u32_union_u32_u32u32() Struct_u32_Union_u32_u32u32 {
- return .{ .a = 1, .b = .{ .c = .{ .d = 2, .e = 3 } } };
-}
-
-export fn zig_struct_u32_union_u32_u32u32(s: Struct_u32_Union_u32_u32u32) void {
- expect(s.a == 1) catch @panic("test failure");
- expect(s.b.c.d == 2) catch @panic("test failure");
- expect(s.b.c.e == 3) catch @panic("test failure");
-}
-
-extern fn c_ret_struct_u32_union_u32_u32u32() Struct_u32_Union_u32_u32u32;
-
-extern fn c_struct_u32_union_u32_u32u32(Struct_u32_Union_u32_u32u32) void;
-
-test "C ABI struct{u32,union{u32,struct{u32,u32}}}" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- const s = c_ret_struct_u32_union_u32_u32u32();
- try expect(s.a == 1);
- try expect(s.b.c.d == 2);
- try expect(s.b.c.e == 3);
- c_struct_u32_union_u32_u32u32(.{ .a = 1, .b = .{ .c = .{ .d = 2, .e = 3 } } });
-}
-
-const Struct_i32_i32 = extern struct {
- a: i32,
- b: i32,
-};
-extern fn c_mut_struct_i32_i32(Struct_i32_i32) Struct_i32_i32;
-extern fn c_struct_i32_i32(Struct_i32_i32) void;
-
-test "C ABI struct i32 i32" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
- if (builtin.cpu.arch == .riscv32) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
- if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
-
- const s: Struct_i32_i32 = .{
- .a = 1,
- .b = 2,
- };
- const mut_res = c_mut_struct_i32_i32(s);
- try expect(s.a == 1);
- try expect(s.b == 2);
- try expect(mut_res.a == 101);
- try expect(mut_res.b == 252);
- c_struct_i32_i32(s);
-}
-
-export fn zig_struct_i32_i32(s: Struct_i32_i32) void {
- expect(s.a == 1) catch @panic("test failure: zig_struct_i32_i32 1");
- expect(s.b == 2) catch @panic("test failure: zig_struct_i32_i32 2");
-}
-
-const BigStruct = extern struct {
- a: u64,
- b: u64,
- c: u64,
- d: u64,
- e: u8,
-};
-extern fn c_big_struct(BigStruct) void;
-
-test "C ABI big struct" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- const s = BigStruct{
- .a = 1,
- .b = 2,
- .c = 3,
- .d = 4,
- .e = 5,
- };
- c_big_struct(s);
-}
-
-export fn zig_big_struct(x: BigStruct) void {
- expect(x.a == 1) catch @panic("test failure: zig_big_struct 1");
- expect(x.b == 2) catch @panic("test failure: zig_big_struct 2");
- expect(x.c == 3) catch @panic("test failure: zig_big_struct 3");
- expect(x.d == 4) catch @panic("test failure: zig_big_struct 4");
- expect(x.e == 5) catch @panic("test failure: zig_big_struct 5");
-}
-
-const BigUnion = extern union {
- a: BigStruct,
-};
-extern fn c_big_union(BigUnion) void;
-
-test "C ABI big union" {
- if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- const x = BigUnion{
- .a = BigStruct{
- .a = 1,
- .b = 2,
- .c = 3,
- .d = 4,
- .e = 5,
- },
- };
- c_big_union(x);
-}
-
-export fn zig_big_union(x: BigUnion) void {
- expect(x.a.a == 1) catch @panic("test failure: zig_big_union a");
- expect(x.a.b == 2) catch @panic("test failure: zig_big_union b");
- expect(x.a.c == 3) catch @panic("test failure: zig_big_union c");
- expect(x.a.d == 4) catch @panic("test failure: zig_big_union d");
- expect(x.a.e == 5) catch @panic("test failure: zig_big_union e");
-}
-
-const MedStructMixed = extern struct {
- a: u32,
- b: f32,
- c: f32,
- d: u32 = 0,
-};
-extern fn c_med_struct_mixed(MedStructMixed) void;
-extern fn c_ret_med_struct_mixed() MedStructMixed;
-
-test "C ABI medium struct of ints and floats" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- const s = MedStructMixed{
- .a = 1234,
- .b = 100.0,
- .c = 1337.0,
- };
- c_med_struct_mixed(s);
- const s2 = c_ret_med_struct_mixed();
- try expect(s2.a == 1234);
- try expect(s2.b == 100.0);
- try expect(s2.c == 1337.0);
-}
-
-export fn zig_med_struct_mixed(x: MedStructMixed) void {
- expect(x.a == 1234) catch @panic("test failure");
- expect(x.b == 100.0) catch @panic("test failure");
- expect(x.c == 1337.0) catch @panic("test failure");
-}
-
-const SmallStructInts = extern struct {
- a: u8,
- b: u8,
- c: u8,
- d: u8,
-};
-extern fn c_small_struct_ints(SmallStructInts) void;
-extern fn c_ret_small_struct_ints() SmallStructInts;
-
-test "C ABI small struct of ints" {
- if (builtin.cpu.arch == .x86) return error.SkipZigTest;
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- const s = SmallStructInts{
- .a = 1,
- .b = 2,
- .c = 3,
- .d = 4,
- };
- c_small_struct_ints(s);
- const s2 = c_ret_small_struct_ints();
- try expect(s2.a == 1);
- try expect(s2.b == 2);
- try expect(s2.c == 3);
- try expect(s2.d == 4);
-}
-
-export fn zig_small_struct_ints(x: SmallStructInts) void {
- expect(x.a == 1) catch @panic("test failure");
- expect(x.b == 2) catch @panic("test failure");
- expect(x.c == 3) catch @panic("test failure");
- expect(x.d == 4) catch @panic("test failure");
-}
-
-const MedStructInts = extern struct {
- x: i32,
- y: i32,
- z: i32,
-};
-extern fn c_med_struct_ints(MedStructInts) void;
-extern fn c_ret_med_struct_ints() MedStructInts;
-
-test "C ABI medium struct of ints" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- const s = MedStructInts{
- .x = 1,
- .y = 2,
- .z = 3,
- };
- c_med_struct_ints(s);
- const s2 = c_ret_med_struct_ints();
- try expect(s2.x == 1);
- try expect(s2.y == 2);
- try expect(s2.z == 3);
-}
-
-export fn zig_med_struct_ints(s: MedStructInts) void {
- expect(s.x == 1) catch @panic("test failure");
- expect(s.y == 2) catch @panic("test failure");
- expect(s.z == 3) catch @panic("test failure");
-}
-
-const SmallPackedStruct = packed struct(u8) {
- a: u2,
- b: u2,
- c: u2,
- d: u2,
-};
-extern fn c_small_packed_struct(SmallPackedStruct) void;
-extern fn c_ret_small_packed_struct() SmallPackedStruct;
-
-export fn zig_small_packed_struct(x: SmallPackedStruct) void {
- expect(x.a == 0) catch @panic("test failure");
- expect(x.b == 1) catch @panic("test failure");
- expect(x.c == 2) catch @panic("test failure");
- expect(x.d == 3) catch @panic("test failure");
-}
-
-test "C ABI small packed struct" {
- const s = SmallPackedStruct{ .a = 0, .b = 1, .c = 2, .d = 3 };
- c_small_packed_struct(s);
- const s2 = c_ret_small_packed_struct();
- try expect(s2.a == 0);
- try expect(s2.b == 1);
- try expect(s2.c == 2);
- try expect(s2.d == 3);
-}
-
-const BigPackedStruct = packed struct(u128) {
- a: u64,
- b: u64,
-};
-extern fn c_big_packed_struct(BigPackedStruct) void;
-extern fn c_ret_big_packed_struct() BigPackedStruct;
-
-export fn zig_big_packed_struct(x: BigPackedStruct) void {
- expect(x.a == 1) catch @panic("test failure");
- expect(x.b == 2) catch @panic("test failure");
-}
-
-test "C ABI big packed struct" {
- if (!have_i128) return error.SkipZigTest;
-
- const s = BigPackedStruct{ .a = 1, .b = 2 };
- c_big_packed_struct(s);
- const s2 = c_ret_big_packed_struct();
- try expect(s2.a == 1);
- try expect(s2.b == 2);
-}
-
-const SplitStructInt = extern struct {
- a: u64,
- b: u8,
- c: u32,
-};
-extern fn c_split_struct_ints(SplitStructInt) void;
-
-test "C ABI split struct of ints" {
- if (builtin.cpu.arch == .x86) return error.SkipZigTest;
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- const s = SplitStructInt{
- .a = 1234,
- .b = 100,
- .c = 1337,
- };
- c_split_struct_ints(s);
-}
-
-export fn zig_split_struct_ints(x: SplitStructInt) void {
- expect(x.a == 1234) catch @panic("test failure");
- expect(x.b == 100) catch @panic("test failure");
- expect(x.c == 1337) catch @panic("test failure");
-}
-
-const SplitStructMixed = extern struct {
- a: u64,
- b: u8,
- c: f32,
-};
-extern fn c_split_struct_mixed(SplitStructMixed) void;
-extern fn c_ret_split_struct_mixed() SplitStructMixed;
-
-test "C ABI split struct of ints and floats" {
- if (builtin.cpu.arch == .x86) return error.SkipZigTest;
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- const s = SplitStructMixed{
- .a = 1234,
- .b = 100,
- .c = 1337.0,
- };
- c_split_struct_mixed(s);
- const s2 = c_ret_split_struct_mixed();
- try expect(s2.a == 1234);
- try expect(s2.b == 100);
- try expect(s2.c == 1337.0);
-}
-
-export fn zig_split_struct_mixed(x: SplitStructMixed) void {
- expect(x.a == 1234) catch @panic("test failure");
- expect(x.b == 100) catch @panic("test failure");
- expect(x.c == 1337.0) catch @panic("test failure");
-}
-
-extern fn c_big_struct_both(BigStruct) BigStruct;
-
-extern fn c_multiple_struct_ints(Rect, Rect) void;
-extern fn c_multiple_struct_floats(FloatRect, FloatRect) void;
-
-test "C ABI sret and byval together" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- const s = BigStruct{
- .a = 1,
- .b = 2,
- .c = 3,
- .d = 4,
- .e = 5,
- };
- const y = c_big_struct_both(s);
- try expect(y.a == 10);
- try expect(y.b == 11);
- try expect(y.c == 12);
- try expect(y.d == 13);
- try expect(y.e == 14);
-}
-
-export fn zig_big_struct_both(x: BigStruct) BigStruct {
- expect(x.a == 30) catch @panic("test failure");
- expect(x.b == 31) catch @panic("test failure");
- expect(x.c == 32) catch @panic("test failure");
- expect(x.d == 33) catch @panic("test failure");
- expect(x.e == 34) catch @panic("test failure");
- const s = BigStruct{
- .a = 20,
- .b = 21,
- .c = 22,
- .d = 23,
- .e = 24,
- };
- return s;
-}
-
-const Vector3 = extern struct {
- x: f32,
- y: f32,
- z: f32,
-};
-extern fn c_small_struct_floats(Vector3) void;
-extern fn c_small_struct_floats_extra(Vector3, ?[*]const u8) void;
-
-const Vector5 = extern struct {
- x: f32,
- y: f32,
- z: f32,
- w: f32,
- q: f32,
-};
-extern fn c_big_struct_floats(Vector5) void;
-
-test "C ABI structs of floats as parameter" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- const v3 = Vector3{
- .x = 3.0,
- .y = 6.0,
- .z = 12.0,
- };
- c_small_struct_floats(v3);
- c_small_struct_floats_extra(v3, "hello");
-
- const v5 = Vector5{
- .x = 76.0,
- .y = -1.0,
- .z = -12.0,
- .w = 69.0,
- .q = 55,
- };
- c_big_struct_floats(v5);
-}
-
-const Rect = extern struct {
- left: u32,
- right: u32,
- top: u32,
- bottom: u32,
-};
-
-export fn zig_multiple_struct_ints(x: Rect, y: Rect) void {
- expect(x.left == 1) catch @panic("test failure");
- expect(x.right == 21) catch @panic("test failure");
- expect(x.top == 16) catch @panic("test failure");
- expect(x.bottom == 4) catch @panic("test failure");
- expect(y.left == 178) catch @panic("test failure");
- expect(y.right == 189) catch @panic("test failure");
- expect(y.top == 21) catch @panic("test failure");
- expect(y.bottom == 15) catch @panic("test failure");
-}
-
-test "C ABI structs of ints as multiple parameters" {
- if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- const r1 = Rect{
- .left = 1,
- .right = 21,
- .top = 16,
- .bottom = 4,
- };
- const r2 = Rect{
- .left = 178,
- .right = 189,
- .top = 21,
- .bottom = 15,
- };
- c_multiple_struct_ints(r1, r2);
-}
-
-const FloatRect = extern struct {
- left: f32,
- right: f32,
- top: f32,
- bottom: f32,
-};
-
-export fn zig_multiple_struct_floats(x: FloatRect, y: FloatRect) void {
- expect(x.left == 1) catch @panic("test failure");
- expect(x.right == 21) catch @panic("test failure");
- expect(x.top == 16) catch @panic("test failure");
- expect(x.bottom == 4) catch @panic("test failure");
- expect(y.left == 178) catch @panic("test failure");
- expect(y.right == 189) catch @panic("test failure");
- expect(y.top == 21) catch @panic("test failure");
- expect(y.bottom == 15) catch @panic("test failure");
-}
-
-test "C ABI structs of floats as multiple parameters" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- const r1 = FloatRect{
- .left = 1,
- .right = 21,
- .top = 16,
- .bottom = 4,
- };
- const r2 = FloatRect{
- .left = 178,
- .right = 189,
- .top = 21,
- .bottom = 15,
- };
- c_multiple_struct_floats(r1, r2);
-}
-
-export fn zig_ret_bool() bool {
- return true;
-}
-export fn zig_ret_u8() u8 {
- return 0xff;
-}
-export fn zig_ret_u16() u16 {
- return 0xffff;
-}
-export fn zig_ret_u32() u32 {
- return 0xffffffff;
-}
-export fn zig_ret_u64() u64 {
- return 0xffffffffffffffff;
-}
-export fn zig_ret_i8() i8 {
- return -1;
-}
-export fn zig_ret_i16() i16 {
- return -1;
-}
-export fn zig_ret_i32() i32 {
- return -1;
-}
-export fn zig_ret_i64() i64 {
- return -1;
-}
-
-export fn zig_ret_small_struct_ints() SmallStructInts {
- return .{
- .a = 1,
- .b = 2,
- .c = 3,
- .d = 4,
- };
-}
-
-export fn zig_ret_med_struct_ints() MedStructInts {
- return .{
- .x = 1,
- .y = 2,
- .z = 3,
- };
-}
-
-export fn zig_ret_med_struct_mixed() MedStructMixed {
- return .{
- .a = 1234,
- .b = 100.0,
- .c = 1337.0,
- };
-}
-
-export fn zig_ret_split_struct_mixed() SplitStructMixed {
- return .{
- .a = 1234,
- .b = 100,
- .c = 1337.0,
- };
-}
-
-extern fn c_ret_bool() bool;
-extern fn c_ret_u8() u8;
-extern fn c_ret_u16() u16;
-extern fn c_ret_u32() u32;
-extern fn c_ret_u64() u64;
-extern fn c_ret_i8() i8;
-extern fn c_ret_i16() i16;
-extern fn c_ret_i32() i32;
-extern fn c_ret_i64() i64;
-
-test "C ABI integer return types" {
- try expect(c_ret_bool() == true);
-
- try expect(c_ret_u8() == 0xff);
- try expect(c_ret_u16() == 0xffff);
- try expect(c_ret_u32() == 0xffffffff);
- try expect(c_ret_u64() == 0xffffffffffffffff);
-
- try expect(c_ret_i8() == -1);
- try expect(c_ret_i16() == -1);
- try expect(c_ret_i32() == -1);
- try expect(c_ret_i64() == -1);
-}
-
-const StructWithArray = extern struct {
- a: i32,
- padding: [4]u8,
- b: i64,
-};
-extern fn c_struct_with_array(StructWithArray) void;
-extern fn c_ret_struct_with_array() StructWithArray;
-
-test "Struct with array as padding." {
- if (builtin.cpu.arch == .x86) return error.SkipZigTest;
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- c_struct_with_array(.{ .a = 1, .padding = undefined, .b = 2 });
-
- const x = c_ret_struct_with_array();
- try expect(x.a == 4);
- try expect(x.b == 155);
-}
-
-const FloatArrayStruct = extern struct {
- origin: extern struct {
- x: f64,
- y: f64,
- },
- size: extern struct {
- width: f64,
- height: f64,
- },
-};
-
-extern fn c_float_array_struct(FloatArrayStruct) void;
-extern fn c_ret_float_array_struct() FloatArrayStruct;
-
-test "Float array like struct" {
- if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- c_float_array_struct(.{
- .origin = .{
- .x = 5,
- .y = 6,
- },
- .size = .{
- .width = 7,
- .height = 8,
- },
- });
-
- const x = c_ret_float_array_struct();
- try expect(x.origin.x == 1);
- try expect(x.origin.y == 2);
- try expect(x.size.width == 3);
- try expect(x.size.height == 4);
-}
-
-const SmallVec = @Vector(2, u32);
-
-extern fn c_small_vec(SmallVec) void;
-extern fn c_ret_small_vec() SmallVec;
-
-test "small simd vector" {
- if (builtin.cpu.arch == .x86) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- c_small_vec(.{ 1, 2 });
-
- const x = c_ret_small_vec();
- try expect(x[0] == 3);
- try expect(x[1] == 4);
-}
-
-const MediumVec = @Vector(4, usize);
-
-extern fn c_medium_vec(MediumVec) void;
-extern fn c_ret_medium_vec() MediumVec;
-
-test "medium simd vector" {
- if (builtin.zig_backend == .stage2_x86_64 and !comptime builtin.cpu.has(.x86, .avx)) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- c_medium_vec(.{ 1, 2, 3, 4 });
-
- const x = c_ret_medium_vec();
- try expect(x[0] == 5);
- try expect(x[1] == 6);
- try expect(x[2] == 7);
- try expect(x[3] == 8);
-}
-
-const BigVec = @Vector(8, usize);
-
-extern fn c_big_vec(BigVec) void;
-extern fn c_ret_big_vec() BigVec;
-
-test "big simd vector" {
- if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
-
- if (builtin.cpu.arch.isMIPS64() and builtin.mode != .Debug) return error.SkipZigTest;
- if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag.isDarwin() and builtin.mode != .Debug) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- c_big_vec(.{ 1, 2, 3, 4, 5, 6, 7, 8 });
-
- const x = c_ret_big_vec();
- try expect(x[0] == 9);
- try expect(x[1] == 10);
- try expect(x[2] == 11);
- try expect(x[3] == 12);
- try expect(x[4] == 13);
- try expect(x[5] == 14);
- try expect(x[6] == 15);
- try expect(x[7] == 16);
-}
-
-const Vector2Float = @Vector(2, f32);
-const Vector4Float = @Vector(4, f32);
-
-extern fn c_vector_2_float(Vector2Float) void;
-extern fn c_vector_4_float(Vector4Float) void;
-
-extern fn c_ret_vector_2_float() Vector2Float;
-extern fn c_ret_vector_4_float() Vector4Float;
-
-test "float simd vectors" {
- if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
- if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-
- {
- c_vector_2_float(.{ 1.0, 2.0 });
- const vec = c_ret_vector_2_float();
- try expect(vec[0] == 1.0);
- try expect(vec[1] == 2.0);
- }
- {
- c_vector_4_float(.{ 1.0, 2.0, 3.0, 4.0 });
- const vec = c_ret_vector_4_float();
- try expect(vec[0] == 1.0);
- try expect(vec[1] == 2.0);
- try expect(vec[2] == 3.0);
- try expect(vec[3] == 4.0);
- }
-}
-
-const Vector2Bool = @Vector(2, bool);
-const Vector4Bool = @Vector(4, bool);
-const Vector8Bool = @Vector(8, bool);
-const Vector16Bool = @Vector(16, bool);
-const Vector32Bool = @Vector(32, bool);
-const Vector64Bool = @Vector(64, bool);
-const Vector128Bool = @Vector(128, bool);
-const Vector256Bool = @Vector(256, bool);
-const Vector512Bool = @Vector(512, bool);
-
-extern fn c_vector_2_bool(Vector2Bool) void;
-extern fn c_vector_4_bool(Vector4Bool) void;
-extern fn c_vector_8_bool(Vector8Bool) void;
-extern fn c_vector_16_bool(Vector16Bool) void;
-extern fn c_vector_32_bool(Vector32Bool) void;
-extern fn c_vector_64_bool(Vector64Bool) void;
-extern fn c_vector_128_bool(Vector128Bool) void;
-extern fn c_vector_256_bool(Vector256Bool) void;
-extern fn c_vector_512_bool(Vector512Bool) void;
-
-extern fn c_ret_vector_2_bool() Vector2Bool;
-extern fn c_ret_vector_4_bool() Vector4Bool;
-extern fn c_ret_vector_8_bool() Vector8Bool;
-extern fn c_ret_vector_16_bool() Vector16Bool;
-extern fn c_ret_vector_32_bool() Vector32Bool;
-extern fn c_ret_vector_64_bool() Vector64Bool;
-extern fn c_ret_vector_128_bool() Vector128Bool;
-extern fn c_ret_vector_256_bool() Vector256Bool;
-extern fn c_ret_vector_512_bool() Vector512Bool;
-
-test "bool simd vector" {
- if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
-
- {
- c_vector_2_bool(.{
- true,
- true,
- });
-
- const vec = c_ret_vector_2_bool();
- try expect(vec[0] == true);
- try expect(vec[1] == false);
- }
- {
- c_vector_4_bool(.{
- true,
- true,
- false,
- true,
- });
-
- const vec = c_ret_vector_4_bool();
- try expect(vec[0] == true);
- try expect(vec[1] == false);
- try expect(vec[2] == true);
- try expect(vec[3] == false);
- }
- {
- c_vector_8_bool(.{
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- });
-
- const vec = c_ret_vector_8_bool();
- try expect(vec[0] == false);
- try expect(vec[1] == true);
- try expect(vec[2] == false);
- try expect(vec[3] == false);
- try expect(vec[4] == true);
- try expect(vec[5] == false);
- try expect(vec[6] == false);
- try expect(vec[7] == true);
- }
- {
- c_vector_16_bool(.{
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- });
-
- const vec = c_ret_vector_16_bool();
- try expect(vec[0] == true);
- try expect(vec[1] == true);
- try expect(vec[2] == false);
- try expect(vec[3] == false);
- try expect(vec[4] == false);
- try expect(vec[5] == false);
- try expect(vec[6] == true);
- try expect(vec[7] == false);
- try expect(vec[8] == true);
- try expect(vec[9] == false);
- try expect(vec[10] == false);
- try expect(vec[11] == true);
- try expect(vec[12] == true);
- try expect(vec[13] == false);
- try expect(vec[14] == true);
- try expect(vec[15] == true);
- }
- {
- c_vector_32_bool(.{
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- });
-
- const vec = c_ret_vector_32_bool();
- try expect(vec[0] == true);
- try expect(vec[1] == false);
- try expect(vec[2] == true);
- try expect(vec[3] == true);
- try expect(vec[4] == true);
- try expect(vec[5] == false);
- try expect(vec[6] == true);
- try expect(vec[7] == false);
- try expect(vec[8] == true);
- try expect(vec[9] == true);
- try expect(vec[10] == true);
- try expect(vec[11] == false);
- try expect(vec[12] == true);
- try expect(vec[13] == true);
- try expect(vec[14] == false);
- try expect(vec[15] == false);
- try expect(vec[16] == true);
- try expect(vec[17] == false);
- try expect(vec[18] == false);
- try expect(vec[19] == false);
- try expect(vec[20] == false);
- try expect(vec[21] == true);
- try expect(vec[22] == true);
- try expect(vec[23] == true);
- try expect(vec[24] == false);
- try expect(vec[25] == true);
- try expect(vec[26] == false);
- try expect(vec[27] == false);
- try expect(vec[28] == true);
- try expect(vec[29] == false);
- try expect(vec[30] == false);
- try expect(vec[31] == false);
- }
- {
- c_vector_64_bool(.{
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- });
-
- const vec = c_ret_vector_64_bool();
- try expect(vec[0] == false);
- try expect(vec[1] == true);
- try expect(vec[2] == false);
- try expect(vec[3] == true);
- try expect(vec[4] == true);
- try expect(vec[5] == true);
- try expect(vec[6] == false);
- try expect(vec[7] == true);
- try expect(vec[8] == true);
- try expect(vec[9] == true);
- try expect(vec[10] == true);
- try expect(vec[11] == true);
- try expect(vec[12] == true);
- try expect(vec[13] == false);
- try expect(vec[14] == true);
- try expect(vec[15] == true);
- try expect(vec[16] == true);
- try expect(vec[17] == false);
- try expect(vec[18] == false);
- try expect(vec[19] == false);
- try expect(vec[20] == true);
- try expect(vec[21] == true);
- try expect(vec[22] == false);
- try expect(vec[23] == true);
- try expect(vec[24] == false);
- try expect(vec[25] == true);
- try expect(vec[26] == false);
- try expect(vec[27] == true);
- try expect(vec[28] == false);
- try expect(vec[29] == true);
- try expect(vec[30] == false);
- try expect(vec[31] == true);
- try expect(vec[32] == false);
- try expect(vec[33] == false);
- try expect(vec[34] == true);
- try expect(vec[35] == true);
- try expect(vec[36] == false);
- try expect(vec[37] == false);
- try expect(vec[38] == false);
- try expect(vec[39] == true);
- try expect(vec[40] == true);
- try expect(vec[41] == true);
- try expect(vec[42] == true);
- try expect(vec[43] == false);
- try expect(vec[44] == false);
- try expect(vec[45] == false);
- try expect(vec[46] == true);
- try expect(vec[47] == true);
- try expect(vec[48] == false);
- try expect(vec[49] == false);
- try expect(vec[50] == true);
- try expect(vec[51] == false);
- try expect(vec[52] == false);
- try expect(vec[53] == false);
- try expect(vec[54] == false);
- try expect(vec[55] == true);
- try expect(vec[56] == false);
- try expect(vec[57] == false);
- try expect(vec[58] == false);
- try expect(vec[59] == true);
- try expect(vec[60] == true);
- try expect(vec[61] == true);
- try expect(vec[62] == true);
- try expect(vec[63] == true);
- }
- {
- c_vector_128_bool(.{
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- });
-
- const vec = c_ret_vector_128_bool();
- try expect(vec[0] == false);
- try expect(vec[1] == true);
- try expect(vec[2] == true);
- try expect(vec[3] == false);
- try expect(vec[4] == true);
- try expect(vec[5] == false);
- try expect(vec[6] == false);
- try expect(vec[7] == true);
- try expect(vec[8] == true);
- try expect(vec[9] == false);
- try expect(vec[10] == true);
- try expect(vec[11] == false);
- try expect(vec[12] == false);
- try expect(vec[13] == false);
- try expect(vec[14] == true);
- try expect(vec[15] == false);
- try expect(vec[16] == true);
- try expect(vec[17] == false);
- try expect(vec[18] == false);
- try expect(vec[19] == true);
- try expect(vec[20] == false);
- try expect(vec[21] == true);
- try expect(vec[22] == false);
- try expect(vec[23] == false);
- try expect(vec[24] == false);
- try expect(vec[25] == true);
- try expect(vec[26] == true);
- try expect(vec[27] == true);
- try expect(vec[28] == false);
- try expect(vec[29] == false);
- try expect(vec[30] == false);
- try expect(vec[31] == false);
- try expect(vec[32] == true);
- try expect(vec[33] == true);
- try expect(vec[34] == true);
- try expect(vec[35] == false);
- try expect(vec[36] == true);
- try expect(vec[37] == true);
- try expect(vec[38] == false);
- try expect(vec[39] == false);
- try expect(vec[40] == false);
- try expect(vec[41] == false);
- try expect(vec[42] == true);
- try expect(vec[43] == true);
- try expect(vec[44] == true);
- try expect(vec[45] == false);
- try expect(vec[46] == false);
- try expect(vec[47] == false);
- try expect(vec[48] == false);
- try expect(vec[49] == true);
- try expect(vec[50] == false);
- try expect(vec[51] == false);
- try expect(vec[52] == true);
- try expect(vec[53] == false);
- try expect(vec[54] == false);
- try expect(vec[55] == false);
- try expect(vec[56] == false);
- try expect(vec[57] == false);
- try expect(vec[58] == true);
- try expect(vec[59] == true);
- try expect(vec[60] == true);
- try expect(vec[61] == false);
- try expect(vec[62] == true);
- try expect(vec[63] == true);
- try expect(vec[64] == false);
- try expect(vec[65] == false);
- try expect(vec[66] == false);
- try expect(vec[67] == false);
- try expect(vec[68] == false);
- try expect(vec[69] == false);
- try expect(vec[70] == false);
- try expect(vec[71] == false);
- try expect(vec[72] == true);
- try expect(vec[73] == true);
- try expect(vec[74] == true);
- try expect(vec[75] == true);
- try expect(vec[76] == true);
- try expect(vec[77] == false);
- try expect(vec[78] == false);
- try expect(vec[79] == false);
- try expect(vec[80] == false);
- try expect(vec[81] == false);
- try expect(vec[82] == false);
- try expect(vec[83] == true);
- try expect(vec[84] == false);
- try expect(vec[85] == true);
- try expect(vec[86] == false);
- try expect(vec[87] == true);
- try expect(vec[88] == false);
- try expect(vec[89] == true);
- try expect(vec[90] == false);
- try expect(vec[91] == true);
- try expect(vec[92] == true);
- try expect(vec[93] == true);
- try expect(vec[94] == true);
- try expect(vec[95] == false);
- try expect(vec[96] == false);
- try expect(vec[97] == true);
- try expect(vec[98] == false);
- try expect(vec[99] == false);
- try expect(vec[100] == true);
- try expect(vec[101] == true);
- try expect(vec[102] == true);
- try expect(vec[103] == true);
- try expect(vec[104] == false);
- try expect(vec[105] == true);
- try expect(vec[106] == true);
- try expect(vec[107] == true);
- try expect(vec[108] == false);
- try expect(vec[109] == false);
- try expect(vec[110] == true);
- try expect(vec[111] == false);
- try expect(vec[112] == false);
- try expect(vec[113] == true);
- try expect(vec[114] == true);
- try expect(vec[115] == false);
- try expect(vec[116] == true);
- try expect(vec[117] == false);
- try expect(vec[118] == true);
- try expect(vec[119] == true);
- try expect(vec[120] == true);
- try expect(vec[121] == true);
- try expect(vec[122] == true);
- try expect(vec[123] == false);
- try expect(vec[124] == false);
- try expect(vec[125] == true);
- try expect(vec[126] == false);
- try expect(vec[127] == true);
- }
-
- {
- if (!builtin.target.cpu.arch.isWasm()) c_vector_256_bool(.{
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- });
-
- const vec = c_ret_vector_256_bool();
- try expect(vec[0] == true);
- try expect(vec[1] == false);
- try expect(vec[2] == true);
- try expect(vec[3] == true);
- try expect(vec[4] == false);
- try expect(vec[5] == false);
- try expect(vec[6] == false);
- try expect(vec[7] == false);
- try expect(vec[8] == false);
- try expect(vec[9] == true);
- try expect(vec[10] == false);
- try expect(vec[11] == true);
- try expect(vec[12] == false);
- try expect(vec[13] == true);
- try expect(vec[14] == false);
- try expect(vec[15] == false);
- try expect(vec[16] == true);
- try expect(vec[17] == true);
- try expect(vec[18] == true);
- try expect(vec[19] == false);
- try expect(vec[20] == false);
- try expect(vec[21] == false);
- try expect(vec[22] == true);
- try expect(vec[23] == false);
- try expect(vec[24] == true);
- try expect(vec[25] == false);
- try expect(vec[26] == false);
- try expect(vec[27] == true);
- try expect(vec[28] == true);
- try expect(vec[29] == true);
- try expect(vec[30] == false);
- try expect(vec[31] == false);
- try expect(vec[32] == true);
- try expect(vec[33] == true);
- try expect(vec[34] == true);
- try expect(vec[35] == false);
- try expect(vec[36] == true);
- try expect(vec[37] == true);
- try expect(vec[38] == true);
- try expect(vec[39] == false);
- try expect(vec[40] == true);
- try expect(vec[41] == false);
- try expect(vec[42] == true);
- try expect(vec[43] == true);
- try expect(vec[44] == false);
- try expect(vec[45] == true);
- try expect(vec[46] == false);
- try expect(vec[47] == true);
- try expect(vec[48] == true);
- try expect(vec[49] == false);
- try expect(vec[50] == false);
- try expect(vec[51] == true);
- try expect(vec[52] == true);
- try expect(vec[53] == false);
- try expect(vec[54] == false);
- try expect(vec[55] == true);
- try expect(vec[56] == false);
- try expect(vec[57] == true);
- try expect(vec[58] == true);
- try expect(vec[59] == true);
- try expect(vec[60] == false);
- try expect(vec[61] == true);
- try expect(vec[62] == true);
- try expect(vec[63] == false);
- try expect(vec[64] == true);
- try expect(vec[65] == true);
- try expect(vec[66] == false);
- try expect(vec[67] == true);
- try expect(vec[68] == false);
- try expect(vec[69] == true);
- try expect(vec[70] == true);
- try expect(vec[71] == true);
- try expect(vec[72] == false);
- try expect(vec[73] == true);
- try expect(vec[74] == true);
- try expect(vec[75] == false);
- try expect(vec[76] == true);
- try expect(vec[77] == true);
- try expect(vec[78] == true);
- try expect(vec[79] == true);
- try expect(vec[80] == false);
- try expect(vec[81] == true);
- try expect(vec[82] == false);
- try expect(vec[83] == true);
- try expect(vec[84] == true);
- try expect(vec[85] == true);
- try expect(vec[86] == false);
- try expect(vec[87] == true);
- try expect(vec[88] == false);
- try expect(vec[89] == true);
- try expect(vec[90] == false);
- try expect(vec[91] == false);
- try expect(vec[92] == true);
- try expect(vec[93] == false);
- try expect(vec[94] == false);
- try expect(vec[95] == false);
- try expect(vec[96] == true);
- try expect(vec[97] == true);
- try expect(vec[98] == false);
- try expect(vec[99] == false);
- try expect(vec[100] == false);
- try expect(vec[101] == true);
- try expect(vec[102] == true);
- try expect(vec[103] == true);
- try expect(vec[104] == false);
- try expect(vec[105] == false);
- try expect(vec[106] == false);
- try expect(vec[107] == true);
- try expect(vec[108] == false);
- try expect(vec[109] == true);
- try expect(vec[110] == true);
- try expect(vec[111] == true);
- try expect(vec[112] == true);
- try expect(vec[113] == true);
- try expect(vec[114] == true);
- try expect(vec[115] == true);
- try expect(vec[116] == true);
- try expect(vec[117] == false);
- try expect(vec[118] == true);
- try expect(vec[119] == false);
- try expect(vec[120] == true);
- try expect(vec[121] == false);
- try expect(vec[122] == false);
- try expect(vec[123] == true);
- try expect(vec[124] == true);
- try expect(vec[125] == false);
- try expect(vec[126] == true);
- try expect(vec[127] == false);
- try expect(vec[128] == false);
- try expect(vec[129] == false);
- try expect(vec[130] == false);
- try expect(vec[131] == true);
- try expect(vec[132] == false);
- try expect(vec[133] == false);
- try expect(vec[134] == true);
- try expect(vec[135] == false);
- try expect(vec[136] == false);
- try expect(vec[137] == false);
- try expect(vec[138] == false);
- try expect(vec[139] == false);
- try expect(vec[140] == false);
- try expect(vec[141] == true);
- try expect(vec[142] == false);
- try expect(vec[143] == true);
- try expect(vec[144] == false);
- try expect(vec[145] == true);
- try expect(vec[146] == true);
- try expect(vec[147] == true);
- try expect(vec[148] == false);
- try expect(vec[149] == true);
- try expect(vec[150] == true);
- try expect(vec[151] == false);
- try expect(vec[152] == true);
- try expect(vec[153] == true);
- try expect(vec[154] == false);
- try expect(vec[155] == true);
- try expect(vec[156] == true);
- try expect(vec[157] == true);
- try expect(vec[158] == true);
- try expect(vec[159] == true);
- try expect(vec[160] == true);
- try expect(vec[161] == true);
- try expect(vec[162] == false);
- try expect(vec[163] == false);
- try expect(vec[164] == false);
- try expect(vec[165] == true);
- try expect(vec[166] == false);
- try expect(vec[167] == false);
- try expect(vec[168] == true);
- try expect(vec[169] == false);
- try expect(vec[170] == true);
- try expect(vec[171] == true);
- try expect(vec[172] == true);
- try expect(vec[173] == false);
- try expect(vec[174] == false);
- try expect(vec[175] == true);
- try expect(vec[176] == true);
- try expect(vec[177] == true);
- try expect(vec[178] == true);
- try expect(vec[179] == false);
- try expect(vec[180] == true);
- try expect(vec[181] == true);
- try expect(vec[182] == false);
- try expect(vec[183] == true);
- try expect(vec[184] == false);
- try expect(vec[185] == false);
- try expect(vec[186] == false);
- try expect(vec[187] == true);
- try expect(vec[188] == true);
- try expect(vec[189] == true);
- try expect(vec[190] == true);
- try expect(vec[191] == true);
- try expect(vec[192] == true);
- try expect(vec[193] == true);
- try expect(vec[194] == true);
- try expect(vec[195] == false);
- try expect(vec[196] == false);
- try expect(vec[197] == true);
- try expect(vec[198] == false);
- try expect(vec[199] == false);
- try expect(vec[200] == false);
- try expect(vec[201] == true);
- try expect(vec[202] == true);
- try expect(vec[203] == true);
- try expect(vec[204] == true);
- try expect(vec[205] == true);
- try expect(vec[206] == true);
- try expect(vec[207] == false);
- try expect(vec[208] == false);
- try expect(vec[209] == false);
- try expect(vec[210] == true);
- try expect(vec[211] == true);
- try expect(vec[212] == true);
- try expect(vec[213] == false);
- try expect(vec[214] == true);
- try expect(vec[215] == false);
- try expect(vec[216] == true);
- try expect(vec[217] == false);
- try expect(vec[218] == true);
- try expect(vec[219] == false);
- try expect(vec[220] == true);
- try expect(vec[221] == true);
- try expect(vec[222] == true);
- try expect(vec[223] == false);
- try expect(vec[224] == true);
- try expect(vec[225] == false);
- try expect(vec[226] == true);
- try expect(vec[227] == false);
- try expect(vec[228] == true);
- try expect(vec[229] == false);
- try expect(vec[230] == true);
- try expect(vec[231] == false);
- try expect(vec[232] == false);
- try expect(vec[233] == true);
- try expect(vec[234] == false);
- try expect(vec[235] == true);
- try expect(vec[236] == true);
- try expect(vec[237] == false);
- try expect(vec[238] == false);
- try expect(vec[239] == true);
- try expect(vec[240] == false);
- try expect(vec[241] == false);
- try expect(vec[242] == false);
- try expect(vec[243] == true);
- try expect(vec[244] == true);
- try expect(vec[245] == false);
- try expect(vec[246] == false);
- try expect(vec[247] == false);
- try expect(vec[248] == false);
- try expect(vec[249] == false);
- try expect(vec[250] == true);
- try expect(vec[251] == false);
- try expect(vec[252] == true);
- try expect(vec[253] == false);
- try expect(vec[254] == false);
- try expect(vec[255] == false);
- }
- {
- if (!builtin.target.cpu.arch.isWasm()) c_vector_512_bool(.{
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- });
-
- const vec = c_ret_vector_512_bool();
- try expect(vec[0] == false);
- try expect(vec[1] == true);
- try expect(vec[2] == false);
- try expect(vec[3] == false);
- try expect(vec[4] == false);
- try expect(vec[5] == true);
- try expect(vec[6] == false);
- try expect(vec[7] == false);
- try expect(vec[8] == false);
- try expect(vec[9] == true);
- try expect(vec[10] == false);
- try expect(vec[11] == false);
- try expect(vec[12] == false);
- try expect(vec[13] == true);
- try expect(vec[14] == false);
- try expect(vec[15] == true);
- try expect(vec[16] == false);
- try expect(vec[17] == false);
- try expect(vec[18] == false);
- try expect(vec[19] == false);
- try expect(vec[20] == false);
- try expect(vec[21] == false);
- try expect(vec[22] == true);
- try expect(vec[23] == true);
- try expect(vec[24] == false);
- try expect(vec[25] == false);
- try expect(vec[26] == false);
- try expect(vec[27] == false);
- try expect(vec[28] == true);
- try expect(vec[29] == true);
- try expect(vec[30] == false);
- try expect(vec[31] == true);
- try expect(vec[32] == false);
- try expect(vec[33] == true);
- try expect(vec[34] == true);
- try expect(vec[35] == true);
- try expect(vec[36] == false);
- try expect(vec[37] == false);
- try expect(vec[38] == true);
- try expect(vec[39] == true);
- try expect(vec[40] == false);
- try expect(vec[41] == false);
- try expect(vec[42] == false);
- try expect(vec[43] == false);
- try expect(vec[44] == false);
- try expect(vec[45] == true);
- try expect(vec[46] == false);
- try expect(vec[47] == true);
- try expect(vec[48] == true);
- try expect(vec[49] == false);
- try expect(vec[50] == true);
- try expect(vec[51] == true);
- try expect(vec[52] == true);
- try expect(vec[53] == true);
- try expect(vec[54] == false);
- try expect(vec[55] == false);
- try expect(vec[56] == false);
- try expect(vec[57] == true);
- try expect(vec[58] == true);
- try expect(vec[59] == false);
- try expect(vec[60] == false);
- try expect(vec[61] == false);
- try expect(vec[62] == false);
- try expect(vec[63] == true);
- try expect(vec[64] == true);
- try expect(vec[65] == true);
- try expect(vec[66] == true);
- try expect(vec[67] == true);
- try expect(vec[68] == false);
- try expect(vec[69] == false);
- try expect(vec[70] == false);
- try expect(vec[71] == false);
- try expect(vec[72] == false);
- try expect(vec[73] == true);
- try expect(vec[74] == false);
- try expect(vec[75] == true);
- try expect(vec[76] == false);
- try expect(vec[77] == false);
- try expect(vec[78] == true);
- try expect(vec[79] == true);
- try expect(vec[80] == false);
- try expect(vec[81] == false);
- try expect(vec[82] == false);
- try expect(vec[83] == true);
- try expect(vec[84] == false);
- try expect(vec[85] == true);
- try expect(vec[86] == true);
- try expect(vec[87] == true);
- try expect(vec[88] == false);
- try expect(vec[89] == true);
- try expect(vec[90] == false);
- try expect(vec[91] == false);
- try expect(vec[92] == true);
- try expect(vec[93] == true);
- try expect(vec[94] == false);
- try expect(vec[95] == true);
- try expect(vec[96] == true);
- try expect(vec[97] == false);
- try expect(vec[98] == true);
- try expect(vec[99] == false);
- try expect(vec[100] == true);
- try expect(vec[101] == true);
- try expect(vec[102] == false);
- try expect(vec[103] == true);
- try expect(vec[104] == true);
- try expect(vec[105] == false);
- try expect(vec[106] == false);
- try expect(vec[107] == false);
- try expect(vec[108] == true);
- try expect(vec[109] == false);
- try expect(vec[110] == false);
- try expect(vec[111] == false);
- try expect(vec[112] == true);
- try expect(vec[113] == true);
- try expect(vec[114] == true);
- try expect(vec[115] == false);
- try expect(vec[116] == true);
- try expect(vec[117] == false);
- try expect(vec[118] == true);
- try expect(vec[119] == false);
- try expect(vec[120] == true);
- try expect(vec[121] == true);
- try expect(vec[122] == false);
- try expect(vec[123] == true);
- try expect(vec[124] == false);
- try expect(vec[125] == true);
- try expect(vec[126] == true);
- try expect(vec[127] == true);
- try expect(vec[128] == false);
- try expect(vec[129] == true);
- try expect(vec[130] == false);
- try expect(vec[131] == false);
- try expect(vec[132] == false);
- try expect(vec[133] == false);
- try expect(vec[134] == false);
- try expect(vec[135] == false);
- try expect(vec[136] == true);
- try expect(vec[137] == false);
- try expect(vec[138] == true);
- try expect(vec[139] == false);
- try expect(vec[140] == true);
- try expect(vec[141] == true);
- try expect(vec[142] == false);
- try expect(vec[143] == true);
- try expect(vec[144] == false);
- try expect(vec[145] == false);
- try expect(vec[146] == true);
- try expect(vec[147] == false);
- try expect(vec[148] == false);
- try expect(vec[149] == true);
- try expect(vec[150] == false);
- try expect(vec[151] == true);
- try expect(vec[152] == false);
- try expect(vec[153] == true);
- try expect(vec[154] == false);
- try expect(vec[155] == false);
- try expect(vec[156] == true);
- try expect(vec[157] == false);
- try expect(vec[158] == true);
- try expect(vec[159] == true);
- try expect(vec[160] == true);
- try expect(vec[161] == false);
- try expect(vec[162] == false);
- try expect(vec[163] == true);
- try expect(vec[164] == false);
- try expect(vec[165] == false);
- try expect(vec[166] == false);
- try expect(vec[167] == true);
- try expect(vec[168] == true);
- try expect(vec[169] == true);
- try expect(vec[170] == false);
- try expect(vec[171] == true);
- try expect(vec[172] == false);
- try expect(vec[173] == false);
- try expect(vec[174] == false);
- try expect(vec[175] == false);
- try expect(vec[176] == false);
- try expect(vec[177] == true);
- try expect(vec[178] == true);
- try expect(vec[179] == false);
- try expect(vec[180] == false);
- try expect(vec[181] == true);
- try expect(vec[182] == false);
- try expect(vec[183] == false);
- try expect(vec[184] == false);
- try expect(vec[185] == false);
- try expect(vec[186] == false);
- try expect(vec[187] == true);
- try expect(vec[188] == true);
- try expect(vec[189] == false);
- try expect(vec[190] == false);
- try expect(vec[191] == false);
- try expect(vec[192] == false);
- try expect(vec[193] == false);
- try expect(vec[194] == false);
- try expect(vec[195] == true);
- try expect(vec[196] == true);
- try expect(vec[197] == false);
- try expect(vec[198] == true);
- try expect(vec[199] == true);
- try expect(vec[200] == true);
- try expect(vec[201] == true);
- try expect(vec[202] == true);
- try expect(vec[203] == true);
- try expect(vec[204] == false);
- try expect(vec[205] == false);
- try expect(vec[206] == false);
- try expect(vec[207] == false);
- try expect(vec[208] == true);
- try expect(vec[209] == false);
- try expect(vec[210] == true);
- try expect(vec[211] == true);
- try expect(vec[212] == true);
- try expect(vec[213] == true);
- try expect(vec[214] == false);
- try expect(vec[215] == false);
- try expect(vec[216] == false);
- try expect(vec[217] == true);
- try expect(vec[218] == true);
- try expect(vec[219] == false);
- try expect(vec[220] == true);
- try expect(vec[221] == true);
- try expect(vec[222] == false);
- try expect(vec[223] == false);
- try expect(vec[224] == false);
- try expect(vec[225] == true);
- try expect(vec[226] == true);
- try expect(vec[227] == true);
- try expect(vec[228] == true);
- try expect(vec[229] == false);
- try expect(vec[230] == true);
- try expect(vec[231] == false);
- try expect(vec[232] == true);
- try expect(vec[233] == true);
- try expect(vec[234] == true);
- try expect(vec[235] == true);
- try expect(vec[236] == false);
- try expect(vec[237] == true);
- try expect(vec[238] == false);
- try expect(vec[239] == true);
- try expect(vec[240] == false);
- try expect(vec[241] == true);
- try expect(vec[242] == false);
- try expect(vec[243] == false);
- try expect(vec[244] == false);
- try expect(vec[245] == true);
- try expect(vec[246] == true);
- try expect(vec[247] == false);
- try expect(vec[248] == true);
- try expect(vec[249] == false);
- try expect(vec[250] == false);
- try expect(vec[251] == false);
- try expect(vec[252] == true);
- try expect(vec[253] == true);
- try expect(vec[254] == true);
- try expect(vec[255] == true);
- try expect(vec[256] == true);
- try expect(vec[257] == false);
- try expect(vec[258] == true);
- try expect(vec[259] == true);
- try expect(vec[260] == true);
- try expect(vec[261] == true);
- try expect(vec[262] == false);
- try expect(vec[263] == true);
- try expect(vec[264] == false);
- try expect(vec[265] == false);
- try expect(vec[266] == true);
- try expect(vec[267] == false);
- try expect(vec[268] == true);
- try expect(vec[269] == false);
- try expect(vec[270] == false);
- try expect(vec[271] == true);
- try expect(vec[272] == true);
- try expect(vec[273] == false);
- try expect(vec[274] == true);
- try expect(vec[275] == false);
- try expect(vec[276] == false);
- try expect(vec[277] == true);
- try expect(vec[278] == false);
- try expect(vec[279] == false);
- try expect(vec[280] == true);
- try expect(vec[281] == true);
- try expect(vec[282] == true);
- try expect(vec[283] == false);
- try expect(vec[284] == false);
- try expect(vec[285] == true);
- try expect(vec[286] == true);
- try expect(vec[287] == true);
- try expect(vec[288] == false);
- try expect(vec[289] == false);
- try expect(vec[290] == false);
- try expect(vec[291] == false);
- try expect(vec[292] == false);
- try expect(vec[293] == false);
- try expect(vec[294] == true);
- try expect(vec[295] == false);
- try expect(vec[296] == true);
- try expect(vec[297] == false);
- try expect(vec[298] == true);
- try expect(vec[299] == true);
- try expect(vec[300] == false);
- try expect(vec[301] == false);
- try expect(vec[302] == false);
- try expect(vec[303] == false);
- try expect(vec[304] == true);
- try expect(vec[305] == true);
- try expect(vec[306] == true);
- try expect(vec[307] == true);
- try expect(vec[308] == true);
- try expect(vec[309] == false);
- try expect(vec[310] == true);
- try expect(vec[311] == true);
- try expect(vec[312] == true);
- try expect(vec[313] == true);
- try expect(vec[314] == true);
- try expect(vec[315] == false);
- try expect(vec[316] == true);
- try expect(vec[317] == true);
- try expect(vec[318] == true);
- try expect(vec[319] == false);
- try expect(vec[320] == true);
- try expect(vec[321] == false);
- try expect(vec[322] == true);
- try expect(vec[323] == true);
- try expect(vec[324] == true);
- try expect(vec[325] == false);
- try expect(vec[326] == false);
- try expect(vec[327] == true);
- try expect(vec[328] == true);
- try expect(vec[329] == true);
- try expect(vec[330] == false);
- try expect(vec[331] == false);
- try expect(vec[332] == true);
- try expect(vec[333] == true);
- try expect(vec[334] == false);
- try expect(vec[335] == true);
- try expect(vec[336] == true);
- try expect(vec[337] == true);
- try expect(vec[338] == true);
- try expect(vec[339] == true);
- try expect(vec[340] == true);
- try expect(vec[341] == false);
- try expect(vec[342] == true);
- try expect(vec[343] == false);
- try expect(vec[344] == true);
- try expect(vec[345] == false);
- try expect(vec[346] == false);
- try expect(vec[347] == false);
- try expect(vec[348] == false);
- try expect(vec[349] == true);
- try expect(vec[350] == true);
- try expect(vec[351] == true);
- try expect(vec[352] == true);
- try expect(vec[353] == false);
- try expect(vec[354] == true);
- try expect(vec[355] == false);
- try expect(vec[356] == true);
- try expect(vec[357] == true);
- try expect(vec[358] == false);
- try expect(vec[359] == true);
- try expect(vec[360] == false);
- try expect(vec[361] == false);
- try expect(vec[362] == true);
- try expect(vec[363] == false);
- try expect(vec[364] == false);
- try expect(vec[365] == false);
- try expect(vec[366] == false);
- try expect(vec[367] == false);
- try expect(vec[368] == false);
- try expect(vec[369] == false);
- try expect(vec[370] == true);
- try expect(vec[371] == false);
- try expect(vec[372] == true);
- try expect(vec[373] == true);
- try expect(vec[374] == false);
- try expect(vec[375] == false);
- try expect(vec[376] == true);
- try expect(vec[377] == false);
- try expect(vec[378] == false);
- try expect(vec[379] == true);
- try expect(vec[380] == false);
- try expect(vec[381] == false);
- try expect(vec[382] == true);
- try expect(vec[383] == false);
- try expect(vec[384] == false);
- try expect(vec[385] == false);
- try expect(vec[386] == false);
- try expect(vec[387] == true);
- try expect(vec[388] == true);
- try expect(vec[389] == true);
- try expect(vec[390] == true);
- try expect(vec[391] == true);
- try expect(vec[392] == true);
- try expect(vec[393] == true);
- try expect(vec[394] == false);
- try expect(vec[395] == true);
- try expect(vec[396] == true);
- try expect(vec[397] == false);
- try expect(vec[398] == false);
- try expect(vec[399] == false);
- try expect(vec[400] == true);
- try expect(vec[401] == false);
- try expect(vec[402] == true);
- try expect(vec[403] == true);
- try expect(vec[404] == false);
- try expect(vec[405] == true);
- try expect(vec[406] == true);
- try expect(vec[407] == true);
- try expect(vec[408] == true);
- try expect(vec[409] == false);
- try expect(vec[410] == false);
- try expect(vec[411] == false);
- try expect(vec[412] == true);
- try expect(vec[413] == true);
- try expect(vec[414] == false);
- try expect(vec[415] == true);
- try expect(vec[416] == false);
- try expect(vec[417] == true);
- try expect(vec[418] == false);
- try expect(vec[419] == false);
- try expect(vec[420] == false);
- try expect(vec[421] == false);
- try expect(vec[422] == true);
- try expect(vec[423] == true);
- try expect(vec[424] == true);
- try expect(vec[425] == false);
- try expect(vec[426] == true);
- try expect(vec[427] == false);
- try expect(vec[428] == false);
- try expect(vec[429] == false);
- try expect(vec[430] == true);
- try expect(vec[431] == true);
- try expect(vec[432] == false);
- try expect(vec[433] == true);
- try expect(vec[434] == false);
- try expect(vec[435] == false);
- try expect(vec[436] == true);
- try expect(vec[437] == true);
- try expect(vec[438] == true);
- try expect(vec[439] == true);
- try expect(vec[440] == true);
- try expect(vec[441] == true);
- try expect(vec[442] == false);
- try expect(vec[443] == false);
- try expect(vec[444] == false);
- try expect(vec[445] == true);
- try expect(vec[446] == true);
- try expect(vec[447] == true);
- try expect(vec[448] == false);
- try expect(vec[449] == false);
- try expect(vec[450] == false);
- try expect(vec[451] == false);
- try expect(vec[452] == false);
- try expect(vec[453] == false);
- try expect(vec[454] == false);
- try expect(vec[455] == false);
- try expect(vec[456] == false);
- try expect(vec[457] == false);
- try expect(vec[458] == false);
- try expect(vec[459] == true);
- try expect(vec[460] == false);
- try expect(vec[461] == false);
- try expect(vec[462] == false);
- try expect(vec[463] == true);
- try expect(vec[464] == false);
- try expect(vec[465] == false);
- try expect(vec[466] == false);
- try expect(vec[467] == false);
- try expect(vec[468] == true);
- try expect(vec[469] == true);
- try expect(vec[470] == true);
- try expect(vec[471] == true);
- try expect(vec[472] == true);
- try expect(vec[473] == false);
- try expect(vec[474] == false);
- try expect(vec[475] == true);
- try expect(vec[476] == true);
- try expect(vec[477] == true);
- try expect(vec[478] == false);
- try expect(vec[479] == true);
- try expect(vec[480] == true);
- try expect(vec[481] == true);
- try expect(vec[482] == false);
- try expect(vec[483] == true);
- try expect(vec[484] == false);
- try expect(vec[485] == true);
- try expect(vec[486] == false);
- try expect(vec[487] == true);
- try expect(vec[488] == false);
- try expect(vec[489] == true);
- try expect(vec[490] == true);
- try expect(vec[491] == true);
- try expect(vec[492] == true);
- try expect(vec[493] == false);
- try expect(vec[494] == true);
- try expect(vec[495] == true);
- try expect(vec[496] == false);
- try expect(vec[497] == true);
- try expect(vec[498] == false);
- try expect(vec[499] == false);
- try expect(vec[500] == false);
- try expect(vec[501] == false);
- try expect(vec[502] == false);
- try expect(vec[503] == false);
- try expect(vec[504] == false);
- try expect(vec[505] == false);
- try expect(vec[506] == false);
- try expect(vec[507] == true);
- try expect(vec[508] == true);
- try expect(vec[509] == false);
- try expect(vec[510] == true);
- try expect(vec[511] == false);
- }
-}
-
comptime {
skip: {
if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
_ = struct {
- export fn zig_vector_2_bool(vec: Vector2Bool) void {
+ export fn zig_ret_vector_2_bool() @Vector(2, bool) {
+ return .{
+ false,
+ false,
+ };
+ }
+ export fn zig_vector_2_bool(vec: @Vector(2, bool)) void {
expect(vec[0] == false) catch @panic("test failure");
expect(vec[1] == true) catch @panic("test failure");
}
+ };
+ }
+}
- export fn zig_vector_4_bool(vec: Vector4Bool) void {
+extern fn c_ret_vector_2_bool() @Vector(2, bool);
+extern fn c_vector_2_bool(@Vector(2, bool)) void;
+extern fn c_test_vector_2_bool() void;
+
+test "@Vector(2, bool)" {
+ if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
+
+ const vec = c_ret_vector_2_bool();
+ try expect(vec[0] == true);
+ try expect(vec[1] == false);
+ c_vector_2_bool(.{
+ true,
+ true,
+ });
+ c_test_vector_2_bool();
+}
+
+comptime {
+ skip: {
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
+
+ _ = struct {
+ export fn zig_ret_vector_4_bool() @Vector(4, bool) {
+ return .{
+ false,
+ true,
+ true,
+ true,
+ };
+ }
+ export fn zig_vector_4_bool(vec: @Vector(4, bool)) void {
expect(vec[0] == false) catch @panic("test failure");
expect(vec[1] == false) catch @panic("test failure");
expect(vec[2] == false) catch @panic("test failure");
expect(vec[3] == false) catch @panic("test failure");
}
+ };
+ }
+}
- export fn zig_vector_8_bool(vec: Vector8Bool) void {
+extern fn c_ret_vector_4_bool() @Vector(4, bool);
+extern fn c_vector_4_bool(@Vector(4, bool)) void;
+extern fn c_test_vector_4_bool() void;
+
+test "@Vector(4, bool)" {
+ if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
+
+ const vec = c_ret_vector_4_bool();
+ try expect(vec[0] == true);
+ try expect(vec[1] == false);
+ try expect(vec[2] == true);
+ try expect(vec[3] == false);
+ c_vector_4_bool(.{
+ true,
+ true,
+ false,
+ true,
+ });
+ c_test_vector_4_bool();
+}
+
+comptime {
+ skip: {
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
+
+ _ = struct {
+ export fn zig_ret_vector_8_bool() @Vector(8, bool) {
+ return .{
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ };
+ }
+ export fn zig_vector_8_bool(vec: @Vector(8, bool)) void {
expect(vec[0] == true) catch @panic("test failure");
expect(vec[1] == true) catch @panic("test failure");
expect(vec[2] == false) catch @panic("test failure");
@@ -3580,8 +379,66 @@ comptime {
expect(vec[6] == true) catch @panic("test failure");
expect(vec[7] == false) catch @panic("test failure");
}
+ };
+ }
+}
- export fn zig_vector_16_bool(vec: Vector16Bool) void {
+extern fn c_ret_vector_8_bool() @Vector(8, bool);
+extern fn c_vector_8_bool(@Vector(8, bool)) void;
+extern fn c_test_vector_8_bool() void;
+
+test "@Vector(8, bool)" {
+ if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
+
+ const vec = c_ret_vector_8_bool();
+ try expect(vec[0] == false);
+ try expect(vec[1] == true);
+ try expect(vec[2] == false);
+ try expect(vec[3] == false);
+ try expect(vec[4] == true);
+ try expect(vec[5] == false);
+ try expect(vec[6] == false);
+ try expect(vec[7] == true);
+ c_vector_8_bool(.{
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ });
+ c_test_vector_8_bool();
+}
+
+comptime {
+ skip: {
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
+
+ _ = struct {
+ export fn zig_ret_vector_16_bool() @Vector(16, bool) {
+ return .{
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ };
+ }
+ export fn zig_vector_16_bool(vec: @Vector(16, bool)) void {
expect(vec[0] == true) catch @panic("test failure");
expect(vec[1] == false) catch @panic("test failure");
expect(vec[2] == true) catch @panic("test failure");
@@ -3599,8 +456,98 @@ comptime {
expect(vec[14] == false) catch @panic("test failure");
expect(vec[15] == true) catch @panic("test failure");
}
+ };
+ }
+}
- export fn zig_vector_32_bool(vec: Vector32Bool) void {
+extern fn c_ret_vector_16_bool() @Vector(16, bool);
+extern fn c_vector_16_bool(@Vector(16, bool)) void;
+extern fn c_test_vector_16_bool() void;
+
+test "@Vector(16, bool)" {
+ if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
+
+ const vec = c_ret_vector_16_bool();
+ try expect(vec[0] == true);
+ try expect(vec[1] == true);
+ try expect(vec[2] == false);
+ try expect(vec[3] == false);
+ try expect(vec[4] == false);
+ try expect(vec[5] == false);
+ try expect(vec[6] == true);
+ try expect(vec[7] == false);
+ try expect(vec[8] == true);
+ try expect(vec[9] == false);
+ try expect(vec[10] == false);
+ try expect(vec[11] == true);
+ try expect(vec[12] == true);
+ try expect(vec[13] == false);
+ try expect(vec[14] == true);
+ try expect(vec[15] == true);
+ c_vector_16_bool(.{
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ });
+ c_test_vector_16_bool();
+}
+
+comptime {
+ skip: {
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
+
+ _ = struct {
+ export fn zig_ret_vector_32_bool() @Vector(32, bool) {
+ return .{
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ };
+ }
+ export fn zig_vector_32_bool(vec: @Vector(32, bool)) void {
expect(vec[0] == false) catch @panic("test failure");
expect(vec[1] == false) catch @panic("test failure");
expect(vec[2] == false) catch @panic("test failure");
@@ -3634,8 +581,162 @@ comptime {
expect(vec[30] == false) catch @panic("test failure");
expect(vec[31] == true) catch @panic("test failure");
}
+ };
+ }
+}
- export fn zig_vector_64_bool(vec: Vector64Bool) void {
+extern fn c_ret_vector_32_bool() @Vector(32, bool);
+extern fn c_vector_32_bool(@Vector(32, bool)) void;
+extern fn c_test_vector_32_bool() void;
+
+test "@Vector(32, bool)" {
+ if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
+
+ const vec = c_ret_vector_32_bool();
+ try expect(vec[0] == true);
+ try expect(vec[1] == false);
+ try expect(vec[2] == true);
+ try expect(vec[3] == true);
+ try expect(vec[4] == true);
+ try expect(vec[5] == false);
+ try expect(vec[6] == true);
+ try expect(vec[7] == false);
+ try expect(vec[8] == true);
+ try expect(vec[9] == true);
+ try expect(vec[10] == true);
+ try expect(vec[11] == false);
+ try expect(vec[12] == true);
+ try expect(vec[13] == true);
+ try expect(vec[14] == false);
+ try expect(vec[15] == false);
+ try expect(vec[16] == true);
+ try expect(vec[17] == false);
+ try expect(vec[18] == false);
+ try expect(vec[19] == false);
+ try expect(vec[20] == false);
+ try expect(vec[21] == true);
+ try expect(vec[22] == true);
+ try expect(vec[23] == true);
+ try expect(vec[24] == false);
+ try expect(vec[25] == true);
+ try expect(vec[26] == false);
+ try expect(vec[27] == false);
+ try expect(vec[28] == true);
+ try expect(vec[29] == false);
+ try expect(vec[30] == false);
+ try expect(vec[31] == false);
+ c_vector_32_bool(.{
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ });
+ c_test_vector_32_bool();
+}
+
+comptime {
+ skip: {
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
+
+ _ = struct {
+ export fn zig_ret_vector_64_bool() @Vector(64, bool) {
+ return .{
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ };
+ }
+ export fn zig_vector_64_bool(vec: @Vector(64, bool)) void {
expect(vec[0] == true) catch @panic("test failure");
expect(vec[1] == true) catch @panic("test failure");
expect(vec[2] == false) catch @panic("test failure");
@@ -3701,8 +802,290 @@ comptime {
expect(vec[62] == true) catch @panic("test failure");
expect(vec[63] == true) catch @panic("test failure");
}
+ };
+ }
+}
- export fn zig_vector_128_bool(vec: Vector128Bool) void {
+extern fn c_ret_vector_64_bool() @Vector(64, bool);
+extern fn c_vector_64_bool(@Vector(64, bool)) void;
+extern fn c_test_vector_64_bool() void;
+
+test "@Vector(64, bool)" {
+ if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
+
+ const vec = c_ret_vector_64_bool();
+ try expect(vec[0] == false);
+ try expect(vec[1] == true);
+ try expect(vec[2] == false);
+ try expect(vec[3] == true);
+ try expect(vec[4] == true);
+ try expect(vec[5] == true);
+ try expect(vec[6] == false);
+ try expect(vec[7] == true);
+ try expect(vec[8] == true);
+ try expect(vec[9] == true);
+ try expect(vec[10] == true);
+ try expect(vec[11] == true);
+ try expect(vec[12] == true);
+ try expect(vec[13] == false);
+ try expect(vec[14] == true);
+ try expect(vec[15] == true);
+ try expect(vec[16] == true);
+ try expect(vec[17] == false);
+ try expect(vec[18] == false);
+ try expect(vec[19] == false);
+ try expect(vec[20] == true);
+ try expect(vec[21] == true);
+ try expect(vec[22] == false);
+ try expect(vec[23] == true);
+ try expect(vec[24] == false);
+ try expect(vec[25] == true);
+ try expect(vec[26] == false);
+ try expect(vec[27] == true);
+ try expect(vec[28] == false);
+ try expect(vec[29] == true);
+ try expect(vec[30] == false);
+ try expect(vec[31] == true);
+ try expect(vec[32] == false);
+ try expect(vec[33] == false);
+ try expect(vec[34] == true);
+ try expect(vec[35] == true);
+ try expect(vec[36] == false);
+ try expect(vec[37] == false);
+ try expect(vec[38] == false);
+ try expect(vec[39] == true);
+ try expect(vec[40] == true);
+ try expect(vec[41] == true);
+ try expect(vec[42] == true);
+ try expect(vec[43] == false);
+ try expect(vec[44] == false);
+ try expect(vec[45] == false);
+ try expect(vec[46] == true);
+ try expect(vec[47] == true);
+ try expect(vec[48] == false);
+ try expect(vec[49] == false);
+ try expect(vec[50] == true);
+ try expect(vec[51] == false);
+ try expect(vec[52] == false);
+ try expect(vec[53] == false);
+ try expect(vec[54] == false);
+ try expect(vec[55] == true);
+ try expect(vec[56] == false);
+ try expect(vec[57] == false);
+ try expect(vec[58] == false);
+ try expect(vec[59] == true);
+ try expect(vec[60] == true);
+ try expect(vec[61] == true);
+ try expect(vec[62] == true);
+ try expect(vec[63] == true);
+ c_vector_64_bool(.{
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ });
+ c_test_vector_64_bool();
+}
+
+comptime {
+ skip: {
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
+
+ _ = struct {
+ export fn zig_ret_vector_128_bool() @Vector(128, bool) {
+ return .{
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ };
+ }
+ export fn zig_vector_128_bool(vec: @Vector(128, bool)) void {
expect(vec[0] == true) catch @panic("test failure");
expect(vec[1] == true) catch @panic("test failure");
expect(vec[2] == false) catch @panic("test failure");
@@ -3832,8 +1215,546 @@ comptime {
expect(vec[126] == true) catch @panic("test failure");
expect(vec[127] == false) catch @panic("test failure");
}
+ };
+ }
+}
- export fn zig_vector_256_bool(vec: Vector256Bool) void {
+extern fn c_ret_vector_128_bool() @Vector(128, bool);
+extern fn c_vector_128_bool(@Vector(128, bool)) void;
+extern fn c_test_vector_128_bool() void;
+
+test "@Vector(128, bool)" {
+ if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
+
+ const vec = c_ret_vector_128_bool();
+ try expect(vec[0] == false);
+ try expect(vec[1] == true);
+ try expect(vec[2] == true);
+ try expect(vec[3] == false);
+ try expect(vec[4] == true);
+ try expect(vec[5] == false);
+ try expect(vec[6] == false);
+ try expect(vec[7] == true);
+ try expect(vec[8] == true);
+ try expect(vec[9] == false);
+ try expect(vec[10] == true);
+ try expect(vec[11] == false);
+ try expect(vec[12] == false);
+ try expect(vec[13] == false);
+ try expect(vec[14] == true);
+ try expect(vec[15] == false);
+ try expect(vec[16] == true);
+ try expect(vec[17] == false);
+ try expect(vec[18] == false);
+ try expect(vec[19] == true);
+ try expect(vec[20] == false);
+ try expect(vec[21] == true);
+ try expect(vec[22] == false);
+ try expect(vec[23] == false);
+ try expect(vec[24] == false);
+ try expect(vec[25] == true);
+ try expect(vec[26] == true);
+ try expect(vec[27] == true);
+ try expect(vec[28] == false);
+ try expect(vec[29] == false);
+ try expect(vec[30] == false);
+ try expect(vec[31] == false);
+ try expect(vec[32] == true);
+ try expect(vec[33] == true);
+ try expect(vec[34] == true);
+ try expect(vec[35] == false);
+ try expect(vec[36] == true);
+ try expect(vec[37] == true);
+ try expect(vec[38] == false);
+ try expect(vec[39] == false);
+ try expect(vec[40] == false);
+ try expect(vec[41] == false);
+ try expect(vec[42] == true);
+ try expect(vec[43] == true);
+ try expect(vec[44] == true);
+ try expect(vec[45] == false);
+ try expect(vec[46] == false);
+ try expect(vec[47] == false);
+ try expect(vec[48] == false);
+ try expect(vec[49] == true);
+ try expect(vec[50] == false);
+ try expect(vec[51] == false);
+ try expect(vec[52] == true);
+ try expect(vec[53] == false);
+ try expect(vec[54] == false);
+ try expect(vec[55] == false);
+ try expect(vec[56] == false);
+ try expect(vec[57] == false);
+ try expect(vec[58] == true);
+ try expect(vec[59] == true);
+ try expect(vec[60] == true);
+ try expect(vec[61] == false);
+ try expect(vec[62] == true);
+ try expect(vec[63] == true);
+ try expect(vec[64] == false);
+ try expect(vec[65] == false);
+ try expect(vec[66] == false);
+ try expect(vec[67] == false);
+ try expect(vec[68] == false);
+ try expect(vec[69] == false);
+ try expect(vec[70] == false);
+ try expect(vec[71] == false);
+ try expect(vec[72] == true);
+ try expect(vec[73] == true);
+ try expect(vec[74] == true);
+ try expect(vec[75] == true);
+ try expect(vec[76] == true);
+ try expect(vec[77] == false);
+ try expect(vec[78] == false);
+ try expect(vec[79] == false);
+ try expect(vec[80] == false);
+ try expect(vec[81] == false);
+ try expect(vec[82] == false);
+ try expect(vec[83] == true);
+ try expect(vec[84] == false);
+ try expect(vec[85] == true);
+ try expect(vec[86] == false);
+ try expect(vec[87] == true);
+ try expect(vec[88] == false);
+ try expect(vec[89] == true);
+ try expect(vec[90] == false);
+ try expect(vec[91] == true);
+ try expect(vec[92] == true);
+ try expect(vec[93] == true);
+ try expect(vec[94] == true);
+ try expect(vec[95] == false);
+ try expect(vec[96] == false);
+ try expect(vec[97] == true);
+ try expect(vec[98] == false);
+ try expect(vec[99] == false);
+ try expect(vec[100] == true);
+ try expect(vec[101] == true);
+ try expect(vec[102] == true);
+ try expect(vec[103] == true);
+ try expect(vec[104] == false);
+ try expect(vec[105] == true);
+ try expect(vec[106] == true);
+ try expect(vec[107] == true);
+ try expect(vec[108] == false);
+ try expect(vec[109] == false);
+ try expect(vec[110] == true);
+ try expect(vec[111] == false);
+ try expect(vec[112] == false);
+ try expect(vec[113] == true);
+ try expect(vec[114] == true);
+ try expect(vec[115] == false);
+ try expect(vec[116] == true);
+ try expect(vec[117] == false);
+ try expect(vec[118] == true);
+ try expect(vec[119] == true);
+ try expect(vec[120] == true);
+ try expect(vec[121] == true);
+ try expect(vec[122] == true);
+ try expect(vec[123] == false);
+ try expect(vec[124] == false);
+ try expect(vec[125] == true);
+ try expect(vec[126] == false);
+ try expect(vec[127] == true);
+ c_vector_128_bool(.{
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ });
+ c_test_vector_128_bool();
+}
+
+comptime {
+ skip: {
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
+
+ _ = struct {
+ export fn zig_ret_vector_256_bool() @Vector(256, bool) {
+ return .{
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ };
+ }
+ export fn zig_vector_256_bool(vec: @Vector(256, bool)) void {
expect(vec[0] == false) catch @panic("test failure");
expect(vec[1] == false) catch @panic("test failure");
expect(vec[2] == false) catch @panic("test failure");
@@ -4091,8 +2012,1058 @@ comptime {
expect(vec[254] == true) catch @panic("test failure");
expect(vec[255] == true) catch @panic("test failure");
}
+ };
+ }
+}
- export fn zig_vector_512_bool(vec: Vector512Bool) void {
+extern fn c_ret_vector_256_bool() @Vector(256, bool);
+extern fn c_vector_256_bool(@Vector(256, bool)) void;
+extern fn c_test_vector_256_bool() void;
+
+test "@Vector(256, bool)" {
+ if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
+
+ const vec = c_ret_vector_256_bool();
+ try expect(vec[0] == true);
+ try expect(vec[1] == false);
+ try expect(vec[2] == true);
+ try expect(vec[3] == true);
+ try expect(vec[4] == false);
+ try expect(vec[5] == false);
+ try expect(vec[6] == false);
+ try expect(vec[7] == false);
+ try expect(vec[8] == false);
+ try expect(vec[9] == true);
+ try expect(vec[10] == false);
+ try expect(vec[11] == true);
+ try expect(vec[12] == false);
+ try expect(vec[13] == true);
+ try expect(vec[14] == false);
+ try expect(vec[15] == false);
+ try expect(vec[16] == true);
+ try expect(vec[17] == true);
+ try expect(vec[18] == true);
+ try expect(vec[19] == false);
+ try expect(vec[20] == false);
+ try expect(vec[21] == false);
+ try expect(vec[22] == true);
+ try expect(vec[23] == false);
+ try expect(vec[24] == true);
+ try expect(vec[25] == false);
+ try expect(vec[26] == false);
+ try expect(vec[27] == true);
+ try expect(vec[28] == true);
+ try expect(vec[29] == true);
+ try expect(vec[30] == false);
+ try expect(vec[31] == false);
+ try expect(vec[32] == true);
+ try expect(vec[33] == true);
+ try expect(vec[34] == true);
+ try expect(vec[35] == false);
+ try expect(vec[36] == true);
+ try expect(vec[37] == true);
+ try expect(vec[38] == true);
+ try expect(vec[39] == false);
+ try expect(vec[40] == true);
+ try expect(vec[41] == false);
+ try expect(vec[42] == true);
+ try expect(vec[43] == true);
+ try expect(vec[44] == false);
+ try expect(vec[45] == true);
+ try expect(vec[46] == false);
+ try expect(vec[47] == true);
+ try expect(vec[48] == true);
+ try expect(vec[49] == false);
+ try expect(vec[50] == false);
+ try expect(vec[51] == true);
+ try expect(vec[52] == true);
+ try expect(vec[53] == false);
+ try expect(vec[54] == false);
+ try expect(vec[55] == true);
+ try expect(vec[56] == false);
+ try expect(vec[57] == true);
+ try expect(vec[58] == true);
+ try expect(vec[59] == true);
+ try expect(vec[60] == false);
+ try expect(vec[61] == true);
+ try expect(vec[62] == true);
+ try expect(vec[63] == false);
+ try expect(vec[64] == true);
+ try expect(vec[65] == true);
+ try expect(vec[66] == false);
+ try expect(vec[67] == true);
+ try expect(vec[68] == false);
+ try expect(vec[69] == true);
+ try expect(vec[70] == true);
+ try expect(vec[71] == true);
+ try expect(vec[72] == false);
+ try expect(vec[73] == true);
+ try expect(vec[74] == true);
+ try expect(vec[75] == false);
+ try expect(vec[76] == true);
+ try expect(vec[77] == true);
+ try expect(vec[78] == true);
+ try expect(vec[79] == true);
+ try expect(vec[80] == false);
+ try expect(vec[81] == true);
+ try expect(vec[82] == false);
+ try expect(vec[83] == true);
+ try expect(vec[84] == true);
+ try expect(vec[85] == true);
+ try expect(vec[86] == false);
+ try expect(vec[87] == true);
+ try expect(vec[88] == false);
+ try expect(vec[89] == true);
+ try expect(vec[90] == false);
+ try expect(vec[91] == false);
+ try expect(vec[92] == true);
+ try expect(vec[93] == false);
+ try expect(vec[94] == false);
+ try expect(vec[95] == false);
+ try expect(vec[96] == true);
+ try expect(vec[97] == true);
+ try expect(vec[98] == false);
+ try expect(vec[99] == false);
+ try expect(vec[100] == false);
+ try expect(vec[101] == true);
+ try expect(vec[102] == true);
+ try expect(vec[103] == true);
+ try expect(vec[104] == false);
+ try expect(vec[105] == false);
+ try expect(vec[106] == false);
+ try expect(vec[107] == true);
+ try expect(vec[108] == false);
+ try expect(vec[109] == true);
+ try expect(vec[110] == true);
+ try expect(vec[111] == true);
+ try expect(vec[112] == true);
+ try expect(vec[113] == true);
+ try expect(vec[114] == true);
+ try expect(vec[115] == true);
+ try expect(vec[116] == true);
+ try expect(vec[117] == false);
+ try expect(vec[118] == true);
+ try expect(vec[119] == false);
+ try expect(vec[120] == true);
+ try expect(vec[121] == false);
+ try expect(vec[122] == false);
+ try expect(vec[123] == true);
+ try expect(vec[124] == true);
+ try expect(vec[125] == false);
+ try expect(vec[126] == true);
+ try expect(vec[127] == false);
+ try expect(vec[128] == false);
+ try expect(vec[129] == false);
+ try expect(vec[130] == false);
+ try expect(vec[131] == true);
+ try expect(vec[132] == false);
+ try expect(vec[133] == false);
+ try expect(vec[134] == true);
+ try expect(vec[135] == false);
+ try expect(vec[136] == false);
+ try expect(vec[137] == false);
+ try expect(vec[138] == false);
+ try expect(vec[139] == false);
+ try expect(vec[140] == false);
+ try expect(vec[141] == true);
+ try expect(vec[142] == false);
+ try expect(vec[143] == true);
+ try expect(vec[144] == false);
+ try expect(vec[145] == true);
+ try expect(vec[146] == true);
+ try expect(vec[147] == true);
+ try expect(vec[148] == false);
+ try expect(vec[149] == true);
+ try expect(vec[150] == true);
+ try expect(vec[151] == false);
+ try expect(vec[152] == true);
+ try expect(vec[153] == true);
+ try expect(vec[154] == false);
+ try expect(vec[155] == true);
+ try expect(vec[156] == true);
+ try expect(vec[157] == true);
+ try expect(vec[158] == true);
+ try expect(vec[159] == true);
+ try expect(vec[160] == true);
+ try expect(vec[161] == true);
+ try expect(vec[162] == false);
+ try expect(vec[163] == false);
+ try expect(vec[164] == false);
+ try expect(vec[165] == true);
+ try expect(vec[166] == false);
+ try expect(vec[167] == false);
+ try expect(vec[168] == true);
+ try expect(vec[169] == false);
+ try expect(vec[170] == true);
+ try expect(vec[171] == true);
+ try expect(vec[172] == true);
+ try expect(vec[173] == false);
+ try expect(vec[174] == false);
+ try expect(vec[175] == true);
+ try expect(vec[176] == true);
+ try expect(vec[177] == true);
+ try expect(vec[178] == true);
+ try expect(vec[179] == false);
+ try expect(vec[180] == true);
+ try expect(vec[181] == true);
+ try expect(vec[182] == false);
+ try expect(vec[183] == true);
+ try expect(vec[184] == false);
+ try expect(vec[185] == false);
+ try expect(vec[186] == false);
+ try expect(vec[187] == true);
+ try expect(vec[188] == true);
+ try expect(vec[189] == true);
+ try expect(vec[190] == true);
+ try expect(vec[191] == true);
+ try expect(vec[192] == true);
+ try expect(vec[193] == true);
+ try expect(vec[194] == true);
+ try expect(vec[195] == false);
+ try expect(vec[196] == false);
+ try expect(vec[197] == true);
+ try expect(vec[198] == false);
+ try expect(vec[199] == false);
+ try expect(vec[200] == false);
+ try expect(vec[201] == true);
+ try expect(vec[202] == true);
+ try expect(vec[203] == true);
+ try expect(vec[204] == true);
+ try expect(vec[205] == true);
+ try expect(vec[206] == true);
+ try expect(vec[207] == false);
+ try expect(vec[208] == false);
+ try expect(vec[209] == false);
+ try expect(vec[210] == true);
+ try expect(vec[211] == true);
+ try expect(vec[212] == true);
+ try expect(vec[213] == false);
+ try expect(vec[214] == true);
+ try expect(vec[215] == false);
+ try expect(vec[216] == true);
+ try expect(vec[217] == false);
+ try expect(vec[218] == true);
+ try expect(vec[219] == false);
+ try expect(vec[220] == true);
+ try expect(vec[221] == true);
+ try expect(vec[222] == true);
+ try expect(vec[223] == false);
+ try expect(vec[224] == true);
+ try expect(vec[225] == false);
+ try expect(vec[226] == true);
+ try expect(vec[227] == false);
+ try expect(vec[228] == true);
+ try expect(vec[229] == false);
+ try expect(vec[230] == true);
+ try expect(vec[231] == false);
+ try expect(vec[232] == false);
+ try expect(vec[233] == true);
+ try expect(vec[234] == false);
+ try expect(vec[235] == true);
+ try expect(vec[236] == true);
+ try expect(vec[237] == false);
+ try expect(vec[238] == false);
+ try expect(vec[239] == true);
+ try expect(vec[240] == false);
+ try expect(vec[241] == false);
+ try expect(vec[242] == false);
+ try expect(vec[243] == true);
+ try expect(vec[244] == true);
+ try expect(vec[245] == false);
+ try expect(vec[246] == false);
+ try expect(vec[247] == false);
+ try expect(vec[248] == false);
+ try expect(vec[249] == false);
+ try expect(vec[250] == true);
+ try expect(vec[251] == false);
+ try expect(vec[252] == true);
+ try expect(vec[253] == false);
+ try expect(vec[254] == false);
+ try expect(vec[255] == false);
+ if (!builtin.target.cpu.arch.isWasm()) c_vector_256_bool(.{
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ });
+ c_test_vector_512_bool();
+}
+
+comptime {
+ skip: {
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip;
+
+ _ = struct {
+ export fn zig_ret_vector_512_bool() @Vector(512, bool) {
+ return .{
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ };
+ }
+ export fn zig_vector_512_bool(vec: @Vector(512, bool)) void {
expect(vec[0] == false) catch @panic("test failure");
expect(vec[1] == true) catch @panic("test failure");
expect(vec[2] == true) catch @panic("test failure");
@@ -4606,1095 +3577,13100 @@ comptime {
expect(vec[510] == false) catch @panic("test failure");
expect(vec[511] == true) catch @panic("test failure");
}
-
- export fn zig_ret_vector_2_bool() Vector2Bool {
- return .{
- false,
- false,
- };
- }
-
- export fn zig_ret_vector_4_bool() Vector4Bool {
- return .{
- false,
- true,
- true,
- true,
- };
- }
-
- export fn zig_ret_vector_8_bool() Vector8Bool {
- return .{
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- };
- }
-
- export fn zig_ret_vector_16_bool() Vector16Bool {
- return .{
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- };
- }
-
- export fn zig_ret_vector_32_bool() Vector32Bool {
- return .{
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- };
- }
-
- export fn zig_ret_vector_64_bool() Vector64Bool {
- return .{
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- };
- }
-
- export fn zig_ret_vector_128_bool() Vector128Bool {
- return .{
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- };
- }
-
- export fn zig_ret_vector_256_bool() Vector256Bool {
- return .{
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- };
- }
-
- export fn zig_ret_vector_512_bool() Vector512Bool {
- return .{
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- true,
- false,
- true,
- false,
- true,
- false,
- true,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- false,
- false,
- false,
- false,
- true,
- true,
- false,
- true,
- true,
- false,
- false,
- true,
- true,
- true,
- false,
- false,
- true,
- false,
- false,
- false,
- true,
- true,
- false,
- false,
- false,
- false,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- false,
- true,
- false,
- true,
- true,
- true,
- true,
- false,
- false,
- true,
- true,
- false,
- false,
- };
- }
};
}
}
-const Vector2 = extern struct { x: f32, y: f32 };
+extern fn c_ret_vector_512_bool() @Vector(512, bool);
+extern fn c_vector_512_bool(@Vector(512, bool)) void;
+extern fn c_test_vector_512_bool() void;
-extern fn c_ptr_size_float_struct(Vector2) void;
-extern fn c_ret_ptr_size_float_struct() Vector2;
+test "@Vector(512, bool)" {
+ if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest;
-test "C ABI pointer sized float struct" {
+ const vec = c_ret_vector_512_bool();
+ try expect(vec[0] == false);
+ try expect(vec[1] == true);
+ try expect(vec[2] == false);
+ try expect(vec[3] == false);
+ try expect(vec[4] == false);
+ try expect(vec[5] == true);
+ try expect(vec[6] == false);
+ try expect(vec[7] == false);
+ try expect(vec[8] == false);
+ try expect(vec[9] == true);
+ try expect(vec[10] == false);
+ try expect(vec[11] == false);
+ try expect(vec[12] == false);
+ try expect(vec[13] == true);
+ try expect(vec[14] == false);
+ try expect(vec[15] == true);
+ try expect(vec[16] == false);
+ try expect(vec[17] == false);
+ try expect(vec[18] == false);
+ try expect(vec[19] == false);
+ try expect(vec[20] == false);
+ try expect(vec[21] == false);
+ try expect(vec[22] == true);
+ try expect(vec[23] == true);
+ try expect(vec[24] == false);
+ try expect(vec[25] == false);
+ try expect(vec[26] == false);
+ try expect(vec[27] == false);
+ try expect(vec[28] == true);
+ try expect(vec[29] == true);
+ try expect(vec[30] == false);
+ try expect(vec[31] == true);
+ try expect(vec[32] == false);
+ try expect(vec[33] == true);
+ try expect(vec[34] == true);
+ try expect(vec[35] == true);
+ try expect(vec[36] == false);
+ try expect(vec[37] == false);
+ try expect(vec[38] == true);
+ try expect(vec[39] == true);
+ try expect(vec[40] == false);
+ try expect(vec[41] == false);
+ try expect(vec[42] == false);
+ try expect(vec[43] == false);
+ try expect(vec[44] == false);
+ try expect(vec[45] == true);
+ try expect(vec[46] == false);
+ try expect(vec[47] == true);
+ try expect(vec[48] == true);
+ try expect(vec[49] == false);
+ try expect(vec[50] == true);
+ try expect(vec[51] == true);
+ try expect(vec[52] == true);
+ try expect(vec[53] == true);
+ try expect(vec[54] == false);
+ try expect(vec[55] == false);
+ try expect(vec[56] == false);
+ try expect(vec[57] == true);
+ try expect(vec[58] == true);
+ try expect(vec[59] == false);
+ try expect(vec[60] == false);
+ try expect(vec[61] == false);
+ try expect(vec[62] == false);
+ try expect(vec[63] == true);
+ try expect(vec[64] == true);
+ try expect(vec[65] == true);
+ try expect(vec[66] == true);
+ try expect(vec[67] == true);
+ try expect(vec[68] == false);
+ try expect(vec[69] == false);
+ try expect(vec[70] == false);
+ try expect(vec[71] == false);
+ try expect(vec[72] == false);
+ try expect(vec[73] == true);
+ try expect(vec[74] == false);
+ try expect(vec[75] == true);
+ try expect(vec[76] == false);
+ try expect(vec[77] == false);
+ try expect(vec[78] == true);
+ try expect(vec[79] == true);
+ try expect(vec[80] == false);
+ try expect(vec[81] == false);
+ try expect(vec[82] == false);
+ try expect(vec[83] == true);
+ try expect(vec[84] == false);
+ try expect(vec[85] == true);
+ try expect(vec[86] == true);
+ try expect(vec[87] == true);
+ try expect(vec[88] == false);
+ try expect(vec[89] == true);
+ try expect(vec[90] == false);
+ try expect(vec[91] == false);
+ try expect(vec[92] == true);
+ try expect(vec[93] == true);
+ try expect(vec[94] == false);
+ try expect(vec[95] == true);
+ try expect(vec[96] == true);
+ try expect(vec[97] == false);
+ try expect(vec[98] == true);
+ try expect(vec[99] == false);
+ try expect(vec[100] == true);
+ try expect(vec[101] == true);
+ try expect(vec[102] == false);
+ try expect(vec[103] == true);
+ try expect(vec[104] == true);
+ try expect(vec[105] == false);
+ try expect(vec[106] == false);
+ try expect(vec[107] == false);
+ try expect(vec[108] == true);
+ try expect(vec[109] == false);
+ try expect(vec[110] == false);
+ try expect(vec[111] == false);
+ try expect(vec[112] == true);
+ try expect(vec[113] == true);
+ try expect(vec[114] == true);
+ try expect(vec[115] == false);
+ try expect(vec[116] == true);
+ try expect(vec[117] == false);
+ try expect(vec[118] == true);
+ try expect(vec[119] == false);
+ try expect(vec[120] == true);
+ try expect(vec[121] == true);
+ try expect(vec[122] == false);
+ try expect(vec[123] == true);
+ try expect(vec[124] == false);
+ try expect(vec[125] == true);
+ try expect(vec[126] == true);
+ try expect(vec[127] == true);
+ try expect(vec[128] == false);
+ try expect(vec[129] == true);
+ try expect(vec[130] == false);
+ try expect(vec[131] == false);
+ try expect(vec[132] == false);
+ try expect(vec[133] == false);
+ try expect(vec[134] == false);
+ try expect(vec[135] == false);
+ try expect(vec[136] == true);
+ try expect(vec[137] == false);
+ try expect(vec[138] == true);
+ try expect(vec[139] == false);
+ try expect(vec[140] == true);
+ try expect(vec[141] == true);
+ try expect(vec[142] == false);
+ try expect(vec[143] == true);
+ try expect(vec[144] == false);
+ try expect(vec[145] == false);
+ try expect(vec[146] == true);
+ try expect(vec[147] == false);
+ try expect(vec[148] == false);
+ try expect(vec[149] == true);
+ try expect(vec[150] == false);
+ try expect(vec[151] == true);
+ try expect(vec[152] == false);
+ try expect(vec[153] == true);
+ try expect(vec[154] == false);
+ try expect(vec[155] == false);
+ try expect(vec[156] == true);
+ try expect(vec[157] == false);
+ try expect(vec[158] == true);
+ try expect(vec[159] == true);
+ try expect(vec[160] == true);
+ try expect(vec[161] == false);
+ try expect(vec[162] == false);
+ try expect(vec[163] == true);
+ try expect(vec[164] == false);
+ try expect(vec[165] == false);
+ try expect(vec[166] == false);
+ try expect(vec[167] == true);
+ try expect(vec[168] == true);
+ try expect(vec[169] == true);
+ try expect(vec[170] == false);
+ try expect(vec[171] == true);
+ try expect(vec[172] == false);
+ try expect(vec[173] == false);
+ try expect(vec[174] == false);
+ try expect(vec[175] == false);
+ try expect(vec[176] == false);
+ try expect(vec[177] == true);
+ try expect(vec[178] == true);
+ try expect(vec[179] == false);
+ try expect(vec[180] == false);
+ try expect(vec[181] == true);
+ try expect(vec[182] == false);
+ try expect(vec[183] == false);
+ try expect(vec[184] == false);
+ try expect(vec[185] == false);
+ try expect(vec[186] == false);
+ try expect(vec[187] == true);
+ try expect(vec[188] == true);
+ try expect(vec[189] == false);
+ try expect(vec[190] == false);
+ try expect(vec[191] == false);
+ try expect(vec[192] == false);
+ try expect(vec[193] == false);
+ try expect(vec[194] == false);
+ try expect(vec[195] == true);
+ try expect(vec[196] == true);
+ try expect(vec[197] == false);
+ try expect(vec[198] == true);
+ try expect(vec[199] == true);
+ try expect(vec[200] == true);
+ try expect(vec[201] == true);
+ try expect(vec[202] == true);
+ try expect(vec[203] == true);
+ try expect(vec[204] == false);
+ try expect(vec[205] == false);
+ try expect(vec[206] == false);
+ try expect(vec[207] == false);
+ try expect(vec[208] == true);
+ try expect(vec[209] == false);
+ try expect(vec[210] == true);
+ try expect(vec[211] == true);
+ try expect(vec[212] == true);
+ try expect(vec[213] == true);
+ try expect(vec[214] == false);
+ try expect(vec[215] == false);
+ try expect(vec[216] == false);
+ try expect(vec[217] == true);
+ try expect(vec[218] == true);
+ try expect(vec[219] == false);
+ try expect(vec[220] == true);
+ try expect(vec[221] == true);
+ try expect(vec[222] == false);
+ try expect(vec[223] == false);
+ try expect(vec[224] == false);
+ try expect(vec[225] == true);
+ try expect(vec[226] == true);
+ try expect(vec[227] == true);
+ try expect(vec[228] == true);
+ try expect(vec[229] == false);
+ try expect(vec[230] == true);
+ try expect(vec[231] == false);
+ try expect(vec[232] == true);
+ try expect(vec[233] == true);
+ try expect(vec[234] == true);
+ try expect(vec[235] == true);
+ try expect(vec[236] == false);
+ try expect(vec[237] == true);
+ try expect(vec[238] == false);
+ try expect(vec[239] == true);
+ try expect(vec[240] == false);
+ try expect(vec[241] == true);
+ try expect(vec[242] == false);
+ try expect(vec[243] == false);
+ try expect(vec[244] == false);
+ try expect(vec[245] == true);
+ try expect(vec[246] == true);
+ try expect(vec[247] == false);
+ try expect(vec[248] == true);
+ try expect(vec[249] == false);
+ try expect(vec[250] == false);
+ try expect(vec[251] == false);
+ try expect(vec[252] == true);
+ try expect(vec[253] == true);
+ try expect(vec[254] == true);
+ try expect(vec[255] == true);
+ try expect(vec[256] == true);
+ try expect(vec[257] == false);
+ try expect(vec[258] == true);
+ try expect(vec[259] == true);
+ try expect(vec[260] == true);
+ try expect(vec[261] == true);
+ try expect(vec[262] == false);
+ try expect(vec[263] == true);
+ try expect(vec[264] == false);
+ try expect(vec[265] == false);
+ try expect(vec[266] == true);
+ try expect(vec[267] == false);
+ try expect(vec[268] == true);
+ try expect(vec[269] == false);
+ try expect(vec[270] == false);
+ try expect(vec[271] == true);
+ try expect(vec[272] == true);
+ try expect(vec[273] == false);
+ try expect(vec[274] == true);
+ try expect(vec[275] == false);
+ try expect(vec[276] == false);
+ try expect(vec[277] == true);
+ try expect(vec[278] == false);
+ try expect(vec[279] == false);
+ try expect(vec[280] == true);
+ try expect(vec[281] == true);
+ try expect(vec[282] == true);
+ try expect(vec[283] == false);
+ try expect(vec[284] == false);
+ try expect(vec[285] == true);
+ try expect(vec[286] == true);
+ try expect(vec[287] == true);
+ try expect(vec[288] == false);
+ try expect(vec[289] == false);
+ try expect(vec[290] == false);
+ try expect(vec[291] == false);
+ try expect(vec[292] == false);
+ try expect(vec[293] == false);
+ try expect(vec[294] == true);
+ try expect(vec[295] == false);
+ try expect(vec[296] == true);
+ try expect(vec[297] == false);
+ try expect(vec[298] == true);
+ try expect(vec[299] == true);
+ try expect(vec[300] == false);
+ try expect(vec[301] == false);
+ try expect(vec[302] == false);
+ try expect(vec[303] == false);
+ try expect(vec[304] == true);
+ try expect(vec[305] == true);
+ try expect(vec[306] == true);
+ try expect(vec[307] == true);
+ try expect(vec[308] == true);
+ try expect(vec[309] == false);
+ try expect(vec[310] == true);
+ try expect(vec[311] == true);
+ try expect(vec[312] == true);
+ try expect(vec[313] == true);
+ try expect(vec[314] == true);
+ try expect(vec[315] == false);
+ try expect(vec[316] == true);
+ try expect(vec[317] == true);
+ try expect(vec[318] == true);
+ try expect(vec[319] == false);
+ try expect(vec[320] == true);
+ try expect(vec[321] == false);
+ try expect(vec[322] == true);
+ try expect(vec[323] == true);
+ try expect(vec[324] == true);
+ try expect(vec[325] == false);
+ try expect(vec[326] == false);
+ try expect(vec[327] == true);
+ try expect(vec[328] == true);
+ try expect(vec[329] == true);
+ try expect(vec[330] == false);
+ try expect(vec[331] == false);
+ try expect(vec[332] == true);
+ try expect(vec[333] == true);
+ try expect(vec[334] == false);
+ try expect(vec[335] == true);
+ try expect(vec[336] == true);
+ try expect(vec[337] == true);
+ try expect(vec[338] == true);
+ try expect(vec[339] == true);
+ try expect(vec[340] == true);
+ try expect(vec[341] == false);
+ try expect(vec[342] == true);
+ try expect(vec[343] == false);
+ try expect(vec[344] == true);
+ try expect(vec[345] == false);
+ try expect(vec[346] == false);
+ try expect(vec[347] == false);
+ try expect(vec[348] == false);
+ try expect(vec[349] == true);
+ try expect(vec[350] == true);
+ try expect(vec[351] == true);
+ try expect(vec[352] == true);
+ try expect(vec[353] == false);
+ try expect(vec[354] == true);
+ try expect(vec[355] == false);
+ try expect(vec[356] == true);
+ try expect(vec[357] == true);
+ try expect(vec[358] == false);
+ try expect(vec[359] == true);
+ try expect(vec[360] == false);
+ try expect(vec[361] == false);
+ try expect(vec[362] == true);
+ try expect(vec[363] == false);
+ try expect(vec[364] == false);
+ try expect(vec[365] == false);
+ try expect(vec[366] == false);
+ try expect(vec[367] == false);
+ try expect(vec[368] == false);
+ try expect(vec[369] == false);
+ try expect(vec[370] == true);
+ try expect(vec[371] == false);
+ try expect(vec[372] == true);
+ try expect(vec[373] == true);
+ try expect(vec[374] == false);
+ try expect(vec[375] == false);
+ try expect(vec[376] == true);
+ try expect(vec[377] == false);
+ try expect(vec[378] == false);
+ try expect(vec[379] == true);
+ try expect(vec[380] == false);
+ try expect(vec[381] == false);
+ try expect(vec[382] == true);
+ try expect(vec[383] == false);
+ try expect(vec[384] == false);
+ try expect(vec[385] == false);
+ try expect(vec[386] == false);
+ try expect(vec[387] == true);
+ try expect(vec[388] == true);
+ try expect(vec[389] == true);
+ try expect(vec[390] == true);
+ try expect(vec[391] == true);
+ try expect(vec[392] == true);
+ try expect(vec[393] == true);
+ try expect(vec[394] == false);
+ try expect(vec[395] == true);
+ try expect(vec[396] == true);
+ try expect(vec[397] == false);
+ try expect(vec[398] == false);
+ try expect(vec[399] == false);
+ try expect(vec[400] == true);
+ try expect(vec[401] == false);
+ try expect(vec[402] == true);
+ try expect(vec[403] == true);
+ try expect(vec[404] == false);
+ try expect(vec[405] == true);
+ try expect(vec[406] == true);
+ try expect(vec[407] == true);
+ try expect(vec[408] == true);
+ try expect(vec[409] == false);
+ try expect(vec[410] == false);
+ try expect(vec[411] == false);
+ try expect(vec[412] == true);
+ try expect(vec[413] == true);
+ try expect(vec[414] == false);
+ try expect(vec[415] == true);
+ try expect(vec[416] == false);
+ try expect(vec[417] == true);
+ try expect(vec[418] == false);
+ try expect(vec[419] == false);
+ try expect(vec[420] == false);
+ try expect(vec[421] == false);
+ try expect(vec[422] == true);
+ try expect(vec[423] == true);
+ try expect(vec[424] == true);
+ try expect(vec[425] == false);
+ try expect(vec[426] == true);
+ try expect(vec[427] == false);
+ try expect(vec[428] == false);
+ try expect(vec[429] == false);
+ try expect(vec[430] == true);
+ try expect(vec[431] == true);
+ try expect(vec[432] == false);
+ try expect(vec[433] == true);
+ try expect(vec[434] == false);
+ try expect(vec[435] == false);
+ try expect(vec[436] == true);
+ try expect(vec[437] == true);
+ try expect(vec[438] == true);
+ try expect(vec[439] == true);
+ try expect(vec[440] == true);
+ try expect(vec[441] == true);
+ try expect(vec[442] == false);
+ try expect(vec[443] == false);
+ try expect(vec[444] == false);
+ try expect(vec[445] == true);
+ try expect(vec[446] == true);
+ try expect(vec[447] == true);
+ try expect(vec[448] == false);
+ try expect(vec[449] == false);
+ try expect(vec[450] == false);
+ try expect(vec[451] == false);
+ try expect(vec[452] == false);
+ try expect(vec[453] == false);
+ try expect(vec[454] == false);
+ try expect(vec[455] == false);
+ try expect(vec[456] == false);
+ try expect(vec[457] == false);
+ try expect(vec[458] == false);
+ try expect(vec[459] == true);
+ try expect(vec[460] == false);
+ try expect(vec[461] == false);
+ try expect(vec[462] == false);
+ try expect(vec[463] == true);
+ try expect(vec[464] == false);
+ try expect(vec[465] == false);
+ try expect(vec[466] == false);
+ try expect(vec[467] == false);
+ try expect(vec[468] == true);
+ try expect(vec[469] == true);
+ try expect(vec[470] == true);
+ try expect(vec[471] == true);
+ try expect(vec[472] == true);
+ try expect(vec[473] == false);
+ try expect(vec[474] == false);
+ try expect(vec[475] == true);
+ try expect(vec[476] == true);
+ try expect(vec[477] == true);
+ try expect(vec[478] == false);
+ try expect(vec[479] == true);
+ try expect(vec[480] == true);
+ try expect(vec[481] == true);
+ try expect(vec[482] == false);
+ try expect(vec[483] == true);
+ try expect(vec[484] == false);
+ try expect(vec[485] == true);
+ try expect(vec[486] == false);
+ try expect(vec[487] == true);
+ try expect(vec[488] == false);
+ try expect(vec[489] == true);
+ try expect(vec[490] == true);
+ try expect(vec[491] == true);
+ try expect(vec[492] == true);
+ try expect(vec[493] == false);
+ try expect(vec[494] == true);
+ try expect(vec[495] == true);
+ try expect(vec[496] == false);
+ try expect(vec[497] == true);
+ try expect(vec[498] == false);
+ try expect(vec[499] == false);
+ try expect(vec[500] == false);
+ try expect(vec[501] == false);
+ try expect(vec[502] == false);
+ try expect(vec[503] == false);
+ try expect(vec[504] == false);
+ try expect(vec[505] == false);
+ try expect(vec[506] == false);
+ try expect(vec[507] == true);
+ try expect(vec[508] == true);
+ try expect(vec[509] == false);
+ try expect(vec[510] == true);
+ try expect(vec[511] == false);
+ if (!builtin.target.cpu.arch.isWasm()) c_vector_512_bool(.{
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ false,
+ true,
+ });
+ c_test_vector_512_bool();
+}
+
+export fn zig_ret_vector_1_u8() @Vector(1, u8) {
+ return .{1};
+}
+export fn zig_vector_1_u8(v: @Vector(1, u8), i: usize) void {
+ expect(v[0] == 2) catch @panic("test failure");
+ expect(i == 1) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_1_u8() @Vector(1, u8);
+extern fn c_vector_1_u8(@Vector(1, u8), usize) void;
+extern fn c_test_vector_1_u8() void;
+
+test "@Vector(1, u8)" {
+ if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+
+ const v = c_ret_vector_1_u8();
+ try expect(v[0] == 3);
+ c_vector_1_u8(.{4}, 1);
+ c_test_vector_1_u8();
+}
+
+export fn zig_ret_vector_2_u8() @Vector(2, u8) {
+ return .{ 5, 6 };
+}
+export fn zig_vector_2_u8(v: @Vector(2, u8), i: usize) void {
+ expect(v[0] == 7) catch @panic("test failure");
+ expect(v[1] == 8) catch @panic("test failure");
+ expect(i == 2) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_2_u8() @Vector(2, u8);
+extern fn c_vector_2_u8(@Vector(2, u8), usize) void;
+extern fn c_test_vector_2_u8() void;
+
+test "@Vector(2, u8)" {
+ if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest;
+
+ const v = c_ret_vector_2_u8();
+ try expect(v[0] == 9);
+ try expect(v[1] == 10);
+ c_vector_2_u8(.{ 11, 12 }, 2);
+ c_test_vector_2_u8();
+}
+
+export fn zig_ret_vector_3_u8() @Vector(3, u8) {
+ return .{ 13, 14, 15 };
+}
+export fn zig_vector_3_u8(v: @Vector(3, u8), i: usize) void {
+ expect(v[0] == 16) catch @panic("test failure");
+ expect(v[1] == 17) catch @panic("test failure");
+ expect(v[2] == 18) catch @panic("test failure");
+ expect(i == 3) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_3_u8() @Vector(3, u8);
+extern fn c_vector_3_u8(@Vector(3, u8), usize) void;
+extern fn c_test_vector_3_u8() void;
+
+test "@Vector(3, u8)" {
+ if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest;
+
+ const v = c_ret_vector_3_u8();
+ try expect(v[0] == 19);
+ try expect(v[1] == 20);
+ try expect(v[2] == 21);
+ c_vector_3_u8(.{ 22, 23, 24 }, 3);
+ c_test_vector_3_u8();
+}
+
+export fn zig_ret_vector_4_u8() @Vector(4, u8) {
+ return .{ 25, 26, 27, 28 };
+}
+export fn zig_vector_4_u8(v: @Vector(4, u8), i: usize) void {
+ expect(v[0] == 29) catch @panic("test failure");
+ expect(v[1] == 30) catch @panic("test failure");
+ expect(v[2] == 31) catch @panic("test failure");
+ expect(v[3] == 32) catch @panic("test failure");
+ expect(i == 4) catch @panic("test failure");
+}
+export fn zig_vector_4_u8_vector_4_u8(v0: @Vector(4, u8), v1: @Vector(4, u8), i: usize) void {
+ expect(v0[0] == 33) catch @panic("test failure");
+ expect(v0[1] == 34) catch @panic("test failure");
+ expect(v0[2] == 35) catch @panic("test failure");
+ expect(v0[3] == 36) catch @panic("test failure");
+ expect(v1[0] == 37) catch @panic("test failure");
+ expect(v1[1] == 38) catch @panic("test failure");
+ expect(v1[2] == 39) catch @panic("test failure");
+ expect(v1[3] == 40) catch @panic("test failure");
+ expect(i == 8) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_4_u8() @Vector(4, u8);
+extern fn c_vector_4_u8(@Vector(4, u8), usize) void;
+extern fn c_vector_4_u8_vector_4_u8(@Vector(4, u8), @Vector(4, u8), usize) void;
+extern fn c_test_vector_4_u8() void;
+
+test "@Vector(4, u8)" {
+ if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest;
+
+ const v = c_ret_vector_4_u8();
+ try expect(v[0] == 41);
+ try expect(v[1] == 42);
+ try expect(v[2] == 43);
+ try expect(v[3] == 44);
+ c_vector_4_u8(.{ 45, 46, 47, 48 }, 4);
+ c_vector_4_u8_vector_4_u8(.{ 49, 50, 51, 52 }, .{ 53, 54, 55, 56 }, 8);
+ c_test_vector_4_u8();
+}
+
+export fn zig_ret_vector_6_u8() @Vector(6, u8) {
+ return .{ 41, 42, 43, 44, 45, 46 };
+}
+export fn zig_vector_6_u8(v: @Vector(6, u8), i: usize) void {
+ expect(v[0] == 47) catch @panic("test failure");
+ expect(v[1] == 48) catch @panic("test failure");
+ expect(v[2] == 49) catch @panic("test failure");
+ expect(v[3] == 50) catch @panic("test failure");
+ expect(v[4] == 51) catch @panic("test failure");
+ expect(v[5] == 52) catch @panic("test failure");
+ expect(i == 6) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_6_u8() @Vector(6, u8);
+extern fn c_vector_6_u8(@Vector(6, u8), usize) void;
+extern fn c_test_vector_6_u8() void;
+
+test "@Vector(6, u8)" {
+ if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest;
+
+ const v = c_ret_vector_6_u8();
+ try expect(v[0] == 53);
+ try expect(v[1] == 54);
+ try expect(v[2] == 55);
+ try expect(v[3] == 56);
+ try expect(v[4] == 57);
+ try expect(v[5] == 58);
+ c_vector_6_u8(.{ 59, 60, 61, 62, 63, 64 }, 6);
+ c_test_vector_6_u8();
+}
+
+export fn zig_ret_vector_8_u8() @Vector(8, u8) {
+ return .{ 65, 66, 67, 68, 69, 70, 71, 72 };
+}
+export fn zig_vector_8_u8(v: @Vector(8, u8), i: usize) void {
+ expect(v[0] == 73) catch @panic("test failure");
+ expect(v[1] == 74) catch @panic("test failure");
+ expect(v[2] == 75) catch @panic("test failure");
+ expect(v[3] == 76) catch @panic("test failure");
+ expect(v[4] == 77) catch @panic("test failure");
+ expect(v[5] == 78) catch @panic("test failure");
+ expect(v[6] == 79) catch @panic("test failure");
+ expect(v[7] == 80) catch @panic("test failure");
+ expect(i == 8) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_8_u8() @Vector(8, u8);
+extern fn c_vector_8_u8(@Vector(8, u8), usize) void;
+extern fn c_test_vector_8_u8() void;
+
+test "@Vector(8, u8)" {
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest;
+
+ const v = c_ret_vector_8_u8();
+ try expect(v[0] == 81);
+ try expect(v[1] == 82);
+ try expect(v[2] == 83);
+ try expect(v[3] == 84);
+ try expect(v[4] == 85);
+ try expect(v[5] == 86);
+ try expect(v[6] == 87);
+ try expect(v[7] == 88);
+ c_vector_8_u8(.{ 89, 90, 91, 92, 93, 94, 95, 96 }, 8);
+ c_test_vector_8_u8();
+}
+
+export fn zig_ret_vector_12_u8() @Vector(12, u8) {
+ return .{ 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8 };
+}
+export fn zig_vector_12_u8(v: @Vector(12, u8), i: usize) void {
+ expect(v[0] == 9) catch @panic("test failure");
+ expect(v[1] == 10) catch @panic("test failure");
+ expect(v[2] == 11) catch @panic("test failure");
+ expect(v[3] == 12) catch @panic("test failure");
+ expect(v[4] == 13) catch @panic("test failure");
+ expect(v[5] == 14) catch @panic("test failure");
+ expect(v[6] == 15) catch @panic("test failure");
+ expect(v[7] == 16) catch @panic("test failure");
+ expect(v[8] == 17) catch @panic("test failure");
+ expect(v[9] == 18) catch @panic("test failure");
+ expect(v[10] == 19) catch @panic("test failure");
+ expect(v[11] == 20) catch @panic("test failure");
+ expect(i == 12) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_12_u8() @Vector(12, u8);
+extern fn c_vector_12_u8(@Vector(12, u8), usize) void;
+extern fn c_test_vector_12_u8() void;
+
+test "@Vector(12, u8)" {
+ if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+
+ const v = c_ret_vector_12_u8();
+ try expect(v[0] == 21);
+ try expect(v[1] == 22);
+ try expect(v[2] == 23);
+ try expect(v[3] == 24);
+ try expect(v[4] == 25);
+ try expect(v[5] == 26);
+ try expect(v[6] == 27);
+ try expect(v[7] == 28);
+ try expect(v[8] == 29);
+ try expect(v[9] == 30);
+ try expect(v[10] == 31);
+ try expect(v[11] == 32);
+ c_vector_12_u8(.{ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44 }, 12);
+ c_test_vector_12_u8();
+}
+
+export fn zig_ret_vector_16_u8() @Vector(16, u8) {
+ return .{ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 };
+}
+export fn zig_vector_16_u8(v: @Vector(16, u8), i: usize) void {
+ expect(v[0] == 61) catch @panic("test failure");
+ expect(v[1] == 62) catch @panic("test failure");
+ expect(v[2] == 63) catch @panic("test failure");
+ expect(v[3] == 64) catch @panic("test failure");
+ expect(v[4] == 65) catch @panic("test failure");
+ expect(v[5] == 66) catch @panic("test failure");
+ expect(v[6] == 67) catch @panic("test failure");
+ expect(v[7] == 68) catch @panic("test failure");
+ expect(v[8] == 69) catch @panic("test failure");
+ expect(v[9] == 70) catch @panic("test failure");
+ expect(v[10] == 71) catch @panic("test failure");
+ expect(v[11] == 72) catch @panic("test failure");
+ expect(v[12] == 73) catch @panic("test failure");
+ expect(v[13] == 74) catch @panic("test failure");
+ expect(v[14] == 75) catch @panic("test failure");
+ expect(v[15] == 76) catch @panic("test failure");
+ expect(i == 16) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_16_u8() @Vector(16, u8);
+extern fn c_vector_16_u8(@Vector(16, u8), usize) void;
+extern fn c_test_vector_16_u8() void;
+
+test "@Vector(16, u8)" {
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+
+ const v = c_ret_vector_16_u8();
+ try expect(v[0] == 77);
+ try expect(v[1] == 78);
+ try expect(v[2] == 79);
+ try expect(v[3] == 80);
+ try expect(v[4] == 81);
+ try expect(v[5] == 82);
+ try expect(v[6] == 83);
+ try expect(v[7] == 84);
+ try expect(v[8] == 85);
+ try expect(v[9] == 86);
+ try expect(v[10] == 87);
+ try expect(v[11] == 88);
+ try expect(v[12] == 89);
+ try expect(v[13] == 90);
+ try expect(v[14] == 91);
+ try expect(v[15] == 92);
+ c_vector_16_u8(.{ 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8 }, 16);
+ c_test_vector_16_u8();
+}
+
+export fn zig_ret_vector_24_u8() @Vector(24, u8) {
+ return .{
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32,
+ };
+}
+export fn zig_vector_24_u8(v: @Vector(24, u8), i: usize) void {
+ expect(v[0] == 33) catch @panic("test failure");
+ expect(v[1] == 34) catch @panic("test failure");
+ expect(v[2] == 35) catch @panic("test failure");
+ expect(v[3] == 36) catch @panic("test failure");
+ expect(v[4] == 37) catch @panic("test failure");
+ expect(v[5] == 38) catch @panic("test failure");
+ expect(v[6] == 39) catch @panic("test failure");
+ expect(v[7] == 40) catch @panic("test failure");
+ expect(v[8] == 41) catch @panic("test failure");
+ expect(v[9] == 42) catch @panic("test failure");
+ expect(v[10] == 43) catch @panic("test failure");
+ expect(v[11] == 44) catch @panic("test failure");
+ expect(v[12] == 45) catch @panic("test failure");
+ expect(v[13] == 46) catch @panic("test failure");
+ expect(v[14] == 47) catch @panic("test failure");
+ expect(v[15] == 48) catch @panic("test failure");
+ expect(v[16] == 49) catch @panic("test failure");
+ expect(v[17] == 50) catch @panic("test failure");
+ expect(v[18] == 51) catch @panic("test failure");
+ expect(v[19] == 52) catch @panic("test failure");
+ expect(v[20] == 53) catch @panic("test failure");
+ expect(v[21] == 54) catch @panic("test failure");
+ expect(v[22] == 55) catch @panic("test failure");
+ expect(v[23] == 56) catch @panic("test failure");
+ expect(i == 24) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_24_u8() @Vector(24, u8);
+extern fn c_vector_24_u8(@Vector(24, u8), usize) void;
+extern fn c_test_vector_24_u8() void;
+
+test "@Vector(24, u8)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_24_u8();
+ try expect(v[0] == 57);
+ try expect(v[1] == 58);
+ try expect(v[2] == 59);
+ try expect(v[3] == 60);
+ try expect(v[4] == 61);
+ try expect(v[5] == 62);
+ try expect(v[6] == 63);
+ try expect(v[7] == 64);
+ try expect(v[8] == 65);
+ try expect(v[9] == 66);
+ try expect(v[10] == 67);
+ try expect(v[11] == 68);
+ try expect(v[12] == 69);
+ try expect(v[13] == 70);
+ try expect(v[14] == 71);
+ try expect(v[15] == 72);
+ try expect(v[16] == 73);
+ try expect(v[17] == 74);
+ try expect(v[18] == 75);
+ try expect(v[19] == 76);
+ try expect(v[20] == 77);
+ try expect(v[21] == 78);
+ try expect(v[22] == 79);
+ try expect(v[23] == 80);
+ c_vector_24_u8(.{
+ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 0, 1, 2, 3, 4,
+ }, 24);
+ c_test_vector_24_u8();
+}
+
+export fn zig_ret_vector_32_u8() @Vector(32, u8) {
+ return .{
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ };
+}
+export fn zig_vector_32_u8(v: @Vector(32, u8), i: usize) void {
+ expect(v[0] == 37) catch @panic("test failure");
+ expect(v[1] == 38) catch @panic("test failure");
+ expect(v[2] == 39) catch @panic("test failure");
+ expect(v[3] == 40) catch @panic("test failure");
+ expect(v[4] == 41) catch @panic("test failure");
+ expect(v[5] == 42) catch @panic("test failure");
+ expect(v[6] == 43) catch @panic("test failure");
+ expect(v[7] == 44) catch @panic("test failure");
+ expect(v[8] == 45) catch @panic("test failure");
+ expect(v[9] == 46) catch @panic("test failure");
+ expect(v[10] == 47) catch @panic("test failure");
+ expect(v[11] == 48) catch @panic("test failure");
+ expect(v[12] == 49) catch @panic("test failure");
+ expect(v[13] == 50) catch @panic("test failure");
+ expect(v[14] == 51) catch @panic("test failure");
+ expect(v[15] == 52) catch @panic("test failure");
+ expect(v[16] == 53) catch @panic("test failure");
+ expect(v[17] == 54) catch @panic("test failure");
+ expect(v[18] == 55) catch @panic("test failure");
+ expect(v[19] == 56) catch @panic("test failure");
+ expect(v[20] == 57) catch @panic("test failure");
+ expect(v[21] == 58) catch @panic("test failure");
+ expect(v[22] == 59) catch @panic("test failure");
+ expect(v[23] == 60) catch @panic("test failure");
+ expect(v[24] == 61) catch @panic("test failure");
+ expect(v[25] == 62) catch @panic("test failure");
+ expect(v[26] == 63) catch @panic("test failure");
+ expect(v[27] == 64) catch @panic("test failure");
+ expect(v[28] == 65) catch @panic("test failure");
+ expect(v[29] == 66) catch @panic("test failure");
+ expect(v[30] == 67) catch @panic("test failure");
+ expect(v[31] == 68) catch @panic("test failure");
+ expect(i == 32) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_32_u8() @Vector(32, u8);
+extern fn c_vector_32_u8(@Vector(32, u8), usize) void;
+extern fn c_test_vector_32_u8() void;
+
+test "@Vector(32, u8)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_32_u8();
+ try expect(v[0] == 69);
+ try expect(v[1] == 70);
+ try expect(v[2] == 71);
+ try expect(v[3] == 72);
+ try expect(v[4] == 73);
+ try expect(v[5] == 74);
+ try expect(v[6] == 75);
+ try expect(v[7] == 76);
+ try expect(v[8] == 77);
+ try expect(v[9] == 78);
+ try expect(v[10] == 79);
+ try expect(v[11] == 80);
+ try expect(v[12] == 81);
+ try expect(v[13] == 82);
+ try expect(v[14] == 83);
+ try expect(v[15] == 84);
+ try expect(v[16] == 85);
+ try expect(v[17] == 86);
+ try expect(v[18] == 87);
+ try expect(v[19] == 88);
+ try expect(v[20] == 89);
+ try expect(v[21] == 90);
+ try expect(v[22] == 91);
+ try expect(v[23] == 92);
+ try expect(v[24] == 93);
+ try expect(v[25] == 94);
+ try expect(v[26] == 95);
+ try expect(v[27] == 96);
+ try expect(v[28] == 97);
+ try expect(v[29] == 98);
+ try expect(v[30] == 99);
+ try expect(v[31] == 0);
+ c_vector_32_u8(.{
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ }, 32);
+ c_test_vector_32_u8();
+}
+
+export fn zig_ret_vector_48_u8() @Vector(48, u8) {
+ return .{
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ };
+}
+export fn zig_vector_48_u8(v: @Vector(48, u8), i: usize) void {
+ expect(v[0] == 81) catch @panic("test failure");
+ expect(v[1] == 82) catch @panic("test failure");
+ expect(v[2] == 83) catch @panic("test failure");
+ expect(v[3] == 84) catch @panic("test failure");
+ expect(v[4] == 85) catch @panic("test failure");
+ expect(v[5] == 86) catch @panic("test failure");
+ expect(v[6] == 87) catch @panic("test failure");
+ expect(v[7] == 88) catch @panic("test failure");
+ expect(v[8] == 89) catch @panic("test failure");
+ expect(v[9] == 90) catch @panic("test failure");
+ expect(v[10] == 91) catch @panic("test failure");
+ expect(v[11] == 92) catch @panic("test failure");
+ expect(v[12] == 93) catch @panic("test failure");
+ expect(v[13] == 94) catch @panic("test failure");
+ expect(v[14] == 95) catch @panic("test failure");
+ expect(v[15] == 96) catch @panic("test failure");
+ expect(v[16] == 97) catch @panic("test failure");
+ expect(v[17] == 98) catch @panic("test failure");
+ expect(v[18] == 99) catch @panic("test failure");
+ expect(v[19] == 0) catch @panic("test failure");
+ expect(v[20] == 1) catch @panic("test failure");
+ expect(v[21] == 2) catch @panic("test failure");
+ expect(v[22] == 3) catch @panic("test failure");
+ expect(v[23] == 4) catch @panic("test failure");
+ expect(v[24] == 5) catch @panic("test failure");
+ expect(v[25] == 6) catch @panic("test failure");
+ expect(v[26] == 7) catch @panic("test failure");
+ expect(v[27] == 8) catch @panic("test failure");
+ expect(v[28] == 9) catch @panic("test failure");
+ expect(v[29] == 10) catch @panic("test failure");
+ expect(v[30] == 11) catch @panic("test failure");
+ expect(v[31] == 12) catch @panic("test failure");
+ expect(v[32] == 13) catch @panic("test failure");
+ expect(v[33] == 14) catch @panic("test failure");
+ expect(v[34] == 15) catch @panic("test failure");
+ expect(v[35] == 16) catch @panic("test failure");
+ expect(v[36] == 17) catch @panic("test failure");
+ expect(v[37] == 18) catch @panic("test failure");
+ expect(v[38] == 19) catch @panic("test failure");
+ expect(v[39] == 20) catch @panic("test failure");
+ expect(v[40] == 21) catch @panic("test failure");
+ expect(v[41] == 22) catch @panic("test failure");
+ expect(v[42] == 23) catch @panic("test failure");
+ expect(v[43] == 24) catch @panic("test failure");
+ expect(v[44] == 25) catch @panic("test failure");
+ expect(v[45] == 26) catch @panic("test failure");
+ expect(v[46] == 27) catch @panic("test failure");
+ expect(v[47] == 28) catch @panic("test failure");
+ expect(i == 48) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_48_u8() @Vector(48, u8);
+extern fn c_vector_48_u8(@Vector(48, u8), usize) void;
+extern fn c_test_vector_48_u8() void;
+
+test "@Vector(48, u8)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_48_u8();
+ try expect(v[0] == 29);
+ try expect(v[1] == 30);
+ try expect(v[2] == 31);
+ try expect(v[3] == 32);
+ try expect(v[4] == 33);
+ try expect(v[5] == 34);
+ try expect(v[6] == 35);
+ try expect(v[7] == 36);
+ try expect(v[8] == 37);
+ try expect(v[9] == 38);
+ try expect(v[10] == 39);
+ try expect(v[11] == 40);
+ try expect(v[12] == 41);
+ try expect(v[13] == 42);
+ try expect(v[14] == 43);
+ try expect(v[15] == 44);
+ try expect(v[16] == 45);
+ try expect(v[17] == 46);
+ try expect(v[18] == 47);
+ try expect(v[19] == 48);
+ try expect(v[20] == 49);
+ try expect(v[21] == 50);
+ try expect(v[22] == 51);
+ try expect(v[23] == 52);
+ try expect(v[24] == 53);
+ try expect(v[25] == 54);
+ try expect(v[26] == 55);
+ try expect(v[27] == 56);
+ try expect(v[28] == 57);
+ try expect(v[29] == 58);
+ try expect(v[30] == 59);
+ try expect(v[31] == 60);
+ try expect(v[32] == 61);
+ try expect(v[33] == 62);
+ try expect(v[34] == 63);
+ try expect(v[35] == 64);
+ try expect(v[36] == 65);
+ try expect(v[37] == 66);
+ try expect(v[38] == 67);
+ try expect(v[39] == 68);
+ try expect(v[40] == 69);
+ try expect(v[41] == 70);
+ try expect(v[42] == 71);
+ try expect(v[43] == 72);
+ try expect(v[44] == 73);
+ try expect(v[45] == 74);
+ try expect(v[46] == 75);
+ try expect(v[47] == 76);
+ c_vector_48_u8(.{
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ }, 48);
+ c_test_vector_48_u8();
+}
+
+export fn zig_ret_vector_64_u8() @Vector(64, u8) {
+ return .{
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ };
+}
+export fn zig_vector_64_u8(v: @Vector(64, u8), i: usize) void {
+ expect(v[0] == 89) catch @panic("test failure");
+ expect(v[1] == 90) catch @panic("test failure");
+ expect(v[2] == 91) catch @panic("test failure");
+ expect(v[3] == 92) catch @panic("test failure");
+ expect(v[4] == 93) catch @panic("test failure");
+ expect(v[5] == 94) catch @panic("test failure");
+ expect(v[6] == 95) catch @panic("test failure");
+ expect(v[7] == 96) catch @panic("test failure");
+ expect(v[8] == 97) catch @panic("test failure");
+ expect(v[9] == 98) catch @panic("test failure");
+ expect(v[10] == 99) catch @panic("test failure");
+ expect(v[11] == 0) catch @panic("test failure");
+ expect(v[12] == 1) catch @panic("test failure");
+ expect(v[13] == 2) catch @panic("test failure");
+ expect(v[14] == 3) catch @panic("test failure");
+ expect(v[15] == 4) catch @panic("test failure");
+ expect(v[16] == 5) catch @panic("test failure");
+ expect(v[17] == 6) catch @panic("test failure");
+ expect(v[18] == 7) catch @panic("test failure");
+ expect(v[19] == 8) catch @panic("test failure");
+ expect(v[20] == 9) catch @panic("test failure");
+ expect(v[21] == 10) catch @panic("test failure");
+ expect(v[22] == 11) catch @panic("test failure");
+ expect(v[23] == 12) catch @panic("test failure");
+ expect(v[24] == 13) catch @panic("test failure");
+ expect(v[25] == 14) catch @panic("test failure");
+ expect(v[26] == 15) catch @panic("test failure");
+ expect(v[27] == 16) catch @panic("test failure");
+ expect(v[28] == 17) catch @panic("test failure");
+ expect(v[29] == 18) catch @panic("test failure");
+ expect(v[30] == 19) catch @panic("test failure");
+ expect(v[31] == 20) catch @panic("test failure");
+ expect(v[32] == 21) catch @panic("test failure");
+ expect(v[33] == 22) catch @panic("test failure");
+ expect(v[34] == 23) catch @panic("test failure");
+ expect(v[35] == 24) catch @panic("test failure");
+ expect(v[36] == 25) catch @panic("test failure");
+ expect(v[37] == 26) catch @panic("test failure");
+ expect(v[38] == 27) catch @panic("test failure");
+ expect(v[39] == 28) catch @panic("test failure");
+ expect(v[40] == 29) catch @panic("test failure");
+ expect(v[41] == 30) catch @panic("test failure");
+ expect(v[42] == 31) catch @panic("test failure");
+ expect(v[43] == 32) catch @panic("test failure");
+ expect(v[44] == 33) catch @panic("test failure");
+ expect(v[45] == 34) catch @panic("test failure");
+ expect(v[46] == 35) catch @panic("test failure");
+ expect(v[47] == 36) catch @panic("test failure");
+ expect(v[48] == 37) catch @panic("test failure");
+ expect(v[49] == 38) catch @panic("test failure");
+ expect(v[50] == 39) catch @panic("test failure");
+ expect(v[51] == 40) catch @panic("test failure");
+ expect(v[52] == 41) catch @panic("test failure");
+ expect(v[53] == 42) catch @panic("test failure");
+ expect(v[54] == 43) catch @panic("test failure");
+ expect(v[55] == 44) catch @panic("test failure");
+ expect(v[56] == 45) catch @panic("test failure");
+ expect(v[57] == 46) catch @panic("test failure");
+ expect(v[58] == 47) catch @panic("test failure");
+ expect(v[59] == 48) catch @panic("test failure");
+ expect(v[60] == 49) catch @panic("test failure");
+ expect(v[61] == 50) catch @panic("test failure");
+ expect(v[62] == 51) catch @panic("test failure");
+ expect(v[63] == 52) catch @panic("test failure");
+ expect(i == 64) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_64_u8() @Vector(64, u8);
+extern fn c_vector_64_u8(@Vector(64, u8), usize) void;
+extern fn c_test_vector_64_u8() void;
+
+test "@Vector(64, u8)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_64_u8();
+ try expect(v[0] == 53);
+ try expect(v[1] == 54);
+ try expect(v[2] == 55);
+ try expect(v[3] == 56);
+ try expect(v[4] == 57);
+ try expect(v[5] == 58);
+ try expect(v[6] == 59);
+ try expect(v[7] == 60);
+ try expect(v[8] == 61);
+ try expect(v[9] == 62);
+ try expect(v[10] == 63);
+ try expect(v[11] == 64);
+ try expect(v[12] == 65);
+ try expect(v[13] == 66);
+ try expect(v[14] == 67);
+ try expect(v[15] == 68);
+ try expect(v[16] == 69);
+ try expect(v[17] == 70);
+ try expect(v[18] == 71);
+ try expect(v[19] == 72);
+ try expect(v[20] == 73);
+ try expect(v[21] == 74);
+ try expect(v[22] == 75);
+ try expect(v[23] == 76);
+ try expect(v[24] == 77);
+ try expect(v[25] == 78);
+ try expect(v[26] == 79);
+ try expect(v[27] == 80);
+ try expect(v[28] == 81);
+ try expect(v[29] == 82);
+ try expect(v[30] == 83);
+ try expect(v[31] == 84);
+ try expect(v[32] == 85);
+ try expect(v[33] == 86);
+ try expect(v[34] == 87);
+ try expect(v[35] == 88);
+ try expect(v[36] == 89);
+ try expect(v[37] == 90);
+ try expect(v[38] == 91);
+ try expect(v[39] == 92);
+ try expect(v[40] == 93);
+ try expect(v[41] == 94);
+ try expect(v[42] == 95);
+ try expect(v[43] == 96);
+ try expect(v[44] == 97);
+ try expect(v[45] == 98);
+ try expect(v[46] == 99);
+ try expect(v[47] == 0);
+ try expect(v[48] == 1);
+ try expect(v[49] == 2);
+ try expect(v[50] == 3);
+ try expect(v[51] == 4);
+ try expect(v[52] == 5);
+ try expect(v[53] == 6);
+ try expect(v[54] == 7);
+ try expect(v[55] == 8);
+ try expect(v[56] == 9);
+ try expect(v[57] == 10);
+ try expect(v[58] == 11);
+ try expect(v[59] == 12);
+ try expect(v[60] == 13);
+ try expect(v[61] == 14);
+ try expect(v[62] == 15);
+ try expect(v[63] == 16);
+ c_vector_64_u8(.{
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ }, 64);
+ c_test_vector_64_u8();
+}
+
+export fn zig_ret_vector_96_u8() @Vector(96, u8) {
+ return .{
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ };
+}
+export fn zig_vector_96_u8(v: @Vector(96, u8), i: usize) void {
+ expect(v[0] == 86) catch @panic("test failure");
+ expect(v[1] == 87) catch @panic("test failure");
+ expect(v[2] == 88) catch @panic("test failure");
+ expect(v[3] == 89) catch @panic("test failure");
+ expect(v[4] == 90) catch @panic("test failure");
+ expect(v[5] == 91) catch @panic("test failure");
+ expect(v[6] == 92) catch @panic("test failure");
+ expect(v[7] == 93) catch @panic("test failure");
+ expect(v[8] == 94) catch @panic("test failure");
+ expect(v[9] == 95) catch @panic("test failure");
+ expect(v[10] == 96) catch @panic("test failure");
+ expect(v[11] == 97) catch @panic("test failure");
+ expect(v[12] == 98) catch @panic("test failure");
+ expect(v[13] == 99) catch @panic("test failure");
+ expect(v[14] == 0) catch @panic("test failure");
+ expect(v[15] == 1) catch @panic("test failure");
+ expect(v[16] == 2) catch @panic("test failure");
+ expect(v[17] == 3) catch @panic("test failure");
+ expect(v[18] == 4) catch @panic("test failure");
+ expect(v[19] == 5) catch @panic("test failure");
+ expect(v[20] == 6) catch @panic("test failure");
+ expect(v[21] == 7) catch @panic("test failure");
+ expect(v[22] == 8) catch @panic("test failure");
+ expect(v[23] == 9) catch @panic("test failure");
+ expect(v[24] == 10) catch @panic("test failure");
+ expect(v[25] == 11) catch @panic("test failure");
+ expect(v[26] == 12) catch @panic("test failure");
+ expect(v[27] == 13) catch @panic("test failure");
+ expect(v[28] == 14) catch @panic("test failure");
+ expect(v[29] == 15) catch @panic("test failure");
+ expect(v[30] == 16) catch @panic("test failure");
+ expect(v[31] == 17) catch @panic("test failure");
+ expect(v[32] == 18) catch @panic("test failure");
+ expect(v[33] == 19) catch @panic("test failure");
+ expect(v[34] == 20) catch @panic("test failure");
+ expect(v[35] == 21) catch @panic("test failure");
+ expect(v[36] == 22) catch @panic("test failure");
+ expect(v[37] == 23) catch @panic("test failure");
+ expect(v[38] == 24) catch @panic("test failure");
+ expect(v[39] == 25) catch @panic("test failure");
+ expect(v[40] == 26) catch @panic("test failure");
+ expect(v[41] == 27) catch @panic("test failure");
+ expect(v[42] == 28) catch @panic("test failure");
+ expect(v[43] == 29) catch @panic("test failure");
+ expect(v[44] == 30) catch @panic("test failure");
+ expect(v[45] == 31) catch @panic("test failure");
+ expect(v[46] == 32) catch @panic("test failure");
+ expect(v[47] == 33) catch @panic("test failure");
+ expect(v[48] == 34) catch @panic("test failure");
+ expect(v[49] == 35) catch @panic("test failure");
+ expect(v[50] == 36) catch @panic("test failure");
+ expect(v[51] == 37) catch @panic("test failure");
+ expect(v[52] == 38) catch @panic("test failure");
+ expect(v[53] == 39) catch @panic("test failure");
+ expect(v[54] == 40) catch @panic("test failure");
+ expect(v[55] == 41) catch @panic("test failure");
+ expect(v[56] == 42) catch @panic("test failure");
+ expect(v[57] == 43) catch @panic("test failure");
+ expect(v[58] == 44) catch @panic("test failure");
+ expect(v[59] == 45) catch @panic("test failure");
+ expect(v[60] == 46) catch @panic("test failure");
+ expect(v[61] == 47) catch @panic("test failure");
+ expect(v[62] == 48) catch @panic("test failure");
+ expect(v[63] == 49) catch @panic("test failure");
+ expect(v[64] == 50) catch @panic("test failure");
+ expect(v[65] == 51) catch @panic("test failure");
+ expect(v[66] == 52) catch @panic("test failure");
+ expect(v[67] == 53) catch @panic("test failure");
+ expect(v[68] == 54) catch @panic("test failure");
+ expect(v[69] == 55) catch @panic("test failure");
+ expect(v[70] == 56) catch @panic("test failure");
+ expect(v[71] == 57) catch @panic("test failure");
+ expect(v[72] == 58) catch @panic("test failure");
+ expect(v[73] == 59) catch @panic("test failure");
+ expect(v[74] == 60) catch @panic("test failure");
+ expect(v[75] == 61) catch @panic("test failure");
+ expect(v[76] == 62) catch @panic("test failure");
+ expect(v[77] == 63) catch @panic("test failure");
+ expect(v[78] == 64) catch @panic("test failure");
+ expect(v[79] == 65) catch @panic("test failure");
+ expect(v[80] == 66) catch @panic("test failure");
+ expect(v[81] == 67) catch @panic("test failure");
+ expect(v[82] == 68) catch @panic("test failure");
+ expect(v[83] == 69) catch @panic("test failure");
+ expect(v[84] == 70) catch @panic("test failure");
+ expect(v[85] == 71) catch @panic("test failure");
+ expect(v[86] == 72) catch @panic("test failure");
+ expect(v[87] == 73) catch @panic("test failure");
+ expect(v[88] == 74) catch @panic("test failure");
+ expect(v[89] == 75) catch @panic("test failure");
+ expect(v[90] == 76) catch @panic("test failure");
+ expect(v[91] == 77) catch @panic("test failure");
+ expect(v[92] == 78) catch @panic("test failure");
+ expect(v[93] == 79) catch @panic("test failure");
+ expect(v[94] == 80) catch @panic("test failure");
+ expect(v[95] == 81) catch @panic("test failure");
+ expect(i == 96) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_96_u8() @Vector(96, u8);
+extern fn c_vector_96_u8(@Vector(96, u8), usize) void;
+extern fn c_test_vector_96_u8() void;
+
+test "@Vector(96, u8)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_96_u8();
+ try expect(v[0] == 82);
+ try expect(v[1] == 83);
+ try expect(v[2] == 84);
+ try expect(v[3] == 85);
+ try expect(v[4] == 86);
+ try expect(v[5] == 87);
+ try expect(v[6] == 88);
+ try expect(v[7] == 89);
+ try expect(v[8] == 90);
+ try expect(v[9] == 91);
+ try expect(v[10] == 92);
+ try expect(v[11] == 93);
+ try expect(v[12] == 94);
+ try expect(v[13] == 95);
+ try expect(v[14] == 96);
+ try expect(v[15] == 97);
+ try expect(v[16] == 98);
+ try expect(v[17] == 99);
+ try expect(v[18] == 0);
+ try expect(v[19] == 1);
+ try expect(v[20] == 2);
+ try expect(v[21] == 3);
+ try expect(v[22] == 4);
+ try expect(v[23] == 5);
+ try expect(v[24] == 6);
+ try expect(v[25] == 7);
+ try expect(v[26] == 8);
+ try expect(v[27] == 9);
+ try expect(v[28] == 10);
+ try expect(v[29] == 11);
+ try expect(v[30] == 12);
+ try expect(v[31] == 13);
+ try expect(v[32] == 14);
+ try expect(v[33] == 15);
+ try expect(v[34] == 16);
+ try expect(v[35] == 17);
+ try expect(v[36] == 18);
+ try expect(v[37] == 19);
+ try expect(v[38] == 20);
+ try expect(v[39] == 21);
+ try expect(v[40] == 22);
+ try expect(v[41] == 23);
+ try expect(v[42] == 24);
+ try expect(v[43] == 25);
+ try expect(v[44] == 26);
+ try expect(v[45] == 27);
+ try expect(v[46] == 28);
+ try expect(v[47] == 29);
+ try expect(v[48] == 30);
+ try expect(v[49] == 31);
+ try expect(v[50] == 32);
+ try expect(v[51] == 33);
+ try expect(v[52] == 34);
+ try expect(v[53] == 35);
+ try expect(v[54] == 36);
+ try expect(v[55] == 37);
+ try expect(v[56] == 38);
+ try expect(v[57] == 39);
+ try expect(v[58] == 40);
+ try expect(v[59] == 41);
+ try expect(v[60] == 42);
+ try expect(v[61] == 43);
+ try expect(v[62] == 44);
+ try expect(v[63] == 45);
+ try expect(v[64] == 46);
+ try expect(v[65] == 47);
+ try expect(v[66] == 48);
+ try expect(v[67] == 49);
+ try expect(v[68] == 50);
+ try expect(v[69] == 51);
+ try expect(v[70] == 52);
+ try expect(v[71] == 53);
+ try expect(v[72] == 54);
+ try expect(v[73] == 55);
+ try expect(v[74] == 56);
+ try expect(v[75] == 57);
+ try expect(v[76] == 58);
+ try expect(v[77] == 59);
+ try expect(v[78] == 60);
+ try expect(v[79] == 61);
+ try expect(v[80] == 62);
+ try expect(v[81] == 63);
+ try expect(v[82] == 64);
+ try expect(v[83] == 65);
+ try expect(v[84] == 66);
+ try expect(v[85] == 67);
+ try expect(v[86] == 68);
+ try expect(v[87] == 69);
+ try expect(v[88] == 70);
+ try expect(v[89] == 71);
+ try expect(v[90] == 72);
+ try expect(v[91] == 73);
+ try expect(v[92] == 74);
+ try expect(v[93] == 75);
+ try expect(v[94] == 76);
+ try expect(v[95] == 77);
+ c_vector_96_u8(.{
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ }, 96);
+ c_test_vector_96_u8();
+}
+
+export fn zig_ret_vector_128_u8() @Vector(128, u8) {
+ return .{
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1,
+ };
+}
+export fn zig_vector_128_u8(v: @Vector(128, u8), i: usize) void {
+ expect(v[0] == 2) catch @panic("test failure");
+ expect(v[1] == 3) catch @panic("test failure");
+ expect(v[2] == 4) catch @panic("test failure");
+ expect(v[3] == 5) catch @panic("test failure");
+ expect(v[4] == 6) catch @panic("test failure");
+ expect(v[5] == 7) catch @panic("test failure");
+ expect(v[6] == 8) catch @panic("test failure");
+ expect(v[7] == 9) catch @panic("test failure");
+ expect(v[8] == 10) catch @panic("test failure");
+ expect(v[9] == 11) catch @panic("test failure");
+ expect(v[10] == 12) catch @panic("test failure");
+ expect(v[11] == 13) catch @panic("test failure");
+ expect(v[12] == 14) catch @panic("test failure");
+ expect(v[13] == 15) catch @panic("test failure");
+ expect(v[14] == 16) catch @panic("test failure");
+ expect(v[15] == 17) catch @panic("test failure");
+ expect(v[16] == 18) catch @panic("test failure");
+ expect(v[17] == 19) catch @panic("test failure");
+ expect(v[18] == 20) catch @panic("test failure");
+ expect(v[19] == 21) catch @panic("test failure");
+ expect(v[20] == 22) catch @panic("test failure");
+ expect(v[21] == 23) catch @panic("test failure");
+ expect(v[22] == 24) catch @panic("test failure");
+ expect(v[23] == 25) catch @panic("test failure");
+ expect(v[24] == 26) catch @panic("test failure");
+ expect(v[25] == 27) catch @panic("test failure");
+ expect(v[26] == 28) catch @panic("test failure");
+ expect(v[27] == 29) catch @panic("test failure");
+ expect(v[28] == 30) catch @panic("test failure");
+ expect(v[29] == 31) catch @panic("test failure");
+ expect(v[30] == 32) catch @panic("test failure");
+ expect(v[31] == 33) catch @panic("test failure");
+ expect(v[32] == 34) catch @panic("test failure");
+ expect(v[33] == 35) catch @panic("test failure");
+ expect(v[34] == 36) catch @panic("test failure");
+ expect(v[35] == 37) catch @panic("test failure");
+ expect(v[36] == 38) catch @panic("test failure");
+ expect(v[37] == 39) catch @panic("test failure");
+ expect(v[38] == 40) catch @panic("test failure");
+ expect(v[39] == 41) catch @panic("test failure");
+ expect(v[40] == 42) catch @panic("test failure");
+ expect(v[41] == 43) catch @panic("test failure");
+ expect(v[42] == 44) catch @panic("test failure");
+ expect(v[43] == 45) catch @panic("test failure");
+ expect(v[44] == 46) catch @panic("test failure");
+ expect(v[45] == 47) catch @panic("test failure");
+ expect(v[46] == 48) catch @panic("test failure");
+ expect(v[47] == 49) catch @panic("test failure");
+ expect(v[48] == 50) catch @panic("test failure");
+ expect(v[49] == 51) catch @panic("test failure");
+ expect(v[50] == 52) catch @panic("test failure");
+ expect(v[51] == 53) catch @panic("test failure");
+ expect(v[52] == 54) catch @panic("test failure");
+ expect(v[53] == 55) catch @panic("test failure");
+ expect(v[54] == 56) catch @panic("test failure");
+ expect(v[55] == 57) catch @panic("test failure");
+ expect(v[56] == 58) catch @panic("test failure");
+ expect(v[57] == 59) catch @panic("test failure");
+ expect(v[58] == 60) catch @panic("test failure");
+ expect(v[59] == 61) catch @panic("test failure");
+ expect(v[60] == 62) catch @panic("test failure");
+ expect(v[61] == 63) catch @panic("test failure");
+ expect(v[62] == 64) catch @panic("test failure");
+ expect(v[63] == 65) catch @panic("test failure");
+ expect(v[64] == 66) catch @panic("test failure");
+ expect(v[65] == 67) catch @panic("test failure");
+ expect(v[66] == 68) catch @panic("test failure");
+ expect(v[67] == 69) catch @panic("test failure");
+ expect(v[68] == 70) catch @panic("test failure");
+ expect(v[69] == 71) catch @panic("test failure");
+ expect(v[70] == 72) catch @panic("test failure");
+ expect(v[71] == 73) catch @panic("test failure");
+ expect(v[72] == 74) catch @panic("test failure");
+ expect(v[73] == 75) catch @panic("test failure");
+ expect(v[74] == 76) catch @panic("test failure");
+ expect(v[75] == 77) catch @panic("test failure");
+ expect(v[76] == 78) catch @panic("test failure");
+ expect(v[77] == 79) catch @panic("test failure");
+ expect(v[78] == 80) catch @panic("test failure");
+ expect(v[79] == 81) catch @panic("test failure");
+ expect(v[80] == 82) catch @panic("test failure");
+ expect(v[81] == 83) catch @panic("test failure");
+ expect(v[82] == 84) catch @panic("test failure");
+ expect(v[83] == 85) catch @panic("test failure");
+ expect(v[84] == 86) catch @panic("test failure");
+ expect(v[85] == 87) catch @panic("test failure");
+ expect(v[86] == 88) catch @panic("test failure");
+ expect(v[87] == 89) catch @panic("test failure");
+ expect(v[88] == 90) catch @panic("test failure");
+ expect(v[89] == 91) catch @panic("test failure");
+ expect(v[90] == 92) catch @panic("test failure");
+ expect(v[91] == 93) catch @panic("test failure");
+ expect(v[92] == 94) catch @panic("test failure");
+ expect(v[93] == 95) catch @panic("test failure");
+ expect(v[94] == 96) catch @panic("test failure");
+ expect(v[95] == 97) catch @panic("test failure");
+ expect(v[96] == 98) catch @panic("test failure");
+ expect(v[97] == 99) catch @panic("test failure");
+ expect(v[98] == 0) catch @panic("test failure");
+ expect(v[99] == 1) catch @panic("test failure");
+ expect(v[100] == 2) catch @panic("test failure");
+ expect(v[101] == 3) catch @panic("test failure");
+ expect(v[102] == 4) catch @panic("test failure");
+ expect(v[103] == 5) catch @panic("test failure");
+ expect(v[104] == 6) catch @panic("test failure");
+ expect(v[105] == 7) catch @panic("test failure");
+ expect(v[106] == 8) catch @panic("test failure");
+ expect(v[107] == 9) catch @panic("test failure");
+ expect(v[108] == 10) catch @panic("test failure");
+ expect(v[109] == 11) catch @panic("test failure");
+ expect(v[110] == 12) catch @panic("test failure");
+ expect(v[111] == 13) catch @panic("test failure");
+ expect(v[112] == 14) catch @panic("test failure");
+ expect(v[113] == 15) catch @panic("test failure");
+ expect(v[114] == 16) catch @panic("test failure");
+ expect(v[115] == 17) catch @panic("test failure");
+ expect(v[116] == 18) catch @panic("test failure");
+ expect(v[117] == 19) catch @panic("test failure");
+ expect(v[118] == 20) catch @panic("test failure");
+ expect(v[119] == 21) catch @panic("test failure");
+ expect(v[120] == 22) catch @panic("test failure");
+ expect(v[121] == 23) catch @panic("test failure");
+ expect(v[122] == 24) catch @panic("test failure");
+ expect(v[123] == 25) catch @panic("test failure");
+ expect(v[124] == 26) catch @panic("test failure");
+ expect(v[125] == 27) catch @panic("test failure");
+ expect(v[126] == 28) catch @panic("test failure");
+ expect(v[127] == 29) catch @panic("test failure");
+ expect(i == 128) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_128_u8() @Vector(128, u8);
+extern fn c_vector_128_u8(@Vector(128, u8), usize) void;
+extern fn c_test_vector_128_u8() void;
+
+test "@Vector(128, u8)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_128_u8();
+ try expect(v[0] == 30);
+ try expect(v[1] == 31);
+ try expect(v[2] == 32);
+ try expect(v[3] == 33);
+ try expect(v[4] == 34);
+ try expect(v[5] == 35);
+ try expect(v[6] == 36);
+ try expect(v[7] == 37);
+ try expect(v[8] == 38);
+ try expect(v[9] == 39);
+ try expect(v[10] == 40);
+ try expect(v[11] == 41);
+ try expect(v[12] == 42);
+ try expect(v[13] == 43);
+ try expect(v[14] == 44);
+ try expect(v[15] == 45);
+ try expect(v[16] == 46);
+ try expect(v[17] == 47);
+ try expect(v[18] == 48);
+ try expect(v[19] == 49);
+ try expect(v[20] == 50);
+ try expect(v[21] == 51);
+ try expect(v[22] == 52);
+ try expect(v[23] == 53);
+ try expect(v[24] == 54);
+ try expect(v[25] == 55);
+ try expect(v[26] == 56);
+ try expect(v[27] == 57);
+ try expect(v[28] == 58);
+ try expect(v[29] == 59);
+ try expect(v[30] == 60);
+ try expect(v[31] == 61);
+ try expect(v[32] == 62);
+ try expect(v[33] == 63);
+ try expect(v[34] == 64);
+ try expect(v[35] == 65);
+ try expect(v[36] == 66);
+ try expect(v[37] == 67);
+ try expect(v[38] == 68);
+ try expect(v[39] == 69);
+ try expect(v[40] == 70);
+ try expect(v[41] == 71);
+ try expect(v[42] == 72);
+ try expect(v[43] == 73);
+ try expect(v[44] == 74);
+ try expect(v[45] == 75);
+ try expect(v[46] == 76);
+ try expect(v[47] == 77);
+ try expect(v[48] == 78);
+ try expect(v[49] == 79);
+ try expect(v[50] == 80);
+ try expect(v[51] == 81);
+ try expect(v[52] == 82);
+ try expect(v[53] == 83);
+ try expect(v[54] == 84);
+ try expect(v[55] == 85);
+ try expect(v[56] == 86);
+ try expect(v[57] == 87);
+ try expect(v[58] == 88);
+ try expect(v[59] == 89);
+ try expect(v[60] == 90);
+ try expect(v[61] == 91);
+ try expect(v[62] == 92);
+ try expect(v[63] == 93);
+ try expect(v[64] == 94);
+ try expect(v[65] == 95);
+ try expect(v[66] == 96);
+ try expect(v[67] == 97);
+ try expect(v[68] == 98);
+ try expect(v[69] == 99);
+ try expect(v[70] == 0);
+ try expect(v[71] == 1);
+ try expect(v[72] == 2);
+ try expect(v[73] == 3);
+ try expect(v[74] == 4);
+ try expect(v[75] == 5);
+ try expect(v[76] == 6);
+ try expect(v[77] == 7);
+ try expect(v[78] == 8);
+ try expect(v[79] == 9);
+ try expect(v[80] == 10);
+ try expect(v[81] == 11);
+ try expect(v[82] == 12);
+ try expect(v[83] == 13);
+ try expect(v[84] == 14);
+ try expect(v[85] == 15);
+ try expect(v[86] == 16);
+ try expect(v[87] == 17);
+ try expect(v[88] == 18);
+ try expect(v[89] == 19);
+ try expect(v[90] == 20);
+ try expect(v[91] == 21);
+ try expect(v[92] == 22);
+ try expect(v[93] == 23);
+ try expect(v[94] == 24);
+ try expect(v[95] == 25);
+ try expect(v[96] == 26);
+ try expect(v[97] == 27);
+ try expect(v[98] == 28);
+ try expect(v[99] == 29);
+ try expect(v[100] == 30);
+ try expect(v[101] == 31);
+ try expect(v[102] == 32);
+ try expect(v[103] == 33);
+ try expect(v[104] == 34);
+ try expect(v[105] == 35);
+ try expect(v[106] == 36);
+ try expect(v[107] == 37);
+ try expect(v[108] == 38);
+ try expect(v[109] == 39);
+ try expect(v[110] == 40);
+ try expect(v[111] == 41);
+ try expect(v[112] == 42);
+ try expect(v[113] == 43);
+ try expect(v[114] == 44);
+ try expect(v[115] == 45);
+ try expect(v[116] == 46);
+ try expect(v[117] == 47);
+ try expect(v[118] == 48);
+ try expect(v[119] == 49);
+ try expect(v[120] == 50);
+ try expect(v[121] == 51);
+ try expect(v[122] == 52);
+ try expect(v[123] == 53);
+ try expect(v[124] == 54);
+ try expect(v[125] == 55);
+ try expect(v[126] == 56);
+ try expect(v[127] == 57);
+ c_vector_128_u8(.{
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ }, 128);
+ c_test_vector_128_u8();
+}
+
+export fn zig_ret_vector_192_u8() @Vector(192, u8) {
+ return .{
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ };
+}
+export fn zig_vector_192_u8(v: @Vector(192, u8), i: usize) void {
+ expect(v[0] == 78) catch @panic("test failure");
+ expect(v[1] == 79) catch @panic("test failure");
+ expect(v[2] == 80) catch @panic("test failure");
+ expect(v[3] == 81) catch @panic("test failure");
+ expect(v[4] == 82) catch @panic("test failure");
+ expect(v[5] == 83) catch @panic("test failure");
+ expect(v[6] == 84) catch @panic("test failure");
+ expect(v[7] == 85) catch @panic("test failure");
+ expect(v[8] == 86) catch @panic("test failure");
+ expect(v[9] == 87) catch @panic("test failure");
+ expect(v[10] == 88) catch @panic("test failure");
+ expect(v[11] == 89) catch @panic("test failure");
+ expect(v[12] == 90) catch @panic("test failure");
+ expect(v[13] == 91) catch @panic("test failure");
+ expect(v[14] == 92) catch @panic("test failure");
+ expect(v[15] == 93) catch @panic("test failure");
+ expect(v[16] == 94) catch @panic("test failure");
+ expect(v[17] == 95) catch @panic("test failure");
+ expect(v[18] == 96) catch @panic("test failure");
+ expect(v[19] == 97) catch @panic("test failure");
+ expect(v[20] == 98) catch @panic("test failure");
+ expect(v[21] == 99) catch @panic("test failure");
+ expect(v[22] == 0) catch @panic("test failure");
+ expect(v[23] == 1) catch @panic("test failure");
+ expect(v[24] == 2) catch @panic("test failure");
+ expect(v[25] == 3) catch @panic("test failure");
+ expect(v[26] == 4) catch @panic("test failure");
+ expect(v[27] == 5) catch @panic("test failure");
+ expect(v[28] == 6) catch @panic("test failure");
+ expect(v[29] == 7) catch @panic("test failure");
+ expect(v[30] == 8) catch @panic("test failure");
+ expect(v[31] == 9) catch @panic("test failure");
+ expect(v[32] == 10) catch @panic("test failure");
+ expect(v[33] == 11) catch @panic("test failure");
+ expect(v[34] == 12) catch @panic("test failure");
+ expect(v[35] == 13) catch @panic("test failure");
+ expect(v[36] == 14) catch @panic("test failure");
+ expect(v[37] == 15) catch @panic("test failure");
+ expect(v[38] == 16) catch @panic("test failure");
+ expect(v[39] == 17) catch @panic("test failure");
+ expect(v[40] == 18) catch @panic("test failure");
+ expect(v[41] == 19) catch @panic("test failure");
+ expect(v[42] == 20) catch @panic("test failure");
+ expect(v[43] == 21) catch @panic("test failure");
+ expect(v[44] == 22) catch @panic("test failure");
+ expect(v[45] == 23) catch @panic("test failure");
+ expect(v[46] == 24) catch @panic("test failure");
+ expect(v[47] == 25) catch @panic("test failure");
+ expect(v[48] == 26) catch @panic("test failure");
+ expect(v[49] == 27) catch @panic("test failure");
+ expect(v[50] == 28) catch @panic("test failure");
+ expect(v[51] == 29) catch @panic("test failure");
+ expect(v[52] == 30) catch @panic("test failure");
+ expect(v[53] == 31) catch @panic("test failure");
+ expect(v[54] == 32) catch @panic("test failure");
+ expect(v[55] == 33) catch @panic("test failure");
+ expect(v[56] == 34) catch @panic("test failure");
+ expect(v[57] == 35) catch @panic("test failure");
+ expect(v[58] == 36) catch @panic("test failure");
+ expect(v[59] == 37) catch @panic("test failure");
+ expect(v[60] == 38) catch @panic("test failure");
+ expect(v[61] == 39) catch @panic("test failure");
+ expect(v[62] == 40) catch @panic("test failure");
+ expect(v[63] == 41) catch @panic("test failure");
+ expect(v[64] == 42) catch @panic("test failure");
+ expect(v[65] == 43) catch @panic("test failure");
+ expect(v[66] == 44) catch @panic("test failure");
+ expect(v[67] == 45) catch @panic("test failure");
+ expect(v[68] == 46) catch @panic("test failure");
+ expect(v[69] == 47) catch @panic("test failure");
+ expect(v[70] == 48) catch @panic("test failure");
+ expect(v[71] == 49) catch @panic("test failure");
+ expect(v[72] == 50) catch @panic("test failure");
+ expect(v[73] == 51) catch @panic("test failure");
+ expect(v[74] == 52) catch @panic("test failure");
+ expect(v[75] == 53) catch @panic("test failure");
+ expect(v[76] == 54) catch @panic("test failure");
+ expect(v[77] == 55) catch @panic("test failure");
+ expect(v[78] == 56) catch @panic("test failure");
+ expect(v[79] == 57) catch @panic("test failure");
+ expect(v[80] == 58) catch @panic("test failure");
+ expect(v[81] == 59) catch @panic("test failure");
+ expect(v[82] == 60) catch @panic("test failure");
+ expect(v[83] == 61) catch @panic("test failure");
+ expect(v[84] == 62) catch @panic("test failure");
+ expect(v[85] == 63) catch @panic("test failure");
+ expect(v[86] == 64) catch @panic("test failure");
+ expect(v[87] == 65) catch @panic("test failure");
+ expect(v[88] == 66) catch @panic("test failure");
+ expect(v[89] == 67) catch @panic("test failure");
+ expect(v[90] == 68) catch @panic("test failure");
+ expect(v[91] == 69) catch @panic("test failure");
+ expect(v[92] == 70) catch @panic("test failure");
+ expect(v[93] == 71) catch @panic("test failure");
+ expect(v[94] == 72) catch @panic("test failure");
+ expect(v[95] == 73) catch @panic("test failure");
+ expect(v[96] == 74) catch @panic("test failure");
+ expect(v[97] == 75) catch @panic("test failure");
+ expect(v[98] == 76) catch @panic("test failure");
+ expect(v[99] == 77) catch @panic("test failure");
+ expect(v[100] == 78) catch @panic("test failure");
+ expect(v[101] == 79) catch @panic("test failure");
+ expect(v[102] == 80) catch @panic("test failure");
+ expect(v[103] == 81) catch @panic("test failure");
+ expect(v[104] == 82) catch @panic("test failure");
+ expect(v[105] == 83) catch @panic("test failure");
+ expect(v[106] == 84) catch @panic("test failure");
+ expect(v[107] == 85) catch @panic("test failure");
+ expect(v[108] == 86) catch @panic("test failure");
+ expect(v[109] == 87) catch @panic("test failure");
+ expect(v[110] == 88) catch @panic("test failure");
+ expect(v[111] == 89) catch @panic("test failure");
+ expect(v[112] == 90) catch @panic("test failure");
+ expect(v[113] == 91) catch @panic("test failure");
+ expect(v[114] == 92) catch @panic("test failure");
+ expect(v[115] == 93) catch @panic("test failure");
+ expect(v[116] == 94) catch @panic("test failure");
+ expect(v[117] == 95) catch @panic("test failure");
+ expect(v[118] == 96) catch @panic("test failure");
+ expect(v[119] == 97) catch @panic("test failure");
+ expect(v[120] == 98) catch @panic("test failure");
+ expect(v[121] == 99) catch @panic("test failure");
+ expect(v[122] == 0) catch @panic("test failure");
+ expect(v[123] == 1) catch @panic("test failure");
+ expect(v[124] == 2) catch @panic("test failure");
+ expect(v[125] == 3) catch @panic("test failure");
+ expect(v[126] == 4) catch @panic("test failure");
+ expect(v[127] == 5) catch @panic("test failure");
+ expect(v[128] == 6) catch @panic("test failure");
+ expect(v[129] == 7) catch @panic("test failure");
+ expect(v[130] == 8) catch @panic("test failure");
+ expect(v[131] == 9) catch @panic("test failure");
+ expect(v[132] == 10) catch @panic("test failure");
+ expect(v[133] == 11) catch @panic("test failure");
+ expect(v[134] == 12) catch @panic("test failure");
+ expect(v[135] == 13) catch @panic("test failure");
+ expect(v[136] == 14) catch @panic("test failure");
+ expect(v[137] == 15) catch @panic("test failure");
+ expect(v[138] == 16) catch @panic("test failure");
+ expect(v[139] == 17) catch @panic("test failure");
+ expect(v[140] == 18) catch @panic("test failure");
+ expect(v[141] == 19) catch @panic("test failure");
+ expect(v[142] == 20) catch @panic("test failure");
+ expect(v[143] == 21) catch @panic("test failure");
+ expect(v[144] == 22) catch @panic("test failure");
+ expect(v[145] == 23) catch @panic("test failure");
+ expect(v[146] == 24) catch @panic("test failure");
+ expect(v[147] == 25) catch @panic("test failure");
+ expect(v[148] == 26) catch @panic("test failure");
+ expect(v[149] == 27) catch @panic("test failure");
+ expect(v[150] == 28) catch @panic("test failure");
+ expect(v[151] == 29) catch @panic("test failure");
+ expect(v[152] == 30) catch @panic("test failure");
+ expect(v[153] == 31) catch @panic("test failure");
+ expect(v[154] == 32) catch @panic("test failure");
+ expect(v[155] == 33) catch @panic("test failure");
+ expect(v[156] == 34) catch @panic("test failure");
+ expect(v[157] == 35) catch @panic("test failure");
+ expect(v[158] == 36) catch @panic("test failure");
+ expect(v[159] == 37) catch @panic("test failure");
+ expect(v[160] == 38) catch @panic("test failure");
+ expect(v[161] == 39) catch @panic("test failure");
+ expect(v[162] == 40) catch @panic("test failure");
+ expect(v[163] == 41) catch @panic("test failure");
+ expect(v[164] == 42) catch @panic("test failure");
+ expect(v[165] == 43) catch @panic("test failure");
+ expect(v[166] == 44) catch @panic("test failure");
+ expect(v[167] == 45) catch @panic("test failure");
+ expect(v[168] == 46) catch @panic("test failure");
+ expect(v[169] == 47) catch @panic("test failure");
+ expect(v[170] == 48) catch @panic("test failure");
+ expect(v[171] == 49) catch @panic("test failure");
+ expect(v[172] == 50) catch @panic("test failure");
+ expect(v[173] == 51) catch @panic("test failure");
+ expect(v[174] == 52) catch @panic("test failure");
+ expect(v[175] == 53) catch @panic("test failure");
+ expect(v[176] == 54) catch @panic("test failure");
+ expect(v[177] == 55) catch @panic("test failure");
+ expect(v[178] == 56) catch @panic("test failure");
+ expect(v[179] == 57) catch @panic("test failure");
+ expect(v[180] == 58) catch @panic("test failure");
+ expect(v[181] == 59) catch @panic("test failure");
+ expect(v[182] == 60) catch @panic("test failure");
+ expect(v[183] == 61) catch @panic("test failure");
+ expect(v[184] == 62) catch @panic("test failure");
+ expect(v[185] == 63) catch @panic("test failure");
+ expect(v[186] == 64) catch @panic("test failure");
+ expect(v[187] == 65) catch @panic("test failure");
+ expect(v[188] == 66) catch @panic("test failure");
+ expect(v[189] == 67) catch @panic("test failure");
+ expect(v[190] == 68) catch @panic("test failure");
+ expect(v[191] == 69) catch @panic("test failure");
+ expect(i == 192) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_192_u8() @Vector(192, u8);
+extern fn c_vector_192_u8(@Vector(192, u8), usize) void;
+extern fn c_test_vector_192_u8() void;
+
+test "@Vector(192, u8)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_192_u8();
+ try expect(v[0] == 70);
+ try expect(v[1] == 71);
+ try expect(v[2] == 72);
+ try expect(v[3] == 73);
+ try expect(v[4] == 74);
+ try expect(v[5] == 75);
+ try expect(v[6] == 76);
+ try expect(v[7] == 77);
+ try expect(v[8] == 78);
+ try expect(v[9] == 79);
+ try expect(v[10] == 80);
+ try expect(v[11] == 81);
+ try expect(v[12] == 82);
+ try expect(v[13] == 83);
+ try expect(v[14] == 84);
+ try expect(v[15] == 85);
+ try expect(v[16] == 86);
+ try expect(v[17] == 87);
+ try expect(v[18] == 88);
+ try expect(v[19] == 89);
+ try expect(v[20] == 90);
+ try expect(v[21] == 91);
+ try expect(v[22] == 92);
+ try expect(v[23] == 93);
+ try expect(v[24] == 94);
+ try expect(v[25] == 95);
+ try expect(v[26] == 96);
+ try expect(v[27] == 97);
+ try expect(v[28] == 98);
+ try expect(v[29] == 99);
+ try expect(v[30] == 0);
+ try expect(v[31] == 1);
+ try expect(v[32] == 2);
+ try expect(v[33] == 3);
+ try expect(v[34] == 4);
+ try expect(v[35] == 5);
+ try expect(v[36] == 6);
+ try expect(v[37] == 7);
+ try expect(v[38] == 8);
+ try expect(v[39] == 9);
+ try expect(v[40] == 10);
+ try expect(v[41] == 11);
+ try expect(v[42] == 12);
+ try expect(v[43] == 13);
+ try expect(v[44] == 14);
+ try expect(v[45] == 15);
+ try expect(v[46] == 16);
+ try expect(v[47] == 17);
+ try expect(v[48] == 18);
+ try expect(v[49] == 19);
+ try expect(v[50] == 20);
+ try expect(v[51] == 21);
+ try expect(v[52] == 22);
+ try expect(v[53] == 23);
+ try expect(v[54] == 24);
+ try expect(v[55] == 25);
+ try expect(v[56] == 26);
+ try expect(v[57] == 27);
+ try expect(v[58] == 28);
+ try expect(v[59] == 29);
+ try expect(v[60] == 30);
+ try expect(v[61] == 31);
+ try expect(v[62] == 32);
+ try expect(v[63] == 33);
+ try expect(v[64] == 34);
+ try expect(v[65] == 35);
+ try expect(v[66] == 36);
+ try expect(v[67] == 37);
+ try expect(v[68] == 38);
+ try expect(v[69] == 39);
+ try expect(v[70] == 40);
+ try expect(v[71] == 41);
+ try expect(v[72] == 42);
+ try expect(v[73] == 43);
+ try expect(v[74] == 44);
+ try expect(v[75] == 45);
+ try expect(v[76] == 46);
+ try expect(v[77] == 47);
+ try expect(v[78] == 48);
+ try expect(v[79] == 49);
+ try expect(v[80] == 50);
+ try expect(v[81] == 51);
+ try expect(v[82] == 52);
+ try expect(v[83] == 53);
+ try expect(v[84] == 54);
+ try expect(v[85] == 55);
+ try expect(v[86] == 56);
+ try expect(v[87] == 57);
+ try expect(v[88] == 58);
+ try expect(v[89] == 59);
+ try expect(v[90] == 60);
+ try expect(v[91] == 61);
+ try expect(v[92] == 62);
+ try expect(v[93] == 63);
+ try expect(v[94] == 64);
+ try expect(v[95] == 65);
+ try expect(v[96] == 66);
+ try expect(v[97] == 67);
+ try expect(v[98] == 68);
+ try expect(v[99] == 69);
+ try expect(v[100] == 70);
+ try expect(v[101] == 71);
+ try expect(v[102] == 72);
+ try expect(v[103] == 73);
+ try expect(v[104] == 74);
+ try expect(v[105] == 75);
+ try expect(v[106] == 76);
+ try expect(v[107] == 77);
+ try expect(v[108] == 78);
+ try expect(v[109] == 79);
+ try expect(v[110] == 80);
+ try expect(v[111] == 81);
+ try expect(v[112] == 82);
+ try expect(v[113] == 83);
+ try expect(v[114] == 84);
+ try expect(v[115] == 85);
+ try expect(v[116] == 86);
+ try expect(v[117] == 87);
+ try expect(v[118] == 88);
+ try expect(v[119] == 89);
+ try expect(v[120] == 90);
+ try expect(v[121] == 91);
+ try expect(v[122] == 92);
+ try expect(v[123] == 93);
+ try expect(v[124] == 94);
+ try expect(v[125] == 95);
+ try expect(v[126] == 96);
+ try expect(v[127] == 97);
+ try expect(v[128] == 98);
+ try expect(v[129] == 99);
+ try expect(v[130] == 0);
+ try expect(v[131] == 1);
+ try expect(v[132] == 2);
+ try expect(v[133] == 3);
+ try expect(v[134] == 4);
+ try expect(v[135] == 5);
+ try expect(v[136] == 6);
+ try expect(v[137] == 7);
+ try expect(v[138] == 8);
+ try expect(v[139] == 9);
+ try expect(v[140] == 10);
+ try expect(v[141] == 11);
+ try expect(v[142] == 12);
+ try expect(v[143] == 13);
+ try expect(v[144] == 14);
+ try expect(v[145] == 15);
+ try expect(v[146] == 16);
+ try expect(v[147] == 17);
+ try expect(v[148] == 18);
+ try expect(v[149] == 19);
+ try expect(v[150] == 20);
+ try expect(v[151] == 21);
+ try expect(v[152] == 22);
+ try expect(v[153] == 23);
+ try expect(v[154] == 24);
+ try expect(v[155] == 25);
+ try expect(v[156] == 26);
+ try expect(v[157] == 27);
+ try expect(v[158] == 28);
+ try expect(v[159] == 29);
+ try expect(v[160] == 30);
+ try expect(v[161] == 31);
+ try expect(v[162] == 32);
+ try expect(v[163] == 33);
+ try expect(v[164] == 34);
+ try expect(v[165] == 35);
+ try expect(v[166] == 36);
+ try expect(v[167] == 37);
+ try expect(v[168] == 38);
+ try expect(v[169] == 39);
+ try expect(v[170] == 40);
+ try expect(v[171] == 41);
+ try expect(v[172] == 42);
+ try expect(v[173] == 43);
+ try expect(v[174] == 44);
+ try expect(v[175] == 45);
+ try expect(v[176] == 46);
+ try expect(v[177] == 47);
+ try expect(v[178] == 48);
+ try expect(v[179] == 49);
+ try expect(v[180] == 50);
+ try expect(v[181] == 51);
+ try expect(v[182] == 52);
+ try expect(v[183] == 53);
+ try expect(v[184] == 54);
+ try expect(v[185] == 55);
+ try expect(v[186] == 56);
+ try expect(v[187] == 57);
+ try expect(v[188] == 58);
+ try expect(v[189] == 59);
+ try expect(v[190] == 60);
+ try expect(v[191] == 61);
+ c_vector_192_u8(.{
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ }, 192);
+ c_test_vector_192_u8();
+}
+
+export fn zig_ret_vector_256_u8() @Vector(256, u8) {
+ return .{
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ };
+}
+export fn zig_vector_256_u8(v: @Vector(256, u8), i: usize) void {
+ expect(v[0] == 10) catch @panic("test failure");
+ expect(v[1] == 11) catch @panic("test failure");
+ expect(v[2] == 12) catch @panic("test failure");
+ expect(v[3] == 13) catch @panic("test failure");
+ expect(v[4] == 14) catch @panic("test failure");
+ expect(v[5] == 15) catch @panic("test failure");
+ expect(v[6] == 16) catch @panic("test failure");
+ expect(v[7] == 17) catch @panic("test failure");
+ expect(v[8] == 18) catch @panic("test failure");
+ expect(v[9] == 19) catch @panic("test failure");
+ expect(v[10] == 20) catch @panic("test failure");
+ expect(v[11] == 21) catch @panic("test failure");
+ expect(v[12] == 22) catch @panic("test failure");
+ expect(v[13] == 23) catch @panic("test failure");
+ expect(v[14] == 24) catch @panic("test failure");
+ expect(v[15] == 25) catch @panic("test failure");
+ expect(v[16] == 26) catch @panic("test failure");
+ expect(v[17] == 27) catch @panic("test failure");
+ expect(v[18] == 28) catch @panic("test failure");
+ expect(v[19] == 29) catch @panic("test failure");
+ expect(v[20] == 30) catch @panic("test failure");
+ expect(v[21] == 31) catch @panic("test failure");
+ expect(v[22] == 32) catch @panic("test failure");
+ expect(v[23] == 33) catch @panic("test failure");
+ expect(v[24] == 34) catch @panic("test failure");
+ expect(v[25] == 35) catch @panic("test failure");
+ expect(v[26] == 36) catch @panic("test failure");
+ expect(v[27] == 37) catch @panic("test failure");
+ expect(v[28] == 38) catch @panic("test failure");
+ expect(v[29] == 39) catch @panic("test failure");
+ expect(v[30] == 40) catch @panic("test failure");
+ expect(v[31] == 41) catch @panic("test failure");
+ expect(v[32] == 42) catch @panic("test failure");
+ expect(v[33] == 43) catch @panic("test failure");
+ expect(v[34] == 44) catch @panic("test failure");
+ expect(v[35] == 45) catch @panic("test failure");
+ expect(v[36] == 46) catch @panic("test failure");
+ expect(v[37] == 47) catch @panic("test failure");
+ expect(v[38] == 48) catch @panic("test failure");
+ expect(v[39] == 49) catch @panic("test failure");
+ expect(v[40] == 50) catch @panic("test failure");
+ expect(v[41] == 51) catch @panic("test failure");
+ expect(v[42] == 52) catch @panic("test failure");
+ expect(v[43] == 53) catch @panic("test failure");
+ expect(v[44] == 54) catch @panic("test failure");
+ expect(v[45] == 55) catch @panic("test failure");
+ expect(v[46] == 56) catch @panic("test failure");
+ expect(v[47] == 57) catch @panic("test failure");
+ expect(v[48] == 58) catch @panic("test failure");
+ expect(v[49] == 59) catch @panic("test failure");
+ expect(v[50] == 60) catch @panic("test failure");
+ expect(v[51] == 61) catch @panic("test failure");
+ expect(v[52] == 62) catch @panic("test failure");
+ expect(v[53] == 63) catch @panic("test failure");
+ expect(v[54] == 64) catch @panic("test failure");
+ expect(v[55] == 65) catch @panic("test failure");
+ expect(v[56] == 66) catch @panic("test failure");
+ expect(v[57] == 67) catch @panic("test failure");
+ expect(v[58] == 68) catch @panic("test failure");
+ expect(v[59] == 69) catch @panic("test failure");
+ expect(v[60] == 70) catch @panic("test failure");
+ expect(v[61] == 71) catch @panic("test failure");
+ expect(v[62] == 72) catch @panic("test failure");
+ expect(v[63] == 73) catch @panic("test failure");
+ expect(v[64] == 74) catch @panic("test failure");
+ expect(v[65] == 75) catch @panic("test failure");
+ expect(v[66] == 76) catch @panic("test failure");
+ expect(v[67] == 77) catch @panic("test failure");
+ expect(v[68] == 78) catch @panic("test failure");
+ expect(v[69] == 79) catch @panic("test failure");
+ expect(v[70] == 80) catch @panic("test failure");
+ expect(v[71] == 81) catch @panic("test failure");
+ expect(v[72] == 82) catch @panic("test failure");
+ expect(v[73] == 83) catch @panic("test failure");
+ expect(v[74] == 84) catch @panic("test failure");
+ expect(v[75] == 85) catch @panic("test failure");
+ expect(v[76] == 86) catch @panic("test failure");
+ expect(v[77] == 87) catch @panic("test failure");
+ expect(v[78] == 88) catch @panic("test failure");
+ expect(v[79] == 89) catch @panic("test failure");
+ expect(v[80] == 90) catch @panic("test failure");
+ expect(v[81] == 91) catch @panic("test failure");
+ expect(v[82] == 92) catch @panic("test failure");
+ expect(v[83] == 93) catch @panic("test failure");
+ expect(v[84] == 94) catch @panic("test failure");
+ expect(v[85] == 95) catch @panic("test failure");
+ expect(v[86] == 96) catch @panic("test failure");
+ expect(v[87] == 97) catch @panic("test failure");
+ expect(v[88] == 98) catch @panic("test failure");
+ expect(v[89] == 99) catch @panic("test failure");
+ expect(v[90] == 0) catch @panic("test failure");
+ expect(v[91] == 1) catch @panic("test failure");
+ expect(v[92] == 2) catch @panic("test failure");
+ expect(v[93] == 3) catch @panic("test failure");
+ expect(v[94] == 4) catch @panic("test failure");
+ expect(v[95] == 5) catch @panic("test failure");
+ expect(v[96] == 6) catch @panic("test failure");
+ expect(v[97] == 7) catch @panic("test failure");
+ expect(v[98] == 8) catch @panic("test failure");
+ expect(v[99] == 9) catch @panic("test failure");
+ expect(v[100] == 10) catch @panic("test failure");
+ expect(v[101] == 11) catch @panic("test failure");
+ expect(v[102] == 12) catch @panic("test failure");
+ expect(v[103] == 13) catch @panic("test failure");
+ expect(v[104] == 14) catch @panic("test failure");
+ expect(v[105] == 15) catch @panic("test failure");
+ expect(v[106] == 16) catch @panic("test failure");
+ expect(v[107] == 17) catch @panic("test failure");
+ expect(v[108] == 18) catch @panic("test failure");
+ expect(v[109] == 19) catch @panic("test failure");
+ expect(v[110] == 20) catch @panic("test failure");
+ expect(v[111] == 21) catch @panic("test failure");
+ expect(v[112] == 22) catch @panic("test failure");
+ expect(v[113] == 23) catch @panic("test failure");
+ expect(v[114] == 24) catch @panic("test failure");
+ expect(v[115] == 25) catch @panic("test failure");
+ expect(v[116] == 26) catch @panic("test failure");
+ expect(v[117] == 27) catch @panic("test failure");
+ expect(v[118] == 28) catch @panic("test failure");
+ expect(v[119] == 29) catch @panic("test failure");
+ expect(v[120] == 30) catch @panic("test failure");
+ expect(v[121] == 31) catch @panic("test failure");
+ expect(v[122] == 32) catch @panic("test failure");
+ expect(v[123] == 33) catch @panic("test failure");
+ expect(v[124] == 34) catch @panic("test failure");
+ expect(v[125] == 35) catch @panic("test failure");
+ expect(v[126] == 36) catch @panic("test failure");
+ expect(v[127] == 37) catch @panic("test failure");
+ expect(v[128] == 38) catch @panic("test failure");
+ expect(v[129] == 39) catch @panic("test failure");
+ expect(v[130] == 40) catch @panic("test failure");
+ expect(v[131] == 41) catch @panic("test failure");
+ expect(v[132] == 42) catch @panic("test failure");
+ expect(v[133] == 43) catch @panic("test failure");
+ expect(v[134] == 44) catch @panic("test failure");
+ expect(v[135] == 45) catch @panic("test failure");
+ expect(v[136] == 46) catch @panic("test failure");
+ expect(v[137] == 47) catch @panic("test failure");
+ expect(v[138] == 48) catch @panic("test failure");
+ expect(v[139] == 49) catch @panic("test failure");
+ expect(v[140] == 50) catch @panic("test failure");
+ expect(v[141] == 51) catch @panic("test failure");
+ expect(v[142] == 52) catch @panic("test failure");
+ expect(v[143] == 53) catch @panic("test failure");
+ expect(v[144] == 54) catch @panic("test failure");
+ expect(v[145] == 55) catch @panic("test failure");
+ expect(v[146] == 56) catch @panic("test failure");
+ expect(v[147] == 57) catch @panic("test failure");
+ expect(v[148] == 58) catch @panic("test failure");
+ expect(v[149] == 59) catch @panic("test failure");
+ expect(v[150] == 60) catch @panic("test failure");
+ expect(v[151] == 61) catch @panic("test failure");
+ expect(v[152] == 62) catch @panic("test failure");
+ expect(v[153] == 63) catch @panic("test failure");
+ expect(v[154] == 64) catch @panic("test failure");
+ expect(v[155] == 65) catch @panic("test failure");
+ expect(v[156] == 66) catch @panic("test failure");
+ expect(v[157] == 67) catch @panic("test failure");
+ expect(v[158] == 68) catch @panic("test failure");
+ expect(v[159] == 69) catch @panic("test failure");
+ expect(v[160] == 70) catch @panic("test failure");
+ expect(v[161] == 71) catch @panic("test failure");
+ expect(v[162] == 72) catch @panic("test failure");
+ expect(v[163] == 73) catch @panic("test failure");
+ expect(v[164] == 74) catch @panic("test failure");
+ expect(v[165] == 75) catch @panic("test failure");
+ expect(v[166] == 76) catch @panic("test failure");
+ expect(v[167] == 77) catch @panic("test failure");
+ expect(v[168] == 78) catch @panic("test failure");
+ expect(v[169] == 79) catch @panic("test failure");
+ expect(v[170] == 80) catch @panic("test failure");
+ expect(v[171] == 81) catch @panic("test failure");
+ expect(v[172] == 82) catch @panic("test failure");
+ expect(v[173] == 83) catch @panic("test failure");
+ expect(v[174] == 84) catch @panic("test failure");
+ expect(v[175] == 85) catch @panic("test failure");
+ expect(v[176] == 86) catch @panic("test failure");
+ expect(v[177] == 87) catch @panic("test failure");
+ expect(v[178] == 88) catch @panic("test failure");
+ expect(v[179] == 89) catch @panic("test failure");
+ expect(v[180] == 90) catch @panic("test failure");
+ expect(v[181] == 91) catch @panic("test failure");
+ expect(v[182] == 92) catch @panic("test failure");
+ expect(v[183] == 93) catch @panic("test failure");
+ expect(v[184] == 94) catch @panic("test failure");
+ expect(v[185] == 95) catch @panic("test failure");
+ expect(v[186] == 96) catch @panic("test failure");
+ expect(v[187] == 97) catch @panic("test failure");
+ expect(v[188] == 98) catch @panic("test failure");
+ expect(v[189] == 99) catch @panic("test failure");
+ expect(v[190] == 0) catch @panic("test failure");
+ expect(v[191] == 1) catch @panic("test failure");
+ expect(v[192] == 2) catch @panic("test failure");
+ expect(v[193] == 3) catch @panic("test failure");
+ expect(v[194] == 4) catch @panic("test failure");
+ expect(v[195] == 5) catch @panic("test failure");
+ expect(v[196] == 6) catch @panic("test failure");
+ expect(v[197] == 7) catch @panic("test failure");
+ expect(v[198] == 8) catch @panic("test failure");
+ expect(v[199] == 9) catch @panic("test failure");
+ expect(v[200] == 10) catch @panic("test failure");
+ expect(v[201] == 11) catch @panic("test failure");
+ expect(v[202] == 12) catch @panic("test failure");
+ expect(v[203] == 13) catch @panic("test failure");
+ expect(v[204] == 14) catch @panic("test failure");
+ expect(v[205] == 15) catch @panic("test failure");
+ expect(v[206] == 16) catch @panic("test failure");
+ expect(v[207] == 17) catch @panic("test failure");
+ expect(v[208] == 18) catch @panic("test failure");
+ expect(v[209] == 19) catch @panic("test failure");
+ expect(v[210] == 20) catch @panic("test failure");
+ expect(v[211] == 21) catch @panic("test failure");
+ expect(v[212] == 22) catch @panic("test failure");
+ expect(v[213] == 23) catch @panic("test failure");
+ expect(v[214] == 24) catch @panic("test failure");
+ expect(v[215] == 25) catch @panic("test failure");
+ expect(v[216] == 26) catch @panic("test failure");
+ expect(v[217] == 27) catch @panic("test failure");
+ expect(v[218] == 28) catch @panic("test failure");
+ expect(v[219] == 29) catch @panic("test failure");
+ expect(v[220] == 30) catch @panic("test failure");
+ expect(v[221] == 31) catch @panic("test failure");
+ expect(v[222] == 32) catch @panic("test failure");
+ expect(v[223] == 33) catch @panic("test failure");
+ expect(v[224] == 34) catch @panic("test failure");
+ expect(v[225] == 35) catch @panic("test failure");
+ expect(v[226] == 36) catch @panic("test failure");
+ expect(v[227] == 37) catch @panic("test failure");
+ expect(v[228] == 38) catch @panic("test failure");
+ expect(v[229] == 39) catch @panic("test failure");
+ expect(v[230] == 40) catch @panic("test failure");
+ expect(v[231] == 41) catch @panic("test failure");
+ expect(v[232] == 42) catch @panic("test failure");
+ expect(v[233] == 43) catch @panic("test failure");
+ expect(v[234] == 44) catch @panic("test failure");
+ expect(v[235] == 45) catch @panic("test failure");
+ expect(v[236] == 46) catch @panic("test failure");
+ expect(v[237] == 47) catch @panic("test failure");
+ expect(v[238] == 48) catch @panic("test failure");
+ expect(v[239] == 49) catch @panic("test failure");
+ expect(v[240] == 50) catch @panic("test failure");
+ expect(v[241] == 51) catch @panic("test failure");
+ expect(v[242] == 52) catch @panic("test failure");
+ expect(v[243] == 53) catch @panic("test failure");
+ expect(v[244] == 54) catch @panic("test failure");
+ expect(v[245] == 55) catch @panic("test failure");
+ expect(v[246] == 56) catch @panic("test failure");
+ expect(v[247] == 57) catch @panic("test failure");
+ expect(v[248] == 58) catch @panic("test failure");
+ expect(v[249] == 59) catch @panic("test failure");
+ expect(v[250] == 60) catch @panic("test failure");
+ expect(v[251] == 61) catch @panic("test failure");
+ expect(v[252] == 62) catch @panic("test failure");
+ expect(v[253] == 63) catch @panic("test failure");
+ expect(v[254] == 64) catch @panic("test failure");
+ expect(v[255] == 65) catch @panic("test failure");
+ expect(i == 256) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_256_u8() @Vector(256, u8);
+extern fn c_vector_256_u8(@Vector(256, u8), usize) void;
+extern fn c_test_vector_256_u8() void;
+
+test "@Vector(256, u8)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_256_u8();
+ try expect(v[0] == 66);
+ try expect(v[1] == 67);
+ try expect(v[2] == 68);
+ try expect(v[3] == 69);
+ try expect(v[4] == 70);
+ try expect(v[5] == 71);
+ try expect(v[6] == 72);
+ try expect(v[7] == 73);
+ try expect(v[8] == 74);
+ try expect(v[9] == 75);
+ try expect(v[10] == 76);
+ try expect(v[11] == 77);
+ try expect(v[12] == 78);
+ try expect(v[13] == 79);
+ try expect(v[14] == 80);
+ try expect(v[15] == 81);
+ try expect(v[16] == 82);
+ try expect(v[17] == 83);
+ try expect(v[18] == 84);
+ try expect(v[19] == 85);
+ try expect(v[20] == 86);
+ try expect(v[21] == 87);
+ try expect(v[22] == 88);
+ try expect(v[23] == 89);
+ try expect(v[24] == 90);
+ try expect(v[25] == 91);
+ try expect(v[26] == 92);
+ try expect(v[27] == 93);
+ try expect(v[28] == 94);
+ try expect(v[29] == 95);
+ try expect(v[30] == 96);
+ try expect(v[31] == 97);
+ try expect(v[32] == 98);
+ try expect(v[33] == 99);
+ try expect(v[34] == 0);
+ try expect(v[35] == 1);
+ try expect(v[36] == 2);
+ try expect(v[37] == 3);
+ try expect(v[38] == 4);
+ try expect(v[39] == 5);
+ try expect(v[40] == 6);
+ try expect(v[41] == 7);
+ try expect(v[42] == 8);
+ try expect(v[43] == 9);
+ try expect(v[44] == 10);
+ try expect(v[45] == 11);
+ try expect(v[46] == 12);
+ try expect(v[47] == 13);
+ try expect(v[48] == 14);
+ try expect(v[49] == 15);
+ try expect(v[50] == 16);
+ try expect(v[51] == 17);
+ try expect(v[52] == 18);
+ try expect(v[53] == 19);
+ try expect(v[54] == 20);
+ try expect(v[55] == 21);
+ try expect(v[56] == 22);
+ try expect(v[57] == 23);
+ try expect(v[58] == 24);
+ try expect(v[59] == 25);
+ try expect(v[60] == 26);
+ try expect(v[61] == 27);
+ try expect(v[62] == 28);
+ try expect(v[63] == 29);
+ try expect(v[64] == 30);
+ try expect(v[65] == 31);
+ try expect(v[66] == 32);
+ try expect(v[67] == 33);
+ try expect(v[68] == 34);
+ try expect(v[69] == 35);
+ try expect(v[70] == 36);
+ try expect(v[71] == 37);
+ try expect(v[72] == 38);
+ try expect(v[73] == 39);
+ try expect(v[74] == 40);
+ try expect(v[75] == 41);
+ try expect(v[76] == 42);
+ try expect(v[77] == 43);
+ try expect(v[78] == 44);
+ try expect(v[79] == 45);
+ try expect(v[80] == 46);
+ try expect(v[81] == 47);
+ try expect(v[82] == 48);
+ try expect(v[83] == 49);
+ try expect(v[84] == 50);
+ try expect(v[85] == 51);
+ try expect(v[86] == 52);
+ try expect(v[87] == 53);
+ try expect(v[88] == 54);
+ try expect(v[89] == 55);
+ try expect(v[90] == 56);
+ try expect(v[91] == 57);
+ try expect(v[92] == 58);
+ try expect(v[93] == 59);
+ try expect(v[94] == 60);
+ try expect(v[95] == 61);
+ try expect(v[96] == 62);
+ try expect(v[97] == 63);
+ try expect(v[98] == 64);
+ try expect(v[99] == 65);
+ try expect(v[100] == 66);
+ try expect(v[101] == 67);
+ try expect(v[102] == 68);
+ try expect(v[103] == 69);
+ try expect(v[104] == 70);
+ try expect(v[105] == 71);
+ try expect(v[106] == 72);
+ try expect(v[107] == 73);
+ try expect(v[108] == 74);
+ try expect(v[109] == 75);
+ try expect(v[110] == 76);
+ try expect(v[111] == 77);
+ try expect(v[112] == 78);
+ try expect(v[113] == 79);
+ try expect(v[114] == 80);
+ try expect(v[115] == 81);
+ try expect(v[116] == 82);
+ try expect(v[117] == 83);
+ try expect(v[118] == 84);
+ try expect(v[119] == 85);
+ try expect(v[120] == 86);
+ try expect(v[121] == 87);
+ try expect(v[122] == 88);
+ try expect(v[123] == 89);
+ try expect(v[124] == 90);
+ try expect(v[125] == 91);
+ try expect(v[126] == 92);
+ try expect(v[127] == 93);
+ try expect(v[128] == 94);
+ try expect(v[129] == 95);
+ try expect(v[130] == 96);
+ try expect(v[131] == 97);
+ try expect(v[132] == 98);
+ try expect(v[133] == 99);
+ try expect(v[134] == 0);
+ try expect(v[135] == 1);
+ try expect(v[136] == 2);
+ try expect(v[137] == 3);
+ try expect(v[138] == 4);
+ try expect(v[139] == 5);
+ try expect(v[140] == 6);
+ try expect(v[141] == 7);
+ try expect(v[142] == 8);
+ try expect(v[143] == 9);
+ try expect(v[144] == 10);
+ try expect(v[145] == 11);
+ try expect(v[146] == 12);
+ try expect(v[147] == 13);
+ try expect(v[148] == 14);
+ try expect(v[149] == 15);
+ try expect(v[150] == 16);
+ try expect(v[151] == 17);
+ try expect(v[152] == 18);
+ try expect(v[153] == 19);
+ try expect(v[154] == 20);
+ try expect(v[155] == 21);
+ try expect(v[156] == 22);
+ try expect(v[157] == 23);
+ try expect(v[158] == 24);
+ try expect(v[159] == 25);
+ try expect(v[160] == 26);
+ try expect(v[161] == 27);
+ try expect(v[162] == 28);
+ try expect(v[163] == 29);
+ try expect(v[164] == 30);
+ try expect(v[165] == 31);
+ try expect(v[166] == 32);
+ try expect(v[167] == 33);
+ try expect(v[168] == 34);
+ try expect(v[169] == 35);
+ try expect(v[170] == 36);
+ try expect(v[171] == 37);
+ try expect(v[172] == 38);
+ try expect(v[173] == 39);
+ try expect(v[174] == 40);
+ try expect(v[175] == 41);
+ try expect(v[176] == 42);
+ try expect(v[177] == 43);
+ try expect(v[178] == 44);
+ try expect(v[179] == 45);
+ try expect(v[180] == 46);
+ try expect(v[181] == 47);
+ try expect(v[182] == 48);
+ try expect(v[183] == 49);
+ try expect(v[184] == 50);
+ try expect(v[185] == 51);
+ try expect(v[186] == 52);
+ try expect(v[187] == 53);
+ try expect(v[188] == 54);
+ try expect(v[189] == 55);
+ try expect(v[190] == 56);
+ try expect(v[191] == 57);
+ try expect(v[192] == 58);
+ try expect(v[193] == 59);
+ try expect(v[194] == 60);
+ try expect(v[195] == 61);
+ try expect(v[196] == 62);
+ try expect(v[197] == 63);
+ try expect(v[198] == 64);
+ try expect(v[199] == 65);
+ try expect(v[200] == 66);
+ try expect(v[201] == 67);
+ try expect(v[202] == 68);
+ try expect(v[203] == 69);
+ try expect(v[204] == 70);
+ try expect(v[205] == 71);
+ try expect(v[206] == 72);
+ try expect(v[207] == 73);
+ try expect(v[208] == 74);
+ try expect(v[209] == 75);
+ try expect(v[210] == 76);
+ try expect(v[211] == 77);
+ try expect(v[212] == 78);
+ try expect(v[213] == 79);
+ try expect(v[214] == 80);
+ try expect(v[215] == 81);
+ try expect(v[216] == 82);
+ try expect(v[217] == 83);
+ try expect(v[218] == 84);
+ try expect(v[219] == 85);
+ try expect(v[220] == 86);
+ try expect(v[221] == 87);
+ try expect(v[222] == 88);
+ try expect(v[223] == 89);
+ try expect(v[224] == 90);
+ try expect(v[225] == 91);
+ try expect(v[226] == 92);
+ try expect(v[227] == 93);
+ try expect(v[228] == 94);
+ try expect(v[229] == 95);
+ try expect(v[230] == 96);
+ try expect(v[231] == 97);
+ try expect(v[232] == 98);
+ try expect(v[233] == 99);
+ try expect(v[234] == 0);
+ try expect(v[235] == 1);
+ try expect(v[236] == 2);
+ try expect(v[237] == 3);
+ try expect(v[238] == 4);
+ try expect(v[239] == 5);
+ try expect(v[240] == 6);
+ try expect(v[241] == 7);
+ try expect(v[242] == 8);
+ try expect(v[243] == 9);
+ try expect(v[244] == 10);
+ try expect(v[245] == 11);
+ try expect(v[246] == 12);
+ try expect(v[247] == 13);
+ try expect(v[248] == 14);
+ try expect(v[249] == 15);
+ try expect(v[250] == 16);
+ try expect(v[251] == 17);
+ try expect(v[252] == 18);
+ try expect(v[253] == 19);
+ try expect(v[254] == 20);
+ try expect(v[255] == 21);
+ c_vector_256_u8(.{
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ }, 256);
+ c_test_vector_256_u8();
+}
+
+export fn zig_ret_vector_384_u8() @Vector(384, u8) {
+ return .{
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ };
+}
+export fn zig_vector_384_u8(v: @Vector(384, u8), i: usize) void {
+ expect(v[0] == 62) catch @panic("test failure");
+ expect(v[1] == 63) catch @panic("test failure");
+ expect(v[2] == 64) catch @panic("test failure");
+ expect(v[3] == 65) catch @panic("test failure");
+ expect(v[4] == 66) catch @panic("test failure");
+ expect(v[5] == 67) catch @panic("test failure");
+ expect(v[6] == 68) catch @panic("test failure");
+ expect(v[7] == 69) catch @panic("test failure");
+ expect(v[8] == 70) catch @panic("test failure");
+ expect(v[9] == 71) catch @panic("test failure");
+ expect(v[10] == 72) catch @panic("test failure");
+ expect(v[11] == 73) catch @panic("test failure");
+ expect(v[12] == 74) catch @panic("test failure");
+ expect(v[13] == 75) catch @panic("test failure");
+ expect(v[14] == 76) catch @panic("test failure");
+ expect(v[15] == 77) catch @panic("test failure");
+ expect(v[16] == 78) catch @panic("test failure");
+ expect(v[17] == 79) catch @panic("test failure");
+ expect(v[18] == 80) catch @panic("test failure");
+ expect(v[19] == 81) catch @panic("test failure");
+ expect(v[20] == 82) catch @panic("test failure");
+ expect(v[21] == 83) catch @panic("test failure");
+ expect(v[22] == 84) catch @panic("test failure");
+ expect(v[23] == 85) catch @panic("test failure");
+ expect(v[24] == 86) catch @panic("test failure");
+ expect(v[25] == 87) catch @panic("test failure");
+ expect(v[26] == 88) catch @panic("test failure");
+ expect(v[27] == 89) catch @panic("test failure");
+ expect(v[28] == 90) catch @panic("test failure");
+ expect(v[29] == 91) catch @panic("test failure");
+ expect(v[30] == 92) catch @panic("test failure");
+ expect(v[31] == 93) catch @panic("test failure");
+ expect(v[32] == 94) catch @panic("test failure");
+ expect(v[33] == 95) catch @panic("test failure");
+ expect(v[34] == 96) catch @panic("test failure");
+ expect(v[35] == 97) catch @panic("test failure");
+ expect(v[36] == 98) catch @panic("test failure");
+ expect(v[37] == 99) catch @panic("test failure");
+ expect(v[38] == 0) catch @panic("test failure");
+ expect(v[39] == 1) catch @panic("test failure");
+ expect(v[40] == 2) catch @panic("test failure");
+ expect(v[41] == 3) catch @panic("test failure");
+ expect(v[42] == 4) catch @panic("test failure");
+ expect(v[43] == 5) catch @panic("test failure");
+ expect(v[44] == 6) catch @panic("test failure");
+ expect(v[45] == 7) catch @panic("test failure");
+ expect(v[46] == 8) catch @panic("test failure");
+ expect(v[47] == 9) catch @panic("test failure");
+ expect(v[48] == 10) catch @panic("test failure");
+ expect(v[49] == 11) catch @panic("test failure");
+ expect(v[50] == 12) catch @panic("test failure");
+ expect(v[51] == 13) catch @panic("test failure");
+ expect(v[52] == 14) catch @panic("test failure");
+ expect(v[53] == 15) catch @panic("test failure");
+ expect(v[54] == 16) catch @panic("test failure");
+ expect(v[55] == 17) catch @panic("test failure");
+ expect(v[56] == 18) catch @panic("test failure");
+ expect(v[57] == 19) catch @panic("test failure");
+ expect(v[58] == 20) catch @panic("test failure");
+ expect(v[59] == 21) catch @panic("test failure");
+ expect(v[60] == 22) catch @panic("test failure");
+ expect(v[61] == 23) catch @panic("test failure");
+ expect(v[62] == 24) catch @panic("test failure");
+ expect(v[63] == 25) catch @panic("test failure");
+ expect(v[64] == 26) catch @panic("test failure");
+ expect(v[65] == 27) catch @panic("test failure");
+ expect(v[66] == 28) catch @panic("test failure");
+ expect(v[67] == 29) catch @panic("test failure");
+ expect(v[68] == 30) catch @panic("test failure");
+ expect(v[69] == 31) catch @panic("test failure");
+ expect(v[70] == 32) catch @panic("test failure");
+ expect(v[71] == 33) catch @panic("test failure");
+ expect(v[72] == 34) catch @panic("test failure");
+ expect(v[73] == 35) catch @panic("test failure");
+ expect(v[74] == 36) catch @panic("test failure");
+ expect(v[75] == 37) catch @panic("test failure");
+ expect(v[76] == 38) catch @panic("test failure");
+ expect(v[77] == 39) catch @panic("test failure");
+ expect(v[78] == 40) catch @panic("test failure");
+ expect(v[79] == 41) catch @panic("test failure");
+ expect(v[80] == 42) catch @panic("test failure");
+ expect(v[81] == 43) catch @panic("test failure");
+ expect(v[82] == 44) catch @panic("test failure");
+ expect(v[83] == 45) catch @panic("test failure");
+ expect(v[84] == 46) catch @panic("test failure");
+ expect(v[85] == 47) catch @panic("test failure");
+ expect(v[86] == 48) catch @panic("test failure");
+ expect(v[87] == 49) catch @panic("test failure");
+ expect(v[88] == 50) catch @panic("test failure");
+ expect(v[89] == 51) catch @panic("test failure");
+ expect(v[90] == 52) catch @panic("test failure");
+ expect(v[91] == 53) catch @panic("test failure");
+ expect(v[92] == 54) catch @panic("test failure");
+ expect(v[93] == 55) catch @panic("test failure");
+ expect(v[94] == 56) catch @panic("test failure");
+ expect(v[95] == 57) catch @panic("test failure");
+ expect(v[96] == 58) catch @panic("test failure");
+ expect(v[97] == 59) catch @panic("test failure");
+ expect(v[98] == 60) catch @panic("test failure");
+ expect(v[99] == 61) catch @panic("test failure");
+ expect(v[100] == 62) catch @panic("test failure");
+ expect(v[101] == 63) catch @panic("test failure");
+ expect(v[102] == 64) catch @panic("test failure");
+ expect(v[103] == 65) catch @panic("test failure");
+ expect(v[104] == 66) catch @panic("test failure");
+ expect(v[105] == 67) catch @panic("test failure");
+ expect(v[106] == 68) catch @panic("test failure");
+ expect(v[107] == 69) catch @panic("test failure");
+ expect(v[108] == 70) catch @panic("test failure");
+ expect(v[109] == 71) catch @panic("test failure");
+ expect(v[110] == 72) catch @panic("test failure");
+ expect(v[111] == 73) catch @panic("test failure");
+ expect(v[112] == 74) catch @panic("test failure");
+ expect(v[113] == 75) catch @panic("test failure");
+ expect(v[114] == 76) catch @panic("test failure");
+ expect(v[115] == 77) catch @panic("test failure");
+ expect(v[116] == 78) catch @panic("test failure");
+ expect(v[117] == 79) catch @panic("test failure");
+ expect(v[118] == 80) catch @panic("test failure");
+ expect(v[119] == 81) catch @panic("test failure");
+ expect(v[120] == 82) catch @panic("test failure");
+ expect(v[121] == 83) catch @panic("test failure");
+ expect(v[122] == 84) catch @panic("test failure");
+ expect(v[123] == 85) catch @panic("test failure");
+ expect(v[124] == 86) catch @panic("test failure");
+ expect(v[125] == 87) catch @panic("test failure");
+ expect(v[126] == 88) catch @panic("test failure");
+ expect(v[127] == 89) catch @panic("test failure");
+ expect(v[128] == 90) catch @panic("test failure");
+ expect(v[129] == 91) catch @panic("test failure");
+ expect(v[130] == 92) catch @panic("test failure");
+ expect(v[131] == 93) catch @panic("test failure");
+ expect(v[132] == 94) catch @panic("test failure");
+ expect(v[133] == 95) catch @panic("test failure");
+ expect(v[134] == 96) catch @panic("test failure");
+ expect(v[135] == 97) catch @panic("test failure");
+ expect(v[136] == 98) catch @panic("test failure");
+ expect(v[137] == 99) catch @panic("test failure");
+ expect(v[138] == 0) catch @panic("test failure");
+ expect(v[139] == 1) catch @panic("test failure");
+ expect(v[140] == 2) catch @panic("test failure");
+ expect(v[141] == 3) catch @panic("test failure");
+ expect(v[142] == 4) catch @panic("test failure");
+ expect(v[143] == 5) catch @panic("test failure");
+ expect(v[144] == 6) catch @panic("test failure");
+ expect(v[145] == 7) catch @panic("test failure");
+ expect(v[146] == 8) catch @panic("test failure");
+ expect(v[147] == 9) catch @panic("test failure");
+ expect(v[148] == 10) catch @panic("test failure");
+ expect(v[149] == 11) catch @panic("test failure");
+ expect(v[150] == 12) catch @panic("test failure");
+ expect(v[151] == 13) catch @panic("test failure");
+ expect(v[152] == 14) catch @panic("test failure");
+ expect(v[153] == 15) catch @panic("test failure");
+ expect(v[154] == 16) catch @panic("test failure");
+ expect(v[155] == 17) catch @panic("test failure");
+ expect(v[156] == 18) catch @panic("test failure");
+ expect(v[157] == 19) catch @panic("test failure");
+ expect(v[158] == 20) catch @panic("test failure");
+ expect(v[159] == 21) catch @panic("test failure");
+ expect(v[160] == 22) catch @panic("test failure");
+ expect(v[161] == 23) catch @panic("test failure");
+ expect(v[162] == 24) catch @panic("test failure");
+ expect(v[163] == 25) catch @panic("test failure");
+ expect(v[164] == 26) catch @panic("test failure");
+ expect(v[165] == 27) catch @panic("test failure");
+ expect(v[166] == 28) catch @panic("test failure");
+ expect(v[167] == 29) catch @panic("test failure");
+ expect(v[168] == 30) catch @panic("test failure");
+ expect(v[169] == 31) catch @panic("test failure");
+ expect(v[170] == 32) catch @panic("test failure");
+ expect(v[171] == 33) catch @panic("test failure");
+ expect(v[172] == 34) catch @panic("test failure");
+ expect(v[173] == 35) catch @panic("test failure");
+ expect(v[174] == 36) catch @panic("test failure");
+ expect(v[175] == 37) catch @panic("test failure");
+ expect(v[176] == 38) catch @panic("test failure");
+ expect(v[177] == 39) catch @panic("test failure");
+ expect(v[178] == 40) catch @panic("test failure");
+ expect(v[179] == 41) catch @panic("test failure");
+ expect(v[180] == 42) catch @panic("test failure");
+ expect(v[181] == 43) catch @panic("test failure");
+ expect(v[182] == 44) catch @panic("test failure");
+ expect(v[183] == 45) catch @panic("test failure");
+ expect(v[184] == 46) catch @panic("test failure");
+ expect(v[185] == 47) catch @panic("test failure");
+ expect(v[186] == 48) catch @panic("test failure");
+ expect(v[187] == 49) catch @panic("test failure");
+ expect(v[188] == 50) catch @panic("test failure");
+ expect(v[189] == 51) catch @panic("test failure");
+ expect(v[190] == 52) catch @panic("test failure");
+ expect(v[191] == 53) catch @panic("test failure");
+ expect(v[192] == 54) catch @panic("test failure");
+ expect(v[193] == 55) catch @panic("test failure");
+ expect(v[194] == 56) catch @panic("test failure");
+ expect(v[195] == 57) catch @panic("test failure");
+ expect(v[196] == 58) catch @panic("test failure");
+ expect(v[197] == 59) catch @panic("test failure");
+ expect(v[198] == 60) catch @panic("test failure");
+ expect(v[199] == 61) catch @panic("test failure");
+ expect(v[200] == 62) catch @panic("test failure");
+ expect(v[201] == 63) catch @panic("test failure");
+ expect(v[202] == 64) catch @panic("test failure");
+ expect(v[203] == 65) catch @panic("test failure");
+ expect(v[204] == 66) catch @panic("test failure");
+ expect(v[205] == 67) catch @panic("test failure");
+ expect(v[206] == 68) catch @panic("test failure");
+ expect(v[207] == 69) catch @panic("test failure");
+ expect(v[208] == 70) catch @panic("test failure");
+ expect(v[209] == 71) catch @panic("test failure");
+ expect(v[210] == 72) catch @panic("test failure");
+ expect(v[211] == 73) catch @panic("test failure");
+ expect(v[212] == 74) catch @panic("test failure");
+ expect(v[213] == 75) catch @panic("test failure");
+ expect(v[214] == 76) catch @panic("test failure");
+ expect(v[215] == 77) catch @panic("test failure");
+ expect(v[216] == 78) catch @panic("test failure");
+ expect(v[217] == 79) catch @panic("test failure");
+ expect(v[218] == 80) catch @panic("test failure");
+ expect(v[219] == 81) catch @panic("test failure");
+ expect(v[220] == 82) catch @panic("test failure");
+ expect(v[221] == 83) catch @panic("test failure");
+ expect(v[222] == 84) catch @panic("test failure");
+ expect(v[223] == 85) catch @panic("test failure");
+ expect(v[224] == 86) catch @panic("test failure");
+ expect(v[225] == 87) catch @panic("test failure");
+ expect(v[226] == 88) catch @panic("test failure");
+ expect(v[227] == 89) catch @panic("test failure");
+ expect(v[228] == 90) catch @panic("test failure");
+ expect(v[229] == 91) catch @panic("test failure");
+ expect(v[230] == 92) catch @panic("test failure");
+ expect(v[231] == 93) catch @panic("test failure");
+ expect(v[232] == 94) catch @panic("test failure");
+ expect(v[233] == 95) catch @panic("test failure");
+ expect(v[234] == 96) catch @panic("test failure");
+ expect(v[235] == 97) catch @panic("test failure");
+ expect(v[236] == 98) catch @panic("test failure");
+ expect(v[237] == 99) catch @panic("test failure");
+ expect(v[238] == 0) catch @panic("test failure");
+ expect(v[239] == 1) catch @panic("test failure");
+ expect(v[240] == 2) catch @panic("test failure");
+ expect(v[241] == 3) catch @panic("test failure");
+ expect(v[242] == 4) catch @panic("test failure");
+ expect(v[243] == 5) catch @panic("test failure");
+ expect(v[244] == 6) catch @panic("test failure");
+ expect(v[245] == 7) catch @panic("test failure");
+ expect(v[246] == 8) catch @panic("test failure");
+ expect(v[247] == 9) catch @panic("test failure");
+ expect(v[248] == 10) catch @panic("test failure");
+ expect(v[249] == 11) catch @panic("test failure");
+ expect(v[250] == 12) catch @panic("test failure");
+ expect(v[251] == 13) catch @panic("test failure");
+ expect(v[252] == 14) catch @panic("test failure");
+ expect(v[253] == 15) catch @panic("test failure");
+ expect(v[254] == 16) catch @panic("test failure");
+ expect(v[255] == 17) catch @panic("test failure");
+ expect(v[256] == 18) catch @panic("test failure");
+ expect(v[257] == 19) catch @panic("test failure");
+ expect(v[258] == 20) catch @panic("test failure");
+ expect(v[259] == 21) catch @panic("test failure");
+ expect(v[260] == 22) catch @panic("test failure");
+ expect(v[261] == 23) catch @panic("test failure");
+ expect(v[262] == 24) catch @panic("test failure");
+ expect(v[263] == 25) catch @panic("test failure");
+ expect(v[264] == 26) catch @panic("test failure");
+ expect(v[265] == 27) catch @panic("test failure");
+ expect(v[266] == 28) catch @panic("test failure");
+ expect(v[267] == 29) catch @panic("test failure");
+ expect(v[268] == 30) catch @panic("test failure");
+ expect(v[269] == 31) catch @panic("test failure");
+ expect(v[270] == 32) catch @panic("test failure");
+ expect(v[271] == 33) catch @panic("test failure");
+ expect(v[272] == 34) catch @panic("test failure");
+ expect(v[273] == 35) catch @panic("test failure");
+ expect(v[274] == 36) catch @panic("test failure");
+ expect(v[275] == 37) catch @panic("test failure");
+ expect(v[276] == 38) catch @panic("test failure");
+ expect(v[277] == 39) catch @panic("test failure");
+ expect(v[278] == 40) catch @panic("test failure");
+ expect(v[279] == 41) catch @panic("test failure");
+ expect(v[280] == 42) catch @panic("test failure");
+ expect(v[281] == 43) catch @panic("test failure");
+ expect(v[282] == 44) catch @panic("test failure");
+ expect(v[283] == 45) catch @panic("test failure");
+ expect(v[284] == 46) catch @panic("test failure");
+ expect(v[285] == 47) catch @panic("test failure");
+ expect(v[286] == 48) catch @panic("test failure");
+ expect(v[287] == 49) catch @panic("test failure");
+ expect(v[288] == 50) catch @panic("test failure");
+ expect(v[289] == 51) catch @panic("test failure");
+ expect(v[290] == 52) catch @panic("test failure");
+ expect(v[291] == 53) catch @panic("test failure");
+ expect(v[292] == 54) catch @panic("test failure");
+ expect(v[293] == 55) catch @panic("test failure");
+ expect(v[294] == 56) catch @panic("test failure");
+ expect(v[295] == 57) catch @panic("test failure");
+ expect(v[296] == 58) catch @panic("test failure");
+ expect(v[297] == 59) catch @panic("test failure");
+ expect(v[298] == 60) catch @panic("test failure");
+ expect(v[299] == 61) catch @panic("test failure");
+ expect(v[300] == 62) catch @panic("test failure");
+ expect(v[301] == 63) catch @panic("test failure");
+ expect(v[302] == 64) catch @panic("test failure");
+ expect(v[303] == 65) catch @panic("test failure");
+ expect(v[304] == 66) catch @panic("test failure");
+ expect(v[305] == 67) catch @panic("test failure");
+ expect(v[306] == 68) catch @panic("test failure");
+ expect(v[307] == 69) catch @panic("test failure");
+ expect(v[308] == 70) catch @panic("test failure");
+ expect(v[309] == 71) catch @panic("test failure");
+ expect(v[310] == 72) catch @panic("test failure");
+ expect(v[311] == 73) catch @panic("test failure");
+ expect(v[312] == 74) catch @panic("test failure");
+ expect(v[313] == 75) catch @panic("test failure");
+ expect(v[314] == 76) catch @panic("test failure");
+ expect(v[315] == 77) catch @panic("test failure");
+ expect(v[316] == 78) catch @panic("test failure");
+ expect(v[317] == 79) catch @panic("test failure");
+ expect(v[318] == 80) catch @panic("test failure");
+ expect(v[319] == 81) catch @panic("test failure");
+ expect(v[320] == 82) catch @panic("test failure");
+ expect(v[321] == 83) catch @panic("test failure");
+ expect(v[322] == 84) catch @panic("test failure");
+ expect(v[323] == 85) catch @panic("test failure");
+ expect(v[324] == 86) catch @panic("test failure");
+ expect(v[325] == 87) catch @panic("test failure");
+ expect(v[326] == 88) catch @panic("test failure");
+ expect(v[327] == 89) catch @panic("test failure");
+ expect(v[328] == 90) catch @panic("test failure");
+ expect(v[329] == 91) catch @panic("test failure");
+ expect(v[330] == 92) catch @panic("test failure");
+ expect(v[331] == 93) catch @panic("test failure");
+ expect(v[332] == 94) catch @panic("test failure");
+ expect(v[333] == 95) catch @panic("test failure");
+ expect(v[334] == 96) catch @panic("test failure");
+ expect(v[335] == 97) catch @panic("test failure");
+ expect(v[336] == 98) catch @panic("test failure");
+ expect(v[337] == 99) catch @panic("test failure");
+ expect(v[338] == 0) catch @panic("test failure");
+ expect(v[339] == 1) catch @panic("test failure");
+ expect(v[340] == 2) catch @panic("test failure");
+ expect(v[341] == 3) catch @panic("test failure");
+ expect(v[342] == 4) catch @panic("test failure");
+ expect(v[343] == 5) catch @panic("test failure");
+ expect(v[344] == 6) catch @panic("test failure");
+ expect(v[345] == 7) catch @panic("test failure");
+ expect(v[346] == 8) catch @panic("test failure");
+ expect(v[347] == 9) catch @panic("test failure");
+ expect(v[348] == 10) catch @panic("test failure");
+ expect(v[349] == 11) catch @panic("test failure");
+ expect(v[350] == 12) catch @panic("test failure");
+ expect(v[351] == 13) catch @panic("test failure");
+ expect(v[352] == 14) catch @panic("test failure");
+ expect(v[353] == 15) catch @panic("test failure");
+ expect(v[354] == 16) catch @panic("test failure");
+ expect(v[355] == 17) catch @panic("test failure");
+ expect(v[356] == 18) catch @panic("test failure");
+ expect(v[357] == 19) catch @panic("test failure");
+ expect(v[358] == 20) catch @panic("test failure");
+ expect(v[359] == 21) catch @panic("test failure");
+ expect(v[360] == 22) catch @panic("test failure");
+ expect(v[361] == 23) catch @panic("test failure");
+ expect(v[362] == 24) catch @panic("test failure");
+ expect(v[363] == 25) catch @panic("test failure");
+ expect(v[364] == 26) catch @panic("test failure");
+ expect(v[365] == 27) catch @panic("test failure");
+ expect(v[366] == 28) catch @panic("test failure");
+ expect(v[367] == 29) catch @panic("test failure");
+ expect(v[368] == 30) catch @panic("test failure");
+ expect(v[369] == 31) catch @panic("test failure");
+ expect(v[370] == 32) catch @panic("test failure");
+ expect(v[371] == 33) catch @panic("test failure");
+ expect(v[372] == 34) catch @panic("test failure");
+ expect(v[373] == 35) catch @panic("test failure");
+ expect(v[374] == 36) catch @panic("test failure");
+ expect(v[375] == 37) catch @panic("test failure");
+ expect(v[376] == 38) catch @panic("test failure");
+ expect(v[377] == 39) catch @panic("test failure");
+ expect(v[378] == 40) catch @panic("test failure");
+ expect(v[379] == 41) catch @panic("test failure");
+ expect(v[380] == 42) catch @panic("test failure");
+ expect(v[381] == 43) catch @panic("test failure");
+ expect(v[382] == 44) catch @panic("test failure");
+ expect(v[383] == 45) catch @panic("test failure");
+ expect(i == 384) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_384_u8() @Vector(384, u8);
+extern fn c_vector_384_u8(@Vector(384, u8), usize) void;
+extern fn c_test_vector_384_u8() void;
+
+test "@Vector(384, u8)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_384_u8();
+ try expect(v[0] == 46);
+ try expect(v[1] == 47);
+ try expect(v[2] == 48);
+ try expect(v[3] == 49);
+ try expect(v[4] == 50);
+ try expect(v[5] == 51);
+ try expect(v[6] == 52);
+ try expect(v[7] == 53);
+ try expect(v[8] == 54);
+ try expect(v[9] == 55);
+ try expect(v[10] == 56);
+ try expect(v[11] == 57);
+ try expect(v[12] == 58);
+ try expect(v[13] == 59);
+ try expect(v[14] == 60);
+ try expect(v[15] == 61);
+ try expect(v[16] == 62);
+ try expect(v[17] == 63);
+ try expect(v[18] == 64);
+ try expect(v[19] == 65);
+ try expect(v[20] == 66);
+ try expect(v[21] == 67);
+ try expect(v[22] == 68);
+ try expect(v[23] == 69);
+ try expect(v[24] == 70);
+ try expect(v[25] == 71);
+ try expect(v[26] == 72);
+ try expect(v[27] == 73);
+ try expect(v[28] == 74);
+ try expect(v[29] == 75);
+ try expect(v[30] == 76);
+ try expect(v[31] == 77);
+ try expect(v[32] == 78);
+ try expect(v[33] == 79);
+ try expect(v[34] == 80);
+ try expect(v[35] == 81);
+ try expect(v[36] == 82);
+ try expect(v[37] == 83);
+ try expect(v[38] == 84);
+ try expect(v[39] == 85);
+ try expect(v[40] == 86);
+ try expect(v[41] == 87);
+ try expect(v[42] == 88);
+ try expect(v[43] == 89);
+ try expect(v[44] == 90);
+ try expect(v[45] == 91);
+ try expect(v[46] == 92);
+ try expect(v[47] == 93);
+ try expect(v[48] == 94);
+ try expect(v[49] == 95);
+ try expect(v[50] == 96);
+ try expect(v[51] == 97);
+ try expect(v[52] == 98);
+ try expect(v[53] == 99);
+ try expect(v[54] == 0);
+ try expect(v[55] == 1);
+ try expect(v[56] == 2);
+ try expect(v[57] == 3);
+ try expect(v[58] == 4);
+ try expect(v[59] == 5);
+ try expect(v[60] == 6);
+ try expect(v[61] == 7);
+ try expect(v[62] == 8);
+ try expect(v[63] == 9);
+ try expect(v[64] == 10);
+ try expect(v[65] == 11);
+ try expect(v[66] == 12);
+ try expect(v[67] == 13);
+ try expect(v[68] == 14);
+ try expect(v[69] == 15);
+ try expect(v[70] == 16);
+ try expect(v[71] == 17);
+ try expect(v[72] == 18);
+ try expect(v[73] == 19);
+ try expect(v[74] == 20);
+ try expect(v[75] == 21);
+ try expect(v[76] == 22);
+ try expect(v[77] == 23);
+ try expect(v[78] == 24);
+ try expect(v[79] == 25);
+ try expect(v[80] == 26);
+ try expect(v[81] == 27);
+ try expect(v[82] == 28);
+ try expect(v[83] == 29);
+ try expect(v[84] == 30);
+ try expect(v[85] == 31);
+ try expect(v[86] == 32);
+ try expect(v[87] == 33);
+ try expect(v[88] == 34);
+ try expect(v[89] == 35);
+ try expect(v[90] == 36);
+ try expect(v[91] == 37);
+ try expect(v[92] == 38);
+ try expect(v[93] == 39);
+ try expect(v[94] == 40);
+ try expect(v[95] == 41);
+ try expect(v[96] == 42);
+ try expect(v[97] == 43);
+ try expect(v[98] == 44);
+ try expect(v[99] == 45);
+ try expect(v[100] == 46);
+ try expect(v[101] == 47);
+ try expect(v[102] == 48);
+ try expect(v[103] == 49);
+ try expect(v[104] == 50);
+ try expect(v[105] == 51);
+ try expect(v[106] == 52);
+ try expect(v[107] == 53);
+ try expect(v[108] == 54);
+ try expect(v[109] == 55);
+ try expect(v[110] == 56);
+ try expect(v[111] == 57);
+ try expect(v[112] == 58);
+ try expect(v[113] == 59);
+ try expect(v[114] == 60);
+ try expect(v[115] == 61);
+ try expect(v[116] == 62);
+ try expect(v[117] == 63);
+ try expect(v[118] == 64);
+ try expect(v[119] == 65);
+ try expect(v[120] == 66);
+ try expect(v[121] == 67);
+ try expect(v[122] == 68);
+ try expect(v[123] == 69);
+ try expect(v[124] == 70);
+ try expect(v[125] == 71);
+ try expect(v[126] == 72);
+ try expect(v[127] == 73);
+ try expect(v[128] == 74);
+ try expect(v[129] == 75);
+ try expect(v[130] == 76);
+ try expect(v[131] == 77);
+ try expect(v[132] == 78);
+ try expect(v[133] == 79);
+ try expect(v[134] == 80);
+ try expect(v[135] == 81);
+ try expect(v[136] == 82);
+ try expect(v[137] == 83);
+ try expect(v[138] == 84);
+ try expect(v[139] == 85);
+ try expect(v[140] == 86);
+ try expect(v[141] == 87);
+ try expect(v[142] == 88);
+ try expect(v[143] == 89);
+ try expect(v[144] == 90);
+ try expect(v[145] == 91);
+ try expect(v[146] == 92);
+ try expect(v[147] == 93);
+ try expect(v[148] == 94);
+ try expect(v[149] == 95);
+ try expect(v[150] == 96);
+ try expect(v[151] == 97);
+ try expect(v[152] == 98);
+ try expect(v[153] == 99);
+ try expect(v[154] == 0);
+ try expect(v[155] == 1);
+ try expect(v[156] == 2);
+ try expect(v[157] == 3);
+ try expect(v[158] == 4);
+ try expect(v[159] == 5);
+ try expect(v[160] == 6);
+ try expect(v[161] == 7);
+ try expect(v[162] == 8);
+ try expect(v[163] == 9);
+ try expect(v[164] == 10);
+ try expect(v[165] == 11);
+ try expect(v[166] == 12);
+ try expect(v[167] == 13);
+ try expect(v[168] == 14);
+ try expect(v[169] == 15);
+ try expect(v[170] == 16);
+ try expect(v[171] == 17);
+ try expect(v[172] == 18);
+ try expect(v[173] == 19);
+ try expect(v[174] == 20);
+ try expect(v[175] == 21);
+ try expect(v[176] == 22);
+ try expect(v[177] == 23);
+ try expect(v[178] == 24);
+ try expect(v[179] == 25);
+ try expect(v[180] == 26);
+ try expect(v[181] == 27);
+ try expect(v[182] == 28);
+ try expect(v[183] == 29);
+ try expect(v[184] == 30);
+ try expect(v[185] == 31);
+ try expect(v[186] == 32);
+ try expect(v[187] == 33);
+ try expect(v[188] == 34);
+ try expect(v[189] == 35);
+ try expect(v[190] == 36);
+ try expect(v[191] == 37);
+ try expect(v[192] == 38);
+ try expect(v[193] == 39);
+ try expect(v[194] == 40);
+ try expect(v[195] == 41);
+ try expect(v[196] == 42);
+ try expect(v[197] == 43);
+ try expect(v[198] == 44);
+ try expect(v[199] == 45);
+ try expect(v[200] == 46);
+ try expect(v[201] == 47);
+ try expect(v[202] == 48);
+ try expect(v[203] == 49);
+ try expect(v[204] == 50);
+ try expect(v[205] == 51);
+ try expect(v[206] == 52);
+ try expect(v[207] == 53);
+ try expect(v[208] == 54);
+ try expect(v[209] == 55);
+ try expect(v[210] == 56);
+ try expect(v[211] == 57);
+ try expect(v[212] == 58);
+ try expect(v[213] == 59);
+ try expect(v[214] == 60);
+ try expect(v[215] == 61);
+ try expect(v[216] == 62);
+ try expect(v[217] == 63);
+ try expect(v[218] == 64);
+ try expect(v[219] == 65);
+ try expect(v[220] == 66);
+ try expect(v[221] == 67);
+ try expect(v[222] == 68);
+ try expect(v[223] == 69);
+ try expect(v[224] == 70);
+ try expect(v[225] == 71);
+ try expect(v[226] == 72);
+ try expect(v[227] == 73);
+ try expect(v[228] == 74);
+ try expect(v[229] == 75);
+ try expect(v[230] == 76);
+ try expect(v[231] == 77);
+ try expect(v[232] == 78);
+ try expect(v[233] == 79);
+ try expect(v[234] == 80);
+ try expect(v[235] == 81);
+ try expect(v[236] == 82);
+ try expect(v[237] == 83);
+ try expect(v[238] == 84);
+ try expect(v[239] == 85);
+ try expect(v[240] == 86);
+ try expect(v[241] == 87);
+ try expect(v[242] == 88);
+ try expect(v[243] == 89);
+ try expect(v[244] == 90);
+ try expect(v[245] == 91);
+ try expect(v[246] == 92);
+ try expect(v[247] == 93);
+ try expect(v[248] == 94);
+ try expect(v[249] == 95);
+ try expect(v[250] == 96);
+ try expect(v[251] == 97);
+ try expect(v[252] == 98);
+ try expect(v[253] == 99);
+ try expect(v[254] == 0);
+ try expect(v[255] == 1);
+ try expect(v[256] == 2);
+ try expect(v[257] == 3);
+ try expect(v[258] == 4);
+ try expect(v[259] == 5);
+ try expect(v[260] == 6);
+ try expect(v[261] == 7);
+ try expect(v[262] == 8);
+ try expect(v[263] == 9);
+ try expect(v[264] == 10);
+ try expect(v[265] == 11);
+ try expect(v[266] == 12);
+ try expect(v[267] == 13);
+ try expect(v[268] == 14);
+ try expect(v[269] == 15);
+ try expect(v[270] == 16);
+ try expect(v[271] == 17);
+ try expect(v[272] == 18);
+ try expect(v[273] == 19);
+ try expect(v[274] == 20);
+ try expect(v[275] == 21);
+ try expect(v[276] == 22);
+ try expect(v[277] == 23);
+ try expect(v[278] == 24);
+ try expect(v[279] == 25);
+ try expect(v[280] == 26);
+ try expect(v[281] == 27);
+ try expect(v[282] == 28);
+ try expect(v[283] == 29);
+ try expect(v[284] == 30);
+ try expect(v[285] == 31);
+ try expect(v[286] == 32);
+ try expect(v[287] == 33);
+ try expect(v[288] == 34);
+ try expect(v[289] == 35);
+ try expect(v[290] == 36);
+ try expect(v[291] == 37);
+ try expect(v[292] == 38);
+ try expect(v[293] == 39);
+ try expect(v[294] == 40);
+ try expect(v[295] == 41);
+ try expect(v[296] == 42);
+ try expect(v[297] == 43);
+ try expect(v[298] == 44);
+ try expect(v[299] == 45);
+ try expect(v[300] == 46);
+ try expect(v[301] == 47);
+ try expect(v[302] == 48);
+ try expect(v[303] == 49);
+ try expect(v[304] == 50);
+ try expect(v[305] == 51);
+ try expect(v[306] == 52);
+ try expect(v[307] == 53);
+ try expect(v[308] == 54);
+ try expect(v[309] == 55);
+ try expect(v[310] == 56);
+ try expect(v[311] == 57);
+ try expect(v[312] == 58);
+ try expect(v[313] == 59);
+ try expect(v[314] == 60);
+ try expect(v[315] == 61);
+ try expect(v[316] == 62);
+ try expect(v[317] == 63);
+ try expect(v[318] == 64);
+ try expect(v[319] == 65);
+ try expect(v[320] == 66);
+ try expect(v[321] == 67);
+ try expect(v[322] == 68);
+ try expect(v[323] == 69);
+ try expect(v[324] == 70);
+ try expect(v[325] == 71);
+ try expect(v[326] == 72);
+ try expect(v[327] == 73);
+ try expect(v[328] == 74);
+ try expect(v[329] == 75);
+ try expect(v[330] == 76);
+ try expect(v[331] == 77);
+ try expect(v[332] == 78);
+ try expect(v[333] == 79);
+ try expect(v[334] == 80);
+ try expect(v[335] == 81);
+ try expect(v[336] == 82);
+ try expect(v[337] == 83);
+ try expect(v[338] == 84);
+ try expect(v[339] == 85);
+ try expect(v[340] == 86);
+ try expect(v[341] == 87);
+ try expect(v[342] == 88);
+ try expect(v[343] == 89);
+ try expect(v[344] == 90);
+ try expect(v[345] == 91);
+ try expect(v[346] == 92);
+ try expect(v[347] == 93);
+ try expect(v[348] == 94);
+ try expect(v[349] == 95);
+ try expect(v[350] == 96);
+ try expect(v[351] == 97);
+ try expect(v[352] == 98);
+ try expect(v[353] == 99);
+ try expect(v[354] == 0);
+ try expect(v[355] == 1);
+ try expect(v[356] == 2);
+ try expect(v[357] == 3);
+ try expect(v[358] == 4);
+ try expect(v[359] == 5);
+ try expect(v[360] == 6);
+ try expect(v[361] == 7);
+ try expect(v[362] == 8);
+ try expect(v[363] == 9);
+ try expect(v[364] == 10);
+ try expect(v[365] == 11);
+ try expect(v[366] == 12);
+ try expect(v[367] == 13);
+ try expect(v[368] == 14);
+ try expect(v[369] == 15);
+ try expect(v[370] == 16);
+ try expect(v[371] == 17);
+ try expect(v[372] == 18);
+ try expect(v[373] == 19);
+ try expect(v[374] == 20);
+ try expect(v[375] == 21);
+ try expect(v[376] == 22);
+ try expect(v[377] == 23);
+ try expect(v[378] == 24);
+ try expect(v[379] == 25);
+ try expect(v[380] == 26);
+ try expect(v[381] == 27);
+ try expect(v[382] == 28);
+ try expect(v[383] == 29);
+ c_vector_384_u8(.{
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ }, 384);
+ c_test_vector_384_u8();
+}
+
+export fn zig_ret_vector_512_u8() @Vector(512, u8) {
+ return .{
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ };
+}
+export fn zig_vector_512_u8(v: @Vector(512, u8), i: usize) void {
+ expect(v[0] == 26) catch @panic("test failure");
+ expect(v[1] == 27) catch @panic("test failure");
+ expect(v[2] == 28) catch @panic("test failure");
+ expect(v[3] == 29) catch @panic("test failure");
+ expect(v[4] == 30) catch @panic("test failure");
+ expect(v[5] == 31) catch @panic("test failure");
+ expect(v[6] == 32) catch @panic("test failure");
+ expect(v[7] == 33) catch @panic("test failure");
+ expect(v[8] == 34) catch @panic("test failure");
+ expect(v[9] == 35) catch @panic("test failure");
+ expect(v[10] == 36) catch @panic("test failure");
+ expect(v[11] == 37) catch @panic("test failure");
+ expect(v[12] == 38) catch @panic("test failure");
+ expect(v[13] == 39) catch @panic("test failure");
+ expect(v[14] == 40) catch @panic("test failure");
+ expect(v[15] == 41) catch @panic("test failure");
+ expect(v[16] == 42) catch @panic("test failure");
+ expect(v[17] == 43) catch @panic("test failure");
+ expect(v[18] == 44) catch @panic("test failure");
+ expect(v[19] == 45) catch @panic("test failure");
+ expect(v[20] == 46) catch @panic("test failure");
+ expect(v[21] == 47) catch @panic("test failure");
+ expect(v[22] == 48) catch @panic("test failure");
+ expect(v[23] == 49) catch @panic("test failure");
+ expect(v[24] == 50) catch @panic("test failure");
+ expect(v[25] == 51) catch @panic("test failure");
+ expect(v[26] == 52) catch @panic("test failure");
+ expect(v[27] == 53) catch @panic("test failure");
+ expect(v[28] == 54) catch @panic("test failure");
+ expect(v[29] == 55) catch @panic("test failure");
+ expect(v[30] == 56) catch @panic("test failure");
+ expect(v[31] == 57) catch @panic("test failure");
+ expect(v[32] == 58) catch @panic("test failure");
+ expect(v[33] == 59) catch @panic("test failure");
+ expect(v[34] == 60) catch @panic("test failure");
+ expect(v[35] == 61) catch @panic("test failure");
+ expect(v[36] == 62) catch @panic("test failure");
+ expect(v[37] == 63) catch @panic("test failure");
+ expect(v[38] == 64) catch @panic("test failure");
+ expect(v[39] == 65) catch @panic("test failure");
+ expect(v[40] == 66) catch @panic("test failure");
+ expect(v[41] == 67) catch @panic("test failure");
+ expect(v[42] == 68) catch @panic("test failure");
+ expect(v[43] == 69) catch @panic("test failure");
+ expect(v[44] == 70) catch @panic("test failure");
+ expect(v[45] == 71) catch @panic("test failure");
+ expect(v[46] == 72) catch @panic("test failure");
+ expect(v[47] == 73) catch @panic("test failure");
+ expect(v[48] == 74) catch @panic("test failure");
+ expect(v[49] == 75) catch @panic("test failure");
+ expect(v[50] == 76) catch @panic("test failure");
+ expect(v[51] == 77) catch @panic("test failure");
+ expect(v[52] == 78) catch @panic("test failure");
+ expect(v[53] == 79) catch @panic("test failure");
+ expect(v[54] == 80) catch @panic("test failure");
+ expect(v[55] == 81) catch @panic("test failure");
+ expect(v[56] == 82) catch @panic("test failure");
+ expect(v[57] == 83) catch @panic("test failure");
+ expect(v[58] == 84) catch @panic("test failure");
+ expect(v[59] == 85) catch @panic("test failure");
+ expect(v[60] == 86) catch @panic("test failure");
+ expect(v[61] == 87) catch @panic("test failure");
+ expect(v[62] == 88) catch @panic("test failure");
+ expect(v[63] == 89) catch @panic("test failure");
+ expect(v[64] == 90) catch @panic("test failure");
+ expect(v[65] == 91) catch @panic("test failure");
+ expect(v[66] == 92) catch @panic("test failure");
+ expect(v[67] == 93) catch @panic("test failure");
+ expect(v[68] == 94) catch @panic("test failure");
+ expect(v[69] == 95) catch @panic("test failure");
+ expect(v[70] == 96) catch @panic("test failure");
+ expect(v[71] == 97) catch @panic("test failure");
+ expect(v[72] == 98) catch @panic("test failure");
+ expect(v[73] == 99) catch @panic("test failure");
+ expect(v[74] == 0) catch @panic("test failure");
+ expect(v[75] == 1) catch @panic("test failure");
+ expect(v[76] == 2) catch @panic("test failure");
+ expect(v[77] == 3) catch @panic("test failure");
+ expect(v[78] == 4) catch @panic("test failure");
+ expect(v[79] == 5) catch @panic("test failure");
+ expect(v[80] == 6) catch @panic("test failure");
+ expect(v[81] == 7) catch @panic("test failure");
+ expect(v[82] == 8) catch @panic("test failure");
+ expect(v[83] == 9) catch @panic("test failure");
+ expect(v[84] == 10) catch @panic("test failure");
+ expect(v[85] == 11) catch @panic("test failure");
+ expect(v[86] == 12) catch @panic("test failure");
+ expect(v[87] == 13) catch @panic("test failure");
+ expect(v[88] == 14) catch @panic("test failure");
+ expect(v[89] == 15) catch @panic("test failure");
+ expect(v[90] == 16) catch @panic("test failure");
+ expect(v[91] == 17) catch @panic("test failure");
+ expect(v[92] == 18) catch @panic("test failure");
+ expect(v[93] == 19) catch @panic("test failure");
+ expect(v[94] == 20) catch @panic("test failure");
+ expect(v[95] == 21) catch @panic("test failure");
+ expect(v[96] == 22) catch @panic("test failure");
+ expect(v[97] == 23) catch @panic("test failure");
+ expect(v[98] == 24) catch @panic("test failure");
+ expect(v[99] == 25) catch @panic("test failure");
+ expect(v[100] == 26) catch @panic("test failure");
+ expect(v[101] == 27) catch @panic("test failure");
+ expect(v[102] == 28) catch @panic("test failure");
+ expect(v[103] == 29) catch @panic("test failure");
+ expect(v[104] == 30) catch @panic("test failure");
+ expect(v[105] == 31) catch @panic("test failure");
+ expect(v[106] == 32) catch @panic("test failure");
+ expect(v[107] == 33) catch @panic("test failure");
+ expect(v[108] == 34) catch @panic("test failure");
+ expect(v[109] == 35) catch @panic("test failure");
+ expect(v[110] == 36) catch @panic("test failure");
+ expect(v[111] == 37) catch @panic("test failure");
+ expect(v[112] == 38) catch @panic("test failure");
+ expect(v[113] == 39) catch @panic("test failure");
+ expect(v[114] == 40) catch @panic("test failure");
+ expect(v[115] == 41) catch @panic("test failure");
+ expect(v[116] == 42) catch @panic("test failure");
+ expect(v[117] == 43) catch @panic("test failure");
+ expect(v[118] == 44) catch @panic("test failure");
+ expect(v[119] == 45) catch @panic("test failure");
+ expect(v[120] == 46) catch @panic("test failure");
+ expect(v[121] == 47) catch @panic("test failure");
+ expect(v[122] == 48) catch @panic("test failure");
+ expect(v[123] == 49) catch @panic("test failure");
+ expect(v[124] == 50) catch @panic("test failure");
+ expect(v[125] == 51) catch @panic("test failure");
+ expect(v[126] == 52) catch @panic("test failure");
+ expect(v[127] == 53) catch @panic("test failure");
+ expect(v[128] == 54) catch @panic("test failure");
+ expect(v[129] == 55) catch @panic("test failure");
+ expect(v[130] == 56) catch @panic("test failure");
+ expect(v[131] == 57) catch @panic("test failure");
+ expect(v[132] == 58) catch @panic("test failure");
+ expect(v[133] == 59) catch @panic("test failure");
+ expect(v[134] == 60) catch @panic("test failure");
+ expect(v[135] == 61) catch @panic("test failure");
+ expect(v[136] == 62) catch @panic("test failure");
+ expect(v[137] == 63) catch @panic("test failure");
+ expect(v[138] == 64) catch @panic("test failure");
+ expect(v[139] == 65) catch @panic("test failure");
+ expect(v[140] == 66) catch @panic("test failure");
+ expect(v[141] == 67) catch @panic("test failure");
+ expect(v[142] == 68) catch @panic("test failure");
+ expect(v[143] == 69) catch @panic("test failure");
+ expect(v[144] == 70) catch @panic("test failure");
+ expect(v[145] == 71) catch @panic("test failure");
+ expect(v[146] == 72) catch @panic("test failure");
+ expect(v[147] == 73) catch @panic("test failure");
+ expect(v[148] == 74) catch @panic("test failure");
+ expect(v[149] == 75) catch @panic("test failure");
+ expect(v[150] == 76) catch @panic("test failure");
+ expect(v[151] == 77) catch @panic("test failure");
+ expect(v[152] == 78) catch @panic("test failure");
+ expect(v[153] == 79) catch @panic("test failure");
+ expect(v[154] == 80) catch @panic("test failure");
+ expect(v[155] == 81) catch @panic("test failure");
+ expect(v[156] == 82) catch @panic("test failure");
+ expect(v[157] == 83) catch @panic("test failure");
+ expect(v[158] == 84) catch @panic("test failure");
+ expect(v[159] == 85) catch @panic("test failure");
+ expect(v[160] == 86) catch @panic("test failure");
+ expect(v[161] == 87) catch @panic("test failure");
+ expect(v[162] == 88) catch @panic("test failure");
+ expect(v[163] == 89) catch @panic("test failure");
+ expect(v[164] == 90) catch @panic("test failure");
+ expect(v[165] == 91) catch @panic("test failure");
+ expect(v[166] == 92) catch @panic("test failure");
+ expect(v[167] == 93) catch @panic("test failure");
+ expect(v[168] == 94) catch @panic("test failure");
+ expect(v[169] == 95) catch @panic("test failure");
+ expect(v[170] == 96) catch @panic("test failure");
+ expect(v[171] == 97) catch @panic("test failure");
+ expect(v[172] == 98) catch @panic("test failure");
+ expect(v[173] == 99) catch @panic("test failure");
+ expect(v[174] == 0) catch @panic("test failure");
+ expect(v[175] == 1) catch @panic("test failure");
+ expect(v[176] == 2) catch @panic("test failure");
+ expect(v[177] == 3) catch @panic("test failure");
+ expect(v[178] == 4) catch @panic("test failure");
+ expect(v[179] == 5) catch @panic("test failure");
+ expect(v[180] == 6) catch @panic("test failure");
+ expect(v[181] == 7) catch @panic("test failure");
+ expect(v[182] == 8) catch @panic("test failure");
+ expect(v[183] == 9) catch @panic("test failure");
+ expect(v[184] == 10) catch @panic("test failure");
+ expect(v[185] == 11) catch @panic("test failure");
+ expect(v[186] == 12) catch @panic("test failure");
+ expect(v[187] == 13) catch @panic("test failure");
+ expect(v[188] == 14) catch @panic("test failure");
+ expect(v[189] == 15) catch @panic("test failure");
+ expect(v[190] == 16) catch @panic("test failure");
+ expect(v[191] == 17) catch @panic("test failure");
+ expect(v[192] == 18) catch @panic("test failure");
+ expect(v[193] == 19) catch @panic("test failure");
+ expect(v[194] == 20) catch @panic("test failure");
+ expect(v[195] == 21) catch @panic("test failure");
+ expect(v[196] == 22) catch @panic("test failure");
+ expect(v[197] == 23) catch @panic("test failure");
+ expect(v[198] == 24) catch @panic("test failure");
+ expect(v[199] == 25) catch @panic("test failure");
+ expect(v[200] == 26) catch @panic("test failure");
+ expect(v[201] == 27) catch @panic("test failure");
+ expect(v[202] == 28) catch @panic("test failure");
+ expect(v[203] == 29) catch @panic("test failure");
+ expect(v[204] == 30) catch @panic("test failure");
+ expect(v[205] == 31) catch @panic("test failure");
+ expect(v[206] == 32) catch @panic("test failure");
+ expect(v[207] == 33) catch @panic("test failure");
+ expect(v[208] == 34) catch @panic("test failure");
+ expect(v[209] == 35) catch @panic("test failure");
+ expect(v[210] == 36) catch @panic("test failure");
+ expect(v[211] == 37) catch @panic("test failure");
+ expect(v[212] == 38) catch @panic("test failure");
+ expect(v[213] == 39) catch @panic("test failure");
+ expect(v[214] == 40) catch @panic("test failure");
+ expect(v[215] == 41) catch @panic("test failure");
+ expect(v[216] == 42) catch @panic("test failure");
+ expect(v[217] == 43) catch @panic("test failure");
+ expect(v[218] == 44) catch @panic("test failure");
+ expect(v[219] == 45) catch @panic("test failure");
+ expect(v[220] == 46) catch @panic("test failure");
+ expect(v[221] == 47) catch @panic("test failure");
+ expect(v[222] == 48) catch @panic("test failure");
+ expect(v[223] == 49) catch @panic("test failure");
+ expect(v[224] == 50) catch @panic("test failure");
+ expect(v[225] == 51) catch @panic("test failure");
+ expect(v[226] == 52) catch @panic("test failure");
+ expect(v[227] == 53) catch @panic("test failure");
+ expect(v[228] == 54) catch @panic("test failure");
+ expect(v[229] == 55) catch @panic("test failure");
+ expect(v[230] == 56) catch @panic("test failure");
+ expect(v[231] == 57) catch @panic("test failure");
+ expect(v[232] == 58) catch @panic("test failure");
+ expect(v[233] == 59) catch @panic("test failure");
+ expect(v[234] == 60) catch @panic("test failure");
+ expect(v[235] == 61) catch @panic("test failure");
+ expect(v[236] == 62) catch @panic("test failure");
+ expect(v[237] == 63) catch @panic("test failure");
+ expect(v[238] == 64) catch @panic("test failure");
+ expect(v[239] == 65) catch @panic("test failure");
+ expect(v[240] == 66) catch @panic("test failure");
+ expect(v[241] == 67) catch @panic("test failure");
+ expect(v[242] == 68) catch @panic("test failure");
+ expect(v[243] == 69) catch @panic("test failure");
+ expect(v[244] == 70) catch @panic("test failure");
+ expect(v[245] == 71) catch @panic("test failure");
+ expect(v[246] == 72) catch @panic("test failure");
+ expect(v[247] == 73) catch @panic("test failure");
+ expect(v[248] == 74) catch @panic("test failure");
+ expect(v[249] == 75) catch @panic("test failure");
+ expect(v[250] == 76) catch @panic("test failure");
+ expect(v[251] == 77) catch @panic("test failure");
+ expect(v[252] == 78) catch @panic("test failure");
+ expect(v[253] == 79) catch @panic("test failure");
+ expect(v[254] == 80) catch @panic("test failure");
+ expect(v[255] == 81) catch @panic("test failure");
+ expect(v[256] == 82) catch @panic("test failure");
+ expect(v[257] == 83) catch @panic("test failure");
+ expect(v[258] == 84) catch @panic("test failure");
+ expect(v[259] == 85) catch @panic("test failure");
+ expect(v[260] == 86) catch @panic("test failure");
+ expect(v[261] == 87) catch @panic("test failure");
+ expect(v[262] == 88) catch @panic("test failure");
+ expect(v[263] == 89) catch @panic("test failure");
+ expect(v[264] == 90) catch @panic("test failure");
+ expect(v[265] == 91) catch @panic("test failure");
+ expect(v[266] == 92) catch @panic("test failure");
+ expect(v[267] == 93) catch @panic("test failure");
+ expect(v[268] == 94) catch @panic("test failure");
+ expect(v[269] == 95) catch @panic("test failure");
+ expect(v[270] == 96) catch @panic("test failure");
+ expect(v[271] == 97) catch @panic("test failure");
+ expect(v[272] == 98) catch @panic("test failure");
+ expect(v[273] == 99) catch @panic("test failure");
+ expect(v[274] == 0) catch @panic("test failure");
+ expect(v[275] == 1) catch @panic("test failure");
+ expect(v[276] == 2) catch @panic("test failure");
+ expect(v[277] == 3) catch @panic("test failure");
+ expect(v[278] == 4) catch @panic("test failure");
+ expect(v[279] == 5) catch @panic("test failure");
+ expect(v[280] == 6) catch @panic("test failure");
+ expect(v[281] == 7) catch @panic("test failure");
+ expect(v[282] == 8) catch @panic("test failure");
+ expect(v[283] == 9) catch @panic("test failure");
+ expect(v[284] == 10) catch @panic("test failure");
+ expect(v[285] == 11) catch @panic("test failure");
+ expect(v[286] == 12) catch @panic("test failure");
+ expect(v[287] == 13) catch @panic("test failure");
+ expect(v[288] == 14) catch @panic("test failure");
+ expect(v[289] == 15) catch @panic("test failure");
+ expect(v[290] == 16) catch @panic("test failure");
+ expect(v[291] == 17) catch @panic("test failure");
+ expect(v[292] == 18) catch @panic("test failure");
+ expect(v[293] == 19) catch @panic("test failure");
+ expect(v[294] == 20) catch @panic("test failure");
+ expect(v[295] == 21) catch @panic("test failure");
+ expect(v[296] == 22) catch @panic("test failure");
+ expect(v[297] == 23) catch @panic("test failure");
+ expect(v[298] == 24) catch @panic("test failure");
+ expect(v[299] == 25) catch @panic("test failure");
+ expect(v[300] == 26) catch @panic("test failure");
+ expect(v[301] == 27) catch @panic("test failure");
+ expect(v[302] == 28) catch @panic("test failure");
+ expect(v[303] == 29) catch @panic("test failure");
+ expect(v[304] == 30) catch @panic("test failure");
+ expect(v[305] == 31) catch @panic("test failure");
+ expect(v[306] == 32) catch @panic("test failure");
+ expect(v[307] == 33) catch @panic("test failure");
+ expect(v[308] == 34) catch @panic("test failure");
+ expect(v[309] == 35) catch @panic("test failure");
+ expect(v[310] == 36) catch @panic("test failure");
+ expect(v[311] == 37) catch @panic("test failure");
+ expect(v[312] == 38) catch @panic("test failure");
+ expect(v[313] == 39) catch @panic("test failure");
+ expect(v[314] == 40) catch @panic("test failure");
+ expect(v[315] == 41) catch @panic("test failure");
+ expect(v[316] == 42) catch @panic("test failure");
+ expect(v[317] == 43) catch @panic("test failure");
+ expect(v[318] == 44) catch @panic("test failure");
+ expect(v[319] == 45) catch @panic("test failure");
+ expect(v[320] == 46) catch @panic("test failure");
+ expect(v[321] == 47) catch @panic("test failure");
+ expect(v[322] == 48) catch @panic("test failure");
+ expect(v[323] == 49) catch @panic("test failure");
+ expect(v[324] == 50) catch @panic("test failure");
+ expect(v[325] == 51) catch @panic("test failure");
+ expect(v[326] == 52) catch @panic("test failure");
+ expect(v[327] == 53) catch @panic("test failure");
+ expect(v[328] == 54) catch @panic("test failure");
+ expect(v[329] == 55) catch @panic("test failure");
+ expect(v[330] == 56) catch @panic("test failure");
+ expect(v[331] == 57) catch @panic("test failure");
+ expect(v[332] == 58) catch @panic("test failure");
+ expect(v[333] == 59) catch @panic("test failure");
+ expect(v[334] == 60) catch @panic("test failure");
+ expect(v[335] == 61) catch @panic("test failure");
+ expect(v[336] == 62) catch @panic("test failure");
+ expect(v[337] == 63) catch @panic("test failure");
+ expect(v[338] == 64) catch @panic("test failure");
+ expect(v[339] == 65) catch @panic("test failure");
+ expect(v[340] == 66) catch @panic("test failure");
+ expect(v[341] == 67) catch @panic("test failure");
+ expect(v[342] == 68) catch @panic("test failure");
+ expect(v[343] == 69) catch @panic("test failure");
+ expect(v[344] == 70) catch @panic("test failure");
+ expect(v[345] == 71) catch @panic("test failure");
+ expect(v[346] == 72) catch @panic("test failure");
+ expect(v[347] == 73) catch @panic("test failure");
+ expect(v[348] == 74) catch @panic("test failure");
+ expect(v[349] == 75) catch @panic("test failure");
+ expect(v[350] == 76) catch @panic("test failure");
+ expect(v[351] == 77) catch @panic("test failure");
+ expect(v[352] == 78) catch @panic("test failure");
+ expect(v[353] == 79) catch @panic("test failure");
+ expect(v[354] == 80) catch @panic("test failure");
+ expect(v[355] == 81) catch @panic("test failure");
+ expect(v[356] == 82) catch @panic("test failure");
+ expect(v[357] == 83) catch @panic("test failure");
+ expect(v[358] == 84) catch @panic("test failure");
+ expect(v[359] == 85) catch @panic("test failure");
+ expect(v[360] == 86) catch @panic("test failure");
+ expect(v[361] == 87) catch @panic("test failure");
+ expect(v[362] == 88) catch @panic("test failure");
+ expect(v[363] == 89) catch @panic("test failure");
+ expect(v[364] == 90) catch @panic("test failure");
+ expect(v[365] == 91) catch @panic("test failure");
+ expect(v[366] == 92) catch @panic("test failure");
+ expect(v[367] == 93) catch @panic("test failure");
+ expect(v[368] == 94) catch @panic("test failure");
+ expect(v[369] == 95) catch @panic("test failure");
+ expect(v[370] == 96) catch @panic("test failure");
+ expect(v[371] == 97) catch @panic("test failure");
+ expect(v[372] == 98) catch @panic("test failure");
+ expect(v[373] == 99) catch @panic("test failure");
+ expect(v[374] == 0) catch @panic("test failure");
+ expect(v[375] == 1) catch @panic("test failure");
+ expect(v[376] == 2) catch @panic("test failure");
+ expect(v[377] == 3) catch @panic("test failure");
+ expect(v[378] == 4) catch @panic("test failure");
+ expect(v[379] == 5) catch @panic("test failure");
+ expect(v[380] == 6) catch @panic("test failure");
+ expect(v[381] == 7) catch @panic("test failure");
+ expect(v[382] == 8) catch @panic("test failure");
+ expect(v[383] == 9) catch @panic("test failure");
+ expect(v[384] == 10) catch @panic("test failure");
+ expect(v[385] == 11) catch @panic("test failure");
+ expect(v[386] == 12) catch @panic("test failure");
+ expect(v[387] == 13) catch @panic("test failure");
+ expect(v[388] == 14) catch @panic("test failure");
+ expect(v[389] == 15) catch @panic("test failure");
+ expect(v[390] == 16) catch @panic("test failure");
+ expect(v[391] == 17) catch @panic("test failure");
+ expect(v[392] == 18) catch @panic("test failure");
+ expect(v[393] == 19) catch @panic("test failure");
+ expect(v[394] == 20) catch @panic("test failure");
+ expect(v[395] == 21) catch @panic("test failure");
+ expect(v[396] == 22) catch @panic("test failure");
+ expect(v[397] == 23) catch @panic("test failure");
+ expect(v[398] == 24) catch @panic("test failure");
+ expect(v[399] == 25) catch @panic("test failure");
+ expect(v[400] == 26) catch @panic("test failure");
+ expect(v[401] == 27) catch @panic("test failure");
+ expect(v[402] == 28) catch @panic("test failure");
+ expect(v[403] == 29) catch @panic("test failure");
+ expect(v[404] == 30) catch @panic("test failure");
+ expect(v[405] == 31) catch @panic("test failure");
+ expect(v[406] == 32) catch @panic("test failure");
+ expect(v[407] == 33) catch @panic("test failure");
+ expect(v[408] == 34) catch @panic("test failure");
+ expect(v[409] == 35) catch @panic("test failure");
+ expect(v[410] == 36) catch @panic("test failure");
+ expect(v[411] == 37) catch @panic("test failure");
+ expect(v[412] == 38) catch @panic("test failure");
+ expect(v[413] == 39) catch @panic("test failure");
+ expect(v[414] == 40) catch @panic("test failure");
+ expect(v[415] == 41) catch @panic("test failure");
+ expect(v[416] == 42) catch @panic("test failure");
+ expect(v[417] == 43) catch @panic("test failure");
+ expect(v[418] == 44) catch @panic("test failure");
+ expect(v[419] == 45) catch @panic("test failure");
+ expect(v[420] == 46) catch @panic("test failure");
+ expect(v[421] == 47) catch @panic("test failure");
+ expect(v[422] == 48) catch @panic("test failure");
+ expect(v[423] == 49) catch @panic("test failure");
+ expect(v[424] == 50) catch @panic("test failure");
+ expect(v[425] == 51) catch @panic("test failure");
+ expect(v[426] == 52) catch @panic("test failure");
+ expect(v[427] == 53) catch @panic("test failure");
+ expect(v[428] == 54) catch @panic("test failure");
+ expect(v[429] == 55) catch @panic("test failure");
+ expect(v[430] == 56) catch @panic("test failure");
+ expect(v[431] == 57) catch @panic("test failure");
+ expect(v[432] == 58) catch @panic("test failure");
+ expect(v[433] == 59) catch @panic("test failure");
+ expect(v[434] == 60) catch @panic("test failure");
+ expect(v[435] == 61) catch @panic("test failure");
+ expect(v[436] == 62) catch @panic("test failure");
+ expect(v[437] == 63) catch @panic("test failure");
+ expect(v[438] == 64) catch @panic("test failure");
+ expect(v[439] == 65) catch @panic("test failure");
+ expect(v[440] == 66) catch @panic("test failure");
+ expect(v[441] == 67) catch @panic("test failure");
+ expect(v[442] == 68) catch @panic("test failure");
+ expect(v[443] == 69) catch @panic("test failure");
+ expect(v[444] == 70) catch @panic("test failure");
+ expect(v[445] == 71) catch @panic("test failure");
+ expect(v[446] == 72) catch @panic("test failure");
+ expect(v[447] == 73) catch @panic("test failure");
+ expect(v[448] == 74) catch @panic("test failure");
+ expect(v[449] == 75) catch @panic("test failure");
+ expect(v[450] == 76) catch @panic("test failure");
+ expect(v[451] == 77) catch @panic("test failure");
+ expect(v[452] == 78) catch @panic("test failure");
+ expect(v[453] == 79) catch @panic("test failure");
+ expect(v[454] == 80) catch @panic("test failure");
+ expect(v[455] == 81) catch @panic("test failure");
+ expect(v[456] == 82) catch @panic("test failure");
+ expect(v[457] == 83) catch @panic("test failure");
+ expect(v[458] == 84) catch @panic("test failure");
+ expect(v[459] == 85) catch @panic("test failure");
+ expect(v[460] == 86) catch @panic("test failure");
+ expect(v[461] == 87) catch @panic("test failure");
+ expect(v[462] == 88) catch @panic("test failure");
+ expect(v[463] == 89) catch @panic("test failure");
+ expect(v[464] == 90) catch @panic("test failure");
+ expect(v[465] == 91) catch @panic("test failure");
+ expect(v[466] == 92) catch @panic("test failure");
+ expect(v[467] == 93) catch @panic("test failure");
+ expect(v[468] == 94) catch @panic("test failure");
+ expect(v[469] == 95) catch @panic("test failure");
+ expect(v[470] == 96) catch @panic("test failure");
+ expect(v[471] == 97) catch @panic("test failure");
+ expect(v[472] == 98) catch @panic("test failure");
+ expect(v[473] == 99) catch @panic("test failure");
+ expect(v[474] == 0) catch @panic("test failure");
+ expect(v[475] == 1) catch @panic("test failure");
+ expect(v[476] == 2) catch @panic("test failure");
+ expect(v[477] == 3) catch @panic("test failure");
+ expect(v[478] == 4) catch @panic("test failure");
+ expect(v[479] == 5) catch @panic("test failure");
+ expect(v[480] == 6) catch @panic("test failure");
+ expect(v[481] == 7) catch @panic("test failure");
+ expect(v[482] == 8) catch @panic("test failure");
+ expect(v[483] == 9) catch @panic("test failure");
+ expect(v[484] == 10) catch @panic("test failure");
+ expect(v[485] == 11) catch @panic("test failure");
+ expect(v[486] == 12) catch @panic("test failure");
+ expect(v[487] == 13) catch @panic("test failure");
+ expect(v[488] == 14) catch @panic("test failure");
+ expect(v[489] == 15) catch @panic("test failure");
+ expect(v[490] == 16) catch @panic("test failure");
+ expect(v[491] == 17) catch @panic("test failure");
+ expect(v[492] == 18) catch @panic("test failure");
+ expect(v[493] == 19) catch @panic("test failure");
+ expect(v[494] == 20) catch @panic("test failure");
+ expect(v[495] == 21) catch @panic("test failure");
+ expect(v[496] == 22) catch @panic("test failure");
+ expect(v[497] == 23) catch @panic("test failure");
+ expect(v[498] == 24) catch @panic("test failure");
+ expect(v[499] == 25) catch @panic("test failure");
+ expect(v[500] == 26) catch @panic("test failure");
+ expect(v[501] == 27) catch @panic("test failure");
+ expect(v[502] == 28) catch @panic("test failure");
+ expect(v[503] == 29) catch @panic("test failure");
+ expect(v[504] == 30) catch @panic("test failure");
+ expect(v[505] == 31) catch @panic("test failure");
+ expect(v[506] == 32) catch @panic("test failure");
+ expect(v[507] == 33) catch @panic("test failure");
+ expect(v[508] == 34) catch @panic("test failure");
+ expect(v[509] == 35) catch @panic("test failure");
+ expect(v[510] == 36) catch @panic("test failure");
+ expect(v[511] == 37) catch @panic("test failure");
+ expect(i == 512) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_512_u8() @Vector(512, u8);
+extern fn c_vector_512_u8(@Vector(512, u8), usize) void;
+extern fn c_test_vector_512_u8() void;
+
+test "@Vector(512, u8)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_512_u8();
+ try expect(v[0] == 38);
+ try expect(v[1] == 39);
+ try expect(v[2] == 40);
+ try expect(v[3] == 41);
+ try expect(v[4] == 42);
+ try expect(v[5] == 43);
+ try expect(v[6] == 44);
+ try expect(v[7] == 45);
+ try expect(v[8] == 46);
+ try expect(v[9] == 47);
+ try expect(v[10] == 48);
+ try expect(v[11] == 49);
+ try expect(v[12] == 50);
+ try expect(v[13] == 51);
+ try expect(v[14] == 52);
+ try expect(v[15] == 53);
+ try expect(v[16] == 54);
+ try expect(v[17] == 55);
+ try expect(v[18] == 56);
+ try expect(v[19] == 57);
+ try expect(v[20] == 58);
+ try expect(v[21] == 59);
+ try expect(v[22] == 60);
+ try expect(v[23] == 61);
+ try expect(v[24] == 62);
+ try expect(v[25] == 63);
+ try expect(v[26] == 64);
+ try expect(v[27] == 65);
+ try expect(v[28] == 66);
+ try expect(v[29] == 67);
+ try expect(v[30] == 68);
+ try expect(v[31] == 69);
+ try expect(v[32] == 70);
+ try expect(v[33] == 71);
+ try expect(v[34] == 72);
+ try expect(v[35] == 73);
+ try expect(v[36] == 74);
+ try expect(v[37] == 75);
+ try expect(v[38] == 76);
+ try expect(v[39] == 77);
+ try expect(v[40] == 78);
+ try expect(v[41] == 79);
+ try expect(v[42] == 80);
+ try expect(v[43] == 81);
+ try expect(v[44] == 82);
+ try expect(v[45] == 83);
+ try expect(v[46] == 84);
+ try expect(v[47] == 85);
+ try expect(v[48] == 86);
+ try expect(v[49] == 87);
+ try expect(v[50] == 88);
+ try expect(v[51] == 89);
+ try expect(v[52] == 90);
+ try expect(v[53] == 91);
+ try expect(v[54] == 92);
+ try expect(v[55] == 93);
+ try expect(v[56] == 94);
+ try expect(v[57] == 95);
+ try expect(v[58] == 96);
+ try expect(v[59] == 97);
+ try expect(v[60] == 98);
+ try expect(v[61] == 99);
+ try expect(v[62] == 0);
+ try expect(v[63] == 1);
+ try expect(v[64] == 2);
+ try expect(v[65] == 3);
+ try expect(v[66] == 4);
+ try expect(v[67] == 5);
+ try expect(v[68] == 6);
+ try expect(v[69] == 7);
+ try expect(v[70] == 8);
+ try expect(v[71] == 9);
+ try expect(v[72] == 10);
+ try expect(v[73] == 11);
+ try expect(v[74] == 12);
+ try expect(v[75] == 13);
+ try expect(v[76] == 14);
+ try expect(v[77] == 15);
+ try expect(v[78] == 16);
+ try expect(v[79] == 17);
+ try expect(v[80] == 18);
+ try expect(v[81] == 19);
+ try expect(v[82] == 20);
+ try expect(v[83] == 21);
+ try expect(v[84] == 22);
+ try expect(v[85] == 23);
+ try expect(v[86] == 24);
+ try expect(v[87] == 25);
+ try expect(v[88] == 26);
+ try expect(v[89] == 27);
+ try expect(v[90] == 28);
+ try expect(v[91] == 29);
+ try expect(v[92] == 30);
+ try expect(v[93] == 31);
+ try expect(v[94] == 32);
+ try expect(v[95] == 33);
+ try expect(v[96] == 34);
+ try expect(v[97] == 35);
+ try expect(v[98] == 36);
+ try expect(v[99] == 37);
+ try expect(v[100] == 38);
+ try expect(v[101] == 39);
+ try expect(v[102] == 40);
+ try expect(v[103] == 41);
+ try expect(v[104] == 42);
+ try expect(v[105] == 43);
+ try expect(v[106] == 44);
+ try expect(v[107] == 45);
+ try expect(v[108] == 46);
+ try expect(v[109] == 47);
+ try expect(v[110] == 48);
+ try expect(v[111] == 49);
+ try expect(v[112] == 50);
+ try expect(v[113] == 51);
+ try expect(v[114] == 52);
+ try expect(v[115] == 53);
+ try expect(v[116] == 54);
+ try expect(v[117] == 55);
+ try expect(v[118] == 56);
+ try expect(v[119] == 57);
+ try expect(v[120] == 58);
+ try expect(v[121] == 59);
+ try expect(v[122] == 60);
+ try expect(v[123] == 61);
+ try expect(v[124] == 62);
+ try expect(v[125] == 63);
+ try expect(v[126] == 64);
+ try expect(v[127] == 65);
+ try expect(v[128] == 66);
+ try expect(v[129] == 67);
+ try expect(v[130] == 68);
+ try expect(v[131] == 69);
+ try expect(v[132] == 70);
+ try expect(v[133] == 71);
+ try expect(v[134] == 72);
+ try expect(v[135] == 73);
+ try expect(v[136] == 74);
+ try expect(v[137] == 75);
+ try expect(v[138] == 76);
+ try expect(v[139] == 77);
+ try expect(v[140] == 78);
+ try expect(v[141] == 79);
+ try expect(v[142] == 80);
+ try expect(v[143] == 81);
+ try expect(v[144] == 82);
+ try expect(v[145] == 83);
+ try expect(v[146] == 84);
+ try expect(v[147] == 85);
+ try expect(v[148] == 86);
+ try expect(v[149] == 87);
+ try expect(v[150] == 88);
+ try expect(v[151] == 89);
+ try expect(v[152] == 90);
+ try expect(v[153] == 91);
+ try expect(v[154] == 92);
+ try expect(v[155] == 93);
+ try expect(v[156] == 94);
+ try expect(v[157] == 95);
+ try expect(v[158] == 96);
+ try expect(v[159] == 97);
+ try expect(v[160] == 98);
+ try expect(v[161] == 99);
+ try expect(v[162] == 0);
+ try expect(v[163] == 1);
+ try expect(v[164] == 2);
+ try expect(v[165] == 3);
+ try expect(v[166] == 4);
+ try expect(v[167] == 5);
+ try expect(v[168] == 6);
+ try expect(v[169] == 7);
+ try expect(v[170] == 8);
+ try expect(v[171] == 9);
+ try expect(v[172] == 10);
+ try expect(v[173] == 11);
+ try expect(v[174] == 12);
+ try expect(v[175] == 13);
+ try expect(v[176] == 14);
+ try expect(v[177] == 15);
+ try expect(v[178] == 16);
+ try expect(v[179] == 17);
+ try expect(v[180] == 18);
+ try expect(v[181] == 19);
+ try expect(v[182] == 20);
+ try expect(v[183] == 21);
+ try expect(v[184] == 22);
+ try expect(v[185] == 23);
+ try expect(v[186] == 24);
+ try expect(v[187] == 25);
+ try expect(v[188] == 26);
+ try expect(v[189] == 27);
+ try expect(v[190] == 28);
+ try expect(v[191] == 29);
+ try expect(v[192] == 30);
+ try expect(v[193] == 31);
+ try expect(v[194] == 32);
+ try expect(v[195] == 33);
+ try expect(v[196] == 34);
+ try expect(v[197] == 35);
+ try expect(v[198] == 36);
+ try expect(v[199] == 37);
+ try expect(v[200] == 38);
+ try expect(v[201] == 39);
+ try expect(v[202] == 40);
+ try expect(v[203] == 41);
+ try expect(v[204] == 42);
+ try expect(v[205] == 43);
+ try expect(v[206] == 44);
+ try expect(v[207] == 45);
+ try expect(v[208] == 46);
+ try expect(v[209] == 47);
+ try expect(v[210] == 48);
+ try expect(v[211] == 49);
+ try expect(v[212] == 50);
+ try expect(v[213] == 51);
+ try expect(v[214] == 52);
+ try expect(v[215] == 53);
+ try expect(v[216] == 54);
+ try expect(v[217] == 55);
+ try expect(v[218] == 56);
+ try expect(v[219] == 57);
+ try expect(v[220] == 58);
+ try expect(v[221] == 59);
+ try expect(v[222] == 60);
+ try expect(v[223] == 61);
+ try expect(v[224] == 62);
+ try expect(v[225] == 63);
+ try expect(v[226] == 64);
+ try expect(v[227] == 65);
+ try expect(v[228] == 66);
+ try expect(v[229] == 67);
+ try expect(v[230] == 68);
+ try expect(v[231] == 69);
+ try expect(v[232] == 70);
+ try expect(v[233] == 71);
+ try expect(v[234] == 72);
+ try expect(v[235] == 73);
+ try expect(v[236] == 74);
+ try expect(v[237] == 75);
+ try expect(v[238] == 76);
+ try expect(v[239] == 77);
+ try expect(v[240] == 78);
+ try expect(v[241] == 79);
+ try expect(v[242] == 80);
+ try expect(v[243] == 81);
+ try expect(v[244] == 82);
+ try expect(v[245] == 83);
+ try expect(v[246] == 84);
+ try expect(v[247] == 85);
+ try expect(v[248] == 86);
+ try expect(v[249] == 87);
+ try expect(v[250] == 88);
+ try expect(v[251] == 89);
+ try expect(v[252] == 90);
+ try expect(v[253] == 91);
+ try expect(v[254] == 92);
+ try expect(v[255] == 93);
+ try expect(v[256] == 94);
+ try expect(v[257] == 95);
+ try expect(v[258] == 96);
+ try expect(v[259] == 97);
+ try expect(v[260] == 98);
+ try expect(v[261] == 99);
+ try expect(v[262] == 0);
+ try expect(v[263] == 1);
+ try expect(v[264] == 2);
+ try expect(v[265] == 3);
+ try expect(v[266] == 4);
+ try expect(v[267] == 5);
+ try expect(v[268] == 6);
+ try expect(v[269] == 7);
+ try expect(v[270] == 8);
+ try expect(v[271] == 9);
+ try expect(v[272] == 10);
+ try expect(v[273] == 11);
+ try expect(v[274] == 12);
+ try expect(v[275] == 13);
+ try expect(v[276] == 14);
+ try expect(v[277] == 15);
+ try expect(v[278] == 16);
+ try expect(v[279] == 17);
+ try expect(v[280] == 18);
+ try expect(v[281] == 19);
+ try expect(v[282] == 20);
+ try expect(v[283] == 21);
+ try expect(v[284] == 22);
+ try expect(v[285] == 23);
+ try expect(v[286] == 24);
+ try expect(v[287] == 25);
+ try expect(v[288] == 26);
+ try expect(v[289] == 27);
+ try expect(v[290] == 28);
+ try expect(v[291] == 29);
+ try expect(v[292] == 30);
+ try expect(v[293] == 31);
+ try expect(v[294] == 32);
+ try expect(v[295] == 33);
+ try expect(v[296] == 34);
+ try expect(v[297] == 35);
+ try expect(v[298] == 36);
+ try expect(v[299] == 37);
+ try expect(v[300] == 38);
+ try expect(v[301] == 39);
+ try expect(v[302] == 40);
+ try expect(v[303] == 41);
+ try expect(v[304] == 42);
+ try expect(v[305] == 43);
+ try expect(v[306] == 44);
+ try expect(v[307] == 45);
+ try expect(v[308] == 46);
+ try expect(v[309] == 47);
+ try expect(v[310] == 48);
+ try expect(v[311] == 49);
+ try expect(v[312] == 50);
+ try expect(v[313] == 51);
+ try expect(v[314] == 52);
+ try expect(v[315] == 53);
+ try expect(v[316] == 54);
+ try expect(v[317] == 55);
+ try expect(v[318] == 56);
+ try expect(v[319] == 57);
+ try expect(v[320] == 58);
+ try expect(v[321] == 59);
+ try expect(v[322] == 60);
+ try expect(v[323] == 61);
+ try expect(v[324] == 62);
+ try expect(v[325] == 63);
+ try expect(v[326] == 64);
+ try expect(v[327] == 65);
+ try expect(v[328] == 66);
+ try expect(v[329] == 67);
+ try expect(v[330] == 68);
+ try expect(v[331] == 69);
+ try expect(v[332] == 70);
+ try expect(v[333] == 71);
+ try expect(v[334] == 72);
+ try expect(v[335] == 73);
+ try expect(v[336] == 74);
+ try expect(v[337] == 75);
+ try expect(v[338] == 76);
+ try expect(v[339] == 77);
+ try expect(v[340] == 78);
+ try expect(v[341] == 79);
+ try expect(v[342] == 80);
+ try expect(v[343] == 81);
+ try expect(v[344] == 82);
+ try expect(v[345] == 83);
+ try expect(v[346] == 84);
+ try expect(v[347] == 85);
+ try expect(v[348] == 86);
+ try expect(v[349] == 87);
+ try expect(v[350] == 88);
+ try expect(v[351] == 89);
+ try expect(v[352] == 90);
+ try expect(v[353] == 91);
+ try expect(v[354] == 92);
+ try expect(v[355] == 93);
+ try expect(v[356] == 94);
+ try expect(v[357] == 95);
+ try expect(v[358] == 96);
+ try expect(v[359] == 97);
+ try expect(v[360] == 98);
+ try expect(v[361] == 99);
+ try expect(v[362] == 0);
+ try expect(v[363] == 1);
+ try expect(v[364] == 2);
+ try expect(v[365] == 3);
+ try expect(v[366] == 4);
+ try expect(v[367] == 5);
+ try expect(v[368] == 6);
+ try expect(v[369] == 7);
+ try expect(v[370] == 8);
+ try expect(v[371] == 9);
+ try expect(v[372] == 10);
+ try expect(v[373] == 11);
+ try expect(v[374] == 12);
+ try expect(v[375] == 13);
+ try expect(v[376] == 14);
+ try expect(v[377] == 15);
+ try expect(v[378] == 16);
+ try expect(v[379] == 17);
+ try expect(v[380] == 18);
+ try expect(v[381] == 19);
+ try expect(v[382] == 20);
+ try expect(v[383] == 21);
+ try expect(v[384] == 22);
+ try expect(v[385] == 23);
+ try expect(v[386] == 24);
+ try expect(v[387] == 25);
+ try expect(v[388] == 26);
+ try expect(v[389] == 27);
+ try expect(v[390] == 28);
+ try expect(v[391] == 29);
+ try expect(v[392] == 30);
+ try expect(v[393] == 31);
+ try expect(v[394] == 32);
+ try expect(v[395] == 33);
+ try expect(v[396] == 34);
+ try expect(v[397] == 35);
+ try expect(v[398] == 36);
+ try expect(v[399] == 37);
+ try expect(v[400] == 38);
+ try expect(v[401] == 39);
+ try expect(v[402] == 40);
+ try expect(v[403] == 41);
+ try expect(v[404] == 42);
+ try expect(v[405] == 43);
+ try expect(v[406] == 44);
+ try expect(v[407] == 45);
+ try expect(v[408] == 46);
+ try expect(v[409] == 47);
+ try expect(v[410] == 48);
+ try expect(v[411] == 49);
+ try expect(v[412] == 50);
+ try expect(v[413] == 51);
+ try expect(v[414] == 52);
+ try expect(v[415] == 53);
+ try expect(v[416] == 54);
+ try expect(v[417] == 55);
+ try expect(v[418] == 56);
+ try expect(v[419] == 57);
+ try expect(v[420] == 58);
+ try expect(v[421] == 59);
+ try expect(v[422] == 60);
+ try expect(v[423] == 61);
+ try expect(v[424] == 62);
+ try expect(v[425] == 63);
+ try expect(v[426] == 64);
+ try expect(v[427] == 65);
+ try expect(v[428] == 66);
+ try expect(v[429] == 67);
+ try expect(v[430] == 68);
+ try expect(v[431] == 69);
+ try expect(v[432] == 70);
+ try expect(v[433] == 71);
+ try expect(v[434] == 72);
+ try expect(v[435] == 73);
+ try expect(v[436] == 74);
+ try expect(v[437] == 75);
+ try expect(v[438] == 76);
+ try expect(v[439] == 77);
+ try expect(v[440] == 78);
+ try expect(v[441] == 79);
+ try expect(v[442] == 80);
+ try expect(v[443] == 81);
+ try expect(v[444] == 82);
+ try expect(v[445] == 83);
+ try expect(v[446] == 84);
+ try expect(v[447] == 85);
+ try expect(v[448] == 86);
+ try expect(v[449] == 87);
+ try expect(v[450] == 88);
+ try expect(v[451] == 89);
+ try expect(v[452] == 90);
+ try expect(v[453] == 91);
+ try expect(v[454] == 92);
+ try expect(v[455] == 93);
+ try expect(v[456] == 94);
+ try expect(v[457] == 95);
+ try expect(v[458] == 96);
+ try expect(v[459] == 97);
+ try expect(v[460] == 98);
+ try expect(v[461] == 99);
+ try expect(v[462] == 0);
+ try expect(v[463] == 1);
+ try expect(v[464] == 2);
+ try expect(v[465] == 3);
+ try expect(v[466] == 4);
+ try expect(v[467] == 5);
+ try expect(v[468] == 6);
+ try expect(v[469] == 7);
+ try expect(v[470] == 8);
+ try expect(v[471] == 9);
+ try expect(v[472] == 10);
+ try expect(v[473] == 11);
+ try expect(v[474] == 12);
+ try expect(v[475] == 13);
+ try expect(v[476] == 14);
+ try expect(v[477] == 15);
+ try expect(v[478] == 16);
+ try expect(v[479] == 17);
+ try expect(v[480] == 18);
+ try expect(v[481] == 19);
+ try expect(v[482] == 20);
+ try expect(v[483] == 21);
+ try expect(v[484] == 22);
+ try expect(v[485] == 23);
+ try expect(v[486] == 24);
+ try expect(v[487] == 25);
+ try expect(v[488] == 26);
+ try expect(v[489] == 27);
+ try expect(v[490] == 28);
+ try expect(v[491] == 29);
+ try expect(v[492] == 30);
+ try expect(v[493] == 31);
+ try expect(v[494] == 32);
+ try expect(v[495] == 33);
+ try expect(v[496] == 34);
+ try expect(v[497] == 35);
+ try expect(v[498] == 36);
+ try expect(v[499] == 37);
+ try expect(v[500] == 38);
+ try expect(v[501] == 39);
+ try expect(v[502] == 40);
+ try expect(v[503] == 41);
+ try expect(v[504] == 42);
+ try expect(v[505] == 43);
+ try expect(v[506] == 44);
+ try expect(v[507] == 45);
+ try expect(v[508] == 46);
+ try expect(v[509] == 47);
+ try expect(v[510] == 48);
+ try expect(v[511] == 49);
+ c_vector_512_u8(.{
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ }, 512);
+ c_test_vector_512_u8();
+}
+
+export fn zig_ret_vector_1_u16() @Vector(1, u16) {
+ return .{1};
+}
+export fn zig_vector_1_u16(v: @Vector(1, u16), i: usize) void {
+ expect(v[0] == 2) catch @panic("test failure");
+ expect(i == 1) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_1_u16() @Vector(1, u16);
+extern fn c_vector_1_u16(@Vector(1, u16), usize) void;
+extern fn c_test_vector_1_u16() void;
+
+test "@Vector(1, u16)" {
+ if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+
+ const v = c_ret_vector_1_u16();
+ try expect(v[0] == 3);
+ c_vector_1_u16(.{4}, 1);
+ c_test_vector_1_u16();
+}
+
+export fn zig_ret_vector_2_u16() @Vector(2, u16) {
+ return .{ 5, 6 };
+}
+export fn zig_vector_2_u16(v: @Vector(2, u16), i: usize) void {
+ expect(v[0] == 7) catch @panic("test failure");
+ expect(v[1] == 8) catch @panic("test failure");
+ expect(i == 2) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_2_u16() @Vector(2, u16);
+extern fn c_vector_2_u16(@Vector(2, u16), usize) void;
+extern fn c_test_vector_2_u16() void;
+
+test "@Vector(2, u16)" {
+ if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest;
+
+ const v = c_ret_vector_2_u16();
+ try expect(v[0] == 9);
+ try expect(v[1] == 10);
+ c_vector_2_u16(.{ 11, 12 }, 2);
+ c_test_vector_2_u16();
+}
+
+export fn zig_ret_vector_3_u16() @Vector(3, u16) {
+ return .{ 13, 14, 15 };
+}
+export fn zig_vector_3_u16(v: @Vector(3, u16), i: usize) void {
+ expect(v[0] == 16) catch @panic("test failure");
+ expect(v[1] == 17) catch @panic("test failure");
+ expect(v[2] == 18) catch @panic("test failure");
+ expect(i == 3) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_3_u16() @Vector(3, u16);
+extern fn c_vector_3_u16(@Vector(3, u16), usize) void;
+extern fn c_test_vector_3_u16() void;
+
+test "@Vector(3, u16)" {
+ if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest;
+
+ const v = c_ret_vector_3_u16();
+ try expect(v[0] == 19);
+ try expect(v[1] == 20);
+ try expect(v[2] == 21);
+ c_vector_3_u16(.{ 22, 23, 24 }, 3);
+ c_test_vector_3_u16();
+}
+
+export fn zig_ret_vector_4_u16() @Vector(4, u16) {
+ return .{ 25, 26, 27, 28 };
+}
+export fn zig_vector_4_u16(v: @Vector(4, u16), i: usize) void {
+ expect(v[0] == 29) catch @panic("test failure");
+ expect(v[1] == 30) catch @panic("test failure");
+ expect(v[2] == 31) catch @panic("test failure");
+ expect(v[3] == 32) catch @panic("test failure");
+ expect(i == 4) catch @panic("test failure");
+}
+export fn zig_vector_4_u16_vector_4_u16(v0: @Vector(4, u16), v1: @Vector(4, u16), i: usize) void {
+ expect(v0[0] == 33) catch @panic("test failure");
+ expect(v0[1] == 34) catch @panic("test failure");
+ expect(v0[2] == 35) catch @panic("test failure");
+ expect(v0[3] == 36) catch @panic("test failure");
+ expect(v1[0] == 37) catch @panic("test failure");
+ expect(v1[1] == 38) catch @panic("test failure");
+ expect(v1[2] == 39) catch @panic("test failure");
+ expect(v1[3] == 40) catch @panic("test failure");
+ expect(i == 8) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_4_u16() @Vector(4, u16);
+extern fn c_vector_4_u16(@Vector(4, u16), usize) void;
+extern fn c_vector_4_u16_vector_4_u16(@Vector(4, u16), @Vector(4, u16), usize) void;
+extern fn c_test_vector_4_u16() void;
+
+test "@Vector(4, u16)" {
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest;
+
+ const v = c_ret_vector_4_u16();
+ try expect(v[0] == 41);
+ try expect(v[1] == 42);
+ try expect(v[2] == 43);
+ try expect(v[3] == 44);
+ c_vector_4_u16(.{ 45, 46, 47, 48 }, 4);
+ c_vector_4_u16_vector_4_u16(.{ 49, 50, 51, 52 }, .{ 53, 54, 55, 56 }, 8);
+ c_test_vector_4_u16();
+}
+
+export fn zig_ret_vector_6_u16() @Vector(6, u16) {
+ return .{ 41, 42, 43, 44, 45, 46 };
+}
+export fn zig_vector_6_u16(v: @Vector(6, u16), i: usize) void {
+ expect(v[0] == 47) catch @panic("test failure");
+ expect(v[1] == 48) catch @panic("test failure");
+ expect(v[2] == 49) catch @panic("test failure");
+ expect(v[3] == 50) catch @panic("test failure");
+ expect(v[4] == 51) catch @panic("test failure");
+ expect(v[5] == 52) catch @panic("test failure");
+ expect(i == 6) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_6_u16() @Vector(6, u16);
+extern fn c_vector_6_u16(@Vector(6, u16), usize) void;
+extern fn c_test_vector_6_u16() void;
+
+test "@Vector(6, u16)" {
+ if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+
+ const v = c_ret_vector_6_u16();
+ try expect(v[0] == 53);
+ try expect(v[1] == 54);
+ try expect(v[2] == 55);
+ try expect(v[3] == 56);
+ try expect(v[4] == 57);
+ try expect(v[5] == 58);
+ c_vector_6_u16(.{ 59, 60, 61, 62, 63, 64 }, 6);
+ c_test_vector_6_u16();
+}
+
+export fn zig_ret_vector_8_u16() @Vector(8, u16) {
+ return .{ 65, 66, 67, 68, 69, 70, 71, 72 };
+}
+export fn zig_vector_8_u16(v: @Vector(8, u16), i: usize) void {
+ expect(v[0] == 73) catch @panic("test failure");
+ expect(v[1] == 74) catch @panic("test failure");
+ expect(v[2] == 75) catch @panic("test failure");
+ expect(v[3] == 76) catch @panic("test failure");
+ expect(v[4] == 77) catch @panic("test failure");
+ expect(v[5] == 78) catch @panic("test failure");
+ expect(v[6] == 79) catch @panic("test failure");
+ expect(v[7] == 80) catch @panic("test failure");
+ expect(i == 8) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_8_u16() @Vector(8, u16);
+extern fn c_vector_8_u16(@Vector(8, u16), usize) void;
+extern fn c_test_vector_8_u16() void;
+
+test "@Vector(8, u16)" {
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+
+ const v = c_ret_vector_8_u16();
+ try expect(v[0] == 81);
+ try expect(v[1] == 82);
+ try expect(v[2] == 83);
+ try expect(v[3] == 84);
+ try expect(v[4] == 85);
+ try expect(v[5] == 86);
+ try expect(v[6] == 87);
+ try expect(v[7] == 88);
+ c_vector_8_u16(.{ 89, 90, 91, 92, 93, 94, 95, 96 }, 8);
+ c_test_vector_8_u16();
+}
+
+export fn zig_ret_vector_12_u16() @Vector(12, u16) {
+ return .{ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108 };
+}
+export fn zig_vector_12_u16(v: @Vector(12, u16), i: usize) void {
+ expect(v[0] == 109) catch @panic("test failure");
+ expect(v[1] == 110) catch @panic("test failure");
+ expect(v[2] == 111) catch @panic("test failure");
+ expect(v[3] == 112) catch @panic("test failure");
+ expect(v[4] == 113) catch @panic("test failure");
+ expect(v[5] == 114) catch @panic("test failure");
+ expect(v[6] == 115) catch @panic("test failure");
+ expect(v[7] == 116) catch @panic("test failure");
+ expect(v[8] == 117) catch @panic("test failure");
+ expect(v[9] == 118) catch @panic("test failure");
+ expect(v[10] == 119) catch @panic("test failure");
+ expect(v[11] == 120) catch @panic("test failure");
+ expect(i == 12) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_12_u16() @Vector(12, u16);
+extern fn c_vector_12_u16(@Vector(12, u16), usize) void;
+extern fn c_test_vector_12_u16() void;
+
+test "@Vector(12, u16)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_12_u16();
+ try expect(v[0] == 121);
+ try expect(v[1] == 122);
+ try expect(v[2] == 123);
+ try expect(v[3] == 124);
+ try expect(v[4] == 125);
+ try expect(v[5] == 126);
+ try expect(v[6] == 127);
+ try expect(v[7] == 128);
+ try expect(v[8] == 129);
+ try expect(v[9] == 130);
+ try expect(v[10] == 131);
+ try expect(v[11] == 132);
+ c_vector_12_u16(.{ 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144 }, 12);
+ c_test_vector_12_u16();
+}
+
+export fn zig_ret_vector_16_u16() @Vector(16, u16) {
+ return .{ 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160 };
+}
+export fn zig_vector_16_u16(v: @Vector(16, u16), i: usize) void {
+ expect(v[0] == 161) catch @panic("test failure");
+ expect(v[1] == 162) catch @panic("test failure");
+ expect(v[2] == 163) catch @panic("test failure");
+ expect(v[3] == 164) catch @panic("test failure");
+ expect(v[4] == 165) catch @panic("test failure");
+ expect(v[5] == 166) catch @panic("test failure");
+ expect(v[6] == 167) catch @panic("test failure");
+ expect(v[7] == 168) catch @panic("test failure");
+ expect(v[8] == 169) catch @panic("test failure");
+ expect(v[9] == 170) catch @panic("test failure");
+ expect(v[10] == 171) catch @panic("test failure");
+ expect(v[11] == 172) catch @panic("test failure");
+ expect(v[12] == 173) catch @panic("test failure");
+ expect(v[13] == 174) catch @panic("test failure");
+ expect(v[14] == 175) catch @panic("test failure");
+ expect(v[15] == 176) catch @panic("test failure");
+ expect(i == 16) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_16_u16() @Vector(16, u16);
+extern fn c_vector_16_u16(@Vector(16, u16), usize) void;
+extern fn c_test_vector_16_u16() void;
+
+test "@Vector(16, u16)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_16_u16();
+ try expect(v[0] == 177);
+ try expect(v[1] == 178);
+ try expect(v[2] == 179);
+ try expect(v[3] == 180);
+ try expect(v[4] == 181);
+ try expect(v[5] == 182);
+ try expect(v[6] == 183);
+ try expect(v[7] == 184);
+ try expect(v[8] == 185);
+ try expect(v[9] == 186);
+ try expect(v[10] == 187);
+ try expect(v[11] == 188);
+ try expect(v[12] == 189);
+ try expect(v[13] == 190);
+ try expect(v[14] == 191);
+ try expect(v[15] == 192);
+ c_vector_16_u16(.{ 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208 }, 16);
+ c_test_vector_16_u16();
+}
+
+export fn zig_ret_vector_24_u16() @Vector(24, u16) {
+ return .{
+ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
+ 225, 226, 227, 228, 229, 230, 231, 232,
+ };
+}
+export fn zig_vector_24_u16(v: @Vector(24, u16), i: usize) void {
+ expect(v[0] == 233) catch @panic("test failure");
+ expect(v[1] == 234) catch @panic("test failure");
+ expect(v[2] == 235) catch @panic("test failure");
+ expect(v[3] == 236) catch @panic("test failure");
+ expect(v[4] == 237) catch @panic("test failure");
+ expect(v[5] == 238) catch @panic("test failure");
+ expect(v[6] == 239) catch @panic("test failure");
+ expect(v[7] == 240) catch @panic("test failure");
+ expect(v[8] == 241) catch @panic("test failure");
+ expect(v[9] == 242) catch @panic("test failure");
+ expect(v[10] == 243) catch @panic("test failure");
+ expect(v[11] == 244) catch @panic("test failure");
+ expect(v[12] == 245) catch @panic("test failure");
+ expect(v[13] == 246) catch @panic("test failure");
+ expect(v[14] == 247) catch @panic("test failure");
+ expect(v[15] == 248) catch @panic("test failure");
+ expect(v[16] == 249) catch @panic("test failure");
+ expect(v[17] == 250) catch @panic("test failure");
+ expect(v[18] == 251) catch @panic("test failure");
+ expect(v[19] == 252) catch @panic("test failure");
+ expect(v[20] == 253) catch @panic("test failure");
+ expect(v[21] == 254) catch @panic("test failure");
+ expect(v[22] == 255) catch @panic("test failure");
+ expect(v[23] == 256) catch @panic("test failure");
+ expect(i == 24) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_24_u16() @Vector(24, u16);
+extern fn c_vector_24_u16(@Vector(24, u16), usize) void;
+extern fn c_test_vector_24_u16() void;
+
+test "@Vector(24, u16)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_24_u16();
+ try expect(v[0] == 257);
+ try expect(v[1] == 258);
+ try expect(v[2] == 259);
+ try expect(v[3] == 260);
+ try expect(v[4] == 261);
+ try expect(v[5] == 262);
+ try expect(v[6] == 263);
+ try expect(v[7] == 264);
+ try expect(v[8] == 265);
+ try expect(v[9] == 266);
+ try expect(v[10] == 267);
+ try expect(v[11] == 268);
+ try expect(v[12] == 269);
+ try expect(v[13] == 270);
+ try expect(v[14] == 271);
+ try expect(v[15] == 272);
+ try expect(v[16] == 273);
+ try expect(v[17] == 274);
+ try expect(v[18] == 275);
+ try expect(v[19] == 276);
+ try expect(v[20] == 277);
+ try expect(v[21] == 278);
+ try expect(v[22] == 279);
+ try expect(v[23] == 280);
+ c_vector_24_u16(.{
+ 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296,
+ 297, 298, 299, 300, 301, 302, 303, 304,
+ }, 24);
+ c_test_vector_24_u16();
+}
+
+export fn zig_ret_vector_32_u16() @Vector(32, u16) {
+ return .{
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320,
+ 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
+ };
+}
+export fn zig_vector_32_u16(v: @Vector(32, u16), i: usize) void {
+ expect(v[0] == 337) catch @panic("test failure");
+ expect(v[1] == 338) catch @panic("test failure");
+ expect(v[2] == 339) catch @panic("test failure");
+ expect(v[3] == 340) catch @panic("test failure");
+ expect(v[4] == 341) catch @panic("test failure");
+ expect(v[5] == 342) catch @panic("test failure");
+ expect(v[6] == 343) catch @panic("test failure");
+ expect(v[7] == 344) catch @panic("test failure");
+ expect(v[8] == 345) catch @panic("test failure");
+ expect(v[9] == 346) catch @panic("test failure");
+ expect(v[10] == 347) catch @panic("test failure");
+ expect(v[11] == 348) catch @panic("test failure");
+ expect(v[12] == 349) catch @panic("test failure");
+ expect(v[13] == 350) catch @panic("test failure");
+ expect(v[14] == 351) catch @panic("test failure");
+ expect(v[15] == 352) catch @panic("test failure");
+ expect(v[16] == 353) catch @panic("test failure");
+ expect(v[17] == 354) catch @panic("test failure");
+ expect(v[18] == 355) catch @panic("test failure");
+ expect(v[19] == 356) catch @panic("test failure");
+ expect(v[20] == 357) catch @panic("test failure");
+ expect(v[21] == 358) catch @panic("test failure");
+ expect(v[22] == 359) catch @panic("test failure");
+ expect(v[23] == 360) catch @panic("test failure");
+ expect(v[24] == 361) catch @panic("test failure");
+ expect(v[25] == 362) catch @panic("test failure");
+ expect(v[26] == 363) catch @panic("test failure");
+ expect(v[27] == 364) catch @panic("test failure");
+ expect(v[28] == 365) catch @panic("test failure");
+ expect(v[29] == 366) catch @panic("test failure");
+ expect(v[30] == 367) catch @panic("test failure");
+ expect(v[31] == 368) catch @panic("test failure");
+ expect(i == 32) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_32_u16() @Vector(32, u16);
+extern fn c_vector_32_u16(@Vector(32, u16), usize) void;
+extern fn c_test_vector_32_u16() void;
+
+test "@Vector(32, u16)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_32_u16();
+ try expect(v[0] == 369);
+ try expect(v[1] == 370);
+ try expect(v[2] == 371);
+ try expect(v[3] == 372);
+ try expect(v[4] == 373);
+ try expect(v[5] == 374);
+ try expect(v[6] == 375);
+ try expect(v[7] == 376);
+ try expect(v[8] == 377);
+ try expect(v[9] == 378);
+ try expect(v[10] == 379);
+ try expect(v[11] == 380);
+ try expect(v[12] == 381);
+ try expect(v[13] == 382);
+ try expect(v[14] == 383);
+ try expect(v[15] == 384);
+ try expect(v[16] == 385);
+ try expect(v[17] == 386);
+ try expect(v[18] == 387);
+ try expect(v[19] == 388);
+ try expect(v[20] == 389);
+ try expect(v[21] == 390);
+ try expect(v[22] == 391);
+ try expect(v[23] == 392);
+ try expect(v[24] == 393);
+ try expect(v[25] == 394);
+ try expect(v[26] == 395);
+ try expect(v[27] == 396);
+ try expect(v[28] == 397);
+ try expect(v[29] == 398);
+ try expect(v[30] == 399);
+ try expect(v[31] == 400);
+ c_vector_32_u16(.{
+ 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416,
+ 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432,
+ }, 32);
+ c_test_vector_32_u16();
+}
+
+export fn zig_ret_vector_48_u16() @Vector(48, u16) {
+ return .{
+ 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448,
+ 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464,
+ 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480,
+ };
+}
+export fn zig_vector_48_u16(v: @Vector(48, u16), i: usize) void {
+ expect(v[0] == 481) catch @panic("test failure");
+ expect(v[1] == 482) catch @panic("test failure");
+ expect(v[2] == 483) catch @panic("test failure");
+ expect(v[3] == 484) catch @panic("test failure");
+ expect(v[4] == 485) catch @panic("test failure");
+ expect(v[5] == 486) catch @panic("test failure");
+ expect(v[6] == 487) catch @panic("test failure");
+ expect(v[7] == 488) catch @panic("test failure");
+ expect(v[8] == 489) catch @panic("test failure");
+ expect(v[9] == 490) catch @panic("test failure");
+ expect(v[10] == 491) catch @panic("test failure");
+ expect(v[11] == 492) catch @panic("test failure");
+ expect(v[12] == 493) catch @panic("test failure");
+ expect(v[13] == 494) catch @panic("test failure");
+ expect(v[14] == 495) catch @panic("test failure");
+ expect(v[15] == 496) catch @panic("test failure");
+ expect(v[16] == 497) catch @panic("test failure");
+ expect(v[17] == 498) catch @panic("test failure");
+ expect(v[18] == 499) catch @panic("test failure");
+ expect(v[19] == 500) catch @panic("test failure");
+ expect(v[20] == 501) catch @panic("test failure");
+ expect(v[21] == 502) catch @panic("test failure");
+ expect(v[22] == 503) catch @panic("test failure");
+ expect(v[23] == 504) catch @panic("test failure");
+ expect(v[24] == 505) catch @panic("test failure");
+ expect(v[25] == 506) catch @panic("test failure");
+ expect(v[26] == 507) catch @panic("test failure");
+ expect(v[27] == 508) catch @panic("test failure");
+ expect(v[28] == 509) catch @panic("test failure");
+ expect(v[29] == 510) catch @panic("test failure");
+ expect(v[30] == 511) catch @panic("test failure");
+ expect(v[31] == 512) catch @panic("test failure");
+ expect(v[32] == 513) catch @panic("test failure");
+ expect(v[33] == 514) catch @panic("test failure");
+ expect(v[34] == 515) catch @panic("test failure");
+ expect(v[35] == 516) catch @panic("test failure");
+ expect(v[36] == 517) catch @panic("test failure");
+ expect(v[37] == 518) catch @panic("test failure");
+ expect(v[38] == 519) catch @panic("test failure");
+ expect(v[39] == 520) catch @panic("test failure");
+ expect(v[40] == 521) catch @panic("test failure");
+ expect(v[41] == 522) catch @panic("test failure");
+ expect(v[42] == 523) catch @panic("test failure");
+ expect(v[43] == 524) catch @panic("test failure");
+ expect(v[44] == 525) catch @panic("test failure");
+ expect(v[45] == 526) catch @panic("test failure");
+ expect(v[46] == 527) catch @panic("test failure");
+ expect(v[47] == 528) catch @panic("test failure");
+ expect(i == 48) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_48_u16() @Vector(48, u16);
+extern fn c_vector_48_u16(@Vector(48, u16), usize) void;
+extern fn c_test_vector_48_u16() void;
+
+test "@Vector(48, u16)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_48_u16();
+ try expect(v[0] == 529);
+ try expect(v[1] == 530);
+ try expect(v[2] == 531);
+ try expect(v[3] == 532);
+ try expect(v[4] == 533);
+ try expect(v[5] == 534);
+ try expect(v[6] == 535);
+ try expect(v[7] == 536);
+ try expect(v[8] == 537);
+ try expect(v[9] == 538);
+ try expect(v[10] == 539);
+ try expect(v[11] == 540);
+ try expect(v[12] == 541);
+ try expect(v[13] == 542);
+ try expect(v[14] == 543);
+ try expect(v[15] == 544);
+ try expect(v[16] == 545);
+ try expect(v[17] == 546);
+ try expect(v[18] == 547);
+ try expect(v[19] == 548);
+ try expect(v[20] == 549);
+ try expect(v[21] == 550);
+ try expect(v[22] == 551);
+ try expect(v[23] == 552);
+ try expect(v[24] == 553);
+ try expect(v[25] == 554);
+ try expect(v[26] == 555);
+ try expect(v[27] == 556);
+ try expect(v[28] == 557);
+ try expect(v[29] == 558);
+ try expect(v[30] == 559);
+ try expect(v[31] == 560);
+ try expect(v[32] == 561);
+ try expect(v[33] == 562);
+ try expect(v[34] == 563);
+ try expect(v[35] == 564);
+ try expect(v[36] == 565);
+ try expect(v[37] == 566);
+ try expect(v[38] == 567);
+ try expect(v[39] == 568);
+ try expect(v[40] == 569);
+ try expect(v[41] == 570);
+ try expect(v[42] == 571);
+ try expect(v[43] == 572);
+ try expect(v[44] == 573);
+ try expect(v[45] == 574);
+ try expect(v[46] == 575);
+ try expect(v[47] == 576);
+ c_vector_48_u16(.{
+ 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592,
+ 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608,
+ 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624,
+ }, 48);
+ c_test_vector_48_u16();
+}
+
+export fn zig_ret_vector_64_u16() @Vector(64, u16) {
+ return .{
+ 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640,
+ 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656,
+ 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672,
+ 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688,
+ };
+}
+export fn zig_vector_64_u16(v: @Vector(64, u16), i: usize) void {
+ expect(v[0] == 689) catch @panic("test failure");
+ expect(v[1] == 690) catch @panic("test failure");
+ expect(v[2] == 691) catch @panic("test failure");
+ expect(v[3] == 692) catch @panic("test failure");
+ expect(v[4] == 693) catch @panic("test failure");
+ expect(v[5] == 694) catch @panic("test failure");
+ expect(v[6] == 695) catch @panic("test failure");
+ expect(v[7] == 696) catch @panic("test failure");
+ expect(v[8] == 697) catch @panic("test failure");
+ expect(v[9] == 698) catch @panic("test failure");
+ expect(v[10] == 699) catch @panic("test failure");
+ expect(v[11] == 700) catch @panic("test failure");
+ expect(v[12] == 701) catch @panic("test failure");
+ expect(v[13] == 702) catch @panic("test failure");
+ expect(v[14] == 703) catch @panic("test failure");
+ expect(v[15] == 704) catch @panic("test failure");
+ expect(v[16] == 705) catch @panic("test failure");
+ expect(v[17] == 706) catch @panic("test failure");
+ expect(v[18] == 707) catch @panic("test failure");
+ expect(v[19] == 708) catch @panic("test failure");
+ expect(v[20] == 709) catch @panic("test failure");
+ expect(v[21] == 710) catch @panic("test failure");
+ expect(v[22] == 711) catch @panic("test failure");
+ expect(v[23] == 712) catch @panic("test failure");
+ expect(v[24] == 713) catch @panic("test failure");
+ expect(v[25] == 714) catch @panic("test failure");
+ expect(v[26] == 715) catch @panic("test failure");
+ expect(v[27] == 716) catch @panic("test failure");
+ expect(v[28] == 717) catch @panic("test failure");
+ expect(v[29] == 718) catch @panic("test failure");
+ expect(v[30] == 719) catch @panic("test failure");
+ expect(v[31] == 720) catch @panic("test failure");
+ expect(v[32] == 721) catch @panic("test failure");
+ expect(v[33] == 722) catch @panic("test failure");
+ expect(v[34] == 723) catch @panic("test failure");
+ expect(v[35] == 724) catch @panic("test failure");
+ expect(v[36] == 725) catch @panic("test failure");
+ expect(v[37] == 726) catch @panic("test failure");
+ expect(v[38] == 727) catch @panic("test failure");
+ expect(v[39] == 728) catch @panic("test failure");
+ expect(v[40] == 729) catch @panic("test failure");
+ expect(v[41] == 730) catch @panic("test failure");
+ expect(v[42] == 731) catch @panic("test failure");
+ expect(v[43] == 732) catch @panic("test failure");
+ expect(v[44] == 733) catch @panic("test failure");
+ expect(v[45] == 734) catch @panic("test failure");
+ expect(v[46] == 735) catch @panic("test failure");
+ expect(v[47] == 736) catch @panic("test failure");
+ expect(v[48] == 737) catch @panic("test failure");
+ expect(v[49] == 738) catch @panic("test failure");
+ expect(v[50] == 739) catch @panic("test failure");
+ expect(v[51] == 740) catch @panic("test failure");
+ expect(v[52] == 741) catch @panic("test failure");
+ expect(v[53] == 742) catch @panic("test failure");
+ expect(v[54] == 743) catch @panic("test failure");
+ expect(v[55] == 744) catch @panic("test failure");
+ expect(v[56] == 745) catch @panic("test failure");
+ expect(v[57] == 746) catch @panic("test failure");
+ expect(v[58] == 747) catch @panic("test failure");
+ expect(v[59] == 748) catch @panic("test failure");
+ expect(v[60] == 749) catch @panic("test failure");
+ expect(v[61] == 750) catch @panic("test failure");
+ expect(v[62] == 751) catch @panic("test failure");
+ expect(v[63] == 752) catch @panic("test failure");
+ expect(i == 64) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_64_u16() @Vector(64, u16);
+extern fn c_vector_64_u16(@Vector(64, u16), usize) void;
+extern fn c_test_vector_64_u16() void;
+
+test "@Vector(64, u16)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_64_u16();
+ try expect(v[0] == 753);
+ try expect(v[1] == 754);
+ try expect(v[2] == 755);
+ try expect(v[3] == 756);
+ try expect(v[4] == 757);
+ try expect(v[5] == 758);
+ try expect(v[6] == 759);
+ try expect(v[7] == 760);
+ try expect(v[8] == 761);
+ try expect(v[9] == 762);
+ try expect(v[10] == 763);
+ try expect(v[11] == 764);
+ try expect(v[12] == 765);
+ try expect(v[13] == 766);
+ try expect(v[14] == 767);
+ try expect(v[15] == 768);
+ try expect(v[16] == 769);
+ try expect(v[17] == 770);
+ try expect(v[18] == 771);
+ try expect(v[19] == 772);
+ try expect(v[20] == 773);
+ try expect(v[21] == 774);
+ try expect(v[22] == 775);
+ try expect(v[23] == 776);
+ try expect(v[24] == 777);
+ try expect(v[25] == 778);
+ try expect(v[26] == 779);
+ try expect(v[27] == 780);
+ try expect(v[28] == 781);
+ try expect(v[29] == 782);
+ try expect(v[30] == 783);
+ try expect(v[31] == 784);
+ try expect(v[32] == 785);
+ try expect(v[33] == 786);
+ try expect(v[34] == 787);
+ try expect(v[35] == 788);
+ try expect(v[36] == 789);
+ try expect(v[37] == 790);
+ try expect(v[38] == 791);
+ try expect(v[39] == 792);
+ try expect(v[40] == 793);
+ try expect(v[41] == 794);
+ try expect(v[42] == 795);
+ try expect(v[43] == 796);
+ try expect(v[44] == 797);
+ try expect(v[45] == 798);
+ try expect(v[46] == 799);
+ try expect(v[47] == 800);
+ try expect(v[48] == 801);
+ try expect(v[49] == 802);
+ try expect(v[50] == 803);
+ try expect(v[51] == 804);
+ try expect(v[52] == 805);
+ try expect(v[53] == 806);
+ try expect(v[54] == 807);
+ try expect(v[55] == 808);
+ try expect(v[56] == 809);
+ try expect(v[57] == 810);
+ try expect(v[58] == 811);
+ try expect(v[59] == 812);
+ try expect(v[60] == 813);
+ try expect(v[61] == 814);
+ try expect(v[62] == 815);
+ try expect(v[63] == 816);
+ c_vector_64_u16(.{
+ 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832,
+ 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848,
+ 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864,
+ 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880,
+ }, 64);
+ c_test_vector_64_u16();
+}
+
+export fn zig_ret_vector_96_u16() @Vector(96, u16) {
+ return .{
+ 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905,
+ 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921,
+ 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937,
+ 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953,
+ 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969,
+ 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985,
+ };
+}
+export fn zig_vector_96_u16(v: @Vector(96, u16), i: usize) void {
+ expect(v[0] == 986) catch @panic("test failure");
+ expect(v[1] == 987) catch @panic("test failure");
+ expect(v[2] == 988) catch @panic("test failure");
+ expect(v[3] == 989) catch @panic("test failure");
+ expect(v[4] == 990) catch @panic("test failure");
+ expect(v[5] == 991) catch @panic("test failure");
+ expect(v[6] == 992) catch @panic("test failure");
+ expect(v[7] == 993) catch @panic("test failure");
+ expect(v[8] == 994) catch @panic("test failure");
+ expect(v[9] == 995) catch @panic("test failure");
+ expect(v[10] == 996) catch @panic("test failure");
+ expect(v[11] == 997) catch @panic("test failure");
+ expect(v[12] == 998) catch @panic("test failure");
+ expect(v[13] == 999) catch @panic("test failure");
+ expect(v[14] == 1000) catch @panic("test failure");
+ expect(v[15] == 1001) catch @panic("test failure");
+ expect(v[16] == 1002) catch @panic("test failure");
+ expect(v[17] == 1003) catch @panic("test failure");
+ expect(v[18] == 1004) catch @panic("test failure");
+ expect(v[19] == 1005) catch @panic("test failure");
+ expect(v[20] == 1006) catch @panic("test failure");
+ expect(v[21] == 1007) catch @panic("test failure");
+ expect(v[22] == 1008) catch @panic("test failure");
+ expect(v[23] == 1009) catch @panic("test failure");
+ expect(v[24] == 1010) catch @panic("test failure");
+ expect(v[25] == 1011) catch @panic("test failure");
+ expect(v[26] == 1012) catch @panic("test failure");
+ expect(v[27] == 1013) catch @panic("test failure");
+ expect(v[28] == 1014) catch @panic("test failure");
+ expect(v[29] == 1015) catch @panic("test failure");
+ expect(v[30] == 1016) catch @panic("test failure");
+ expect(v[31] == 1017) catch @panic("test failure");
+ expect(v[32] == 1018) catch @panic("test failure");
+ expect(v[33] == 1019) catch @panic("test failure");
+ expect(v[34] == 1020) catch @panic("test failure");
+ expect(v[35] == 1021) catch @panic("test failure");
+ expect(v[36] == 1022) catch @panic("test failure");
+ expect(v[37] == 1023) catch @panic("test failure");
+ expect(v[38] == 1024) catch @panic("test failure");
+ expect(v[39] == 1025) catch @panic("test failure");
+ expect(v[40] == 1026) catch @panic("test failure");
+ expect(v[41] == 1027) catch @panic("test failure");
+ expect(v[42] == 1028) catch @panic("test failure");
+ expect(v[43] == 1029) catch @panic("test failure");
+ expect(v[44] == 1030) catch @panic("test failure");
+ expect(v[45] == 1031) catch @panic("test failure");
+ expect(v[46] == 1032) catch @panic("test failure");
+ expect(v[47] == 1033) catch @panic("test failure");
+ expect(v[48] == 1034) catch @panic("test failure");
+ expect(v[49] == 1035) catch @panic("test failure");
+ expect(v[50] == 1036) catch @panic("test failure");
+ expect(v[51] == 1037) catch @panic("test failure");
+ expect(v[52] == 1038) catch @panic("test failure");
+ expect(v[53] == 1039) catch @panic("test failure");
+ expect(v[54] == 1040) catch @panic("test failure");
+ expect(v[55] == 1041) catch @panic("test failure");
+ expect(v[56] == 1042) catch @panic("test failure");
+ expect(v[57] == 1043) catch @panic("test failure");
+ expect(v[58] == 1044) catch @panic("test failure");
+ expect(v[59] == 1045) catch @panic("test failure");
+ expect(v[60] == 1046) catch @panic("test failure");
+ expect(v[61] == 1047) catch @panic("test failure");
+ expect(v[62] == 1048) catch @panic("test failure");
+ expect(v[63] == 1049) catch @panic("test failure");
+ expect(v[64] == 1050) catch @panic("test failure");
+ expect(v[65] == 1051) catch @panic("test failure");
+ expect(v[66] == 1052) catch @panic("test failure");
+ expect(v[67] == 1053) catch @panic("test failure");
+ expect(v[68] == 1054) catch @panic("test failure");
+ expect(v[69] == 1055) catch @panic("test failure");
+ expect(v[70] == 1056) catch @panic("test failure");
+ expect(v[71] == 1057) catch @panic("test failure");
+ expect(v[72] == 1058) catch @panic("test failure");
+ expect(v[73] == 1059) catch @panic("test failure");
+ expect(v[74] == 1060) catch @panic("test failure");
+ expect(v[75] == 1061) catch @panic("test failure");
+ expect(v[76] == 1062) catch @panic("test failure");
+ expect(v[77] == 1063) catch @panic("test failure");
+ expect(v[78] == 1064) catch @panic("test failure");
+ expect(v[79] == 1065) catch @panic("test failure");
+ expect(v[80] == 1066) catch @panic("test failure");
+ expect(v[81] == 1067) catch @panic("test failure");
+ expect(v[82] == 1068) catch @panic("test failure");
+ expect(v[83] == 1069) catch @panic("test failure");
+ expect(v[84] == 1070) catch @panic("test failure");
+ expect(v[85] == 1071) catch @panic("test failure");
+ expect(v[86] == 1072) catch @panic("test failure");
+ expect(v[87] == 1073) catch @panic("test failure");
+ expect(v[88] == 1074) catch @panic("test failure");
+ expect(v[89] == 1075) catch @panic("test failure");
+ expect(v[90] == 1076) catch @panic("test failure");
+ expect(v[91] == 1077) catch @panic("test failure");
+ expect(v[92] == 1078) catch @panic("test failure");
+ expect(v[93] == 1079) catch @panic("test failure");
+ expect(v[94] == 1080) catch @panic("test failure");
+ expect(v[95] == 1081) catch @panic("test failure");
+ expect(i == 96) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_96_u16() @Vector(96, u16);
+extern fn c_vector_96_u16(@Vector(96, u16), usize) void;
+extern fn c_test_vector_96_u16() void;
+
+test "@Vector(96, u16)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_96_u16();
+ try expect(v[0] == 1082);
+ try expect(v[1] == 1083);
+ try expect(v[2] == 1084);
+ try expect(v[3] == 1085);
+ try expect(v[4] == 1086);
+ try expect(v[5] == 1087);
+ try expect(v[6] == 1088);
+ try expect(v[7] == 1089);
+ try expect(v[8] == 1090);
+ try expect(v[9] == 1091);
+ try expect(v[10] == 1092);
+ try expect(v[11] == 1093);
+ try expect(v[12] == 1094);
+ try expect(v[13] == 1095);
+ try expect(v[14] == 1096);
+ try expect(v[15] == 1097);
+ try expect(v[16] == 1098);
+ try expect(v[17] == 1099);
+ try expect(v[18] == 1100);
+ try expect(v[19] == 1101);
+ try expect(v[20] == 1102);
+ try expect(v[21] == 1103);
+ try expect(v[22] == 1104);
+ try expect(v[23] == 1105);
+ try expect(v[24] == 1106);
+ try expect(v[25] == 1107);
+ try expect(v[26] == 1108);
+ try expect(v[27] == 1109);
+ try expect(v[28] == 1110);
+ try expect(v[29] == 1111);
+ try expect(v[30] == 1112);
+ try expect(v[31] == 1113);
+ try expect(v[32] == 1114);
+ try expect(v[33] == 1115);
+ try expect(v[34] == 1116);
+ try expect(v[35] == 1117);
+ try expect(v[36] == 1118);
+ try expect(v[37] == 1119);
+ try expect(v[38] == 1120);
+ try expect(v[39] == 1121);
+ try expect(v[40] == 1122);
+ try expect(v[41] == 1123);
+ try expect(v[42] == 1124);
+ try expect(v[43] == 1125);
+ try expect(v[44] == 1126);
+ try expect(v[45] == 1127);
+ try expect(v[46] == 1128);
+ try expect(v[47] == 1129);
+ try expect(v[48] == 1130);
+ try expect(v[49] == 1131);
+ try expect(v[50] == 1132);
+ try expect(v[51] == 1133);
+ try expect(v[52] == 1134);
+ try expect(v[53] == 1135);
+ try expect(v[54] == 1136);
+ try expect(v[55] == 1137);
+ try expect(v[56] == 1138);
+ try expect(v[57] == 1139);
+ try expect(v[58] == 1140);
+ try expect(v[59] == 1141);
+ try expect(v[60] == 1142);
+ try expect(v[61] == 1143);
+ try expect(v[62] == 1144);
+ try expect(v[63] == 1145);
+ try expect(v[64] == 1146);
+ try expect(v[65] == 1147);
+ try expect(v[66] == 1148);
+ try expect(v[67] == 1149);
+ try expect(v[68] == 1150);
+ try expect(v[69] == 1151);
+ try expect(v[70] == 1152);
+ try expect(v[71] == 1153);
+ try expect(v[72] == 1154);
+ try expect(v[73] == 1155);
+ try expect(v[74] == 1156);
+ try expect(v[75] == 1157);
+ try expect(v[76] == 1158);
+ try expect(v[77] == 1159);
+ try expect(v[78] == 1160);
+ try expect(v[79] == 1161);
+ try expect(v[80] == 1162);
+ try expect(v[81] == 1163);
+ try expect(v[82] == 1164);
+ try expect(v[83] == 1165);
+ try expect(v[84] == 1166);
+ try expect(v[85] == 1167);
+ try expect(v[86] == 1168);
+ try expect(v[87] == 1169);
+ try expect(v[88] == 1170);
+ try expect(v[89] == 1171);
+ try expect(v[90] == 1172);
+ try expect(v[91] == 1173);
+ try expect(v[92] == 1174);
+ try expect(v[93] == 1175);
+ try expect(v[94] == 1176);
+ try expect(v[95] == 1177);
+ c_vector_96_u16(.{
+ 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193,
+ 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209,
+ 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1225,
+ 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241,
+ 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257,
+ 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273,
+ }, 96);
+ c_test_vector_96_u16();
+}
+
+export fn zig_ret_vector_128_u16() @Vector(128, u16) {
+ return .{
+ 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289,
+ 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305,
+ 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321,
+ 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337,
+ 1338, 1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353,
+ 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369,
+ 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385,
+ 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401,
+ };
+}
+export fn zig_vector_128_u16(v: @Vector(128, u16), i: usize) void {
+ expect(v[0] == 1402) catch @panic("test failure");
+ expect(v[1] == 1403) catch @panic("test failure");
+ expect(v[2] == 1404) catch @panic("test failure");
+ expect(v[3] == 1405) catch @panic("test failure");
+ expect(v[4] == 1406) catch @panic("test failure");
+ expect(v[5] == 1407) catch @panic("test failure");
+ expect(v[6] == 1408) catch @panic("test failure");
+ expect(v[7] == 1409) catch @panic("test failure");
+ expect(v[8] == 1410) catch @panic("test failure");
+ expect(v[9] == 1411) catch @panic("test failure");
+ expect(v[10] == 1412) catch @panic("test failure");
+ expect(v[11] == 1413) catch @panic("test failure");
+ expect(v[12] == 1414) catch @panic("test failure");
+ expect(v[13] == 1415) catch @panic("test failure");
+ expect(v[14] == 1416) catch @panic("test failure");
+ expect(v[15] == 1417) catch @panic("test failure");
+ expect(v[16] == 1418) catch @panic("test failure");
+ expect(v[17] == 1419) catch @panic("test failure");
+ expect(v[18] == 1420) catch @panic("test failure");
+ expect(v[19] == 1421) catch @panic("test failure");
+ expect(v[20] == 1422) catch @panic("test failure");
+ expect(v[21] == 1423) catch @panic("test failure");
+ expect(v[22] == 1424) catch @panic("test failure");
+ expect(v[23] == 1425) catch @panic("test failure");
+ expect(v[24] == 1426) catch @panic("test failure");
+ expect(v[25] == 1427) catch @panic("test failure");
+ expect(v[26] == 1428) catch @panic("test failure");
+ expect(v[27] == 1429) catch @panic("test failure");
+ expect(v[28] == 1430) catch @panic("test failure");
+ expect(v[29] == 1431) catch @panic("test failure");
+ expect(v[30] == 1432) catch @panic("test failure");
+ expect(v[31] == 1433) catch @panic("test failure");
+ expect(v[32] == 1434) catch @panic("test failure");
+ expect(v[33] == 1435) catch @panic("test failure");
+ expect(v[34] == 1436) catch @panic("test failure");
+ expect(v[35] == 1437) catch @panic("test failure");
+ expect(v[36] == 1438) catch @panic("test failure");
+ expect(v[37] == 1439) catch @panic("test failure");
+ expect(v[38] == 1440) catch @panic("test failure");
+ expect(v[39] == 1441) catch @panic("test failure");
+ expect(v[40] == 1442) catch @panic("test failure");
+ expect(v[41] == 1443) catch @panic("test failure");
+ expect(v[42] == 1444) catch @panic("test failure");
+ expect(v[43] == 1445) catch @panic("test failure");
+ expect(v[44] == 1446) catch @panic("test failure");
+ expect(v[45] == 1447) catch @panic("test failure");
+ expect(v[46] == 1448) catch @panic("test failure");
+ expect(v[47] == 1449) catch @panic("test failure");
+ expect(v[48] == 1450) catch @panic("test failure");
+ expect(v[49] == 1451) catch @panic("test failure");
+ expect(v[50] == 1452) catch @panic("test failure");
+ expect(v[51] == 1453) catch @panic("test failure");
+ expect(v[52] == 1454) catch @panic("test failure");
+ expect(v[53] == 1455) catch @panic("test failure");
+ expect(v[54] == 1456) catch @panic("test failure");
+ expect(v[55] == 1457) catch @panic("test failure");
+ expect(v[56] == 1458) catch @panic("test failure");
+ expect(v[57] == 1459) catch @panic("test failure");
+ expect(v[58] == 1460) catch @panic("test failure");
+ expect(v[59] == 1461) catch @panic("test failure");
+ expect(v[60] == 1462) catch @panic("test failure");
+ expect(v[61] == 1463) catch @panic("test failure");
+ expect(v[62] == 1464) catch @panic("test failure");
+ expect(v[63] == 1465) catch @panic("test failure");
+ expect(v[64] == 1466) catch @panic("test failure");
+ expect(v[65] == 1467) catch @panic("test failure");
+ expect(v[66] == 1468) catch @panic("test failure");
+ expect(v[67] == 1469) catch @panic("test failure");
+ expect(v[68] == 1470) catch @panic("test failure");
+ expect(v[69] == 1471) catch @panic("test failure");
+ expect(v[70] == 1472) catch @panic("test failure");
+ expect(v[71] == 1473) catch @panic("test failure");
+ expect(v[72] == 1474) catch @panic("test failure");
+ expect(v[73] == 1475) catch @panic("test failure");
+ expect(v[74] == 1476) catch @panic("test failure");
+ expect(v[75] == 1477) catch @panic("test failure");
+ expect(v[76] == 1478) catch @panic("test failure");
+ expect(v[77] == 1479) catch @panic("test failure");
+ expect(v[78] == 1480) catch @panic("test failure");
+ expect(v[79] == 1481) catch @panic("test failure");
+ expect(v[80] == 1482) catch @panic("test failure");
+ expect(v[81] == 1483) catch @panic("test failure");
+ expect(v[82] == 1484) catch @panic("test failure");
+ expect(v[83] == 1485) catch @panic("test failure");
+ expect(v[84] == 1486) catch @panic("test failure");
+ expect(v[85] == 1487) catch @panic("test failure");
+ expect(v[86] == 1488) catch @panic("test failure");
+ expect(v[87] == 1489) catch @panic("test failure");
+ expect(v[88] == 1490) catch @panic("test failure");
+ expect(v[89] == 1491) catch @panic("test failure");
+ expect(v[90] == 1492) catch @panic("test failure");
+ expect(v[91] == 1493) catch @panic("test failure");
+ expect(v[92] == 1494) catch @panic("test failure");
+ expect(v[93] == 1495) catch @panic("test failure");
+ expect(v[94] == 1496) catch @panic("test failure");
+ expect(v[95] == 1497) catch @panic("test failure");
+ expect(v[96] == 1498) catch @panic("test failure");
+ expect(v[97] == 1499) catch @panic("test failure");
+ expect(v[98] == 1500) catch @panic("test failure");
+ expect(v[99] == 1501) catch @panic("test failure");
+ expect(v[100] == 1502) catch @panic("test failure");
+ expect(v[101] == 1503) catch @panic("test failure");
+ expect(v[102] == 1504) catch @panic("test failure");
+ expect(v[103] == 1505) catch @panic("test failure");
+ expect(v[104] == 1506) catch @panic("test failure");
+ expect(v[105] == 1507) catch @panic("test failure");
+ expect(v[106] == 1508) catch @panic("test failure");
+ expect(v[107] == 1509) catch @panic("test failure");
+ expect(v[108] == 1510) catch @panic("test failure");
+ expect(v[109] == 1511) catch @panic("test failure");
+ expect(v[110] == 1512) catch @panic("test failure");
+ expect(v[111] == 1513) catch @panic("test failure");
+ expect(v[112] == 1514) catch @panic("test failure");
+ expect(v[113] == 1515) catch @panic("test failure");
+ expect(v[114] == 1516) catch @panic("test failure");
+ expect(v[115] == 1517) catch @panic("test failure");
+ expect(v[116] == 1518) catch @panic("test failure");
+ expect(v[117] == 1519) catch @panic("test failure");
+ expect(v[118] == 1520) catch @panic("test failure");
+ expect(v[119] == 1521) catch @panic("test failure");
+ expect(v[120] == 1522) catch @panic("test failure");
+ expect(v[121] == 1523) catch @panic("test failure");
+ expect(v[122] == 1524) catch @panic("test failure");
+ expect(v[123] == 1525) catch @panic("test failure");
+ expect(v[124] == 1526) catch @panic("test failure");
+ expect(v[125] == 1527) catch @panic("test failure");
+ expect(v[126] == 1528) catch @panic("test failure");
+ expect(v[127] == 1529) catch @panic("test failure");
+ expect(i == 128) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_128_u16() @Vector(128, u16);
+extern fn c_vector_128_u16(@Vector(128, u16), usize) void;
+extern fn c_test_vector_128_u16() void;
+
+test "@Vector(128, u16)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_128_u16();
+ try expect(v[0] == 1530);
+ try expect(v[1] == 1531);
+ try expect(v[2] == 1532);
+ try expect(v[3] == 1533);
+ try expect(v[4] == 1534);
+ try expect(v[5] == 1535);
+ try expect(v[6] == 1536);
+ try expect(v[7] == 1537);
+ try expect(v[8] == 1538);
+ try expect(v[9] == 1539);
+ try expect(v[10] == 1540);
+ try expect(v[11] == 1541);
+ try expect(v[12] == 1542);
+ try expect(v[13] == 1543);
+ try expect(v[14] == 1544);
+ try expect(v[15] == 1545);
+ try expect(v[16] == 1546);
+ try expect(v[17] == 1547);
+ try expect(v[18] == 1548);
+ try expect(v[19] == 1549);
+ try expect(v[20] == 1550);
+ try expect(v[21] == 1551);
+ try expect(v[22] == 1552);
+ try expect(v[23] == 1553);
+ try expect(v[24] == 1554);
+ try expect(v[25] == 1555);
+ try expect(v[26] == 1556);
+ try expect(v[27] == 1557);
+ try expect(v[28] == 1558);
+ try expect(v[29] == 1559);
+ try expect(v[30] == 1560);
+ try expect(v[31] == 1561);
+ try expect(v[32] == 1562);
+ try expect(v[33] == 1563);
+ try expect(v[34] == 1564);
+ try expect(v[35] == 1565);
+ try expect(v[36] == 1566);
+ try expect(v[37] == 1567);
+ try expect(v[38] == 1568);
+ try expect(v[39] == 1569);
+ try expect(v[40] == 1570);
+ try expect(v[41] == 1571);
+ try expect(v[42] == 1572);
+ try expect(v[43] == 1573);
+ try expect(v[44] == 1574);
+ try expect(v[45] == 1575);
+ try expect(v[46] == 1576);
+ try expect(v[47] == 1577);
+ try expect(v[48] == 1578);
+ try expect(v[49] == 1579);
+ try expect(v[50] == 1580);
+ try expect(v[51] == 1581);
+ try expect(v[52] == 1582);
+ try expect(v[53] == 1583);
+ try expect(v[54] == 1584);
+ try expect(v[55] == 1585);
+ try expect(v[56] == 1586);
+ try expect(v[57] == 1587);
+ try expect(v[58] == 1588);
+ try expect(v[59] == 1589);
+ try expect(v[60] == 1590);
+ try expect(v[61] == 1591);
+ try expect(v[62] == 1592);
+ try expect(v[63] == 1593);
+ try expect(v[64] == 1594);
+ try expect(v[65] == 1595);
+ try expect(v[66] == 1596);
+ try expect(v[67] == 1597);
+ try expect(v[68] == 1598);
+ try expect(v[69] == 1599);
+ try expect(v[70] == 1600);
+ try expect(v[71] == 1601);
+ try expect(v[72] == 1602);
+ try expect(v[73] == 1603);
+ try expect(v[74] == 1604);
+ try expect(v[75] == 1605);
+ try expect(v[76] == 1606);
+ try expect(v[77] == 1607);
+ try expect(v[78] == 1608);
+ try expect(v[79] == 1609);
+ try expect(v[80] == 1610);
+ try expect(v[81] == 1611);
+ try expect(v[82] == 1612);
+ try expect(v[83] == 1613);
+ try expect(v[84] == 1614);
+ try expect(v[85] == 1615);
+ try expect(v[86] == 1616);
+ try expect(v[87] == 1617);
+ try expect(v[88] == 1618);
+ try expect(v[89] == 1619);
+ try expect(v[90] == 1620);
+ try expect(v[91] == 1621);
+ try expect(v[92] == 1622);
+ try expect(v[93] == 1623);
+ try expect(v[94] == 1624);
+ try expect(v[95] == 1625);
+ try expect(v[96] == 1626);
+ try expect(v[97] == 1627);
+ try expect(v[98] == 1628);
+ try expect(v[99] == 1629);
+ try expect(v[100] == 1630);
+ try expect(v[101] == 1631);
+ try expect(v[102] == 1632);
+ try expect(v[103] == 1633);
+ try expect(v[104] == 1634);
+ try expect(v[105] == 1635);
+ try expect(v[106] == 1636);
+ try expect(v[107] == 1637);
+ try expect(v[108] == 1638);
+ try expect(v[109] == 1639);
+ try expect(v[110] == 1640);
+ try expect(v[111] == 1641);
+ try expect(v[112] == 1642);
+ try expect(v[113] == 1643);
+ try expect(v[114] == 1644);
+ try expect(v[115] == 1645);
+ try expect(v[116] == 1646);
+ try expect(v[117] == 1647);
+ try expect(v[118] == 1648);
+ try expect(v[119] == 1649);
+ try expect(v[120] == 1650);
+ try expect(v[121] == 1651);
+ try expect(v[122] == 1652);
+ try expect(v[123] == 1653);
+ try expect(v[124] == 1654);
+ try expect(v[125] == 1655);
+ try expect(v[126] == 1656);
+ try expect(v[127] == 1657);
+ c_vector_128_u16(.{
+ 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673,
+ 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, 1689,
+ 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, 1704, 1705,
+ 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721,
+ 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1737,
+ 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753,
+ 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769,
+ 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785,
+ }, 128);
+ c_test_vector_128_u16();
+}
+
+export fn zig_ret_vector_192_u16() @Vector(192, u16) {
+ return .{
+ 1786, 1787, 1788, 1789, 1790, 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801,
+ 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817,
+ 1818, 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833,
+ 1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849,
+ 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865,
+ 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881,
+ 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897,
+ 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913,
+ 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929,
+ 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945,
+ 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961,
+ 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977,
+ };
+}
+export fn zig_vector_192_u16(v: @Vector(192, u16), i: usize) void {
+ expect(v[0] == 1978) catch @panic("test failure");
+ expect(v[1] == 1979) catch @panic("test failure");
+ expect(v[2] == 1980) catch @panic("test failure");
+ expect(v[3] == 1981) catch @panic("test failure");
+ expect(v[4] == 1982) catch @panic("test failure");
+ expect(v[5] == 1983) catch @panic("test failure");
+ expect(v[6] == 1984) catch @panic("test failure");
+ expect(v[7] == 1985) catch @panic("test failure");
+ expect(v[8] == 1986) catch @panic("test failure");
+ expect(v[9] == 1987) catch @panic("test failure");
+ expect(v[10] == 1988) catch @panic("test failure");
+ expect(v[11] == 1989) catch @panic("test failure");
+ expect(v[12] == 1990) catch @panic("test failure");
+ expect(v[13] == 1991) catch @panic("test failure");
+ expect(v[14] == 1992) catch @panic("test failure");
+ expect(v[15] == 1993) catch @panic("test failure");
+ expect(v[16] == 1994) catch @panic("test failure");
+ expect(v[17] == 1995) catch @panic("test failure");
+ expect(v[18] == 1996) catch @panic("test failure");
+ expect(v[19] == 1997) catch @panic("test failure");
+ expect(v[20] == 1998) catch @panic("test failure");
+ expect(v[21] == 1999) catch @panic("test failure");
+ expect(v[22] == 2000) catch @panic("test failure");
+ expect(v[23] == 2001) catch @panic("test failure");
+ expect(v[24] == 2002) catch @panic("test failure");
+ expect(v[25] == 2003) catch @panic("test failure");
+ expect(v[26] == 2004) catch @panic("test failure");
+ expect(v[27] == 2005) catch @panic("test failure");
+ expect(v[28] == 2006) catch @panic("test failure");
+ expect(v[29] == 2007) catch @panic("test failure");
+ expect(v[30] == 2008) catch @panic("test failure");
+ expect(v[31] == 2009) catch @panic("test failure");
+ expect(v[32] == 2010) catch @panic("test failure");
+ expect(v[33] == 2011) catch @panic("test failure");
+ expect(v[34] == 2012) catch @panic("test failure");
+ expect(v[35] == 2013) catch @panic("test failure");
+ expect(v[36] == 2014) catch @panic("test failure");
+ expect(v[37] == 2015) catch @panic("test failure");
+ expect(v[38] == 2016) catch @panic("test failure");
+ expect(v[39] == 2017) catch @panic("test failure");
+ expect(v[40] == 2018) catch @panic("test failure");
+ expect(v[41] == 2019) catch @panic("test failure");
+ expect(v[42] == 2020) catch @panic("test failure");
+ expect(v[43] == 2021) catch @panic("test failure");
+ expect(v[44] == 2022) catch @panic("test failure");
+ expect(v[45] == 2023) catch @panic("test failure");
+ expect(v[46] == 2024) catch @panic("test failure");
+ expect(v[47] == 2025) catch @panic("test failure");
+ expect(v[48] == 2026) catch @panic("test failure");
+ expect(v[49] == 2027) catch @panic("test failure");
+ expect(v[50] == 2028) catch @panic("test failure");
+ expect(v[51] == 2029) catch @panic("test failure");
+ expect(v[52] == 2030) catch @panic("test failure");
+ expect(v[53] == 2031) catch @panic("test failure");
+ expect(v[54] == 2032) catch @panic("test failure");
+ expect(v[55] == 2033) catch @panic("test failure");
+ expect(v[56] == 2034) catch @panic("test failure");
+ expect(v[57] == 2035) catch @panic("test failure");
+ expect(v[58] == 2036) catch @panic("test failure");
+ expect(v[59] == 2037) catch @panic("test failure");
+ expect(v[60] == 2038) catch @panic("test failure");
+ expect(v[61] == 2039) catch @panic("test failure");
+ expect(v[62] == 2040) catch @panic("test failure");
+ expect(v[63] == 2041) catch @panic("test failure");
+ expect(v[64] == 2042) catch @panic("test failure");
+ expect(v[65] == 2043) catch @panic("test failure");
+ expect(v[66] == 2044) catch @panic("test failure");
+ expect(v[67] == 2045) catch @panic("test failure");
+ expect(v[68] == 2046) catch @panic("test failure");
+ expect(v[69] == 2047) catch @panic("test failure");
+ expect(v[70] == 2048) catch @panic("test failure");
+ expect(v[71] == 2049) catch @panic("test failure");
+ expect(v[72] == 2050) catch @panic("test failure");
+ expect(v[73] == 2051) catch @panic("test failure");
+ expect(v[74] == 2052) catch @panic("test failure");
+ expect(v[75] == 2053) catch @panic("test failure");
+ expect(v[76] == 2054) catch @panic("test failure");
+ expect(v[77] == 2055) catch @panic("test failure");
+ expect(v[78] == 2056) catch @panic("test failure");
+ expect(v[79] == 2057) catch @panic("test failure");
+ expect(v[80] == 2058) catch @panic("test failure");
+ expect(v[81] == 2059) catch @panic("test failure");
+ expect(v[82] == 2060) catch @panic("test failure");
+ expect(v[83] == 2061) catch @panic("test failure");
+ expect(v[84] == 2062) catch @panic("test failure");
+ expect(v[85] == 2063) catch @panic("test failure");
+ expect(v[86] == 2064) catch @panic("test failure");
+ expect(v[87] == 2065) catch @panic("test failure");
+ expect(v[88] == 2066) catch @panic("test failure");
+ expect(v[89] == 2067) catch @panic("test failure");
+ expect(v[90] == 2068) catch @panic("test failure");
+ expect(v[91] == 2069) catch @panic("test failure");
+ expect(v[92] == 2070) catch @panic("test failure");
+ expect(v[93] == 2071) catch @panic("test failure");
+ expect(v[94] == 2072) catch @panic("test failure");
+ expect(v[95] == 2073) catch @panic("test failure");
+ expect(v[96] == 2074) catch @panic("test failure");
+ expect(v[97] == 2075) catch @panic("test failure");
+ expect(v[98] == 2076) catch @panic("test failure");
+ expect(v[99] == 2077) catch @panic("test failure");
+ expect(v[100] == 2078) catch @panic("test failure");
+ expect(v[101] == 2079) catch @panic("test failure");
+ expect(v[102] == 2080) catch @panic("test failure");
+ expect(v[103] == 2081) catch @panic("test failure");
+ expect(v[104] == 2082) catch @panic("test failure");
+ expect(v[105] == 2083) catch @panic("test failure");
+ expect(v[106] == 2084) catch @panic("test failure");
+ expect(v[107] == 2085) catch @panic("test failure");
+ expect(v[108] == 2086) catch @panic("test failure");
+ expect(v[109] == 2087) catch @panic("test failure");
+ expect(v[110] == 2088) catch @panic("test failure");
+ expect(v[111] == 2089) catch @panic("test failure");
+ expect(v[112] == 2090) catch @panic("test failure");
+ expect(v[113] == 2091) catch @panic("test failure");
+ expect(v[114] == 2092) catch @panic("test failure");
+ expect(v[115] == 2093) catch @panic("test failure");
+ expect(v[116] == 2094) catch @panic("test failure");
+ expect(v[117] == 2095) catch @panic("test failure");
+ expect(v[118] == 2096) catch @panic("test failure");
+ expect(v[119] == 2097) catch @panic("test failure");
+ expect(v[120] == 2098) catch @panic("test failure");
+ expect(v[121] == 2099) catch @panic("test failure");
+ expect(v[122] == 2100) catch @panic("test failure");
+ expect(v[123] == 2101) catch @panic("test failure");
+ expect(v[124] == 2102) catch @panic("test failure");
+ expect(v[125] == 2103) catch @panic("test failure");
+ expect(v[126] == 2104) catch @panic("test failure");
+ expect(v[127] == 2105) catch @panic("test failure");
+ expect(v[128] == 2106) catch @panic("test failure");
+ expect(v[129] == 2107) catch @panic("test failure");
+ expect(v[130] == 2108) catch @panic("test failure");
+ expect(v[131] == 2109) catch @panic("test failure");
+ expect(v[132] == 2110) catch @panic("test failure");
+ expect(v[133] == 2111) catch @panic("test failure");
+ expect(v[134] == 2112) catch @panic("test failure");
+ expect(v[135] == 2113) catch @panic("test failure");
+ expect(v[136] == 2114) catch @panic("test failure");
+ expect(v[137] == 2115) catch @panic("test failure");
+ expect(v[138] == 2116) catch @panic("test failure");
+ expect(v[139] == 2117) catch @panic("test failure");
+ expect(v[140] == 2118) catch @panic("test failure");
+ expect(v[141] == 2119) catch @panic("test failure");
+ expect(v[142] == 2120) catch @panic("test failure");
+ expect(v[143] == 2121) catch @panic("test failure");
+ expect(v[144] == 2122) catch @panic("test failure");
+ expect(v[145] == 2123) catch @panic("test failure");
+ expect(v[146] == 2124) catch @panic("test failure");
+ expect(v[147] == 2125) catch @panic("test failure");
+ expect(v[148] == 2126) catch @panic("test failure");
+ expect(v[149] == 2127) catch @panic("test failure");
+ expect(v[150] == 2128) catch @panic("test failure");
+ expect(v[151] == 2129) catch @panic("test failure");
+ expect(v[152] == 2130) catch @panic("test failure");
+ expect(v[153] == 2131) catch @panic("test failure");
+ expect(v[154] == 2132) catch @panic("test failure");
+ expect(v[155] == 2133) catch @panic("test failure");
+ expect(v[156] == 2134) catch @panic("test failure");
+ expect(v[157] == 2135) catch @panic("test failure");
+ expect(v[158] == 2136) catch @panic("test failure");
+ expect(v[159] == 2137) catch @panic("test failure");
+ expect(v[160] == 2138) catch @panic("test failure");
+ expect(v[161] == 2139) catch @panic("test failure");
+ expect(v[162] == 2140) catch @panic("test failure");
+ expect(v[163] == 2141) catch @panic("test failure");
+ expect(v[164] == 2142) catch @panic("test failure");
+ expect(v[165] == 2143) catch @panic("test failure");
+ expect(v[166] == 2144) catch @panic("test failure");
+ expect(v[167] == 2145) catch @panic("test failure");
+ expect(v[168] == 2146) catch @panic("test failure");
+ expect(v[169] == 2147) catch @panic("test failure");
+ expect(v[170] == 2148) catch @panic("test failure");
+ expect(v[171] == 2149) catch @panic("test failure");
+ expect(v[172] == 2150) catch @panic("test failure");
+ expect(v[173] == 2151) catch @panic("test failure");
+ expect(v[174] == 2152) catch @panic("test failure");
+ expect(v[175] == 2153) catch @panic("test failure");
+ expect(v[176] == 2154) catch @panic("test failure");
+ expect(v[177] == 2155) catch @panic("test failure");
+ expect(v[178] == 2156) catch @panic("test failure");
+ expect(v[179] == 2157) catch @panic("test failure");
+ expect(v[180] == 2158) catch @panic("test failure");
+ expect(v[181] == 2159) catch @panic("test failure");
+ expect(v[182] == 2160) catch @panic("test failure");
+ expect(v[183] == 2161) catch @panic("test failure");
+ expect(v[184] == 2162) catch @panic("test failure");
+ expect(v[185] == 2163) catch @panic("test failure");
+ expect(v[186] == 2164) catch @panic("test failure");
+ expect(v[187] == 2165) catch @panic("test failure");
+ expect(v[188] == 2166) catch @panic("test failure");
+ expect(v[189] == 2167) catch @panic("test failure");
+ expect(v[190] == 2168) catch @panic("test failure");
+ expect(v[191] == 2169) catch @panic("test failure");
+ expect(i == 192) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_192_u16() @Vector(192, u16);
+extern fn c_vector_192_u16(@Vector(192, u16), usize) void;
+extern fn c_test_vector_192_u16() void;
+
+test "@Vector(192, u16)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_192_u16();
+ try expect(v[0] == 2170);
+ try expect(v[1] == 2171);
+ try expect(v[2] == 2172);
+ try expect(v[3] == 2173);
+ try expect(v[4] == 2174);
+ try expect(v[5] == 2175);
+ try expect(v[6] == 2176);
+ try expect(v[7] == 2177);
+ try expect(v[8] == 2178);
+ try expect(v[9] == 2179);
+ try expect(v[10] == 2180);
+ try expect(v[11] == 2181);
+ try expect(v[12] == 2182);
+ try expect(v[13] == 2183);
+ try expect(v[14] == 2184);
+ try expect(v[15] == 2185);
+ try expect(v[16] == 2186);
+ try expect(v[17] == 2187);
+ try expect(v[18] == 2188);
+ try expect(v[19] == 2189);
+ try expect(v[20] == 2190);
+ try expect(v[21] == 2191);
+ try expect(v[22] == 2192);
+ try expect(v[23] == 2193);
+ try expect(v[24] == 2194);
+ try expect(v[25] == 2195);
+ try expect(v[26] == 2196);
+ try expect(v[27] == 2197);
+ try expect(v[28] == 2198);
+ try expect(v[29] == 2199);
+ try expect(v[30] == 2200);
+ try expect(v[31] == 2201);
+ try expect(v[32] == 2202);
+ try expect(v[33] == 2203);
+ try expect(v[34] == 2204);
+ try expect(v[35] == 2205);
+ try expect(v[36] == 2206);
+ try expect(v[37] == 2207);
+ try expect(v[38] == 2208);
+ try expect(v[39] == 2209);
+ try expect(v[40] == 2210);
+ try expect(v[41] == 2211);
+ try expect(v[42] == 2212);
+ try expect(v[43] == 2213);
+ try expect(v[44] == 2214);
+ try expect(v[45] == 2215);
+ try expect(v[46] == 2216);
+ try expect(v[47] == 2217);
+ try expect(v[48] == 2218);
+ try expect(v[49] == 2219);
+ try expect(v[50] == 2220);
+ try expect(v[51] == 2221);
+ try expect(v[52] == 2222);
+ try expect(v[53] == 2223);
+ try expect(v[54] == 2224);
+ try expect(v[55] == 2225);
+ try expect(v[56] == 2226);
+ try expect(v[57] == 2227);
+ try expect(v[58] == 2228);
+ try expect(v[59] == 2229);
+ try expect(v[60] == 2230);
+ try expect(v[61] == 2231);
+ try expect(v[62] == 2232);
+ try expect(v[63] == 2233);
+ try expect(v[64] == 2234);
+ try expect(v[65] == 2235);
+ try expect(v[66] == 2236);
+ try expect(v[67] == 2237);
+ try expect(v[68] == 2238);
+ try expect(v[69] == 2239);
+ try expect(v[70] == 2240);
+ try expect(v[71] == 2241);
+ try expect(v[72] == 2242);
+ try expect(v[73] == 2243);
+ try expect(v[74] == 2244);
+ try expect(v[75] == 2245);
+ try expect(v[76] == 2246);
+ try expect(v[77] == 2247);
+ try expect(v[78] == 2248);
+ try expect(v[79] == 2249);
+ try expect(v[80] == 2250);
+ try expect(v[81] == 2251);
+ try expect(v[82] == 2252);
+ try expect(v[83] == 2253);
+ try expect(v[84] == 2254);
+ try expect(v[85] == 2255);
+ try expect(v[86] == 2256);
+ try expect(v[87] == 2257);
+ try expect(v[88] == 2258);
+ try expect(v[89] == 2259);
+ try expect(v[90] == 2260);
+ try expect(v[91] == 2261);
+ try expect(v[92] == 2262);
+ try expect(v[93] == 2263);
+ try expect(v[94] == 2264);
+ try expect(v[95] == 2265);
+ try expect(v[96] == 2266);
+ try expect(v[97] == 2267);
+ try expect(v[98] == 2268);
+ try expect(v[99] == 2269);
+ try expect(v[100] == 2270);
+ try expect(v[101] == 2271);
+ try expect(v[102] == 2272);
+ try expect(v[103] == 2273);
+ try expect(v[104] == 2274);
+ try expect(v[105] == 2275);
+ try expect(v[106] == 2276);
+ try expect(v[107] == 2277);
+ try expect(v[108] == 2278);
+ try expect(v[109] == 2279);
+ try expect(v[110] == 2280);
+ try expect(v[111] == 2281);
+ try expect(v[112] == 2282);
+ try expect(v[113] == 2283);
+ try expect(v[114] == 2284);
+ try expect(v[115] == 2285);
+ try expect(v[116] == 2286);
+ try expect(v[117] == 2287);
+ try expect(v[118] == 2288);
+ try expect(v[119] == 2289);
+ try expect(v[120] == 2290);
+ try expect(v[121] == 2291);
+ try expect(v[122] == 2292);
+ try expect(v[123] == 2293);
+ try expect(v[124] == 2294);
+ try expect(v[125] == 2295);
+ try expect(v[126] == 2296);
+ try expect(v[127] == 2297);
+ try expect(v[128] == 2298);
+ try expect(v[129] == 2299);
+ try expect(v[130] == 2300);
+ try expect(v[131] == 2301);
+ try expect(v[132] == 2302);
+ try expect(v[133] == 2303);
+ try expect(v[134] == 2304);
+ try expect(v[135] == 2305);
+ try expect(v[136] == 2306);
+ try expect(v[137] == 2307);
+ try expect(v[138] == 2308);
+ try expect(v[139] == 2309);
+ try expect(v[140] == 2310);
+ try expect(v[141] == 2311);
+ try expect(v[142] == 2312);
+ try expect(v[143] == 2313);
+ try expect(v[144] == 2314);
+ try expect(v[145] == 2315);
+ try expect(v[146] == 2316);
+ try expect(v[147] == 2317);
+ try expect(v[148] == 2318);
+ try expect(v[149] == 2319);
+ try expect(v[150] == 2320);
+ try expect(v[151] == 2321);
+ try expect(v[152] == 2322);
+ try expect(v[153] == 2323);
+ try expect(v[154] == 2324);
+ try expect(v[155] == 2325);
+ try expect(v[156] == 2326);
+ try expect(v[157] == 2327);
+ try expect(v[158] == 2328);
+ try expect(v[159] == 2329);
+ try expect(v[160] == 2330);
+ try expect(v[161] == 2331);
+ try expect(v[162] == 2332);
+ try expect(v[163] == 2333);
+ try expect(v[164] == 2334);
+ try expect(v[165] == 2335);
+ try expect(v[166] == 2336);
+ try expect(v[167] == 2337);
+ try expect(v[168] == 2338);
+ try expect(v[169] == 2339);
+ try expect(v[170] == 2340);
+ try expect(v[171] == 2341);
+ try expect(v[172] == 2342);
+ try expect(v[173] == 2343);
+ try expect(v[174] == 2344);
+ try expect(v[175] == 2345);
+ try expect(v[176] == 2346);
+ try expect(v[177] == 2347);
+ try expect(v[178] == 2348);
+ try expect(v[179] == 2349);
+ try expect(v[180] == 2350);
+ try expect(v[181] == 2351);
+ try expect(v[182] == 2352);
+ try expect(v[183] == 2353);
+ try expect(v[184] == 2354);
+ try expect(v[185] == 2355);
+ try expect(v[186] == 2356);
+ try expect(v[187] == 2357);
+ try expect(v[188] == 2358);
+ try expect(v[189] == 2359);
+ try expect(v[190] == 2360);
+ try expect(v[191] == 2361);
+ c_vector_192_u16(.{
+ 2362, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377,
+ 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, 2391, 2392, 2393,
+ 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, 2407, 2408, 2409,
+ 2410, 2411, 2412, 2413, 2414, 2415, 2416, 2417, 2418, 2419, 2420, 2421, 2422, 2423, 2424, 2425,
+ 2426, 2427, 2428, 2429, 2430, 2431, 2432, 2433, 2434, 2435, 2436, 2437, 2438, 2439, 2440, 2441,
+ 2442, 2443, 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451, 2452, 2453, 2454, 2455, 2456, 2457,
+ 2458, 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2466, 2467, 2468, 2469, 2470, 2471, 2472, 2473,
+ 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, 2482, 2483, 2484, 2485, 2486, 2487, 2488, 2489,
+ 2490, 2491, 2492, 2493, 2494, 2495, 2496, 2497, 2498, 2499, 2500, 2501, 2502, 2503, 2504, 2505,
+ 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513, 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521,
+ 2522, 2523, 2524, 2525, 2526, 2527, 2528, 2529, 2530, 2531, 2532, 2533, 2534, 2535, 2536, 2537,
+ 2538, 2539, 2540, 2541, 2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, 2550, 2551, 2552, 2553,
+ }, 192);
+ c_test_vector_192_u16();
+}
+
+export fn zig_ret_vector_256_u16() @Vector(256, u16) {
+ return .{
+ 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562, 2563, 2564, 2565, 2566, 2567, 2568, 2569,
+ 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, 2585,
+ 2586, 2587, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, 2598, 2599, 2600, 2601,
+ 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2617,
+ 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631, 2632, 2633,
+ 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, 2646, 2647, 2648, 2649,
+ 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, 2662, 2663, 2664, 2665,
+ 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, 2678, 2679, 2680, 2681,
+ 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, 2692, 2693, 2694, 2695, 2696, 2697,
+ 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2710, 2711, 2712, 2713,
+ 2714, 2715, 2716, 2717, 2718, 2719, 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729,
+ 2730, 2731, 2732, 2733, 2734, 2735, 2736, 2737, 2738, 2739, 2740, 2741, 2742, 2743, 2744, 2745,
+ 2746, 2747, 2748, 2749, 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, 2761,
+ 2762, 2763, 2764, 2765, 2766, 2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777,
+ 2778, 2779, 2780, 2781, 2782, 2783, 2784, 2785, 2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793,
+ 2794, 2795, 2796, 2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809,
+ };
+}
+export fn zig_vector_256_u16(v: @Vector(256, u16), i: usize) void {
+ expect(v[0] == 2810) catch @panic("test failure");
+ expect(v[1] == 2811) catch @panic("test failure");
+ expect(v[2] == 2812) catch @panic("test failure");
+ expect(v[3] == 2813) catch @panic("test failure");
+ expect(v[4] == 2814) catch @panic("test failure");
+ expect(v[5] == 2815) catch @panic("test failure");
+ expect(v[6] == 2816) catch @panic("test failure");
+ expect(v[7] == 2817) catch @panic("test failure");
+ expect(v[8] == 2818) catch @panic("test failure");
+ expect(v[9] == 2819) catch @panic("test failure");
+ expect(v[10] == 2820) catch @panic("test failure");
+ expect(v[11] == 2821) catch @panic("test failure");
+ expect(v[12] == 2822) catch @panic("test failure");
+ expect(v[13] == 2823) catch @panic("test failure");
+ expect(v[14] == 2824) catch @panic("test failure");
+ expect(v[15] == 2825) catch @panic("test failure");
+ expect(v[16] == 2826) catch @panic("test failure");
+ expect(v[17] == 2827) catch @panic("test failure");
+ expect(v[18] == 2828) catch @panic("test failure");
+ expect(v[19] == 2829) catch @panic("test failure");
+ expect(v[20] == 2830) catch @panic("test failure");
+ expect(v[21] == 2831) catch @panic("test failure");
+ expect(v[22] == 2832) catch @panic("test failure");
+ expect(v[23] == 2833) catch @panic("test failure");
+ expect(v[24] == 2834) catch @panic("test failure");
+ expect(v[25] == 2835) catch @panic("test failure");
+ expect(v[26] == 2836) catch @panic("test failure");
+ expect(v[27] == 2837) catch @panic("test failure");
+ expect(v[28] == 2838) catch @panic("test failure");
+ expect(v[29] == 2839) catch @panic("test failure");
+ expect(v[30] == 2840) catch @panic("test failure");
+ expect(v[31] == 2841) catch @panic("test failure");
+ expect(v[32] == 2842) catch @panic("test failure");
+ expect(v[33] == 2843) catch @panic("test failure");
+ expect(v[34] == 2844) catch @panic("test failure");
+ expect(v[35] == 2845) catch @panic("test failure");
+ expect(v[36] == 2846) catch @panic("test failure");
+ expect(v[37] == 2847) catch @panic("test failure");
+ expect(v[38] == 2848) catch @panic("test failure");
+ expect(v[39] == 2849) catch @panic("test failure");
+ expect(v[40] == 2850) catch @panic("test failure");
+ expect(v[41] == 2851) catch @panic("test failure");
+ expect(v[42] == 2852) catch @panic("test failure");
+ expect(v[43] == 2853) catch @panic("test failure");
+ expect(v[44] == 2854) catch @panic("test failure");
+ expect(v[45] == 2855) catch @panic("test failure");
+ expect(v[46] == 2856) catch @panic("test failure");
+ expect(v[47] == 2857) catch @panic("test failure");
+ expect(v[48] == 2858) catch @panic("test failure");
+ expect(v[49] == 2859) catch @panic("test failure");
+ expect(v[50] == 2860) catch @panic("test failure");
+ expect(v[51] == 2861) catch @panic("test failure");
+ expect(v[52] == 2862) catch @panic("test failure");
+ expect(v[53] == 2863) catch @panic("test failure");
+ expect(v[54] == 2864) catch @panic("test failure");
+ expect(v[55] == 2865) catch @panic("test failure");
+ expect(v[56] == 2866) catch @panic("test failure");
+ expect(v[57] == 2867) catch @panic("test failure");
+ expect(v[58] == 2868) catch @panic("test failure");
+ expect(v[59] == 2869) catch @panic("test failure");
+ expect(v[60] == 2870) catch @panic("test failure");
+ expect(v[61] == 2871) catch @panic("test failure");
+ expect(v[62] == 2872) catch @panic("test failure");
+ expect(v[63] == 2873) catch @panic("test failure");
+ expect(v[64] == 2874) catch @panic("test failure");
+ expect(v[65] == 2875) catch @panic("test failure");
+ expect(v[66] == 2876) catch @panic("test failure");
+ expect(v[67] == 2877) catch @panic("test failure");
+ expect(v[68] == 2878) catch @panic("test failure");
+ expect(v[69] == 2879) catch @panic("test failure");
+ expect(v[70] == 2880) catch @panic("test failure");
+ expect(v[71] == 2881) catch @panic("test failure");
+ expect(v[72] == 2882) catch @panic("test failure");
+ expect(v[73] == 2883) catch @panic("test failure");
+ expect(v[74] == 2884) catch @panic("test failure");
+ expect(v[75] == 2885) catch @panic("test failure");
+ expect(v[76] == 2886) catch @panic("test failure");
+ expect(v[77] == 2887) catch @panic("test failure");
+ expect(v[78] == 2888) catch @panic("test failure");
+ expect(v[79] == 2889) catch @panic("test failure");
+ expect(v[80] == 2890) catch @panic("test failure");
+ expect(v[81] == 2891) catch @panic("test failure");
+ expect(v[82] == 2892) catch @panic("test failure");
+ expect(v[83] == 2893) catch @panic("test failure");
+ expect(v[84] == 2894) catch @panic("test failure");
+ expect(v[85] == 2895) catch @panic("test failure");
+ expect(v[86] == 2896) catch @panic("test failure");
+ expect(v[87] == 2897) catch @panic("test failure");
+ expect(v[88] == 2898) catch @panic("test failure");
+ expect(v[89] == 2899) catch @panic("test failure");
+ expect(v[90] == 2900) catch @panic("test failure");
+ expect(v[91] == 2901) catch @panic("test failure");
+ expect(v[92] == 2902) catch @panic("test failure");
+ expect(v[93] == 2903) catch @panic("test failure");
+ expect(v[94] == 2904) catch @panic("test failure");
+ expect(v[95] == 2905) catch @panic("test failure");
+ expect(v[96] == 2906) catch @panic("test failure");
+ expect(v[97] == 2907) catch @panic("test failure");
+ expect(v[98] == 2908) catch @panic("test failure");
+ expect(v[99] == 2909) catch @panic("test failure");
+ expect(v[100] == 2910) catch @panic("test failure");
+ expect(v[101] == 2911) catch @panic("test failure");
+ expect(v[102] == 2912) catch @panic("test failure");
+ expect(v[103] == 2913) catch @panic("test failure");
+ expect(v[104] == 2914) catch @panic("test failure");
+ expect(v[105] == 2915) catch @panic("test failure");
+ expect(v[106] == 2916) catch @panic("test failure");
+ expect(v[107] == 2917) catch @panic("test failure");
+ expect(v[108] == 2918) catch @panic("test failure");
+ expect(v[109] == 2919) catch @panic("test failure");
+ expect(v[110] == 2920) catch @panic("test failure");
+ expect(v[111] == 2921) catch @panic("test failure");
+ expect(v[112] == 2922) catch @panic("test failure");
+ expect(v[113] == 2923) catch @panic("test failure");
+ expect(v[114] == 2924) catch @panic("test failure");
+ expect(v[115] == 2925) catch @panic("test failure");
+ expect(v[116] == 2926) catch @panic("test failure");
+ expect(v[117] == 2927) catch @panic("test failure");
+ expect(v[118] == 2928) catch @panic("test failure");
+ expect(v[119] == 2929) catch @panic("test failure");
+ expect(v[120] == 2930) catch @panic("test failure");
+ expect(v[121] == 2931) catch @panic("test failure");
+ expect(v[122] == 2932) catch @panic("test failure");
+ expect(v[123] == 2933) catch @panic("test failure");
+ expect(v[124] == 2934) catch @panic("test failure");
+ expect(v[125] == 2935) catch @panic("test failure");
+ expect(v[126] == 2936) catch @panic("test failure");
+ expect(v[127] == 2937) catch @panic("test failure");
+ expect(v[128] == 2938) catch @panic("test failure");
+ expect(v[129] == 2939) catch @panic("test failure");
+ expect(v[130] == 2940) catch @panic("test failure");
+ expect(v[131] == 2941) catch @panic("test failure");
+ expect(v[132] == 2942) catch @panic("test failure");
+ expect(v[133] == 2943) catch @panic("test failure");
+ expect(v[134] == 2944) catch @panic("test failure");
+ expect(v[135] == 2945) catch @panic("test failure");
+ expect(v[136] == 2946) catch @panic("test failure");
+ expect(v[137] == 2947) catch @panic("test failure");
+ expect(v[138] == 2948) catch @panic("test failure");
+ expect(v[139] == 2949) catch @panic("test failure");
+ expect(v[140] == 2950) catch @panic("test failure");
+ expect(v[141] == 2951) catch @panic("test failure");
+ expect(v[142] == 2952) catch @panic("test failure");
+ expect(v[143] == 2953) catch @panic("test failure");
+ expect(v[144] == 2954) catch @panic("test failure");
+ expect(v[145] == 2955) catch @panic("test failure");
+ expect(v[146] == 2956) catch @panic("test failure");
+ expect(v[147] == 2957) catch @panic("test failure");
+ expect(v[148] == 2958) catch @panic("test failure");
+ expect(v[149] == 2959) catch @panic("test failure");
+ expect(v[150] == 2960) catch @panic("test failure");
+ expect(v[151] == 2961) catch @panic("test failure");
+ expect(v[152] == 2962) catch @panic("test failure");
+ expect(v[153] == 2963) catch @panic("test failure");
+ expect(v[154] == 2964) catch @panic("test failure");
+ expect(v[155] == 2965) catch @panic("test failure");
+ expect(v[156] == 2966) catch @panic("test failure");
+ expect(v[157] == 2967) catch @panic("test failure");
+ expect(v[158] == 2968) catch @panic("test failure");
+ expect(v[159] == 2969) catch @panic("test failure");
+ expect(v[160] == 2970) catch @panic("test failure");
+ expect(v[161] == 2971) catch @panic("test failure");
+ expect(v[162] == 2972) catch @panic("test failure");
+ expect(v[163] == 2973) catch @panic("test failure");
+ expect(v[164] == 2974) catch @panic("test failure");
+ expect(v[165] == 2975) catch @panic("test failure");
+ expect(v[166] == 2976) catch @panic("test failure");
+ expect(v[167] == 2977) catch @panic("test failure");
+ expect(v[168] == 2978) catch @panic("test failure");
+ expect(v[169] == 2979) catch @panic("test failure");
+ expect(v[170] == 2980) catch @panic("test failure");
+ expect(v[171] == 2981) catch @panic("test failure");
+ expect(v[172] == 2982) catch @panic("test failure");
+ expect(v[173] == 2983) catch @panic("test failure");
+ expect(v[174] == 2984) catch @panic("test failure");
+ expect(v[175] == 2985) catch @panic("test failure");
+ expect(v[176] == 2986) catch @panic("test failure");
+ expect(v[177] == 2987) catch @panic("test failure");
+ expect(v[178] == 2988) catch @panic("test failure");
+ expect(v[179] == 2989) catch @panic("test failure");
+ expect(v[180] == 2990) catch @panic("test failure");
+ expect(v[181] == 2991) catch @panic("test failure");
+ expect(v[182] == 2992) catch @panic("test failure");
+ expect(v[183] == 2993) catch @panic("test failure");
+ expect(v[184] == 2994) catch @panic("test failure");
+ expect(v[185] == 2995) catch @panic("test failure");
+ expect(v[186] == 2996) catch @panic("test failure");
+ expect(v[187] == 2997) catch @panic("test failure");
+ expect(v[188] == 2998) catch @panic("test failure");
+ expect(v[189] == 2999) catch @panic("test failure");
+ expect(v[190] == 3000) catch @panic("test failure");
+ expect(v[191] == 3001) catch @panic("test failure");
+ expect(v[192] == 3002) catch @panic("test failure");
+ expect(v[193] == 3003) catch @panic("test failure");
+ expect(v[194] == 3004) catch @panic("test failure");
+ expect(v[195] == 3005) catch @panic("test failure");
+ expect(v[196] == 3006) catch @panic("test failure");
+ expect(v[197] == 3007) catch @panic("test failure");
+ expect(v[198] == 3008) catch @panic("test failure");
+ expect(v[199] == 3009) catch @panic("test failure");
+ expect(v[200] == 3010) catch @panic("test failure");
+ expect(v[201] == 3011) catch @panic("test failure");
+ expect(v[202] == 3012) catch @panic("test failure");
+ expect(v[203] == 3013) catch @panic("test failure");
+ expect(v[204] == 3014) catch @panic("test failure");
+ expect(v[205] == 3015) catch @panic("test failure");
+ expect(v[206] == 3016) catch @panic("test failure");
+ expect(v[207] == 3017) catch @panic("test failure");
+ expect(v[208] == 3018) catch @panic("test failure");
+ expect(v[209] == 3019) catch @panic("test failure");
+ expect(v[210] == 3020) catch @panic("test failure");
+ expect(v[211] == 3021) catch @panic("test failure");
+ expect(v[212] == 3022) catch @panic("test failure");
+ expect(v[213] == 3023) catch @panic("test failure");
+ expect(v[214] == 3024) catch @panic("test failure");
+ expect(v[215] == 3025) catch @panic("test failure");
+ expect(v[216] == 3026) catch @panic("test failure");
+ expect(v[217] == 3027) catch @panic("test failure");
+ expect(v[218] == 3028) catch @panic("test failure");
+ expect(v[219] == 3029) catch @panic("test failure");
+ expect(v[220] == 3030) catch @panic("test failure");
+ expect(v[221] == 3031) catch @panic("test failure");
+ expect(v[222] == 3032) catch @panic("test failure");
+ expect(v[223] == 3033) catch @panic("test failure");
+ expect(v[224] == 3034) catch @panic("test failure");
+ expect(v[225] == 3035) catch @panic("test failure");
+ expect(v[226] == 3036) catch @panic("test failure");
+ expect(v[227] == 3037) catch @panic("test failure");
+ expect(v[228] == 3038) catch @panic("test failure");
+ expect(v[229] == 3039) catch @panic("test failure");
+ expect(v[230] == 3040) catch @panic("test failure");
+ expect(v[231] == 3041) catch @panic("test failure");
+ expect(v[232] == 3042) catch @panic("test failure");
+ expect(v[233] == 3043) catch @panic("test failure");
+ expect(v[234] == 3044) catch @panic("test failure");
+ expect(v[235] == 3045) catch @panic("test failure");
+ expect(v[236] == 3046) catch @panic("test failure");
+ expect(v[237] == 3047) catch @panic("test failure");
+ expect(v[238] == 3048) catch @panic("test failure");
+ expect(v[239] == 3049) catch @panic("test failure");
+ expect(v[240] == 3050) catch @panic("test failure");
+ expect(v[241] == 3051) catch @panic("test failure");
+ expect(v[242] == 3052) catch @panic("test failure");
+ expect(v[243] == 3053) catch @panic("test failure");
+ expect(v[244] == 3054) catch @panic("test failure");
+ expect(v[245] == 3055) catch @panic("test failure");
+ expect(v[246] == 3056) catch @panic("test failure");
+ expect(v[247] == 3057) catch @panic("test failure");
+ expect(v[248] == 3058) catch @panic("test failure");
+ expect(v[249] == 3059) catch @panic("test failure");
+ expect(v[250] == 3060) catch @panic("test failure");
+ expect(v[251] == 3061) catch @panic("test failure");
+ expect(v[252] == 3062) catch @panic("test failure");
+ expect(v[253] == 3063) catch @panic("test failure");
+ expect(v[254] == 3064) catch @panic("test failure");
+ expect(v[255] == 3065) catch @panic("test failure");
+ expect(i == 256) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_256_u16() @Vector(256, u16);
+extern fn c_vector_256_u16(@Vector(256, u16), usize) void;
+extern fn c_test_vector_256_u16() void;
+
+test "@Vector(256, u16)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_256_u16();
+ try expect(v[0] == 3066);
+ try expect(v[1] == 3067);
+ try expect(v[2] == 3068);
+ try expect(v[3] == 3069);
+ try expect(v[4] == 3070);
+ try expect(v[5] == 3071);
+ try expect(v[6] == 3072);
+ try expect(v[7] == 3073);
+ try expect(v[8] == 3074);
+ try expect(v[9] == 3075);
+ try expect(v[10] == 3076);
+ try expect(v[11] == 3077);
+ try expect(v[12] == 3078);
+ try expect(v[13] == 3079);
+ try expect(v[14] == 3080);
+ try expect(v[15] == 3081);
+ try expect(v[16] == 3082);
+ try expect(v[17] == 3083);
+ try expect(v[18] == 3084);
+ try expect(v[19] == 3085);
+ try expect(v[20] == 3086);
+ try expect(v[21] == 3087);
+ try expect(v[22] == 3088);
+ try expect(v[23] == 3089);
+ try expect(v[24] == 3090);
+ try expect(v[25] == 3091);
+ try expect(v[26] == 3092);
+ try expect(v[27] == 3093);
+ try expect(v[28] == 3094);
+ try expect(v[29] == 3095);
+ try expect(v[30] == 3096);
+ try expect(v[31] == 3097);
+ try expect(v[32] == 3098);
+ try expect(v[33] == 3099);
+ try expect(v[34] == 3100);
+ try expect(v[35] == 3101);
+ try expect(v[36] == 3102);
+ try expect(v[37] == 3103);
+ try expect(v[38] == 3104);
+ try expect(v[39] == 3105);
+ try expect(v[40] == 3106);
+ try expect(v[41] == 3107);
+ try expect(v[42] == 3108);
+ try expect(v[43] == 3109);
+ try expect(v[44] == 3110);
+ try expect(v[45] == 3111);
+ try expect(v[46] == 3112);
+ try expect(v[47] == 3113);
+ try expect(v[48] == 3114);
+ try expect(v[49] == 3115);
+ try expect(v[50] == 3116);
+ try expect(v[51] == 3117);
+ try expect(v[52] == 3118);
+ try expect(v[53] == 3119);
+ try expect(v[54] == 3120);
+ try expect(v[55] == 3121);
+ try expect(v[56] == 3122);
+ try expect(v[57] == 3123);
+ try expect(v[58] == 3124);
+ try expect(v[59] == 3125);
+ try expect(v[60] == 3126);
+ try expect(v[61] == 3127);
+ try expect(v[62] == 3128);
+ try expect(v[63] == 3129);
+ try expect(v[64] == 3130);
+ try expect(v[65] == 3131);
+ try expect(v[66] == 3132);
+ try expect(v[67] == 3133);
+ try expect(v[68] == 3134);
+ try expect(v[69] == 3135);
+ try expect(v[70] == 3136);
+ try expect(v[71] == 3137);
+ try expect(v[72] == 3138);
+ try expect(v[73] == 3139);
+ try expect(v[74] == 3140);
+ try expect(v[75] == 3141);
+ try expect(v[76] == 3142);
+ try expect(v[77] == 3143);
+ try expect(v[78] == 3144);
+ try expect(v[79] == 3145);
+ try expect(v[80] == 3146);
+ try expect(v[81] == 3147);
+ try expect(v[82] == 3148);
+ try expect(v[83] == 3149);
+ try expect(v[84] == 3150);
+ try expect(v[85] == 3151);
+ try expect(v[86] == 3152);
+ try expect(v[87] == 3153);
+ try expect(v[88] == 3154);
+ try expect(v[89] == 3155);
+ try expect(v[90] == 3156);
+ try expect(v[91] == 3157);
+ try expect(v[92] == 3158);
+ try expect(v[93] == 3159);
+ try expect(v[94] == 3160);
+ try expect(v[95] == 3161);
+ try expect(v[96] == 3162);
+ try expect(v[97] == 3163);
+ try expect(v[98] == 3164);
+ try expect(v[99] == 3165);
+ try expect(v[100] == 3166);
+ try expect(v[101] == 3167);
+ try expect(v[102] == 3168);
+ try expect(v[103] == 3169);
+ try expect(v[104] == 3170);
+ try expect(v[105] == 3171);
+ try expect(v[106] == 3172);
+ try expect(v[107] == 3173);
+ try expect(v[108] == 3174);
+ try expect(v[109] == 3175);
+ try expect(v[110] == 3176);
+ try expect(v[111] == 3177);
+ try expect(v[112] == 3178);
+ try expect(v[113] == 3179);
+ try expect(v[114] == 3180);
+ try expect(v[115] == 3181);
+ try expect(v[116] == 3182);
+ try expect(v[117] == 3183);
+ try expect(v[118] == 3184);
+ try expect(v[119] == 3185);
+ try expect(v[120] == 3186);
+ try expect(v[121] == 3187);
+ try expect(v[122] == 3188);
+ try expect(v[123] == 3189);
+ try expect(v[124] == 3190);
+ try expect(v[125] == 3191);
+ try expect(v[126] == 3192);
+ try expect(v[127] == 3193);
+ try expect(v[128] == 3194);
+ try expect(v[129] == 3195);
+ try expect(v[130] == 3196);
+ try expect(v[131] == 3197);
+ try expect(v[132] == 3198);
+ try expect(v[133] == 3199);
+ try expect(v[134] == 3200);
+ try expect(v[135] == 3201);
+ try expect(v[136] == 3202);
+ try expect(v[137] == 3203);
+ try expect(v[138] == 3204);
+ try expect(v[139] == 3205);
+ try expect(v[140] == 3206);
+ try expect(v[141] == 3207);
+ try expect(v[142] == 3208);
+ try expect(v[143] == 3209);
+ try expect(v[144] == 3210);
+ try expect(v[145] == 3211);
+ try expect(v[146] == 3212);
+ try expect(v[147] == 3213);
+ try expect(v[148] == 3214);
+ try expect(v[149] == 3215);
+ try expect(v[150] == 3216);
+ try expect(v[151] == 3217);
+ try expect(v[152] == 3218);
+ try expect(v[153] == 3219);
+ try expect(v[154] == 3220);
+ try expect(v[155] == 3221);
+ try expect(v[156] == 3222);
+ try expect(v[157] == 3223);
+ try expect(v[158] == 3224);
+ try expect(v[159] == 3225);
+ try expect(v[160] == 3226);
+ try expect(v[161] == 3227);
+ try expect(v[162] == 3228);
+ try expect(v[163] == 3229);
+ try expect(v[164] == 3230);
+ try expect(v[165] == 3231);
+ try expect(v[166] == 3232);
+ try expect(v[167] == 3233);
+ try expect(v[168] == 3234);
+ try expect(v[169] == 3235);
+ try expect(v[170] == 3236);
+ try expect(v[171] == 3237);
+ try expect(v[172] == 3238);
+ try expect(v[173] == 3239);
+ try expect(v[174] == 3240);
+ try expect(v[175] == 3241);
+ try expect(v[176] == 3242);
+ try expect(v[177] == 3243);
+ try expect(v[178] == 3244);
+ try expect(v[179] == 3245);
+ try expect(v[180] == 3246);
+ try expect(v[181] == 3247);
+ try expect(v[182] == 3248);
+ try expect(v[183] == 3249);
+ try expect(v[184] == 3250);
+ try expect(v[185] == 3251);
+ try expect(v[186] == 3252);
+ try expect(v[187] == 3253);
+ try expect(v[188] == 3254);
+ try expect(v[189] == 3255);
+ try expect(v[190] == 3256);
+ try expect(v[191] == 3257);
+ try expect(v[192] == 3258);
+ try expect(v[193] == 3259);
+ try expect(v[194] == 3260);
+ try expect(v[195] == 3261);
+ try expect(v[196] == 3262);
+ try expect(v[197] == 3263);
+ try expect(v[198] == 3264);
+ try expect(v[199] == 3265);
+ try expect(v[200] == 3266);
+ try expect(v[201] == 3267);
+ try expect(v[202] == 3268);
+ try expect(v[203] == 3269);
+ try expect(v[204] == 3270);
+ try expect(v[205] == 3271);
+ try expect(v[206] == 3272);
+ try expect(v[207] == 3273);
+ try expect(v[208] == 3274);
+ try expect(v[209] == 3275);
+ try expect(v[210] == 3276);
+ try expect(v[211] == 3277);
+ try expect(v[212] == 3278);
+ try expect(v[213] == 3279);
+ try expect(v[214] == 3280);
+ try expect(v[215] == 3281);
+ try expect(v[216] == 3282);
+ try expect(v[217] == 3283);
+ try expect(v[218] == 3284);
+ try expect(v[219] == 3285);
+ try expect(v[220] == 3286);
+ try expect(v[221] == 3287);
+ try expect(v[222] == 3288);
+ try expect(v[223] == 3289);
+ try expect(v[224] == 3290);
+ try expect(v[225] == 3291);
+ try expect(v[226] == 3292);
+ try expect(v[227] == 3293);
+ try expect(v[228] == 3294);
+ try expect(v[229] == 3295);
+ try expect(v[230] == 3296);
+ try expect(v[231] == 3297);
+ try expect(v[232] == 3298);
+ try expect(v[233] == 3299);
+ try expect(v[234] == 3300);
+ try expect(v[235] == 3301);
+ try expect(v[236] == 3302);
+ try expect(v[237] == 3303);
+ try expect(v[238] == 3304);
+ try expect(v[239] == 3305);
+ try expect(v[240] == 3306);
+ try expect(v[241] == 3307);
+ try expect(v[242] == 3308);
+ try expect(v[243] == 3309);
+ try expect(v[244] == 3310);
+ try expect(v[245] == 3311);
+ try expect(v[246] == 3312);
+ try expect(v[247] == 3313);
+ try expect(v[248] == 3314);
+ try expect(v[249] == 3315);
+ try expect(v[250] == 3316);
+ try expect(v[251] == 3317);
+ try expect(v[252] == 3318);
+ try expect(v[253] == 3319);
+ try expect(v[254] == 3320);
+ try expect(v[255] == 3321);
+ c_vector_256_u16(.{
+ 3322, 3323, 3324, 3325, 3326, 3327, 3328, 3329, 3330, 3331, 3332, 3333, 3334, 3335, 3336, 3337,
+ 3338, 3339, 3340, 3341, 3342, 3343, 3344, 3345, 3346, 3347, 3348, 3349, 3350, 3351, 3352, 3353,
+ 3354, 3355, 3356, 3357, 3358, 3359, 3360, 3361, 3362, 3363, 3364, 3365, 3366, 3367, 3368, 3369,
+ 3370, 3371, 3372, 3373, 3374, 3375, 3376, 3377, 3378, 3379, 3380, 3381, 3382, 3383, 3384, 3385,
+ 3386, 3387, 3388, 3389, 3390, 3391, 3392, 3393, 3394, 3395, 3396, 3397, 3398, 3399, 3400, 3401,
+ 3402, 3403, 3404, 3405, 3406, 3407, 3408, 3409, 3410, 3411, 3412, 3413, 3414, 3415, 3416, 3417,
+ 3418, 3419, 3420, 3421, 3422, 3423, 3424, 3425, 3426, 3427, 3428, 3429, 3430, 3431, 3432, 3433,
+ 3434, 3435, 3436, 3437, 3438, 3439, 3440, 3441, 3442, 3443, 3444, 3445, 3446, 3447, 3448, 3449,
+ 3450, 3451, 3452, 3453, 3454, 3455, 3456, 3457, 3458, 3459, 3460, 3461, 3462, 3463, 3464, 3465,
+ 3466, 3467, 3468, 3469, 3470, 3471, 3472, 3473, 3474, 3475, 3476, 3477, 3478, 3479, 3480, 3481,
+ 3482, 3483, 3484, 3485, 3486, 3487, 3488, 3489, 3490, 3491, 3492, 3493, 3494, 3495, 3496, 3497,
+ 3498, 3499, 3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508, 3509, 3510, 3511, 3512, 3513,
+ 3514, 3515, 3516, 3517, 3518, 3519, 3520, 3521, 3522, 3523, 3524, 3525, 3526, 3527, 3528, 3529,
+ 3530, 3531, 3532, 3533, 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 3542, 3543, 3544, 3545,
+ 3546, 3547, 3548, 3549, 3550, 3551, 3552, 3553, 3554, 3555, 3556, 3557, 3558, 3559, 3560, 3561,
+ 3562, 3563, 3564, 3565, 3566, 3567, 3568, 3569, 3570, 3571, 3572, 3573, 3574, 3575, 3576, 3577,
+ }, 256);
+ c_test_vector_256_u16();
+}
+
+export fn zig_ret_vector_1_u32() @Vector(1, u32) {
+ return .{1};
+}
+export fn zig_vector_1_u32(v: @Vector(1, u32), i: usize) void {
+ expect(v[0] == 2) catch @panic("test failure");
+ expect(i == 1) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_1_u32() @Vector(1, u32);
+extern fn c_vector_1_u32(@Vector(1, u32), usize) void;
+extern fn c_test_vector_1_u32() void;
+
+test "@Vector(1, u32)" {
+ if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+
+ const v = c_ret_vector_1_u32();
+ try expect(v[0] == 3);
+ c_vector_1_u32(.{4}, 1);
+ c_test_vector_1_u32();
+}
+
+export fn zig_ret_vector_2_u32() @Vector(2, u32) {
+ return .{ 5, 6 };
+}
+export fn zig_vector_2_u32(v: @Vector(2, u32), i: usize) void {
+ expect(v[0] == 7) catch @panic("test failure");
+ expect(v[1] == 8) catch @panic("test failure");
+ expect(i == 2) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_2_u32() @Vector(2, u32);
+extern fn c_vector_2_u32(@Vector(2, u32), usize) void;
+extern fn c_test_vector_2_u32() void;
+
+test "@Vector(2, u32)" {
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest;
+
+ const v = c_ret_vector_2_u32();
+ try expect(v[0] == 9);
+ try expect(v[1] == 10);
+ c_vector_2_u32(.{ 11, 12 }, 2);
+ c_test_vector_2_u32();
+}
+
+export fn zig_ret_vector_3_u32() @Vector(3, u32) {
+ return .{ 13, 14, 15 };
+}
+export fn zig_vector_3_u32(v: @Vector(3, u32), i: usize) void {
+ expect(v[0] == 16) catch @panic("test failure");
+ expect(v[1] == 17) catch @panic("test failure");
+ expect(v[2] == 18) catch @panic("test failure");
+ expect(i == 3) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_3_u32() @Vector(3, u32);
+extern fn c_vector_3_u32(@Vector(3, u32), usize) void;
+extern fn c_test_vector_3_u32() void;
+
+test "@Vector(3, u32)" {
+ if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+
+ const v = c_ret_vector_3_u32();
+ try expect(v[0] == 19);
+ try expect(v[1] == 20);
+ try expect(v[2] == 21);
+ c_vector_3_u32(.{ 22, 23, 24 }, 3);
+ c_test_vector_3_u32();
+}
+
+export fn zig_ret_vector_4_u32() @Vector(4, u32) {
+ return .{ 25, 26, 27, 28 };
+}
+export fn zig_vector_4_u32(v: @Vector(4, u32), i: usize) void {
+ expect(v[0] == 29) catch @panic("test failure");
+ expect(v[1] == 30) catch @panic("test failure");
+ expect(v[2] == 31) catch @panic("test failure");
+ expect(v[3] == 32) catch @panic("test failure");
+ expect(i == 4) catch @panic("test failure");
+}
+export fn zig_vector_4_u32_vector_4_u32(v0: @Vector(4, u32), v1: @Vector(4, u32), i: usize) void {
+ expect(v0[0] == 33) catch @panic("test failure");
+ expect(v0[1] == 34) catch @panic("test failure");
+ expect(v0[2] == 35) catch @panic("test failure");
+ expect(v0[3] == 36) catch @panic("test failure");
+ expect(v1[0] == 37) catch @panic("test failure");
+ expect(v1[1] == 38) catch @panic("test failure");
+ expect(v1[2] == 39) catch @panic("test failure");
+ expect(v1[3] == 40) catch @panic("test failure");
+ expect(i == 8) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_4_u32() @Vector(4, u32);
+extern fn c_vector_4_u32(@Vector(4, u32), usize) void;
+extern fn c_vector_4_u32_vector_4_u32(@Vector(4, u32), @Vector(4, u32), usize) void;
+extern fn c_test_vector_4_u32() void;
+
+test "@Vector(4, u32)" {
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+
+ const v = c_ret_vector_4_u32();
+ try expect(v[0] == 41);
+ try expect(v[1] == 42);
+ try expect(v[2] == 43);
+ try expect(v[3] == 44);
+ c_vector_4_u32(.{ 45, 46, 47, 48 }, 4);
+ c_vector_4_u32_vector_4_u32(.{ 49, 50, 51, 52 }, .{ 53, 54, 55, 56 }, 8);
+ c_test_vector_4_u32();
+}
+
+export fn zig_ret_vector_6_u32() @Vector(6, u32) {
+ return .{ 41, 42, 43, 44, 45, 46 };
+}
+export fn zig_vector_6_u32(v: @Vector(6, u32), i: usize) void {
+ expect(v[0] == 47) catch @panic("test failure");
+ expect(v[1] == 48) catch @panic("test failure");
+ expect(v[2] == 49) catch @panic("test failure");
+ expect(v[3] == 50) catch @panic("test failure");
+ expect(v[4] == 51) catch @panic("test failure");
+ expect(v[5] == 52) catch @panic("test failure");
+ expect(i == 6) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_6_u32() @Vector(6, u32);
+extern fn c_vector_6_u32(@Vector(6, u32), usize) void;
+extern fn c_test_vector_6_u32() void;
+
+test "@Vector(6, u32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_6_u32();
+ try expect(v[0] == 53);
+ try expect(v[1] == 54);
+ try expect(v[2] == 55);
+ try expect(v[3] == 56);
+ try expect(v[4] == 57);
+ try expect(v[5] == 58);
+ c_vector_6_u32(.{ 59, 60, 61, 62, 63, 64 }, 6);
+ c_test_vector_6_u32();
+}
+
+export fn zig_ret_vector_8_u32() @Vector(8, u32) {
+ return .{ 65, 66, 67, 68, 69, 70, 71, 72 };
+}
+export fn zig_vector_8_u32(v: @Vector(8, u32), i: usize) void {
+ expect(v[0] == 73) catch @panic("test failure");
+ expect(v[1] == 74) catch @panic("test failure");
+ expect(v[2] == 75) catch @panic("test failure");
+ expect(v[3] == 76) catch @panic("test failure");
+ expect(v[4] == 77) catch @panic("test failure");
+ expect(v[5] == 78) catch @panic("test failure");
+ expect(v[6] == 79) catch @panic("test failure");
+ expect(v[7] == 80) catch @panic("test failure");
+ expect(i == 8) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_8_u32() @Vector(8, u32);
+extern fn c_vector_8_u32(@Vector(8, u32), usize) void;
+extern fn c_test_vector_8_u32() void;
+
+test "@Vector(8, u32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_8_u32();
+ try expect(v[0] == 81);
+ try expect(v[1] == 82);
+ try expect(v[2] == 83);
+ try expect(v[3] == 84);
+ try expect(v[4] == 85);
+ try expect(v[5] == 86);
+ try expect(v[6] == 87);
+ try expect(v[7] == 88);
+ c_vector_8_u32(.{ 89, 90, 91, 92, 93, 94, 95, 96 }, 8);
+ c_test_vector_8_u32();
+}
+
+export fn zig_ret_vector_12_u32() @Vector(12, u32) {
+ return .{ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108 };
+}
+export fn zig_vector_12_u32(v: @Vector(12, u32), i: usize) void {
+ expect(v[0] == 109) catch @panic("test failure");
+ expect(v[1] == 110) catch @panic("test failure");
+ expect(v[2] == 111) catch @panic("test failure");
+ expect(v[3] == 112) catch @panic("test failure");
+ expect(v[4] == 113) catch @panic("test failure");
+ expect(v[5] == 114) catch @panic("test failure");
+ expect(v[6] == 115) catch @panic("test failure");
+ expect(v[7] == 116) catch @panic("test failure");
+ expect(v[8] == 117) catch @panic("test failure");
+ expect(v[9] == 118) catch @panic("test failure");
+ expect(v[10] == 119) catch @panic("test failure");
+ expect(v[11] == 120) catch @panic("test failure");
+ expect(i == 12) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_12_u32() @Vector(12, u32);
+extern fn c_vector_12_u32(@Vector(12, u32), usize) void;
+extern fn c_test_vector_12_u32() void;
+
+test "@Vector(12, u32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_12_u32();
+ try expect(v[0] == 121);
+ try expect(v[1] == 122);
+ try expect(v[2] == 123);
+ try expect(v[3] == 124);
+ try expect(v[4] == 125);
+ try expect(v[5] == 126);
+ try expect(v[6] == 127);
+ try expect(v[7] == 128);
+ try expect(v[8] == 129);
+ try expect(v[9] == 130);
+ try expect(v[10] == 131);
+ try expect(v[11] == 132);
+ c_vector_12_u32(.{ 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144 }, 12);
+ c_test_vector_12_u32();
+}
+
+export fn zig_ret_vector_16_u32() @Vector(16, u32) {
+ return .{ 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160 };
+}
+export fn zig_vector_16_u32(v: @Vector(16, u32), i: usize) void {
+ expect(v[0] == 161) catch @panic("test failure");
+ expect(v[1] == 162) catch @panic("test failure");
+ expect(v[2] == 163) catch @panic("test failure");
+ expect(v[3] == 164) catch @panic("test failure");
+ expect(v[4] == 165) catch @panic("test failure");
+ expect(v[5] == 166) catch @panic("test failure");
+ expect(v[6] == 167) catch @panic("test failure");
+ expect(v[7] == 168) catch @panic("test failure");
+ expect(v[8] == 169) catch @panic("test failure");
+ expect(v[9] == 170) catch @panic("test failure");
+ expect(v[10] == 171) catch @panic("test failure");
+ expect(v[11] == 172) catch @panic("test failure");
+ expect(v[12] == 173) catch @panic("test failure");
+ expect(v[13] == 174) catch @panic("test failure");
+ expect(v[14] == 175) catch @panic("test failure");
+ expect(v[15] == 176) catch @panic("test failure");
+ expect(i == 16) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_16_u32() @Vector(16, u32);
+extern fn c_vector_16_u32(@Vector(16, u32), usize) void;
+extern fn c_test_vector_16_u32() void;
+
+test "@Vector(16, u32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_16_u32();
+ try expect(v[0] == 177);
+ try expect(v[1] == 178);
+ try expect(v[2] == 179);
+ try expect(v[3] == 180);
+ try expect(v[4] == 181);
+ try expect(v[5] == 182);
+ try expect(v[6] == 183);
+ try expect(v[7] == 184);
+ try expect(v[8] == 185);
+ try expect(v[9] == 186);
+ try expect(v[10] == 187);
+ try expect(v[11] == 188);
+ try expect(v[12] == 189);
+ try expect(v[13] == 190);
+ try expect(v[14] == 191);
+ try expect(v[15] == 192);
+ c_vector_16_u32(.{ 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208 }, 16);
+ c_test_vector_16_u32();
+}
+
+export fn zig_ret_vector_24_u32() @Vector(24, u32) {
+ return .{
+ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
+ 225, 226, 227, 228, 229, 230, 231, 232,
+ };
+}
+export fn zig_vector_24_u32(v: @Vector(24, u32), i: usize) void {
+ expect(v[0] == 233) catch @panic("test failure");
+ expect(v[1] == 234) catch @panic("test failure");
+ expect(v[2] == 235) catch @panic("test failure");
+ expect(v[3] == 236) catch @panic("test failure");
+ expect(v[4] == 237) catch @panic("test failure");
+ expect(v[5] == 238) catch @panic("test failure");
+ expect(v[6] == 239) catch @panic("test failure");
+ expect(v[7] == 240) catch @panic("test failure");
+ expect(v[8] == 241) catch @panic("test failure");
+ expect(v[9] == 242) catch @panic("test failure");
+ expect(v[10] == 243) catch @panic("test failure");
+ expect(v[11] == 244) catch @panic("test failure");
+ expect(v[12] == 245) catch @panic("test failure");
+ expect(v[13] == 246) catch @panic("test failure");
+ expect(v[14] == 247) catch @panic("test failure");
+ expect(v[15] == 248) catch @panic("test failure");
+ expect(v[16] == 249) catch @panic("test failure");
+ expect(v[17] == 250) catch @panic("test failure");
+ expect(v[18] == 251) catch @panic("test failure");
+ expect(v[19] == 252) catch @panic("test failure");
+ expect(v[20] == 253) catch @panic("test failure");
+ expect(v[21] == 254) catch @panic("test failure");
+ expect(v[22] == 255) catch @panic("test failure");
+ expect(v[23] == 256) catch @panic("test failure");
+ expect(i == 24) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_24_u32() @Vector(24, u32);
+extern fn c_vector_24_u32(@Vector(24, u32), usize) void;
+extern fn c_test_vector_24_u32() void;
+
+test "@Vector(24, u32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_24_u32();
+ try expect(v[0] == 257);
+ try expect(v[1] == 258);
+ try expect(v[2] == 259);
+ try expect(v[3] == 260);
+ try expect(v[4] == 261);
+ try expect(v[5] == 262);
+ try expect(v[6] == 263);
+ try expect(v[7] == 264);
+ try expect(v[8] == 265);
+ try expect(v[9] == 266);
+ try expect(v[10] == 267);
+ try expect(v[11] == 268);
+ try expect(v[12] == 269);
+ try expect(v[13] == 270);
+ try expect(v[14] == 271);
+ try expect(v[15] == 272);
+ try expect(v[16] == 273);
+ try expect(v[17] == 274);
+ try expect(v[18] == 275);
+ try expect(v[19] == 276);
+ try expect(v[20] == 277);
+ try expect(v[21] == 278);
+ try expect(v[22] == 279);
+ try expect(v[23] == 280);
+ c_vector_24_u32(.{
+ 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296,
+ 297, 298, 299, 300, 301, 302, 303, 304,
+ }, 24);
+ c_test_vector_24_u32();
+}
+
+export fn zig_ret_vector_32_u32() @Vector(32, u32) {
+ return .{
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320,
+ 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
+ };
+}
+export fn zig_vector_32_u32(v: @Vector(32, u32), i: usize) void {
+ expect(v[0] == 337) catch @panic("test failure");
+ expect(v[1] == 338) catch @panic("test failure");
+ expect(v[2] == 339) catch @panic("test failure");
+ expect(v[3] == 340) catch @panic("test failure");
+ expect(v[4] == 341) catch @panic("test failure");
+ expect(v[5] == 342) catch @panic("test failure");
+ expect(v[6] == 343) catch @panic("test failure");
+ expect(v[7] == 344) catch @panic("test failure");
+ expect(v[8] == 345) catch @panic("test failure");
+ expect(v[9] == 346) catch @panic("test failure");
+ expect(v[10] == 347) catch @panic("test failure");
+ expect(v[11] == 348) catch @panic("test failure");
+ expect(v[12] == 349) catch @panic("test failure");
+ expect(v[13] == 350) catch @panic("test failure");
+ expect(v[14] == 351) catch @panic("test failure");
+ expect(v[15] == 352) catch @panic("test failure");
+ expect(v[16] == 353) catch @panic("test failure");
+ expect(v[17] == 354) catch @panic("test failure");
+ expect(v[18] == 355) catch @panic("test failure");
+ expect(v[19] == 356) catch @panic("test failure");
+ expect(v[20] == 357) catch @panic("test failure");
+ expect(v[21] == 358) catch @panic("test failure");
+ expect(v[22] == 359) catch @panic("test failure");
+ expect(v[23] == 360) catch @panic("test failure");
+ expect(v[24] == 361) catch @panic("test failure");
+ expect(v[25] == 362) catch @panic("test failure");
+ expect(v[26] == 363) catch @panic("test failure");
+ expect(v[27] == 364) catch @panic("test failure");
+ expect(v[28] == 365) catch @panic("test failure");
+ expect(v[29] == 366) catch @panic("test failure");
+ expect(v[30] == 367) catch @panic("test failure");
+ expect(v[31] == 368) catch @panic("test failure");
+ expect(i == 32) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_32_u32() @Vector(32, u32);
+extern fn c_vector_32_u32(@Vector(32, u32), usize) void;
+extern fn c_test_vector_32_u32() void;
+
+test "@Vector(32, u32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_32_u32();
+ try expect(v[0] == 369);
+ try expect(v[1] == 370);
+ try expect(v[2] == 371);
+ try expect(v[3] == 372);
+ try expect(v[4] == 373);
+ try expect(v[5] == 374);
+ try expect(v[6] == 375);
+ try expect(v[7] == 376);
+ try expect(v[8] == 377);
+ try expect(v[9] == 378);
+ try expect(v[10] == 379);
+ try expect(v[11] == 380);
+ try expect(v[12] == 381);
+ try expect(v[13] == 382);
+ try expect(v[14] == 383);
+ try expect(v[15] == 384);
+ try expect(v[16] == 385);
+ try expect(v[17] == 386);
+ try expect(v[18] == 387);
+ try expect(v[19] == 388);
+ try expect(v[20] == 389);
+ try expect(v[21] == 390);
+ try expect(v[22] == 391);
+ try expect(v[23] == 392);
+ try expect(v[24] == 393);
+ try expect(v[25] == 394);
+ try expect(v[26] == 395);
+ try expect(v[27] == 396);
+ try expect(v[28] == 397);
+ try expect(v[29] == 398);
+ try expect(v[30] == 399);
+ try expect(v[31] == 400);
+ c_vector_32_u32(.{
+ 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416,
+ 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432,
+ }, 32);
+ c_test_vector_32_u32();
+}
+
+export fn zig_ret_vector_48_u32() @Vector(48, u32) {
+ return .{
+ 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448,
+ 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464,
+ 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480,
+ };
+}
+export fn zig_vector_48_u32(v: @Vector(48, u32), i: usize) void {
+ expect(v[0] == 481) catch @panic("test failure");
+ expect(v[1] == 482) catch @panic("test failure");
+ expect(v[2] == 483) catch @panic("test failure");
+ expect(v[3] == 484) catch @panic("test failure");
+ expect(v[4] == 485) catch @panic("test failure");
+ expect(v[5] == 486) catch @panic("test failure");
+ expect(v[6] == 487) catch @panic("test failure");
+ expect(v[7] == 488) catch @panic("test failure");
+ expect(v[8] == 489) catch @panic("test failure");
+ expect(v[9] == 490) catch @panic("test failure");
+ expect(v[10] == 491) catch @panic("test failure");
+ expect(v[11] == 492) catch @panic("test failure");
+ expect(v[12] == 493) catch @panic("test failure");
+ expect(v[13] == 494) catch @panic("test failure");
+ expect(v[14] == 495) catch @panic("test failure");
+ expect(v[15] == 496) catch @panic("test failure");
+ expect(v[16] == 497) catch @panic("test failure");
+ expect(v[17] == 498) catch @panic("test failure");
+ expect(v[18] == 499) catch @panic("test failure");
+ expect(v[19] == 500) catch @panic("test failure");
+ expect(v[20] == 501) catch @panic("test failure");
+ expect(v[21] == 502) catch @panic("test failure");
+ expect(v[22] == 503) catch @panic("test failure");
+ expect(v[23] == 504) catch @panic("test failure");
+ expect(v[24] == 505) catch @panic("test failure");
+ expect(v[25] == 506) catch @panic("test failure");
+ expect(v[26] == 507) catch @panic("test failure");
+ expect(v[27] == 508) catch @panic("test failure");
+ expect(v[28] == 509) catch @panic("test failure");
+ expect(v[29] == 510) catch @panic("test failure");
+ expect(v[30] == 511) catch @panic("test failure");
+ expect(v[31] == 512) catch @panic("test failure");
+ expect(v[32] == 513) catch @panic("test failure");
+ expect(v[33] == 514) catch @panic("test failure");
+ expect(v[34] == 515) catch @panic("test failure");
+ expect(v[35] == 516) catch @panic("test failure");
+ expect(v[36] == 517) catch @panic("test failure");
+ expect(v[37] == 518) catch @panic("test failure");
+ expect(v[38] == 519) catch @panic("test failure");
+ expect(v[39] == 520) catch @panic("test failure");
+ expect(v[40] == 521) catch @panic("test failure");
+ expect(v[41] == 522) catch @panic("test failure");
+ expect(v[42] == 523) catch @panic("test failure");
+ expect(v[43] == 524) catch @panic("test failure");
+ expect(v[44] == 525) catch @panic("test failure");
+ expect(v[45] == 526) catch @panic("test failure");
+ expect(v[46] == 527) catch @panic("test failure");
+ expect(v[47] == 528) catch @panic("test failure");
+ expect(i == 48) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_48_u32() @Vector(48, u32);
+extern fn c_vector_48_u32(@Vector(48, u32), usize) void;
+extern fn c_test_vector_48_u32() void;
+
+test "@Vector(48, u32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_48_u32();
+ try expect(v[0] == 529);
+ try expect(v[1] == 530);
+ try expect(v[2] == 531);
+ try expect(v[3] == 532);
+ try expect(v[4] == 533);
+ try expect(v[5] == 534);
+ try expect(v[6] == 535);
+ try expect(v[7] == 536);
+ try expect(v[8] == 537);
+ try expect(v[9] == 538);
+ try expect(v[10] == 539);
+ try expect(v[11] == 540);
+ try expect(v[12] == 541);
+ try expect(v[13] == 542);
+ try expect(v[14] == 543);
+ try expect(v[15] == 544);
+ try expect(v[16] == 545);
+ try expect(v[17] == 546);
+ try expect(v[18] == 547);
+ try expect(v[19] == 548);
+ try expect(v[20] == 549);
+ try expect(v[21] == 550);
+ try expect(v[22] == 551);
+ try expect(v[23] == 552);
+ try expect(v[24] == 553);
+ try expect(v[25] == 554);
+ try expect(v[26] == 555);
+ try expect(v[27] == 556);
+ try expect(v[28] == 557);
+ try expect(v[29] == 558);
+ try expect(v[30] == 559);
+ try expect(v[31] == 560);
+ try expect(v[32] == 561);
+ try expect(v[33] == 562);
+ try expect(v[34] == 563);
+ try expect(v[35] == 564);
+ try expect(v[36] == 565);
+ try expect(v[37] == 566);
+ try expect(v[38] == 567);
+ try expect(v[39] == 568);
+ try expect(v[40] == 569);
+ try expect(v[41] == 570);
+ try expect(v[42] == 571);
+ try expect(v[43] == 572);
+ try expect(v[44] == 573);
+ try expect(v[45] == 574);
+ try expect(v[46] == 575);
+ try expect(v[47] == 576);
+ c_vector_48_u32(.{
+ 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592,
+ 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608,
+ 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624,
+ }, 48);
+ c_test_vector_48_u32();
+}
+
+export fn zig_ret_vector_64_u32() @Vector(64, u32) {
+ return .{
+ 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640,
+ 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656,
+ 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672,
+ 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688,
+ };
+}
+export fn zig_vector_64_u32(v: @Vector(64, u32), i: usize) void {
+ expect(v[0] == 689) catch @panic("test failure");
+ expect(v[1] == 690) catch @panic("test failure");
+ expect(v[2] == 691) catch @panic("test failure");
+ expect(v[3] == 692) catch @panic("test failure");
+ expect(v[4] == 693) catch @panic("test failure");
+ expect(v[5] == 694) catch @panic("test failure");
+ expect(v[6] == 695) catch @panic("test failure");
+ expect(v[7] == 696) catch @panic("test failure");
+ expect(v[8] == 697) catch @panic("test failure");
+ expect(v[9] == 698) catch @panic("test failure");
+ expect(v[10] == 699) catch @panic("test failure");
+ expect(v[11] == 700) catch @panic("test failure");
+ expect(v[12] == 701) catch @panic("test failure");
+ expect(v[13] == 702) catch @panic("test failure");
+ expect(v[14] == 703) catch @panic("test failure");
+ expect(v[15] == 704) catch @panic("test failure");
+ expect(v[16] == 705) catch @panic("test failure");
+ expect(v[17] == 706) catch @panic("test failure");
+ expect(v[18] == 707) catch @panic("test failure");
+ expect(v[19] == 708) catch @panic("test failure");
+ expect(v[20] == 709) catch @panic("test failure");
+ expect(v[21] == 710) catch @panic("test failure");
+ expect(v[22] == 711) catch @panic("test failure");
+ expect(v[23] == 712) catch @panic("test failure");
+ expect(v[24] == 713) catch @panic("test failure");
+ expect(v[25] == 714) catch @panic("test failure");
+ expect(v[26] == 715) catch @panic("test failure");
+ expect(v[27] == 716) catch @panic("test failure");
+ expect(v[28] == 717) catch @panic("test failure");
+ expect(v[29] == 718) catch @panic("test failure");
+ expect(v[30] == 719) catch @panic("test failure");
+ expect(v[31] == 720) catch @panic("test failure");
+ expect(v[32] == 721) catch @panic("test failure");
+ expect(v[33] == 722) catch @panic("test failure");
+ expect(v[34] == 723) catch @panic("test failure");
+ expect(v[35] == 724) catch @panic("test failure");
+ expect(v[36] == 725) catch @panic("test failure");
+ expect(v[37] == 726) catch @panic("test failure");
+ expect(v[38] == 727) catch @panic("test failure");
+ expect(v[39] == 728) catch @panic("test failure");
+ expect(v[40] == 729) catch @panic("test failure");
+ expect(v[41] == 730) catch @panic("test failure");
+ expect(v[42] == 731) catch @panic("test failure");
+ expect(v[43] == 732) catch @panic("test failure");
+ expect(v[44] == 733) catch @panic("test failure");
+ expect(v[45] == 734) catch @panic("test failure");
+ expect(v[46] == 735) catch @panic("test failure");
+ expect(v[47] == 736) catch @panic("test failure");
+ expect(v[48] == 737) catch @panic("test failure");
+ expect(v[49] == 738) catch @panic("test failure");
+ expect(v[50] == 739) catch @panic("test failure");
+ expect(v[51] == 740) catch @panic("test failure");
+ expect(v[52] == 741) catch @panic("test failure");
+ expect(v[53] == 742) catch @panic("test failure");
+ expect(v[54] == 743) catch @panic("test failure");
+ expect(v[55] == 744) catch @panic("test failure");
+ expect(v[56] == 745) catch @panic("test failure");
+ expect(v[57] == 746) catch @panic("test failure");
+ expect(v[58] == 747) catch @panic("test failure");
+ expect(v[59] == 748) catch @panic("test failure");
+ expect(v[60] == 749) catch @panic("test failure");
+ expect(v[61] == 750) catch @panic("test failure");
+ expect(v[62] == 751) catch @panic("test failure");
+ expect(v[63] == 752) catch @panic("test failure");
+ expect(i == 64) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_64_u32() @Vector(64, u32);
+extern fn c_vector_64_u32(@Vector(64, u32), usize) void;
+extern fn c_test_vector_64_u32() void;
+
+test "@Vector(64, u32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_64_u32();
+ try expect(v[0] == 753);
+ try expect(v[1] == 754);
+ try expect(v[2] == 755);
+ try expect(v[3] == 756);
+ try expect(v[4] == 757);
+ try expect(v[5] == 758);
+ try expect(v[6] == 759);
+ try expect(v[7] == 760);
+ try expect(v[8] == 761);
+ try expect(v[9] == 762);
+ try expect(v[10] == 763);
+ try expect(v[11] == 764);
+ try expect(v[12] == 765);
+ try expect(v[13] == 766);
+ try expect(v[14] == 767);
+ try expect(v[15] == 768);
+ try expect(v[16] == 769);
+ try expect(v[17] == 770);
+ try expect(v[18] == 771);
+ try expect(v[19] == 772);
+ try expect(v[20] == 773);
+ try expect(v[21] == 774);
+ try expect(v[22] == 775);
+ try expect(v[23] == 776);
+ try expect(v[24] == 777);
+ try expect(v[25] == 778);
+ try expect(v[26] == 779);
+ try expect(v[27] == 780);
+ try expect(v[28] == 781);
+ try expect(v[29] == 782);
+ try expect(v[30] == 783);
+ try expect(v[31] == 784);
+ try expect(v[32] == 785);
+ try expect(v[33] == 786);
+ try expect(v[34] == 787);
+ try expect(v[35] == 788);
+ try expect(v[36] == 789);
+ try expect(v[37] == 790);
+ try expect(v[38] == 791);
+ try expect(v[39] == 792);
+ try expect(v[40] == 793);
+ try expect(v[41] == 794);
+ try expect(v[42] == 795);
+ try expect(v[43] == 796);
+ try expect(v[44] == 797);
+ try expect(v[45] == 798);
+ try expect(v[46] == 799);
+ try expect(v[47] == 800);
+ try expect(v[48] == 801);
+ try expect(v[49] == 802);
+ try expect(v[50] == 803);
+ try expect(v[51] == 804);
+ try expect(v[52] == 805);
+ try expect(v[53] == 806);
+ try expect(v[54] == 807);
+ try expect(v[55] == 808);
+ try expect(v[56] == 809);
+ try expect(v[57] == 810);
+ try expect(v[58] == 811);
+ try expect(v[59] == 812);
+ try expect(v[60] == 813);
+ try expect(v[61] == 814);
+ try expect(v[62] == 815);
+ try expect(v[63] == 816);
+ c_vector_64_u32(.{
+ 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832,
+ 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848,
+ 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864,
+ 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880,
+ }, 64);
+ c_test_vector_64_u32();
+}
+
+export fn zig_ret_vector_96_u32() @Vector(96, u32) {
+ return .{
+ 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905,
+ 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921,
+ 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937,
+ 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953,
+ 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969,
+ 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985,
+ };
+}
+export fn zig_vector_96_u32(v: @Vector(96, u32), i: usize) void {
+ expect(v[0] == 986) catch @panic("test failure");
+ expect(v[1] == 987) catch @panic("test failure");
+ expect(v[2] == 988) catch @panic("test failure");
+ expect(v[3] == 989) catch @panic("test failure");
+ expect(v[4] == 990) catch @panic("test failure");
+ expect(v[5] == 991) catch @panic("test failure");
+ expect(v[6] == 992) catch @panic("test failure");
+ expect(v[7] == 993) catch @panic("test failure");
+ expect(v[8] == 994) catch @panic("test failure");
+ expect(v[9] == 995) catch @panic("test failure");
+ expect(v[10] == 996) catch @panic("test failure");
+ expect(v[11] == 997) catch @panic("test failure");
+ expect(v[12] == 998) catch @panic("test failure");
+ expect(v[13] == 999) catch @panic("test failure");
+ expect(v[14] == 1000) catch @panic("test failure");
+ expect(v[15] == 1001) catch @panic("test failure");
+ expect(v[16] == 1002) catch @panic("test failure");
+ expect(v[17] == 1003) catch @panic("test failure");
+ expect(v[18] == 1004) catch @panic("test failure");
+ expect(v[19] == 1005) catch @panic("test failure");
+ expect(v[20] == 1006) catch @panic("test failure");
+ expect(v[21] == 1007) catch @panic("test failure");
+ expect(v[22] == 1008) catch @panic("test failure");
+ expect(v[23] == 1009) catch @panic("test failure");
+ expect(v[24] == 1010) catch @panic("test failure");
+ expect(v[25] == 1011) catch @panic("test failure");
+ expect(v[26] == 1012) catch @panic("test failure");
+ expect(v[27] == 1013) catch @panic("test failure");
+ expect(v[28] == 1014) catch @panic("test failure");
+ expect(v[29] == 1015) catch @panic("test failure");
+ expect(v[30] == 1016) catch @panic("test failure");
+ expect(v[31] == 1017) catch @panic("test failure");
+ expect(v[32] == 1018) catch @panic("test failure");
+ expect(v[33] == 1019) catch @panic("test failure");
+ expect(v[34] == 1020) catch @panic("test failure");
+ expect(v[35] == 1021) catch @panic("test failure");
+ expect(v[36] == 1022) catch @panic("test failure");
+ expect(v[37] == 1023) catch @panic("test failure");
+ expect(v[38] == 1024) catch @panic("test failure");
+ expect(v[39] == 1025) catch @panic("test failure");
+ expect(v[40] == 1026) catch @panic("test failure");
+ expect(v[41] == 1027) catch @panic("test failure");
+ expect(v[42] == 1028) catch @panic("test failure");
+ expect(v[43] == 1029) catch @panic("test failure");
+ expect(v[44] == 1030) catch @panic("test failure");
+ expect(v[45] == 1031) catch @panic("test failure");
+ expect(v[46] == 1032) catch @panic("test failure");
+ expect(v[47] == 1033) catch @panic("test failure");
+ expect(v[48] == 1034) catch @panic("test failure");
+ expect(v[49] == 1035) catch @panic("test failure");
+ expect(v[50] == 1036) catch @panic("test failure");
+ expect(v[51] == 1037) catch @panic("test failure");
+ expect(v[52] == 1038) catch @panic("test failure");
+ expect(v[53] == 1039) catch @panic("test failure");
+ expect(v[54] == 1040) catch @panic("test failure");
+ expect(v[55] == 1041) catch @panic("test failure");
+ expect(v[56] == 1042) catch @panic("test failure");
+ expect(v[57] == 1043) catch @panic("test failure");
+ expect(v[58] == 1044) catch @panic("test failure");
+ expect(v[59] == 1045) catch @panic("test failure");
+ expect(v[60] == 1046) catch @panic("test failure");
+ expect(v[61] == 1047) catch @panic("test failure");
+ expect(v[62] == 1048) catch @panic("test failure");
+ expect(v[63] == 1049) catch @panic("test failure");
+ expect(v[64] == 1050) catch @panic("test failure");
+ expect(v[65] == 1051) catch @panic("test failure");
+ expect(v[66] == 1052) catch @panic("test failure");
+ expect(v[67] == 1053) catch @panic("test failure");
+ expect(v[68] == 1054) catch @panic("test failure");
+ expect(v[69] == 1055) catch @panic("test failure");
+ expect(v[70] == 1056) catch @panic("test failure");
+ expect(v[71] == 1057) catch @panic("test failure");
+ expect(v[72] == 1058) catch @panic("test failure");
+ expect(v[73] == 1059) catch @panic("test failure");
+ expect(v[74] == 1060) catch @panic("test failure");
+ expect(v[75] == 1061) catch @panic("test failure");
+ expect(v[76] == 1062) catch @panic("test failure");
+ expect(v[77] == 1063) catch @panic("test failure");
+ expect(v[78] == 1064) catch @panic("test failure");
+ expect(v[79] == 1065) catch @panic("test failure");
+ expect(v[80] == 1066) catch @panic("test failure");
+ expect(v[81] == 1067) catch @panic("test failure");
+ expect(v[82] == 1068) catch @panic("test failure");
+ expect(v[83] == 1069) catch @panic("test failure");
+ expect(v[84] == 1070) catch @panic("test failure");
+ expect(v[85] == 1071) catch @panic("test failure");
+ expect(v[86] == 1072) catch @panic("test failure");
+ expect(v[87] == 1073) catch @panic("test failure");
+ expect(v[88] == 1074) catch @panic("test failure");
+ expect(v[89] == 1075) catch @panic("test failure");
+ expect(v[90] == 1076) catch @panic("test failure");
+ expect(v[91] == 1077) catch @panic("test failure");
+ expect(v[92] == 1078) catch @panic("test failure");
+ expect(v[93] == 1079) catch @panic("test failure");
+ expect(v[94] == 1080) catch @panic("test failure");
+ expect(v[95] == 1081) catch @panic("test failure");
+ expect(i == 96) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_96_u32() @Vector(96, u32);
+extern fn c_vector_96_u32(@Vector(96, u32), usize) void;
+extern fn c_test_vector_96_u32() void;
+
+test "@Vector(96, u32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_96_u32();
+ try expect(v[0] == 1082);
+ try expect(v[1] == 1083);
+ try expect(v[2] == 1084);
+ try expect(v[3] == 1085);
+ try expect(v[4] == 1086);
+ try expect(v[5] == 1087);
+ try expect(v[6] == 1088);
+ try expect(v[7] == 1089);
+ try expect(v[8] == 1090);
+ try expect(v[9] == 1091);
+ try expect(v[10] == 1092);
+ try expect(v[11] == 1093);
+ try expect(v[12] == 1094);
+ try expect(v[13] == 1095);
+ try expect(v[14] == 1096);
+ try expect(v[15] == 1097);
+ try expect(v[16] == 1098);
+ try expect(v[17] == 1099);
+ try expect(v[18] == 1100);
+ try expect(v[19] == 1101);
+ try expect(v[20] == 1102);
+ try expect(v[21] == 1103);
+ try expect(v[22] == 1104);
+ try expect(v[23] == 1105);
+ try expect(v[24] == 1106);
+ try expect(v[25] == 1107);
+ try expect(v[26] == 1108);
+ try expect(v[27] == 1109);
+ try expect(v[28] == 1110);
+ try expect(v[29] == 1111);
+ try expect(v[30] == 1112);
+ try expect(v[31] == 1113);
+ try expect(v[32] == 1114);
+ try expect(v[33] == 1115);
+ try expect(v[34] == 1116);
+ try expect(v[35] == 1117);
+ try expect(v[36] == 1118);
+ try expect(v[37] == 1119);
+ try expect(v[38] == 1120);
+ try expect(v[39] == 1121);
+ try expect(v[40] == 1122);
+ try expect(v[41] == 1123);
+ try expect(v[42] == 1124);
+ try expect(v[43] == 1125);
+ try expect(v[44] == 1126);
+ try expect(v[45] == 1127);
+ try expect(v[46] == 1128);
+ try expect(v[47] == 1129);
+ try expect(v[48] == 1130);
+ try expect(v[49] == 1131);
+ try expect(v[50] == 1132);
+ try expect(v[51] == 1133);
+ try expect(v[52] == 1134);
+ try expect(v[53] == 1135);
+ try expect(v[54] == 1136);
+ try expect(v[55] == 1137);
+ try expect(v[56] == 1138);
+ try expect(v[57] == 1139);
+ try expect(v[58] == 1140);
+ try expect(v[59] == 1141);
+ try expect(v[60] == 1142);
+ try expect(v[61] == 1143);
+ try expect(v[62] == 1144);
+ try expect(v[63] == 1145);
+ try expect(v[64] == 1146);
+ try expect(v[65] == 1147);
+ try expect(v[66] == 1148);
+ try expect(v[67] == 1149);
+ try expect(v[68] == 1150);
+ try expect(v[69] == 1151);
+ try expect(v[70] == 1152);
+ try expect(v[71] == 1153);
+ try expect(v[72] == 1154);
+ try expect(v[73] == 1155);
+ try expect(v[74] == 1156);
+ try expect(v[75] == 1157);
+ try expect(v[76] == 1158);
+ try expect(v[77] == 1159);
+ try expect(v[78] == 1160);
+ try expect(v[79] == 1161);
+ try expect(v[80] == 1162);
+ try expect(v[81] == 1163);
+ try expect(v[82] == 1164);
+ try expect(v[83] == 1165);
+ try expect(v[84] == 1166);
+ try expect(v[85] == 1167);
+ try expect(v[86] == 1168);
+ try expect(v[87] == 1169);
+ try expect(v[88] == 1170);
+ try expect(v[89] == 1171);
+ try expect(v[90] == 1172);
+ try expect(v[91] == 1173);
+ try expect(v[92] == 1174);
+ try expect(v[93] == 1175);
+ try expect(v[94] == 1176);
+ try expect(v[95] == 1177);
+ c_vector_96_u32(.{
+ 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193,
+ 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209,
+ 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1225,
+ 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241,
+ 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257,
+ 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273,
+ }, 96);
+ c_test_vector_96_u32();
+}
+
+export fn zig_ret_vector_128_u32() @Vector(128, u32) {
+ return .{
+ 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289,
+ 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305,
+ 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321,
+ 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337,
+ 1338, 1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353,
+ 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369,
+ 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385,
+ 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401,
+ };
+}
+export fn zig_vector_128_u32(v: @Vector(128, u32), i: usize) void {
+ expect(v[0] == 1402) catch @panic("test failure");
+ expect(v[1] == 1403) catch @panic("test failure");
+ expect(v[2] == 1404) catch @panic("test failure");
+ expect(v[3] == 1405) catch @panic("test failure");
+ expect(v[4] == 1406) catch @panic("test failure");
+ expect(v[5] == 1407) catch @panic("test failure");
+ expect(v[6] == 1408) catch @panic("test failure");
+ expect(v[7] == 1409) catch @panic("test failure");
+ expect(v[8] == 1410) catch @panic("test failure");
+ expect(v[9] == 1411) catch @panic("test failure");
+ expect(v[10] == 1412) catch @panic("test failure");
+ expect(v[11] == 1413) catch @panic("test failure");
+ expect(v[12] == 1414) catch @panic("test failure");
+ expect(v[13] == 1415) catch @panic("test failure");
+ expect(v[14] == 1416) catch @panic("test failure");
+ expect(v[15] == 1417) catch @panic("test failure");
+ expect(v[16] == 1418) catch @panic("test failure");
+ expect(v[17] == 1419) catch @panic("test failure");
+ expect(v[18] == 1420) catch @panic("test failure");
+ expect(v[19] == 1421) catch @panic("test failure");
+ expect(v[20] == 1422) catch @panic("test failure");
+ expect(v[21] == 1423) catch @panic("test failure");
+ expect(v[22] == 1424) catch @panic("test failure");
+ expect(v[23] == 1425) catch @panic("test failure");
+ expect(v[24] == 1426) catch @panic("test failure");
+ expect(v[25] == 1427) catch @panic("test failure");
+ expect(v[26] == 1428) catch @panic("test failure");
+ expect(v[27] == 1429) catch @panic("test failure");
+ expect(v[28] == 1430) catch @panic("test failure");
+ expect(v[29] == 1431) catch @panic("test failure");
+ expect(v[30] == 1432) catch @panic("test failure");
+ expect(v[31] == 1433) catch @panic("test failure");
+ expect(v[32] == 1434) catch @panic("test failure");
+ expect(v[33] == 1435) catch @panic("test failure");
+ expect(v[34] == 1436) catch @panic("test failure");
+ expect(v[35] == 1437) catch @panic("test failure");
+ expect(v[36] == 1438) catch @panic("test failure");
+ expect(v[37] == 1439) catch @panic("test failure");
+ expect(v[38] == 1440) catch @panic("test failure");
+ expect(v[39] == 1441) catch @panic("test failure");
+ expect(v[40] == 1442) catch @panic("test failure");
+ expect(v[41] == 1443) catch @panic("test failure");
+ expect(v[42] == 1444) catch @panic("test failure");
+ expect(v[43] == 1445) catch @panic("test failure");
+ expect(v[44] == 1446) catch @panic("test failure");
+ expect(v[45] == 1447) catch @panic("test failure");
+ expect(v[46] == 1448) catch @panic("test failure");
+ expect(v[47] == 1449) catch @panic("test failure");
+ expect(v[48] == 1450) catch @panic("test failure");
+ expect(v[49] == 1451) catch @panic("test failure");
+ expect(v[50] == 1452) catch @panic("test failure");
+ expect(v[51] == 1453) catch @panic("test failure");
+ expect(v[52] == 1454) catch @panic("test failure");
+ expect(v[53] == 1455) catch @panic("test failure");
+ expect(v[54] == 1456) catch @panic("test failure");
+ expect(v[55] == 1457) catch @panic("test failure");
+ expect(v[56] == 1458) catch @panic("test failure");
+ expect(v[57] == 1459) catch @panic("test failure");
+ expect(v[58] == 1460) catch @panic("test failure");
+ expect(v[59] == 1461) catch @panic("test failure");
+ expect(v[60] == 1462) catch @panic("test failure");
+ expect(v[61] == 1463) catch @panic("test failure");
+ expect(v[62] == 1464) catch @panic("test failure");
+ expect(v[63] == 1465) catch @panic("test failure");
+ expect(v[64] == 1466) catch @panic("test failure");
+ expect(v[65] == 1467) catch @panic("test failure");
+ expect(v[66] == 1468) catch @panic("test failure");
+ expect(v[67] == 1469) catch @panic("test failure");
+ expect(v[68] == 1470) catch @panic("test failure");
+ expect(v[69] == 1471) catch @panic("test failure");
+ expect(v[70] == 1472) catch @panic("test failure");
+ expect(v[71] == 1473) catch @panic("test failure");
+ expect(v[72] == 1474) catch @panic("test failure");
+ expect(v[73] == 1475) catch @panic("test failure");
+ expect(v[74] == 1476) catch @panic("test failure");
+ expect(v[75] == 1477) catch @panic("test failure");
+ expect(v[76] == 1478) catch @panic("test failure");
+ expect(v[77] == 1479) catch @panic("test failure");
+ expect(v[78] == 1480) catch @panic("test failure");
+ expect(v[79] == 1481) catch @panic("test failure");
+ expect(v[80] == 1482) catch @panic("test failure");
+ expect(v[81] == 1483) catch @panic("test failure");
+ expect(v[82] == 1484) catch @panic("test failure");
+ expect(v[83] == 1485) catch @panic("test failure");
+ expect(v[84] == 1486) catch @panic("test failure");
+ expect(v[85] == 1487) catch @panic("test failure");
+ expect(v[86] == 1488) catch @panic("test failure");
+ expect(v[87] == 1489) catch @panic("test failure");
+ expect(v[88] == 1490) catch @panic("test failure");
+ expect(v[89] == 1491) catch @panic("test failure");
+ expect(v[90] == 1492) catch @panic("test failure");
+ expect(v[91] == 1493) catch @panic("test failure");
+ expect(v[92] == 1494) catch @panic("test failure");
+ expect(v[93] == 1495) catch @panic("test failure");
+ expect(v[94] == 1496) catch @panic("test failure");
+ expect(v[95] == 1497) catch @panic("test failure");
+ expect(v[96] == 1498) catch @panic("test failure");
+ expect(v[97] == 1499) catch @panic("test failure");
+ expect(v[98] == 1500) catch @panic("test failure");
+ expect(v[99] == 1501) catch @panic("test failure");
+ expect(v[100] == 1502) catch @panic("test failure");
+ expect(v[101] == 1503) catch @panic("test failure");
+ expect(v[102] == 1504) catch @panic("test failure");
+ expect(v[103] == 1505) catch @panic("test failure");
+ expect(v[104] == 1506) catch @panic("test failure");
+ expect(v[105] == 1507) catch @panic("test failure");
+ expect(v[106] == 1508) catch @panic("test failure");
+ expect(v[107] == 1509) catch @panic("test failure");
+ expect(v[108] == 1510) catch @panic("test failure");
+ expect(v[109] == 1511) catch @panic("test failure");
+ expect(v[110] == 1512) catch @panic("test failure");
+ expect(v[111] == 1513) catch @panic("test failure");
+ expect(v[112] == 1514) catch @panic("test failure");
+ expect(v[113] == 1515) catch @panic("test failure");
+ expect(v[114] == 1516) catch @panic("test failure");
+ expect(v[115] == 1517) catch @panic("test failure");
+ expect(v[116] == 1518) catch @panic("test failure");
+ expect(v[117] == 1519) catch @panic("test failure");
+ expect(v[118] == 1520) catch @panic("test failure");
+ expect(v[119] == 1521) catch @panic("test failure");
+ expect(v[120] == 1522) catch @panic("test failure");
+ expect(v[121] == 1523) catch @panic("test failure");
+ expect(v[122] == 1524) catch @panic("test failure");
+ expect(v[123] == 1525) catch @panic("test failure");
+ expect(v[124] == 1526) catch @panic("test failure");
+ expect(v[125] == 1527) catch @panic("test failure");
+ expect(v[126] == 1528) catch @panic("test failure");
+ expect(v[127] == 1529) catch @panic("test failure");
+ expect(i == 128) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_128_u32() @Vector(128, u32);
+extern fn c_vector_128_u32(@Vector(128, u32), usize) void;
+extern fn c_test_vector_128_u32() void;
+
+test "@Vector(128, u32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_128_u32();
+ try expect(v[0] == 1530);
+ try expect(v[1] == 1531);
+ try expect(v[2] == 1532);
+ try expect(v[3] == 1533);
+ try expect(v[4] == 1534);
+ try expect(v[5] == 1535);
+ try expect(v[6] == 1536);
+ try expect(v[7] == 1537);
+ try expect(v[8] == 1538);
+ try expect(v[9] == 1539);
+ try expect(v[10] == 1540);
+ try expect(v[11] == 1541);
+ try expect(v[12] == 1542);
+ try expect(v[13] == 1543);
+ try expect(v[14] == 1544);
+ try expect(v[15] == 1545);
+ try expect(v[16] == 1546);
+ try expect(v[17] == 1547);
+ try expect(v[18] == 1548);
+ try expect(v[19] == 1549);
+ try expect(v[20] == 1550);
+ try expect(v[21] == 1551);
+ try expect(v[22] == 1552);
+ try expect(v[23] == 1553);
+ try expect(v[24] == 1554);
+ try expect(v[25] == 1555);
+ try expect(v[26] == 1556);
+ try expect(v[27] == 1557);
+ try expect(v[28] == 1558);
+ try expect(v[29] == 1559);
+ try expect(v[30] == 1560);
+ try expect(v[31] == 1561);
+ try expect(v[32] == 1562);
+ try expect(v[33] == 1563);
+ try expect(v[34] == 1564);
+ try expect(v[35] == 1565);
+ try expect(v[36] == 1566);
+ try expect(v[37] == 1567);
+ try expect(v[38] == 1568);
+ try expect(v[39] == 1569);
+ try expect(v[40] == 1570);
+ try expect(v[41] == 1571);
+ try expect(v[42] == 1572);
+ try expect(v[43] == 1573);
+ try expect(v[44] == 1574);
+ try expect(v[45] == 1575);
+ try expect(v[46] == 1576);
+ try expect(v[47] == 1577);
+ try expect(v[48] == 1578);
+ try expect(v[49] == 1579);
+ try expect(v[50] == 1580);
+ try expect(v[51] == 1581);
+ try expect(v[52] == 1582);
+ try expect(v[53] == 1583);
+ try expect(v[54] == 1584);
+ try expect(v[55] == 1585);
+ try expect(v[56] == 1586);
+ try expect(v[57] == 1587);
+ try expect(v[58] == 1588);
+ try expect(v[59] == 1589);
+ try expect(v[60] == 1590);
+ try expect(v[61] == 1591);
+ try expect(v[62] == 1592);
+ try expect(v[63] == 1593);
+ try expect(v[64] == 1594);
+ try expect(v[65] == 1595);
+ try expect(v[66] == 1596);
+ try expect(v[67] == 1597);
+ try expect(v[68] == 1598);
+ try expect(v[69] == 1599);
+ try expect(v[70] == 1600);
+ try expect(v[71] == 1601);
+ try expect(v[72] == 1602);
+ try expect(v[73] == 1603);
+ try expect(v[74] == 1604);
+ try expect(v[75] == 1605);
+ try expect(v[76] == 1606);
+ try expect(v[77] == 1607);
+ try expect(v[78] == 1608);
+ try expect(v[79] == 1609);
+ try expect(v[80] == 1610);
+ try expect(v[81] == 1611);
+ try expect(v[82] == 1612);
+ try expect(v[83] == 1613);
+ try expect(v[84] == 1614);
+ try expect(v[85] == 1615);
+ try expect(v[86] == 1616);
+ try expect(v[87] == 1617);
+ try expect(v[88] == 1618);
+ try expect(v[89] == 1619);
+ try expect(v[90] == 1620);
+ try expect(v[91] == 1621);
+ try expect(v[92] == 1622);
+ try expect(v[93] == 1623);
+ try expect(v[94] == 1624);
+ try expect(v[95] == 1625);
+ try expect(v[96] == 1626);
+ try expect(v[97] == 1627);
+ try expect(v[98] == 1628);
+ try expect(v[99] == 1629);
+ try expect(v[100] == 1630);
+ try expect(v[101] == 1631);
+ try expect(v[102] == 1632);
+ try expect(v[103] == 1633);
+ try expect(v[104] == 1634);
+ try expect(v[105] == 1635);
+ try expect(v[106] == 1636);
+ try expect(v[107] == 1637);
+ try expect(v[108] == 1638);
+ try expect(v[109] == 1639);
+ try expect(v[110] == 1640);
+ try expect(v[111] == 1641);
+ try expect(v[112] == 1642);
+ try expect(v[113] == 1643);
+ try expect(v[114] == 1644);
+ try expect(v[115] == 1645);
+ try expect(v[116] == 1646);
+ try expect(v[117] == 1647);
+ try expect(v[118] == 1648);
+ try expect(v[119] == 1649);
+ try expect(v[120] == 1650);
+ try expect(v[121] == 1651);
+ try expect(v[122] == 1652);
+ try expect(v[123] == 1653);
+ try expect(v[124] == 1654);
+ try expect(v[125] == 1655);
+ try expect(v[126] == 1656);
+ try expect(v[127] == 1657);
+ c_vector_128_u32(.{
+ 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673,
+ 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, 1689,
+ 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, 1704, 1705,
+ 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721,
+ 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1737,
+ 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753,
+ 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769,
+ 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785,
+ }, 128);
+ c_test_vector_128_u32();
+}
+
+export fn zig_ret_vector_1_u64() @Vector(1, u64) {
+ return .{1};
+}
+export fn zig_vector_1_u64(v: @Vector(1, u64), i: usize) void {
+ expect(v[0] == 2) catch @panic("test failure");
+ expect(i == 1) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_1_u64() @Vector(1, u64);
+extern fn c_vector_1_u64(@Vector(1, u64), usize) void;
+extern fn c_test_vector_1_u64() void;
+
+test "@Vector(1, u64)" {
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest;
+
+ const v = c_ret_vector_1_u64();
+ try expect(v[0] == 3);
+ c_vector_1_u64(.{4}, 1);
+ c_test_vector_1_u64();
+}
+
+export fn zig_ret_vector_2_u64() @Vector(2, u64) {
+ return .{ 5, 6 };
+}
+export fn zig_vector_2_u64(v: @Vector(2, u64), i: usize) void {
+ expect(v[0] == 7) catch @panic("test failure");
+ expect(v[1] == 8) catch @panic("test failure");
+ expect(i == 2) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_2_u64() @Vector(2, u64);
+extern fn c_vector_2_u64(@Vector(2, u64), usize) void;
+extern fn c_test_vector_2_u64() void;
+
+test "@Vector(2, u64)" {
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+
+ const v = c_ret_vector_2_u64();
+ try expect(v[0] == 9);
+ try expect(v[1] == 10);
+ c_vector_2_u64(.{ 11, 12 }, 2);
+ c_test_vector_2_u64();
+}
+
+export fn zig_ret_vector_3_u64() @Vector(3, u64) {
+ return .{ 13, 14, 15 };
+}
+export fn zig_vector_3_u64(v: @Vector(3, u64), i: usize) void {
+ expect(v[0] == 16) catch @panic("test failure");
+ expect(v[1] == 17) catch @panic("test failure");
+ expect(v[2] == 18) catch @panic("test failure");
+ expect(i == 3) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_3_u64() @Vector(3, u64);
+extern fn c_vector_3_u64(@Vector(3, u64), usize) void;
+extern fn c_test_vector_3_u64() void;
+
+test "@Vector(3, u64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_3_u64();
+ try expect(v[0] == 19);
+ try expect(v[1] == 20);
+ try expect(v[2] == 21);
+ c_vector_3_u64(.{ 22, 23, 24 }, 3);
+ c_test_vector_3_u64();
+}
+
+export fn zig_ret_vector_4_u64() @Vector(4, u64) {
+ return .{ 25, 26, 27, 28 };
+}
+export fn zig_vector_4_u64(v: @Vector(4, u64), i: usize) void {
+ expect(v[0] == 29) catch @panic("test failure");
+ expect(v[1] == 30) catch @panic("test failure");
+ expect(v[2] == 31) catch @panic("test failure");
+ expect(v[3] == 32) catch @panic("test failure");
+ expect(i == 4) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_4_u64() @Vector(4, u64);
+extern fn c_vector_4_u64(@Vector(4, u64), usize) void;
+extern fn c_test_vector_4_u64() void;
+
+test "@Vector(4, u64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_4_u64();
+ try expect(v[0] == 33);
+ try expect(v[1] == 34);
+ try expect(v[2] == 35);
+ try expect(v[3] == 36);
+ c_vector_4_u64(.{ 37, 38, 39, 40 }, 4);
+ c_test_vector_4_u64();
+}
+
+export fn zig_ret_vector_6_u64() @Vector(6, u64) {
+ return .{ 41, 42, 43, 44, 45, 46 };
+}
+export fn zig_vector_6_u64(v: @Vector(6, u64), i: usize) void {
+ expect(v[0] == 47) catch @panic("test failure");
+ expect(v[1] == 48) catch @panic("test failure");
+ expect(v[2] == 49) catch @panic("test failure");
+ expect(v[3] == 50) catch @panic("test failure");
+ expect(v[4] == 51) catch @panic("test failure");
+ expect(v[5] == 52) catch @panic("test failure");
+ expect(i == 6) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_6_u64() @Vector(6, u64);
+extern fn c_vector_6_u64(@Vector(6, u64), usize) void;
+extern fn c_test_vector_6_u64() void;
+
+test "@Vector(6, u64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+
+ const v = c_ret_vector_6_u64();
+ try expect(v[0] == 53);
+ try expect(v[1] == 54);
+ try expect(v[2] == 55);
+ try expect(v[3] == 56);
+ try expect(v[4] == 57);
+ try expect(v[5] == 58);
+ c_vector_6_u64(.{ 59, 60, 61, 62, 63, 64 }, 6);
+ c_test_vector_6_u64();
+}
+
+export fn zig_ret_vector_8_u64() @Vector(8, u64) {
+ return .{ 65, 66, 67, 68, 69, 70, 71, 72 };
+}
+export fn zig_vector_8_u64(v: @Vector(8, u64), i: usize) void {
+ expect(v[0] == 73) catch @panic("test failure");
+ expect(v[1] == 74) catch @panic("test failure");
+ expect(v[2] == 75) catch @panic("test failure");
+ expect(v[3] == 76) catch @panic("test failure");
+ expect(v[4] == 77) catch @panic("test failure");
+ expect(v[5] == 78) catch @panic("test failure");
+ expect(v[6] == 79) catch @panic("test failure");
+ expect(v[7] == 80) catch @panic("test failure");
+ expect(i == 8) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_8_u64() @Vector(8, u64);
+extern fn c_vector_8_u64(@Vector(8, u64), usize) void;
+extern fn c_test_vector_8_u64() void;
+
+test "@Vector(8, u64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_8_u64();
+ try expect(v[0] == 81);
+ try expect(v[1] == 82);
+ try expect(v[2] == 83);
+ try expect(v[3] == 84);
+ try expect(v[4] == 85);
+ try expect(v[5] == 86);
+ try expect(v[6] == 87);
+ try expect(v[7] == 88);
+ c_vector_8_u64(.{ 89, 90, 91, 92, 93, 94, 95, 96 }, 8);
+ c_test_vector_8_u64();
+}
+
+export fn zig_ret_vector_12_u64() @Vector(12, u64) {
+ return .{ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108 };
+}
+export fn zig_vector_12_u64(v: @Vector(12, u64), i: usize) void {
+ expect(v[0] == 109) catch @panic("test failure");
+ expect(v[1] == 110) catch @panic("test failure");
+ expect(v[2] == 111) catch @panic("test failure");
+ expect(v[3] == 112) catch @panic("test failure");
+ expect(v[4] == 113) catch @panic("test failure");
+ expect(v[5] == 114) catch @panic("test failure");
+ expect(v[6] == 115) catch @panic("test failure");
+ expect(v[7] == 116) catch @panic("test failure");
+ expect(v[8] == 117) catch @panic("test failure");
+ expect(v[9] == 118) catch @panic("test failure");
+ expect(v[10] == 119) catch @panic("test failure");
+ expect(v[11] == 120) catch @panic("test failure");
+ expect(i == 12) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_12_u64() @Vector(12, u64);
+extern fn c_vector_12_u64(@Vector(12, u64), usize) void;
+extern fn c_test_vector_12_u64() void;
+
+test "@Vector(12, u64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+
+ const v = c_ret_vector_12_u64();
+ try expect(v[0] == 121);
+ try expect(v[1] == 122);
+ try expect(v[2] == 123);
+ try expect(v[3] == 124);
+ try expect(v[4] == 125);
+ try expect(v[5] == 126);
+ try expect(v[6] == 127);
+ try expect(v[7] == 128);
+ try expect(v[8] == 129);
+ try expect(v[9] == 130);
+ try expect(v[10] == 131);
+ try expect(v[11] == 132);
+ c_vector_12_u64(.{ 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144 }, 12);
+ c_test_vector_12_u64();
+}
+
+export fn zig_ret_vector_16_u64() @Vector(16, u64) {
+ return .{ 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160 };
+}
+export fn zig_vector_16_u64(v: @Vector(16, u64), i: usize) void {
+ expect(v[0] == 161) catch @panic("test failure");
+ expect(v[1] == 162) catch @panic("test failure");
+ expect(v[2] == 163) catch @panic("test failure");
+ expect(v[3] == 164) catch @panic("test failure");
+ expect(v[4] == 165) catch @panic("test failure");
+ expect(v[5] == 166) catch @panic("test failure");
+ expect(v[6] == 167) catch @panic("test failure");
+ expect(v[7] == 168) catch @panic("test failure");
+ expect(v[8] == 169) catch @panic("test failure");
+ expect(v[9] == 170) catch @panic("test failure");
+ expect(v[10] == 171) catch @panic("test failure");
+ expect(v[11] == 172) catch @panic("test failure");
+ expect(v[12] == 173) catch @panic("test failure");
+ expect(v[13] == 174) catch @panic("test failure");
+ expect(v[14] == 175) catch @panic("test failure");
+ expect(v[15] == 176) catch @panic("test failure");
+ expect(i == 16) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_16_u64() @Vector(16, u64);
+extern fn c_vector_16_u64(@Vector(16, u64), usize) void;
+extern fn c_test_vector_16_u64() void;
+
+test "@Vector(16, u64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_16_u64();
+ try expect(v[0] == 177);
+ try expect(v[1] == 178);
+ try expect(v[2] == 179);
+ try expect(v[3] == 180);
+ try expect(v[4] == 181);
+ try expect(v[5] == 182);
+ try expect(v[6] == 183);
+ try expect(v[7] == 184);
+ try expect(v[8] == 185);
+ try expect(v[9] == 186);
+ try expect(v[10] == 187);
+ try expect(v[11] == 188);
+ try expect(v[12] == 189);
+ try expect(v[13] == 190);
+ try expect(v[14] == 191);
+ try expect(v[15] == 192);
+ c_vector_16_u64(.{ 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208 }, 16);
+ c_test_vector_16_u64();
+}
+
+export fn zig_ret_vector_24_u64() @Vector(24, u64) {
+ return .{
+ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
+ 225, 226, 227, 228, 229, 230, 231, 232,
+ };
+}
+export fn zig_vector_24_u64(v: @Vector(24, u64), i: usize) void {
+ expect(v[0] == 233) catch @panic("test failure");
+ expect(v[1] == 234) catch @panic("test failure");
+ expect(v[2] == 235) catch @panic("test failure");
+ expect(v[3] == 236) catch @panic("test failure");
+ expect(v[4] == 237) catch @panic("test failure");
+ expect(v[5] == 238) catch @panic("test failure");
+ expect(v[6] == 239) catch @panic("test failure");
+ expect(v[7] == 240) catch @panic("test failure");
+ expect(v[8] == 241) catch @panic("test failure");
+ expect(v[9] == 242) catch @panic("test failure");
+ expect(v[10] == 243) catch @panic("test failure");
+ expect(v[11] == 244) catch @panic("test failure");
+ expect(v[12] == 245) catch @panic("test failure");
+ expect(v[13] == 246) catch @panic("test failure");
+ expect(v[14] == 247) catch @panic("test failure");
+ expect(v[15] == 248) catch @panic("test failure");
+ expect(v[16] == 249) catch @panic("test failure");
+ expect(v[17] == 250) catch @panic("test failure");
+ expect(v[18] == 251) catch @panic("test failure");
+ expect(v[19] == 252) catch @panic("test failure");
+ expect(v[20] == 253) catch @panic("test failure");
+ expect(v[21] == 254) catch @panic("test failure");
+ expect(v[22] == 255) catch @panic("test failure");
+ expect(v[23] == 256) catch @panic("test failure");
+ expect(i == 24) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_24_u64() @Vector(24, u64);
+extern fn c_vector_24_u64(@Vector(24, u64), usize) void;
+extern fn c_test_vector_24_u64() void;
+
+test "@Vector(24, u64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+
+ const v = c_ret_vector_24_u64();
+ try expect(v[0] == 257);
+ try expect(v[1] == 258);
+ try expect(v[2] == 259);
+ try expect(v[3] == 260);
+ try expect(v[4] == 261);
+ try expect(v[5] == 262);
+ try expect(v[6] == 263);
+ try expect(v[7] == 264);
+ try expect(v[8] == 265);
+ try expect(v[9] == 266);
+ try expect(v[10] == 267);
+ try expect(v[11] == 268);
+ try expect(v[12] == 269);
+ try expect(v[13] == 270);
+ try expect(v[14] == 271);
+ try expect(v[15] == 272);
+ try expect(v[16] == 273);
+ try expect(v[17] == 274);
+ try expect(v[18] == 275);
+ try expect(v[19] == 276);
+ try expect(v[20] == 277);
+ try expect(v[21] == 278);
+ try expect(v[22] == 279);
+ try expect(v[23] == 280);
+ c_vector_24_u64(.{
+ 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296,
+ 297, 298, 299, 300, 301, 302, 303, 304,
+ }, 24);
+ c_test_vector_24_u64();
+}
+
+export fn zig_ret_vector_32_u64() @Vector(32, u64) {
+ return .{
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320,
+ 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
+ };
+}
+export fn zig_vector_32_u64(v: @Vector(32, u64), i: usize) void {
+ expect(v[0] == 337) catch @panic("test failure");
+ expect(v[1] == 338) catch @panic("test failure");
+ expect(v[2] == 339) catch @panic("test failure");
+ expect(v[3] == 340) catch @panic("test failure");
+ expect(v[4] == 341) catch @panic("test failure");
+ expect(v[5] == 342) catch @panic("test failure");
+ expect(v[6] == 343) catch @panic("test failure");
+ expect(v[7] == 344) catch @panic("test failure");
+ expect(v[8] == 345) catch @panic("test failure");
+ expect(v[9] == 346) catch @panic("test failure");
+ expect(v[10] == 347) catch @panic("test failure");
+ expect(v[11] == 348) catch @panic("test failure");
+ expect(v[12] == 349) catch @panic("test failure");
+ expect(v[13] == 350) catch @panic("test failure");
+ expect(v[14] == 351) catch @panic("test failure");
+ expect(v[15] == 352) catch @panic("test failure");
+ expect(v[16] == 353) catch @panic("test failure");
+ expect(v[17] == 354) catch @panic("test failure");
+ expect(v[18] == 355) catch @panic("test failure");
+ expect(v[19] == 356) catch @panic("test failure");
+ expect(v[20] == 357) catch @panic("test failure");
+ expect(v[21] == 358) catch @panic("test failure");
+ expect(v[22] == 359) catch @panic("test failure");
+ expect(v[23] == 360) catch @panic("test failure");
+ expect(v[24] == 361) catch @panic("test failure");
+ expect(v[25] == 362) catch @panic("test failure");
+ expect(v[26] == 363) catch @panic("test failure");
+ expect(v[27] == 364) catch @panic("test failure");
+ expect(v[28] == 365) catch @panic("test failure");
+ expect(v[29] == 366) catch @panic("test failure");
+ expect(v[30] == 367) catch @panic("test failure");
+ expect(v[31] == 368) catch @panic("test failure");
+ expect(i == 32) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_32_u64() @Vector(32, u64);
+extern fn c_vector_32_u64(@Vector(32, u64), usize) void;
+extern fn c_test_vector_32_u64() void;
+
+test "@Vector(32, u64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_32_u64();
+ try expect(v[0] == 369);
+ try expect(v[1] == 370);
+ try expect(v[2] == 371);
+ try expect(v[3] == 372);
+ try expect(v[4] == 373);
+ try expect(v[5] == 374);
+ try expect(v[6] == 375);
+ try expect(v[7] == 376);
+ try expect(v[8] == 377);
+ try expect(v[9] == 378);
+ try expect(v[10] == 379);
+ try expect(v[11] == 380);
+ try expect(v[12] == 381);
+ try expect(v[13] == 382);
+ try expect(v[14] == 383);
+ try expect(v[15] == 384);
+ try expect(v[16] == 385);
+ try expect(v[17] == 386);
+ try expect(v[18] == 387);
+ try expect(v[19] == 388);
+ try expect(v[20] == 389);
+ try expect(v[21] == 390);
+ try expect(v[22] == 391);
+ try expect(v[23] == 392);
+ try expect(v[24] == 393);
+ try expect(v[25] == 394);
+ try expect(v[26] == 395);
+ try expect(v[27] == 396);
+ try expect(v[28] == 397);
+ try expect(v[29] == 398);
+ try expect(v[30] == 399);
+ try expect(v[31] == 400);
+ c_vector_32_u64(.{
+ 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416,
+ 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432,
+ }, 32);
+ c_test_vector_32_u64();
+}
+
+export fn zig_ret_vector_48_u64() @Vector(48, u64) {
+ return .{
+ 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448,
+ 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464,
+ 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480,
+ };
+}
+export fn zig_vector_48_u64(v: @Vector(48, u64), i: usize) void {
+ expect(v[0] == 481) catch @panic("test failure");
+ expect(v[1] == 482) catch @panic("test failure");
+ expect(v[2] == 483) catch @panic("test failure");
+ expect(v[3] == 484) catch @panic("test failure");
+ expect(v[4] == 485) catch @panic("test failure");
+ expect(v[5] == 486) catch @panic("test failure");
+ expect(v[6] == 487) catch @panic("test failure");
+ expect(v[7] == 488) catch @panic("test failure");
+ expect(v[8] == 489) catch @panic("test failure");
+ expect(v[9] == 490) catch @panic("test failure");
+ expect(v[10] == 491) catch @panic("test failure");
+ expect(v[11] == 492) catch @panic("test failure");
+ expect(v[12] == 493) catch @panic("test failure");
+ expect(v[13] == 494) catch @panic("test failure");
+ expect(v[14] == 495) catch @panic("test failure");
+ expect(v[15] == 496) catch @panic("test failure");
+ expect(v[16] == 497) catch @panic("test failure");
+ expect(v[17] == 498) catch @panic("test failure");
+ expect(v[18] == 499) catch @panic("test failure");
+ expect(v[19] == 500) catch @panic("test failure");
+ expect(v[20] == 501) catch @panic("test failure");
+ expect(v[21] == 502) catch @panic("test failure");
+ expect(v[22] == 503) catch @panic("test failure");
+ expect(v[23] == 504) catch @panic("test failure");
+ expect(v[24] == 505) catch @panic("test failure");
+ expect(v[25] == 506) catch @panic("test failure");
+ expect(v[26] == 507) catch @panic("test failure");
+ expect(v[27] == 508) catch @panic("test failure");
+ expect(v[28] == 509) catch @panic("test failure");
+ expect(v[29] == 510) catch @panic("test failure");
+ expect(v[30] == 511) catch @panic("test failure");
+ expect(v[31] == 512) catch @panic("test failure");
+ expect(v[32] == 513) catch @panic("test failure");
+ expect(v[33] == 514) catch @panic("test failure");
+ expect(v[34] == 515) catch @panic("test failure");
+ expect(v[35] == 516) catch @panic("test failure");
+ expect(v[36] == 517) catch @panic("test failure");
+ expect(v[37] == 518) catch @panic("test failure");
+ expect(v[38] == 519) catch @panic("test failure");
+ expect(v[39] == 520) catch @panic("test failure");
+ expect(v[40] == 521) catch @panic("test failure");
+ expect(v[41] == 522) catch @panic("test failure");
+ expect(v[42] == 523) catch @panic("test failure");
+ expect(v[43] == 524) catch @panic("test failure");
+ expect(v[44] == 525) catch @panic("test failure");
+ expect(v[45] == 526) catch @panic("test failure");
+ expect(v[46] == 527) catch @panic("test failure");
+ expect(v[47] == 528) catch @panic("test failure");
+ expect(i == 48) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_48_u64() @Vector(48, u64);
+extern fn c_vector_48_u64(@Vector(48, u64), usize) void;
+extern fn c_test_vector_48_u64() void;
+
+test "@Vector(48, u64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+
+ const v = c_ret_vector_48_u64();
+ try expect(v[0] == 529);
+ try expect(v[1] == 530);
+ try expect(v[2] == 531);
+ try expect(v[3] == 532);
+ try expect(v[4] == 533);
+ try expect(v[5] == 534);
+ try expect(v[6] == 535);
+ try expect(v[7] == 536);
+ try expect(v[8] == 537);
+ try expect(v[9] == 538);
+ try expect(v[10] == 539);
+ try expect(v[11] == 540);
+ try expect(v[12] == 541);
+ try expect(v[13] == 542);
+ try expect(v[14] == 543);
+ try expect(v[15] == 544);
+ try expect(v[16] == 545);
+ try expect(v[17] == 546);
+ try expect(v[18] == 547);
+ try expect(v[19] == 548);
+ try expect(v[20] == 549);
+ try expect(v[21] == 550);
+ try expect(v[22] == 551);
+ try expect(v[23] == 552);
+ try expect(v[24] == 553);
+ try expect(v[25] == 554);
+ try expect(v[26] == 555);
+ try expect(v[27] == 556);
+ try expect(v[28] == 557);
+ try expect(v[29] == 558);
+ try expect(v[30] == 559);
+ try expect(v[31] == 560);
+ try expect(v[32] == 561);
+ try expect(v[33] == 562);
+ try expect(v[34] == 563);
+ try expect(v[35] == 564);
+ try expect(v[36] == 565);
+ try expect(v[37] == 566);
+ try expect(v[38] == 567);
+ try expect(v[39] == 568);
+ try expect(v[40] == 569);
+ try expect(v[41] == 570);
+ try expect(v[42] == 571);
+ try expect(v[43] == 572);
+ try expect(v[44] == 573);
+ try expect(v[45] == 574);
+ try expect(v[46] == 575);
+ try expect(v[47] == 576);
+ c_vector_48_u64(.{
+ 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592,
+ 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608,
+ 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624,
+ }, 48);
+ c_test_vector_48_u64();
+}
+
+export fn zig_ret_vector_64_u64() @Vector(64, u64) {
+ return .{
+ 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640,
+ 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656,
+ 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672,
+ 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688,
+ };
+}
+export fn zig_vector_64_u64(v: @Vector(64, u64), i: usize) void {
+ expect(v[0] == 689) catch @panic("test failure");
+ expect(v[1] == 690) catch @panic("test failure");
+ expect(v[2] == 691) catch @panic("test failure");
+ expect(v[3] == 692) catch @panic("test failure");
+ expect(v[4] == 693) catch @panic("test failure");
+ expect(v[5] == 694) catch @panic("test failure");
+ expect(v[6] == 695) catch @panic("test failure");
+ expect(v[7] == 696) catch @panic("test failure");
+ expect(v[8] == 697) catch @panic("test failure");
+ expect(v[9] == 698) catch @panic("test failure");
+ expect(v[10] == 699) catch @panic("test failure");
+ expect(v[11] == 700) catch @panic("test failure");
+ expect(v[12] == 701) catch @panic("test failure");
+ expect(v[13] == 702) catch @panic("test failure");
+ expect(v[14] == 703) catch @panic("test failure");
+ expect(v[15] == 704) catch @panic("test failure");
+ expect(v[16] == 705) catch @panic("test failure");
+ expect(v[17] == 706) catch @panic("test failure");
+ expect(v[18] == 707) catch @panic("test failure");
+ expect(v[19] == 708) catch @panic("test failure");
+ expect(v[20] == 709) catch @panic("test failure");
+ expect(v[21] == 710) catch @panic("test failure");
+ expect(v[22] == 711) catch @panic("test failure");
+ expect(v[23] == 712) catch @panic("test failure");
+ expect(v[24] == 713) catch @panic("test failure");
+ expect(v[25] == 714) catch @panic("test failure");
+ expect(v[26] == 715) catch @panic("test failure");
+ expect(v[27] == 716) catch @panic("test failure");
+ expect(v[28] == 717) catch @panic("test failure");
+ expect(v[29] == 718) catch @panic("test failure");
+ expect(v[30] == 719) catch @panic("test failure");
+ expect(v[31] == 720) catch @panic("test failure");
+ expect(v[32] == 721) catch @panic("test failure");
+ expect(v[33] == 722) catch @panic("test failure");
+ expect(v[34] == 723) catch @panic("test failure");
+ expect(v[35] == 724) catch @panic("test failure");
+ expect(v[36] == 725) catch @panic("test failure");
+ expect(v[37] == 726) catch @panic("test failure");
+ expect(v[38] == 727) catch @panic("test failure");
+ expect(v[39] == 728) catch @panic("test failure");
+ expect(v[40] == 729) catch @panic("test failure");
+ expect(v[41] == 730) catch @panic("test failure");
+ expect(v[42] == 731) catch @panic("test failure");
+ expect(v[43] == 732) catch @panic("test failure");
+ expect(v[44] == 733) catch @panic("test failure");
+ expect(v[45] == 734) catch @panic("test failure");
+ expect(v[46] == 735) catch @panic("test failure");
+ expect(v[47] == 736) catch @panic("test failure");
+ expect(v[48] == 737) catch @panic("test failure");
+ expect(v[49] == 738) catch @panic("test failure");
+ expect(v[50] == 739) catch @panic("test failure");
+ expect(v[51] == 740) catch @panic("test failure");
+ expect(v[52] == 741) catch @panic("test failure");
+ expect(v[53] == 742) catch @panic("test failure");
+ expect(v[54] == 743) catch @panic("test failure");
+ expect(v[55] == 744) catch @panic("test failure");
+ expect(v[56] == 745) catch @panic("test failure");
+ expect(v[57] == 746) catch @panic("test failure");
+ expect(v[58] == 747) catch @panic("test failure");
+ expect(v[59] == 748) catch @panic("test failure");
+ expect(v[60] == 749) catch @panic("test failure");
+ expect(v[61] == 750) catch @panic("test failure");
+ expect(v[62] == 751) catch @panic("test failure");
+ expect(v[63] == 752) catch @panic("test failure");
+ expect(i == 64) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_64_u64() @Vector(64, u64);
+extern fn c_vector_64_u64(@Vector(64, u64), usize) void;
+extern fn c_test_vector_64_u64() void;
+
+test "@Vector(64, u64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_64_u64();
+ try expect(v[0] == 753);
+ try expect(v[1] == 754);
+ try expect(v[2] == 755);
+ try expect(v[3] == 756);
+ try expect(v[4] == 757);
+ try expect(v[5] == 758);
+ try expect(v[6] == 759);
+ try expect(v[7] == 760);
+ try expect(v[8] == 761);
+ try expect(v[9] == 762);
+ try expect(v[10] == 763);
+ try expect(v[11] == 764);
+ try expect(v[12] == 765);
+ try expect(v[13] == 766);
+ try expect(v[14] == 767);
+ try expect(v[15] == 768);
+ try expect(v[16] == 769);
+ try expect(v[17] == 770);
+ try expect(v[18] == 771);
+ try expect(v[19] == 772);
+ try expect(v[20] == 773);
+ try expect(v[21] == 774);
+ try expect(v[22] == 775);
+ try expect(v[23] == 776);
+ try expect(v[24] == 777);
+ try expect(v[25] == 778);
+ try expect(v[26] == 779);
+ try expect(v[27] == 780);
+ try expect(v[28] == 781);
+ try expect(v[29] == 782);
+ try expect(v[30] == 783);
+ try expect(v[31] == 784);
+ try expect(v[32] == 785);
+ try expect(v[33] == 786);
+ try expect(v[34] == 787);
+ try expect(v[35] == 788);
+ try expect(v[36] == 789);
+ try expect(v[37] == 790);
+ try expect(v[38] == 791);
+ try expect(v[39] == 792);
+ try expect(v[40] == 793);
+ try expect(v[41] == 794);
+ try expect(v[42] == 795);
+ try expect(v[43] == 796);
+ try expect(v[44] == 797);
+ try expect(v[45] == 798);
+ try expect(v[46] == 799);
+ try expect(v[47] == 800);
+ try expect(v[48] == 801);
+ try expect(v[49] == 802);
+ try expect(v[50] == 803);
+ try expect(v[51] == 804);
+ try expect(v[52] == 805);
+ try expect(v[53] == 806);
+ try expect(v[54] == 807);
+ try expect(v[55] == 808);
+ try expect(v[56] == 809);
+ try expect(v[57] == 810);
+ try expect(v[58] == 811);
+ try expect(v[59] == 812);
+ try expect(v[60] == 813);
+ try expect(v[61] == 814);
+ try expect(v[62] == 815);
+ try expect(v[63] == 816);
+ c_vector_64_u64(.{
+ 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832,
+ 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848,
+ 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864,
+ 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880,
+ }, 64);
+ c_test_vector_64_u64();
+}
+
+export fn zig_ret_vector_1_f32() @Vector(1, f32) {
+ return .{1};
+}
+export fn zig_vector_1_f32(v: @Vector(1, f32), i: usize) void {
+ expect(v[0] == 2) catch @panic("test failure");
+ expect(i == 1) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_1_f32() @Vector(1, f32);
+extern fn c_vector_1_f32(@Vector(1, f32), usize) void;
+extern fn c_test_vector_1_f32() void;
+
+test "@Vector(1, f32)" {
+ if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest;
+
+ const v = c_ret_vector_1_f32();
+ try expect(v[0] == 3);
+ c_vector_1_f32(.{4}, 1);
+ c_test_vector_1_f32();
+}
+
+export fn zig_ret_vector_2_f32() @Vector(2, f32) {
+ return .{ 5, 6 };
+}
+export fn zig_vector_2_f32(v: @Vector(2, f32), i: usize) void {
+ expect(v[0] == 7) catch @panic("test failure");
+ expect(v[1] == 8) catch @panic("test failure");
+ expect(i == 2) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_2_f32() @Vector(2, f32);
+extern fn c_vector_2_f32(@Vector(2, f32), usize) void;
+extern fn c_test_vector_2_f32() void;
+
+test "@Vector(2, f32)" {
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest;
+
+ const v = c_ret_vector_2_f32();
+ try expect(v[0] == 9);
+ try expect(v[1] == 10);
+ c_vector_2_f32(.{ 11, 12 }, 2);
+ c_test_vector_2_f32();
+}
+
+export fn zig_ret_vector_3_f32() @Vector(3, f32) {
+ return .{ 13, 14, 15 };
+}
+export fn zig_vector_3_f32(v: @Vector(3, f32), i: usize) void {
+ expect(v[0] == 16) catch @panic("test failure");
+ expect(v[1] == 17) catch @panic("test failure");
+ expect(v[2] == 18) catch @panic("test failure");
+ expect(i == 3) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_3_f32() @Vector(3, f32);
+extern fn c_vector_3_f32(@Vector(3, f32), usize) void;
+extern fn c_test_vector_3_f32() void;
+
+test "@Vector(3, f32)" {
+ if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+
+ const v = c_ret_vector_3_f32();
+ try expect(v[0] == 19);
+ try expect(v[1] == 20);
+ try expect(v[2] == 21);
+ c_vector_3_f32(.{ 22, 23, 24 }, 32);
+ c_test_vector_3_f32();
+}
+
+export fn zig_ret_vector_4_f32() @Vector(4, f32) {
+ return .{ 25, 26, 27, 28 };
+}
+export fn zig_vector_4_f32(v: @Vector(4, f32), i: usize) void {
+ expect(v[0] == 29) catch @panic("test failure");
+ expect(v[1] == 30) catch @panic("test failure");
+ expect(v[2] == 31) catch @panic("test failure");
+ expect(v[3] == 32) catch @panic("test failure");
+ expect(i == 4) catch @panic("test failure");
+}
+export fn zig_vector_4_f32_vector_4_f32(v0: @Vector(4, f32), v1: @Vector(4, f32), i: usize) void {
+ expect(v0[0] == 33) catch @panic("test failure");
+ expect(v0[1] == 34) catch @panic("test failure");
+ expect(v0[2] == 35) catch @panic("test failure");
+ expect(v0[3] == 36) catch @panic("test failure");
+ expect(v1[0] == 37) catch @panic("test failure");
+ expect(v1[1] == 38) catch @panic("test failure");
+ expect(v1[2] == 39) catch @panic("test failure");
+ expect(v1[3] == 40) catch @panic("test failure");
+ expect(i == 8) catch @panic("test failure");
+}
+extern fn c_ret_vector_4_f32() @Vector(4, f32);
+
+extern fn c_vector_4_f32(@Vector(4, f32), usize) void;
+extern fn c_vector_4_f32_vector_4_f32(@Vector(4, f32), @Vector(4, f32), usize) void;
+extern fn c_test_vector_4_f32() void;
+
+test "@Vector(4, f32)" {
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+
+ const v = c_ret_vector_4_f32();
+ try expect(v[0] == 41);
+ try expect(v[1] == 42);
+ try expect(v[2] == 43);
+ try expect(v[3] == 44);
+ c_vector_4_f32(.{ 45, 46, 47, 48 }, 4);
+ c_vector_4_f32_vector_4_f32(.{ 49, 50, 51, 52 }, .{ 53, 54, 55, 56 }, 8);
+ c_test_vector_4_f32();
+}
+
+export fn zig_ret_vector_6_f32() @Vector(6, f32) {
+ return .{ 41, 42, 43, 44, 45, 46 };
+}
+export fn zig_vector_6_f32(v: @Vector(6, f32), i: usize) void {
+ expect(v[0] == 47) catch @panic("test failure");
+ expect(v[1] == 48) catch @panic("test failure");
+ expect(v[2] == 49) catch @panic("test failure");
+ expect(v[3] == 50) catch @panic("test failure");
+ expect(v[4] == 51) catch @panic("test failure");
+ expect(v[5] == 52) catch @panic("test failure");
+ expect(i == 6) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_6_f32() @Vector(6, f32);
+extern fn c_vector_6_f32(@Vector(6, f32), usize) void;
+extern fn c_test_vector_6_f32() void;
+
+test "@Vector(6, f32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_6_f32();
+ try expect(v[0] == 53);
+ try expect(v[1] == 54);
+ try expect(v[2] == 55);
+ try expect(v[3] == 56);
+ try expect(v[4] == 57);
+ try expect(v[5] == 58);
+ c_vector_6_f32(.{ 59, 60, 61, 62, 63, 64 }, 6);
+ c_test_vector_6_f32();
+}
+
+export fn zig_ret_vector_8_f32() @Vector(8, f32) {
+ return .{ 65, 66, 67, 68, 69, 70, 71, 72 };
+}
+export fn zig_vector_8_f32(v: @Vector(8, f32), i: usize) void {
+ expect(v[0] == 73) catch @panic("test failure");
+ expect(v[1] == 74) catch @panic("test failure");
+ expect(v[2] == 75) catch @panic("test failure");
+ expect(v[3] == 76) catch @panic("test failure");
+ expect(v[4] == 77) catch @panic("test failure");
+ expect(v[5] == 78) catch @panic("test failure");
+ expect(v[6] == 79) catch @panic("test failure");
+ expect(v[7] == 80) catch @panic("test failure");
+ expect(i == 8) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_8_f32() @Vector(8, f32);
+extern fn c_vector_8_f32(@Vector(8, f32), usize) void;
+extern fn c_test_vector_8_f32() void;
+
+test "@Vector(8, f32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_8_f32();
+ try expect(v[0] == 81);
+ try expect(v[1] == 82);
+ try expect(v[2] == 83);
+ try expect(v[3] == 84);
+ try expect(v[4] == 85);
+ try expect(v[5] == 86);
+ try expect(v[6] == 87);
+ try expect(v[7] == 88);
+ c_vector_8_f32(.{ 89, 90, 91, 92, 93, 94, 95, 96 }, 8);
+ c_test_vector_8_f32();
+}
+
+export fn zig_ret_vector_12_f32() @Vector(12, f32) {
+ return .{ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108 };
+}
+export fn zig_vector_12_f32(v: @Vector(12, f32), i: usize) void {
+ expect(v[0] == 109) catch @panic("test failure");
+ expect(v[1] == 110) catch @panic("test failure");
+ expect(v[2] == 111) catch @panic("test failure");
+ expect(v[3] == 112) catch @panic("test failure");
+ expect(v[4] == 113) catch @panic("test failure");
+ expect(v[5] == 114) catch @panic("test failure");
+ expect(v[6] == 115) catch @panic("test failure");
+ expect(v[7] == 116) catch @panic("test failure");
+ expect(v[8] == 117) catch @panic("test failure");
+ expect(v[9] == 118) catch @panic("test failure");
+ expect(v[10] == 119) catch @panic("test failure");
+ expect(v[11] == 120) catch @panic("test failure");
+ expect(i == 12) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_12_f32() @Vector(12, f32);
+extern fn c_vector_12_f32(@Vector(12, f32), usize) void;
+extern fn c_test_vector_12_f32() void;
+
+test "@Vector(12, f32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_12_f32();
+ try expect(v[0] == 121);
+ try expect(v[1] == 122);
+ try expect(v[2] == 123);
+ try expect(v[3] == 124);
+ try expect(v[4] == 125);
+ try expect(v[5] == 126);
+ try expect(v[6] == 127);
+ try expect(v[7] == 128);
+ try expect(v[8] == 129);
+ try expect(v[9] == 130);
+ try expect(v[10] == 131);
+ try expect(v[11] == 132);
+ c_vector_12_f32(.{ 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144 }, 12);
+ c_test_vector_12_f32();
+}
+
+export fn zig_ret_vector_16_f32() @Vector(16, f32) {
+ return .{ 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160 };
+}
+export fn zig_vector_16_f32(v: @Vector(16, f32), i: usize) void {
+ expect(v[0] == 161) catch @panic("test failure");
+ expect(v[1] == 162) catch @panic("test failure");
+ expect(v[2] == 163) catch @panic("test failure");
+ expect(v[3] == 164) catch @panic("test failure");
+ expect(v[4] == 165) catch @panic("test failure");
+ expect(v[5] == 166) catch @panic("test failure");
+ expect(v[6] == 167) catch @panic("test failure");
+ expect(v[7] == 168) catch @panic("test failure");
+ expect(v[8] == 169) catch @panic("test failure");
+ expect(v[9] == 170) catch @panic("test failure");
+ expect(v[10] == 171) catch @panic("test failure");
+ expect(v[11] == 172) catch @panic("test failure");
+ expect(v[12] == 173) catch @panic("test failure");
+ expect(v[13] == 174) catch @panic("test failure");
+ expect(v[14] == 175) catch @panic("test failure");
+ expect(v[15] == 176) catch @panic("test failure");
+ expect(i == 16) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_16_f32() @Vector(16, f32);
+extern fn c_vector_16_f32(@Vector(16, f32), usize) void;
+extern fn c_test_vector_16_f32() void;
+
+test "@Vector(16, f32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_16_f32();
+ try expect(v[0] == 177);
+ try expect(v[1] == 178);
+ try expect(v[2] == 179);
+ try expect(v[3] == 180);
+ try expect(v[4] == 181);
+ try expect(v[5] == 182);
+ try expect(v[6] == 183);
+ try expect(v[7] == 184);
+ try expect(v[8] == 185);
+ try expect(v[9] == 186);
+ try expect(v[10] == 187);
+ try expect(v[11] == 188);
+ try expect(v[12] == 189);
+ try expect(v[13] == 190);
+ try expect(v[14] == 191);
+ try expect(v[15] == 192);
+ c_vector_16_f32(.{ 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208 }, 16);
+ c_test_vector_16_f32();
+}
+
+export fn zig_ret_vector_24_f32() @Vector(24, f32) {
+ return .{
+ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
+ 225, 226, 227, 228, 229, 230, 231, 232,
+ };
+}
+export fn zig_vector_24_f32(v: @Vector(24, f32), i: usize) void {
+ expect(v[0] == 233) catch @panic("test failure");
+ expect(v[1] == 234) catch @panic("test failure");
+ expect(v[2] == 235) catch @panic("test failure");
+ expect(v[3] == 236) catch @panic("test failure");
+ expect(v[4] == 237) catch @panic("test failure");
+ expect(v[5] == 238) catch @panic("test failure");
+ expect(v[6] == 239) catch @panic("test failure");
+ expect(v[7] == 240) catch @panic("test failure");
+ expect(v[8] == 241) catch @panic("test failure");
+ expect(v[9] == 242) catch @panic("test failure");
+ expect(v[10] == 243) catch @panic("test failure");
+ expect(v[11] == 244) catch @panic("test failure");
+ expect(v[12] == 245) catch @panic("test failure");
+ expect(v[13] == 246) catch @panic("test failure");
+ expect(v[14] == 247) catch @panic("test failure");
+ expect(v[15] == 248) catch @panic("test failure");
+ expect(v[16] == 249) catch @panic("test failure");
+ expect(v[17] == 250) catch @panic("test failure");
+ expect(v[18] == 251) catch @panic("test failure");
+ expect(v[19] == 252) catch @panic("test failure");
+ expect(v[20] == 253) catch @panic("test failure");
+ expect(v[21] == 254) catch @panic("test failure");
+ expect(v[22] == 255) catch @panic("test failure");
+ expect(v[23] == 256) catch @panic("test failure");
+ expect(i == 24) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_24_f32() @Vector(24, f32);
+extern fn c_vector_24_f32(@Vector(24, f32), usize) void;
+extern fn c_test_vector_24_f32() void;
+
+test "@Vector(24, f32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_24_f32();
+ try expect(v[0] == 257);
+ try expect(v[1] == 258);
+ try expect(v[2] == 259);
+ try expect(v[3] == 260);
+ try expect(v[4] == 261);
+ try expect(v[5] == 262);
+ try expect(v[6] == 263);
+ try expect(v[7] == 264);
+ try expect(v[8] == 265);
+ try expect(v[9] == 266);
+ try expect(v[10] == 267);
+ try expect(v[11] == 268);
+ try expect(v[12] == 269);
+ try expect(v[13] == 270);
+ try expect(v[14] == 271);
+ try expect(v[15] == 272);
+ try expect(v[16] == 273);
+ try expect(v[17] == 274);
+ try expect(v[18] == 275);
+ try expect(v[19] == 276);
+ try expect(v[20] == 277);
+ try expect(v[21] == 278);
+ try expect(v[22] == 279);
+ try expect(v[23] == 280);
+ c_vector_24_f32(.{
+ 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296,
+ 297, 298, 299, 300, 301, 302, 303, 304,
+ }, 24);
+ c_test_vector_24_f32();
+}
+
+export fn zig_ret_vector_32_f32() @Vector(32, f32) {
+ return .{
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320,
+ 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
+ };
+}
+export fn zig_vector_32_f32(v: @Vector(32, f32), i: usize) void {
+ expect(v[0] == 337) catch @panic("test failure");
+ expect(v[1] == 338) catch @panic("test failure");
+ expect(v[2] == 339) catch @panic("test failure");
+ expect(v[3] == 340) catch @panic("test failure");
+ expect(v[4] == 341) catch @panic("test failure");
+ expect(v[5] == 342) catch @panic("test failure");
+ expect(v[6] == 343) catch @panic("test failure");
+ expect(v[7] == 344) catch @panic("test failure");
+ expect(v[8] == 345) catch @panic("test failure");
+ expect(v[9] == 346) catch @panic("test failure");
+ expect(v[10] == 347) catch @panic("test failure");
+ expect(v[11] == 348) catch @panic("test failure");
+ expect(v[12] == 349) catch @panic("test failure");
+ expect(v[13] == 350) catch @panic("test failure");
+ expect(v[14] == 351) catch @panic("test failure");
+ expect(v[15] == 352) catch @panic("test failure");
+ expect(v[16] == 353) catch @panic("test failure");
+ expect(v[17] == 354) catch @panic("test failure");
+ expect(v[18] == 355) catch @panic("test failure");
+ expect(v[19] == 356) catch @panic("test failure");
+ expect(v[20] == 357) catch @panic("test failure");
+ expect(v[21] == 358) catch @panic("test failure");
+ expect(v[22] == 359) catch @panic("test failure");
+ expect(v[23] == 360) catch @panic("test failure");
+ expect(v[24] == 361) catch @panic("test failure");
+ expect(v[25] == 362) catch @panic("test failure");
+ expect(v[26] == 363) catch @panic("test failure");
+ expect(v[27] == 364) catch @panic("test failure");
+ expect(v[28] == 365) catch @panic("test failure");
+ expect(v[29] == 366) catch @panic("test failure");
+ expect(v[30] == 367) catch @panic("test failure");
+ expect(v[31] == 368) catch @panic("test failure");
+ expect(i == 32) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_32_f32() @Vector(32, f32);
+extern fn c_vector_32_f32(@Vector(32, f32), usize) void;
+extern fn c_test_vector_32_f32() void;
+
+test "@Vector(32, f32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_32_f32();
+ try expect(v[0] == 369);
+ try expect(v[1] == 370);
+ try expect(v[2] == 371);
+ try expect(v[3] == 372);
+ try expect(v[4] == 373);
+ try expect(v[5] == 374);
+ try expect(v[6] == 375);
+ try expect(v[7] == 376);
+ try expect(v[8] == 377);
+ try expect(v[9] == 378);
+ try expect(v[10] == 379);
+ try expect(v[11] == 380);
+ try expect(v[12] == 381);
+ try expect(v[13] == 382);
+ try expect(v[14] == 383);
+ try expect(v[15] == 384);
+ try expect(v[16] == 385);
+ try expect(v[17] == 386);
+ try expect(v[18] == 387);
+ try expect(v[19] == 388);
+ try expect(v[20] == 389);
+ try expect(v[21] == 390);
+ try expect(v[22] == 391);
+ try expect(v[23] == 392);
+ try expect(v[24] == 393);
+ try expect(v[25] == 394);
+ try expect(v[26] == 395);
+ try expect(v[27] == 396);
+ try expect(v[28] == 397);
+ try expect(v[29] == 398);
+ try expect(v[30] == 399);
+ try expect(v[31] == 400);
+ c_vector_32_f32(.{
+ 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416,
+ 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432,
+ }, 32);
+ c_test_vector_32_f32();
+}
+
+export fn zig_ret_vector_48_f32() @Vector(48, f32) {
+ return .{
+ 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448,
+ 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464,
+ 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480,
+ };
+}
+export fn zig_vector_48_f32(v: @Vector(48, f32), i: usize) void {
+ expect(v[0] == 481) catch @panic("test failure");
+ expect(v[1] == 482) catch @panic("test failure");
+ expect(v[2] == 483) catch @panic("test failure");
+ expect(v[3] == 484) catch @panic("test failure");
+ expect(v[4] == 485) catch @panic("test failure");
+ expect(v[5] == 486) catch @panic("test failure");
+ expect(v[6] == 487) catch @panic("test failure");
+ expect(v[7] == 488) catch @panic("test failure");
+ expect(v[8] == 489) catch @panic("test failure");
+ expect(v[9] == 490) catch @panic("test failure");
+ expect(v[10] == 491) catch @panic("test failure");
+ expect(v[11] == 492) catch @panic("test failure");
+ expect(v[12] == 493) catch @panic("test failure");
+ expect(v[13] == 494) catch @panic("test failure");
+ expect(v[14] == 495) catch @panic("test failure");
+ expect(v[15] == 496) catch @panic("test failure");
+ expect(v[16] == 497) catch @panic("test failure");
+ expect(v[17] == 498) catch @panic("test failure");
+ expect(v[18] == 499) catch @panic("test failure");
+ expect(v[19] == 500) catch @panic("test failure");
+ expect(v[20] == 501) catch @panic("test failure");
+ expect(v[21] == 502) catch @panic("test failure");
+ expect(v[22] == 503) catch @panic("test failure");
+ expect(v[23] == 504) catch @panic("test failure");
+ expect(v[24] == 505) catch @panic("test failure");
+ expect(v[25] == 506) catch @panic("test failure");
+ expect(v[26] == 507) catch @panic("test failure");
+ expect(v[27] == 508) catch @panic("test failure");
+ expect(v[28] == 509) catch @panic("test failure");
+ expect(v[29] == 510) catch @panic("test failure");
+ expect(v[30] == 511) catch @panic("test failure");
+ expect(v[31] == 512) catch @panic("test failure");
+ expect(v[32] == 513) catch @panic("test failure");
+ expect(v[33] == 514) catch @panic("test failure");
+ expect(v[34] == 515) catch @panic("test failure");
+ expect(v[35] == 516) catch @panic("test failure");
+ expect(v[36] == 517) catch @panic("test failure");
+ expect(v[37] == 518) catch @panic("test failure");
+ expect(v[38] == 519) catch @panic("test failure");
+ expect(v[39] == 520) catch @panic("test failure");
+ expect(v[40] == 521) catch @panic("test failure");
+ expect(v[41] == 522) catch @panic("test failure");
+ expect(v[42] == 523) catch @panic("test failure");
+ expect(v[43] == 524) catch @panic("test failure");
+ expect(v[44] == 525) catch @panic("test failure");
+ expect(v[45] == 526) catch @panic("test failure");
+ expect(v[46] == 527) catch @panic("test failure");
+ expect(v[47] == 528) catch @panic("test failure");
+ expect(i == 48) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_48_f32() @Vector(48, f32);
+extern fn c_vector_48_f32(@Vector(48, f32), usize) void;
+extern fn c_test_vector_48_f32() void;
+
+test "@Vector(48, f32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_48_f32();
+ try expect(v[0] == 529);
+ try expect(v[1] == 530);
+ try expect(v[2] == 531);
+ try expect(v[3] == 532);
+ try expect(v[4] == 533);
+ try expect(v[5] == 534);
+ try expect(v[6] == 535);
+ try expect(v[7] == 536);
+ try expect(v[8] == 537);
+ try expect(v[9] == 538);
+ try expect(v[10] == 539);
+ try expect(v[11] == 540);
+ try expect(v[12] == 541);
+ try expect(v[13] == 542);
+ try expect(v[14] == 543);
+ try expect(v[15] == 544);
+ try expect(v[16] == 545);
+ try expect(v[17] == 546);
+ try expect(v[18] == 547);
+ try expect(v[19] == 548);
+ try expect(v[20] == 549);
+ try expect(v[21] == 550);
+ try expect(v[22] == 551);
+ try expect(v[23] == 552);
+ try expect(v[24] == 553);
+ try expect(v[25] == 554);
+ try expect(v[26] == 555);
+ try expect(v[27] == 556);
+ try expect(v[28] == 557);
+ try expect(v[29] == 558);
+ try expect(v[30] == 559);
+ try expect(v[31] == 560);
+ try expect(v[32] == 561);
+ try expect(v[33] == 562);
+ try expect(v[34] == 563);
+ try expect(v[35] == 564);
+ try expect(v[36] == 565);
+ try expect(v[37] == 566);
+ try expect(v[38] == 567);
+ try expect(v[39] == 568);
+ try expect(v[40] == 569);
+ try expect(v[41] == 570);
+ try expect(v[42] == 571);
+ try expect(v[43] == 572);
+ try expect(v[44] == 573);
+ try expect(v[45] == 574);
+ try expect(v[46] == 575);
+ try expect(v[47] == 576);
+ c_vector_48_f32(.{
+ 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592,
+ 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608,
+ 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624,
+ }, 48);
+ c_test_vector_48_f32();
+}
+
+export fn zig_ret_vector_64_f32() @Vector(64, f32) {
+ return .{
+ 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640,
+ 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656,
+ 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672,
+ 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688,
+ };
+}
+export fn zig_vector_64_f32(v: @Vector(64, f32), i: usize) void {
+ expect(v[0] == 689) catch @panic("test failure");
+ expect(v[1] == 690) catch @panic("test failure");
+ expect(v[2] == 691) catch @panic("test failure");
+ expect(v[3] == 692) catch @panic("test failure");
+ expect(v[4] == 693) catch @panic("test failure");
+ expect(v[5] == 694) catch @panic("test failure");
+ expect(v[6] == 695) catch @panic("test failure");
+ expect(v[7] == 696) catch @panic("test failure");
+ expect(v[8] == 697) catch @panic("test failure");
+ expect(v[9] == 698) catch @panic("test failure");
+ expect(v[10] == 699) catch @panic("test failure");
+ expect(v[11] == 700) catch @panic("test failure");
+ expect(v[12] == 701) catch @panic("test failure");
+ expect(v[13] == 702) catch @panic("test failure");
+ expect(v[14] == 703) catch @panic("test failure");
+ expect(v[15] == 704) catch @panic("test failure");
+ expect(v[16] == 705) catch @panic("test failure");
+ expect(v[17] == 706) catch @panic("test failure");
+ expect(v[18] == 707) catch @panic("test failure");
+ expect(v[19] == 708) catch @panic("test failure");
+ expect(v[20] == 709) catch @panic("test failure");
+ expect(v[21] == 710) catch @panic("test failure");
+ expect(v[22] == 711) catch @panic("test failure");
+ expect(v[23] == 712) catch @panic("test failure");
+ expect(v[24] == 713) catch @panic("test failure");
+ expect(v[25] == 714) catch @panic("test failure");
+ expect(v[26] == 715) catch @panic("test failure");
+ expect(v[27] == 716) catch @panic("test failure");
+ expect(v[28] == 717) catch @panic("test failure");
+ expect(v[29] == 718) catch @panic("test failure");
+ expect(v[30] == 719) catch @panic("test failure");
+ expect(v[31] == 720) catch @panic("test failure");
+ expect(v[32] == 721) catch @panic("test failure");
+ expect(v[33] == 722) catch @panic("test failure");
+ expect(v[34] == 723) catch @panic("test failure");
+ expect(v[35] == 724) catch @panic("test failure");
+ expect(v[36] == 725) catch @panic("test failure");
+ expect(v[37] == 726) catch @panic("test failure");
+ expect(v[38] == 727) catch @panic("test failure");
+ expect(v[39] == 728) catch @panic("test failure");
+ expect(v[40] == 729) catch @panic("test failure");
+ expect(v[41] == 730) catch @panic("test failure");
+ expect(v[42] == 731) catch @panic("test failure");
+ expect(v[43] == 732) catch @panic("test failure");
+ expect(v[44] == 733) catch @panic("test failure");
+ expect(v[45] == 734) catch @panic("test failure");
+ expect(v[46] == 735) catch @panic("test failure");
+ expect(v[47] == 736) catch @panic("test failure");
+ expect(v[48] == 737) catch @panic("test failure");
+ expect(v[49] == 738) catch @panic("test failure");
+ expect(v[50] == 739) catch @panic("test failure");
+ expect(v[51] == 740) catch @panic("test failure");
+ expect(v[52] == 741) catch @panic("test failure");
+ expect(v[53] == 742) catch @panic("test failure");
+ expect(v[54] == 743) catch @panic("test failure");
+ expect(v[55] == 744) catch @panic("test failure");
+ expect(v[56] == 745) catch @panic("test failure");
+ expect(v[57] == 746) catch @panic("test failure");
+ expect(v[58] == 747) catch @panic("test failure");
+ expect(v[59] == 748) catch @panic("test failure");
+ expect(v[60] == 749) catch @panic("test failure");
+ expect(v[61] == 750) catch @panic("test failure");
+ expect(v[62] == 751) catch @panic("test failure");
+ expect(v[63] == 752) catch @panic("test failure");
+ expect(i == 64) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_64_f32() @Vector(64, f32);
+extern fn c_vector_64_f32(@Vector(64, f32), usize) void;
+extern fn c_test_vector_64_f32() void;
+
+test "@Vector(64, f32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_64_f32();
+ try expect(v[0] == 753);
+ try expect(v[1] == 754);
+ try expect(v[2] == 755);
+ try expect(v[3] == 756);
+ try expect(v[4] == 757);
+ try expect(v[5] == 758);
+ try expect(v[6] == 759);
+ try expect(v[7] == 760);
+ try expect(v[8] == 761);
+ try expect(v[9] == 762);
+ try expect(v[10] == 763);
+ try expect(v[11] == 764);
+ try expect(v[12] == 765);
+ try expect(v[13] == 766);
+ try expect(v[14] == 767);
+ try expect(v[15] == 768);
+ try expect(v[16] == 769);
+ try expect(v[17] == 770);
+ try expect(v[18] == 771);
+ try expect(v[19] == 772);
+ try expect(v[20] == 773);
+ try expect(v[21] == 774);
+ try expect(v[22] == 775);
+ try expect(v[23] == 776);
+ try expect(v[24] == 777);
+ try expect(v[25] == 778);
+ try expect(v[26] == 779);
+ try expect(v[27] == 780);
+ try expect(v[28] == 781);
+ try expect(v[29] == 782);
+ try expect(v[30] == 783);
+ try expect(v[31] == 784);
+ try expect(v[32] == 785);
+ try expect(v[33] == 786);
+ try expect(v[34] == 787);
+ try expect(v[35] == 788);
+ try expect(v[36] == 789);
+ try expect(v[37] == 790);
+ try expect(v[38] == 791);
+ try expect(v[39] == 792);
+ try expect(v[40] == 793);
+ try expect(v[41] == 794);
+ try expect(v[42] == 795);
+ try expect(v[43] == 796);
+ try expect(v[44] == 797);
+ try expect(v[45] == 798);
+ try expect(v[46] == 799);
+ try expect(v[47] == 800);
+ try expect(v[48] == 801);
+ try expect(v[49] == 802);
+ try expect(v[50] == 803);
+ try expect(v[51] == 804);
+ try expect(v[52] == 805);
+ try expect(v[53] == 806);
+ try expect(v[54] == 807);
+ try expect(v[55] == 808);
+ try expect(v[56] == 809);
+ try expect(v[57] == 810);
+ try expect(v[58] == 811);
+ try expect(v[59] == 812);
+ try expect(v[60] == 813);
+ try expect(v[61] == 814);
+ try expect(v[62] == 815);
+ try expect(v[63] == 816);
+ c_vector_64_f32(.{
+ 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832,
+ 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848,
+ 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864,
+ 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880,
+ }, 64);
+ c_test_vector_64_f32();
+}
+
+export fn zig_ret_vector_96_f32() @Vector(96, f32) {
+ return .{
+ 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905,
+ 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921,
+ 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937,
+ 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953,
+ 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969,
+ 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985,
+ };
+}
+export fn zig_vector_96_f32(v: @Vector(96, f32), i: usize) void {
+ expect(v[0] == 986) catch @panic("test failure");
+ expect(v[1] == 987) catch @panic("test failure");
+ expect(v[2] == 988) catch @panic("test failure");
+ expect(v[3] == 989) catch @panic("test failure");
+ expect(v[4] == 990) catch @panic("test failure");
+ expect(v[5] == 991) catch @panic("test failure");
+ expect(v[6] == 992) catch @panic("test failure");
+ expect(v[7] == 993) catch @panic("test failure");
+ expect(v[8] == 994) catch @panic("test failure");
+ expect(v[9] == 995) catch @panic("test failure");
+ expect(v[10] == 996) catch @panic("test failure");
+ expect(v[11] == 997) catch @panic("test failure");
+ expect(v[12] == 998) catch @panic("test failure");
+ expect(v[13] == 999) catch @panic("test failure");
+ expect(v[14] == 1000) catch @panic("test failure");
+ expect(v[15] == 1001) catch @panic("test failure");
+ expect(v[16] == 1002) catch @panic("test failure");
+ expect(v[17] == 1003) catch @panic("test failure");
+ expect(v[18] == 1004) catch @panic("test failure");
+ expect(v[19] == 1005) catch @panic("test failure");
+ expect(v[20] == 1006) catch @panic("test failure");
+ expect(v[21] == 1007) catch @panic("test failure");
+ expect(v[22] == 1008) catch @panic("test failure");
+ expect(v[23] == 1009) catch @panic("test failure");
+ expect(v[24] == 1010) catch @panic("test failure");
+ expect(v[25] == 1011) catch @panic("test failure");
+ expect(v[26] == 1012) catch @panic("test failure");
+ expect(v[27] == 1013) catch @panic("test failure");
+ expect(v[28] == 1014) catch @panic("test failure");
+ expect(v[29] == 1015) catch @panic("test failure");
+ expect(v[30] == 1016) catch @panic("test failure");
+ expect(v[31] == 1017) catch @panic("test failure");
+ expect(v[32] == 1018) catch @panic("test failure");
+ expect(v[33] == 1019) catch @panic("test failure");
+ expect(v[34] == 1020) catch @panic("test failure");
+ expect(v[35] == 1021) catch @panic("test failure");
+ expect(v[36] == 1022) catch @panic("test failure");
+ expect(v[37] == 1023) catch @panic("test failure");
+ expect(v[38] == 1024) catch @panic("test failure");
+ expect(v[39] == 1025) catch @panic("test failure");
+ expect(v[40] == 1026) catch @panic("test failure");
+ expect(v[41] == 1027) catch @panic("test failure");
+ expect(v[42] == 1028) catch @panic("test failure");
+ expect(v[43] == 1029) catch @panic("test failure");
+ expect(v[44] == 1030) catch @panic("test failure");
+ expect(v[45] == 1031) catch @panic("test failure");
+ expect(v[46] == 1032) catch @panic("test failure");
+ expect(v[47] == 1033) catch @panic("test failure");
+ expect(v[48] == 1034) catch @panic("test failure");
+ expect(v[49] == 1035) catch @panic("test failure");
+ expect(v[50] == 1036) catch @panic("test failure");
+ expect(v[51] == 1037) catch @panic("test failure");
+ expect(v[52] == 1038) catch @panic("test failure");
+ expect(v[53] == 1039) catch @panic("test failure");
+ expect(v[54] == 1040) catch @panic("test failure");
+ expect(v[55] == 1041) catch @panic("test failure");
+ expect(v[56] == 1042) catch @panic("test failure");
+ expect(v[57] == 1043) catch @panic("test failure");
+ expect(v[58] == 1044) catch @panic("test failure");
+ expect(v[59] == 1045) catch @panic("test failure");
+ expect(v[60] == 1046) catch @panic("test failure");
+ expect(v[61] == 1047) catch @panic("test failure");
+ expect(v[62] == 1048) catch @panic("test failure");
+ expect(v[63] == 1049) catch @panic("test failure");
+ expect(v[64] == 1050) catch @panic("test failure");
+ expect(v[65] == 1051) catch @panic("test failure");
+ expect(v[66] == 1052) catch @panic("test failure");
+ expect(v[67] == 1053) catch @panic("test failure");
+ expect(v[68] == 1054) catch @panic("test failure");
+ expect(v[69] == 1055) catch @panic("test failure");
+ expect(v[70] == 1056) catch @panic("test failure");
+ expect(v[71] == 1057) catch @panic("test failure");
+ expect(v[72] == 1058) catch @panic("test failure");
+ expect(v[73] == 1059) catch @panic("test failure");
+ expect(v[74] == 1060) catch @panic("test failure");
+ expect(v[75] == 1061) catch @panic("test failure");
+ expect(v[76] == 1062) catch @panic("test failure");
+ expect(v[77] == 1063) catch @panic("test failure");
+ expect(v[78] == 1064) catch @panic("test failure");
+ expect(v[79] == 1065) catch @panic("test failure");
+ expect(v[80] == 1066) catch @panic("test failure");
+ expect(v[81] == 1067) catch @panic("test failure");
+ expect(v[82] == 1068) catch @panic("test failure");
+ expect(v[83] == 1069) catch @panic("test failure");
+ expect(v[84] == 1070) catch @panic("test failure");
+ expect(v[85] == 1071) catch @panic("test failure");
+ expect(v[86] == 1072) catch @panic("test failure");
+ expect(v[87] == 1073) catch @panic("test failure");
+ expect(v[88] == 1074) catch @panic("test failure");
+ expect(v[89] == 1075) catch @panic("test failure");
+ expect(v[90] == 1076) catch @panic("test failure");
+ expect(v[91] == 1077) catch @panic("test failure");
+ expect(v[92] == 1078) catch @panic("test failure");
+ expect(v[93] == 1079) catch @panic("test failure");
+ expect(v[94] == 1080) catch @panic("test failure");
+ expect(v[95] == 1081) catch @panic("test failure");
+ expect(i == 96) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_96_f32() @Vector(96, f32);
+extern fn c_vector_96_f32(@Vector(96, f32), usize) void;
+extern fn c_test_vector_96_f32() void;
+
+test "@Vector(96, f32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_96_f32();
+ try expect(v[0] == 1082);
+ try expect(v[1] == 1083);
+ try expect(v[2] == 1084);
+ try expect(v[3] == 1085);
+ try expect(v[4] == 1086);
+ try expect(v[5] == 1087);
+ try expect(v[6] == 1088);
+ try expect(v[7] == 1089);
+ try expect(v[8] == 1090);
+ try expect(v[9] == 1091);
+ try expect(v[10] == 1092);
+ try expect(v[11] == 1093);
+ try expect(v[12] == 1094);
+ try expect(v[13] == 1095);
+ try expect(v[14] == 1096);
+ try expect(v[15] == 1097);
+ try expect(v[16] == 1098);
+ try expect(v[17] == 1099);
+ try expect(v[18] == 1100);
+ try expect(v[19] == 1101);
+ try expect(v[20] == 1102);
+ try expect(v[21] == 1103);
+ try expect(v[22] == 1104);
+ try expect(v[23] == 1105);
+ try expect(v[24] == 1106);
+ try expect(v[25] == 1107);
+ try expect(v[26] == 1108);
+ try expect(v[27] == 1109);
+ try expect(v[28] == 1110);
+ try expect(v[29] == 1111);
+ try expect(v[30] == 1112);
+ try expect(v[31] == 1113);
+ try expect(v[32] == 1114);
+ try expect(v[33] == 1115);
+ try expect(v[34] == 1116);
+ try expect(v[35] == 1117);
+ try expect(v[36] == 1118);
+ try expect(v[37] == 1119);
+ try expect(v[38] == 1120);
+ try expect(v[39] == 1121);
+ try expect(v[40] == 1122);
+ try expect(v[41] == 1123);
+ try expect(v[42] == 1124);
+ try expect(v[43] == 1125);
+ try expect(v[44] == 1126);
+ try expect(v[45] == 1127);
+ try expect(v[46] == 1128);
+ try expect(v[47] == 1129);
+ try expect(v[48] == 1130);
+ try expect(v[49] == 1131);
+ try expect(v[50] == 1132);
+ try expect(v[51] == 1133);
+ try expect(v[52] == 1134);
+ try expect(v[53] == 1135);
+ try expect(v[54] == 1136);
+ try expect(v[55] == 1137);
+ try expect(v[56] == 1138);
+ try expect(v[57] == 1139);
+ try expect(v[58] == 1140);
+ try expect(v[59] == 1141);
+ try expect(v[60] == 1142);
+ try expect(v[61] == 1143);
+ try expect(v[62] == 1144);
+ try expect(v[63] == 1145);
+ try expect(v[64] == 1146);
+ try expect(v[65] == 1147);
+ try expect(v[66] == 1148);
+ try expect(v[67] == 1149);
+ try expect(v[68] == 1150);
+ try expect(v[69] == 1151);
+ try expect(v[70] == 1152);
+ try expect(v[71] == 1153);
+ try expect(v[72] == 1154);
+ try expect(v[73] == 1155);
+ try expect(v[74] == 1156);
+ try expect(v[75] == 1157);
+ try expect(v[76] == 1158);
+ try expect(v[77] == 1159);
+ try expect(v[78] == 1160);
+ try expect(v[79] == 1161);
+ try expect(v[80] == 1162);
+ try expect(v[81] == 1163);
+ try expect(v[82] == 1164);
+ try expect(v[83] == 1165);
+ try expect(v[84] == 1166);
+ try expect(v[85] == 1167);
+ try expect(v[86] == 1168);
+ try expect(v[87] == 1169);
+ try expect(v[88] == 1170);
+ try expect(v[89] == 1171);
+ try expect(v[90] == 1172);
+ try expect(v[91] == 1173);
+ try expect(v[92] == 1174);
+ try expect(v[93] == 1175);
+ try expect(v[94] == 1176);
+ try expect(v[95] == 1177);
+ c_vector_96_f32(.{
+ 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193,
+ 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209,
+ 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1225,
+ 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241,
+ 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257,
+ 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273,
+ }, 96);
+ c_test_vector_96_f32();
+}
+
+export fn zig_ret_vector_128_f32() @Vector(128, f32) {
+ return .{
+ 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289,
+ 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305,
+ 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321,
+ 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337,
+ 1338, 1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353,
+ 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369,
+ 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385,
+ 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401,
+ };
+}
+export fn zig_vector_128_f32(v: @Vector(128, f32), i: usize) void {
+ expect(v[0] == 1402) catch @panic("test failure");
+ expect(v[1] == 1403) catch @panic("test failure");
+ expect(v[2] == 1404) catch @panic("test failure");
+ expect(v[3] == 1405) catch @panic("test failure");
+ expect(v[4] == 1406) catch @panic("test failure");
+ expect(v[5] == 1407) catch @panic("test failure");
+ expect(v[6] == 1408) catch @panic("test failure");
+ expect(v[7] == 1409) catch @panic("test failure");
+ expect(v[8] == 1410) catch @panic("test failure");
+ expect(v[9] == 1411) catch @panic("test failure");
+ expect(v[10] == 1412) catch @panic("test failure");
+ expect(v[11] == 1413) catch @panic("test failure");
+ expect(v[12] == 1414) catch @panic("test failure");
+ expect(v[13] == 1415) catch @panic("test failure");
+ expect(v[14] == 1416) catch @panic("test failure");
+ expect(v[15] == 1417) catch @panic("test failure");
+ expect(v[16] == 1418) catch @panic("test failure");
+ expect(v[17] == 1419) catch @panic("test failure");
+ expect(v[18] == 1420) catch @panic("test failure");
+ expect(v[19] == 1421) catch @panic("test failure");
+ expect(v[20] == 1422) catch @panic("test failure");
+ expect(v[21] == 1423) catch @panic("test failure");
+ expect(v[22] == 1424) catch @panic("test failure");
+ expect(v[23] == 1425) catch @panic("test failure");
+ expect(v[24] == 1426) catch @panic("test failure");
+ expect(v[25] == 1427) catch @panic("test failure");
+ expect(v[26] == 1428) catch @panic("test failure");
+ expect(v[27] == 1429) catch @panic("test failure");
+ expect(v[28] == 1430) catch @panic("test failure");
+ expect(v[29] == 1431) catch @panic("test failure");
+ expect(v[30] == 1432) catch @panic("test failure");
+ expect(v[31] == 1433) catch @panic("test failure");
+ expect(v[32] == 1434) catch @panic("test failure");
+ expect(v[33] == 1435) catch @panic("test failure");
+ expect(v[34] == 1436) catch @panic("test failure");
+ expect(v[35] == 1437) catch @panic("test failure");
+ expect(v[36] == 1438) catch @panic("test failure");
+ expect(v[37] == 1439) catch @panic("test failure");
+ expect(v[38] == 1440) catch @panic("test failure");
+ expect(v[39] == 1441) catch @panic("test failure");
+ expect(v[40] == 1442) catch @panic("test failure");
+ expect(v[41] == 1443) catch @panic("test failure");
+ expect(v[42] == 1444) catch @panic("test failure");
+ expect(v[43] == 1445) catch @panic("test failure");
+ expect(v[44] == 1446) catch @panic("test failure");
+ expect(v[45] == 1447) catch @panic("test failure");
+ expect(v[46] == 1448) catch @panic("test failure");
+ expect(v[47] == 1449) catch @panic("test failure");
+ expect(v[48] == 1450) catch @panic("test failure");
+ expect(v[49] == 1451) catch @panic("test failure");
+ expect(v[50] == 1452) catch @panic("test failure");
+ expect(v[51] == 1453) catch @panic("test failure");
+ expect(v[52] == 1454) catch @panic("test failure");
+ expect(v[53] == 1455) catch @panic("test failure");
+ expect(v[54] == 1456) catch @panic("test failure");
+ expect(v[55] == 1457) catch @panic("test failure");
+ expect(v[56] == 1458) catch @panic("test failure");
+ expect(v[57] == 1459) catch @panic("test failure");
+ expect(v[58] == 1460) catch @panic("test failure");
+ expect(v[59] == 1461) catch @panic("test failure");
+ expect(v[60] == 1462) catch @panic("test failure");
+ expect(v[61] == 1463) catch @panic("test failure");
+ expect(v[62] == 1464) catch @panic("test failure");
+ expect(v[63] == 1465) catch @panic("test failure");
+ expect(v[64] == 1466) catch @panic("test failure");
+ expect(v[65] == 1467) catch @panic("test failure");
+ expect(v[66] == 1468) catch @panic("test failure");
+ expect(v[67] == 1469) catch @panic("test failure");
+ expect(v[68] == 1470) catch @panic("test failure");
+ expect(v[69] == 1471) catch @panic("test failure");
+ expect(v[70] == 1472) catch @panic("test failure");
+ expect(v[71] == 1473) catch @panic("test failure");
+ expect(v[72] == 1474) catch @panic("test failure");
+ expect(v[73] == 1475) catch @panic("test failure");
+ expect(v[74] == 1476) catch @panic("test failure");
+ expect(v[75] == 1477) catch @panic("test failure");
+ expect(v[76] == 1478) catch @panic("test failure");
+ expect(v[77] == 1479) catch @panic("test failure");
+ expect(v[78] == 1480) catch @panic("test failure");
+ expect(v[79] == 1481) catch @panic("test failure");
+ expect(v[80] == 1482) catch @panic("test failure");
+ expect(v[81] == 1483) catch @panic("test failure");
+ expect(v[82] == 1484) catch @panic("test failure");
+ expect(v[83] == 1485) catch @panic("test failure");
+ expect(v[84] == 1486) catch @panic("test failure");
+ expect(v[85] == 1487) catch @panic("test failure");
+ expect(v[86] == 1488) catch @panic("test failure");
+ expect(v[87] == 1489) catch @panic("test failure");
+ expect(v[88] == 1490) catch @panic("test failure");
+ expect(v[89] == 1491) catch @panic("test failure");
+ expect(v[90] == 1492) catch @panic("test failure");
+ expect(v[91] == 1493) catch @panic("test failure");
+ expect(v[92] == 1494) catch @panic("test failure");
+ expect(v[93] == 1495) catch @panic("test failure");
+ expect(v[94] == 1496) catch @panic("test failure");
+ expect(v[95] == 1497) catch @panic("test failure");
+ expect(v[96] == 1498) catch @panic("test failure");
+ expect(v[97] == 1499) catch @panic("test failure");
+ expect(v[98] == 1500) catch @panic("test failure");
+ expect(v[99] == 1501) catch @panic("test failure");
+ expect(v[100] == 1502) catch @panic("test failure");
+ expect(v[101] == 1503) catch @panic("test failure");
+ expect(v[102] == 1504) catch @panic("test failure");
+ expect(v[103] == 1505) catch @panic("test failure");
+ expect(v[104] == 1506) catch @panic("test failure");
+ expect(v[105] == 1507) catch @panic("test failure");
+ expect(v[106] == 1508) catch @panic("test failure");
+ expect(v[107] == 1509) catch @panic("test failure");
+ expect(v[108] == 1510) catch @panic("test failure");
+ expect(v[109] == 1511) catch @panic("test failure");
+ expect(v[110] == 1512) catch @panic("test failure");
+ expect(v[111] == 1513) catch @panic("test failure");
+ expect(v[112] == 1514) catch @panic("test failure");
+ expect(v[113] == 1515) catch @panic("test failure");
+ expect(v[114] == 1516) catch @panic("test failure");
+ expect(v[115] == 1517) catch @panic("test failure");
+ expect(v[116] == 1518) catch @panic("test failure");
+ expect(v[117] == 1519) catch @panic("test failure");
+ expect(v[118] == 1520) catch @panic("test failure");
+ expect(v[119] == 1521) catch @panic("test failure");
+ expect(v[120] == 1522) catch @panic("test failure");
+ expect(v[121] == 1523) catch @panic("test failure");
+ expect(v[122] == 1524) catch @panic("test failure");
+ expect(v[123] == 1525) catch @panic("test failure");
+ expect(v[124] == 1526) catch @panic("test failure");
+ expect(v[125] == 1527) catch @panic("test failure");
+ expect(v[126] == 1528) catch @panic("test failure");
+ expect(v[127] == 1529) catch @panic("test failure");
+ expect(i == 128) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_128_f32() @Vector(128, f32);
+extern fn c_vector_128_f32(@Vector(128, f32), usize) void;
+extern fn c_test_vector_128_f32() void;
+
+test "@Vector(128, f32)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_128_f32();
+ try expect(v[0] == 1530);
+ try expect(v[1] == 1531);
+ try expect(v[2] == 1532);
+ try expect(v[3] == 1533);
+ try expect(v[4] == 1534);
+ try expect(v[5] == 1535);
+ try expect(v[6] == 1536);
+ try expect(v[7] == 1537);
+ try expect(v[8] == 1538);
+ try expect(v[9] == 1539);
+ try expect(v[10] == 1540);
+ try expect(v[11] == 1541);
+ try expect(v[12] == 1542);
+ try expect(v[13] == 1543);
+ try expect(v[14] == 1544);
+ try expect(v[15] == 1545);
+ try expect(v[16] == 1546);
+ try expect(v[17] == 1547);
+ try expect(v[18] == 1548);
+ try expect(v[19] == 1549);
+ try expect(v[20] == 1550);
+ try expect(v[21] == 1551);
+ try expect(v[22] == 1552);
+ try expect(v[23] == 1553);
+ try expect(v[24] == 1554);
+ try expect(v[25] == 1555);
+ try expect(v[26] == 1556);
+ try expect(v[27] == 1557);
+ try expect(v[28] == 1558);
+ try expect(v[29] == 1559);
+ try expect(v[30] == 1560);
+ try expect(v[31] == 1561);
+ try expect(v[32] == 1562);
+ try expect(v[33] == 1563);
+ try expect(v[34] == 1564);
+ try expect(v[35] == 1565);
+ try expect(v[36] == 1566);
+ try expect(v[37] == 1567);
+ try expect(v[38] == 1568);
+ try expect(v[39] == 1569);
+ try expect(v[40] == 1570);
+ try expect(v[41] == 1571);
+ try expect(v[42] == 1572);
+ try expect(v[43] == 1573);
+ try expect(v[44] == 1574);
+ try expect(v[45] == 1575);
+ try expect(v[46] == 1576);
+ try expect(v[47] == 1577);
+ try expect(v[48] == 1578);
+ try expect(v[49] == 1579);
+ try expect(v[50] == 1580);
+ try expect(v[51] == 1581);
+ try expect(v[52] == 1582);
+ try expect(v[53] == 1583);
+ try expect(v[54] == 1584);
+ try expect(v[55] == 1585);
+ try expect(v[56] == 1586);
+ try expect(v[57] == 1587);
+ try expect(v[58] == 1588);
+ try expect(v[59] == 1589);
+ try expect(v[60] == 1590);
+ try expect(v[61] == 1591);
+ try expect(v[62] == 1592);
+ try expect(v[63] == 1593);
+ try expect(v[64] == 1594);
+ try expect(v[65] == 1595);
+ try expect(v[66] == 1596);
+ try expect(v[67] == 1597);
+ try expect(v[68] == 1598);
+ try expect(v[69] == 1599);
+ try expect(v[70] == 1600);
+ try expect(v[71] == 1601);
+ try expect(v[72] == 1602);
+ try expect(v[73] == 1603);
+ try expect(v[74] == 1604);
+ try expect(v[75] == 1605);
+ try expect(v[76] == 1606);
+ try expect(v[77] == 1607);
+ try expect(v[78] == 1608);
+ try expect(v[79] == 1609);
+ try expect(v[80] == 1610);
+ try expect(v[81] == 1611);
+ try expect(v[82] == 1612);
+ try expect(v[83] == 1613);
+ try expect(v[84] == 1614);
+ try expect(v[85] == 1615);
+ try expect(v[86] == 1616);
+ try expect(v[87] == 1617);
+ try expect(v[88] == 1618);
+ try expect(v[89] == 1619);
+ try expect(v[90] == 1620);
+ try expect(v[91] == 1621);
+ try expect(v[92] == 1622);
+ try expect(v[93] == 1623);
+ try expect(v[94] == 1624);
+ try expect(v[95] == 1625);
+ try expect(v[96] == 1626);
+ try expect(v[97] == 1627);
+ try expect(v[98] == 1628);
+ try expect(v[99] == 1629);
+ try expect(v[100] == 1630);
+ try expect(v[101] == 1631);
+ try expect(v[102] == 1632);
+ try expect(v[103] == 1633);
+ try expect(v[104] == 1634);
+ try expect(v[105] == 1635);
+ try expect(v[106] == 1636);
+ try expect(v[107] == 1637);
+ try expect(v[108] == 1638);
+ try expect(v[109] == 1639);
+ try expect(v[110] == 1640);
+ try expect(v[111] == 1641);
+ try expect(v[112] == 1642);
+ try expect(v[113] == 1643);
+ try expect(v[114] == 1644);
+ try expect(v[115] == 1645);
+ try expect(v[116] == 1646);
+ try expect(v[117] == 1647);
+ try expect(v[118] == 1648);
+ try expect(v[119] == 1649);
+ try expect(v[120] == 1650);
+ try expect(v[121] == 1651);
+ try expect(v[122] == 1652);
+ try expect(v[123] == 1653);
+ try expect(v[124] == 1654);
+ try expect(v[125] == 1655);
+ try expect(v[126] == 1656);
+ try expect(v[127] == 1657);
+ c_vector_128_f32(.{
+ 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673,
+ 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, 1689,
+ 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, 1704, 1705,
+ 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721,
+ 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1737,
+ 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753,
+ 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769,
+ 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785,
+ }, 128);
+ c_test_vector_128_f32();
+}
+
+export fn zig_ret_vector_1_f64() @Vector(1, f64) {
+ return .{1};
+}
+export fn zig_vector_1_f64(v: @Vector(1, f64), i: usize) void {
+ expect(v[0] == 2) catch @panic("test failure");
+ expect(i == 1) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_1_f64() @Vector(1, f64);
+extern fn c_vector_1_f64(@Vector(1, f64), usize) void;
+extern fn c_test_vector_1_f64() void;
+
+test "@Vector(1, f64)" {
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+
+ const v = c_ret_vector_1_f64();
+ try expect(v[0] == 3);
+ c_vector_1_f64(.{4}, 1);
+ c_test_vector_1_f64();
+}
+
+export fn zig_ret_vector_2_f64() @Vector(2, f64) {
+ return .{ 5, 6 };
+}
+export fn zig_vector_2_f64(v: @Vector(2, f64), i: usize) void {
+ expect(v[0] == 7) catch @panic("test failure");
+ expect(v[1] == 8) catch @panic("test failure");
+ expect(i == 2) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_2_f64() @Vector(2, f64);
+extern fn c_vector_2_f64(@Vector(2, f64), usize) void;
+extern fn c_test_vector_2_f64() void;
+
+test "@Vector(2, f64)" {
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+
+ const v = c_ret_vector_2_f64();
+ try expect(v[0] == 9);
+ try expect(v[1] == 10);
+ c_vector_2_f64(.{ 11, 12 }, 2);
+ c_test_vector_2_f64();
+}
+
+export fn zig_ret_vector_3_f64() @Vector(3, f64) {
+ return .{ 13, 14, 15 };
+}
+export fn zig_vector_3_f64(v: @Vector(3, f64), i: usize) void {
+ expect(v[0] == 16) catch @panic("test failure");
+ expect(v[1] == 17) catch @panic("test failure");
+ expect(v[2] == 18) catch @panic("test failure");
+ expect(i == 3) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_3_f64() @Vector(3, f64);
+extern fn c_vector_3_f64(@Vector(3, f64), usize) void;
+extern fn c_test_vector_3_f64() void;
+
+test "@Vector(3, f64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_3_f64();
+ try expect(v[0] == 19);
+ try expect(v[1] == 20);
+ try expect(v[2] == 21);
+ c_vector_3_f64(.{ 22, 23, 24 }, 3);
+ c_test_vector_3_f64();
+}
+
+export fn zig_ret_vector_4_f64() @Vector(4, f64) {
+ return .{ 25, 26, 27, 28 };
+}
+export fn zig_vector_4_f64(v: @Vector(4, f64), i: usize) void {
+ expect(v[0] == 29) catch @panic("test failure");
+ expect(v[1] == 30) catch @panic("test failure");
+ expect(v[2] == 31) catch @panic("test failure");
+ expect(v[3] == 32) catch @panic("test failure");
+ expect(i == 4) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_4_f64() @Vector(4, f64);
+extern fn c_vector_4_f64(@Vector(4, f64), usize) void;
+extern fn c_test_vector_4_f64() void;
+
+test "@Vector(4, f64)" {
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35899
+
+ const v = c_ret_vector_4_f64();
+ try expect(v[0] == 33);
+ try expect(v[1] == 34);
+ try expect(v[2] == 35);
+ try expect(v[3] == 36);
+ c_vector_4_f64(.{ 37, 38, 39, 40 }, 4);
+ c_test_vector_4_f64();
+}
+
+export fn zig_ret_vector_6_f64() @Vector(6, f64) {
+ return .{ 41, 42, 43, 44, 45, 46 };
+}
+export fn zig_vector_6_f64(v: @Vector(6, f64), i: usize) void {
+ expect(v[0] == 47) catch @panic("test failure");
+ expect(v[1] == 48) catch @panic("test failure");
+ expect(v[2] == 49) catch @panic("test failure");
+ expect(v[3] == 50) catch @panic("test failure");
+ expect(v[4] == 51) catch @panic("test failure");
+ expect(v[5] == 52) catch @panic("test failure");
+ expect(i == 6) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_6_f64() @Vector(6, f64);
+extern fn c_vector_6_f64(@Vector(6, f64), usize) void;
+extern fn c_test_vector_6_f64() void;
+
+test "@Vector(6, f64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_6_f64();
+ try expect(v[0] == 53);
+ try expect(v[1] == 54);
+ try expect(v[2] == 55);
+ try expect(v[3] == 56);
+ try expect(v[4] == 57);
+ try expect(v[5] == 58);
+ c_vector_6_f64(.{ 59, 60, 61, 62, 63, 64 }, 6);
+ c_test_vector_6_f64();
+}
+
+export fn zig_ret_vector_8_f64() @Vector(8, f64) {
+ return .{ 65, 66, 67, 68, 69, 70, 71, 72 };
+}
+export fn zig_vector_8_f64(v: @Vector(8, f64), i: usize) void {
+ expect(v[0] == 73) catch @panic("test failure");
+ expect(v[1] == 74) catch @panic("test failure");
+ expect(v[2] == 75) catch @panic("test failure");
+ expect(v[3] == 76) catch @panic("test failure");
+ expect(v[4] == 77) catch @panic("test failure");
+ expect(v[5] == 78) catch @panic("test failure");
+ expect(v[6] == 79) catch @panic("test failure");
+ expect(v[7] == 80) catch @panic("test failure");
+ expect(i == 8) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_8_f64() @Vector(8, f64);
+extern fn c_vector_8_f64(@Vector(8, f64), usize) void;
+extern fn c_test_vector_8_f64() void;
+
+test "@Vector(8, f64)" {
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35899
+
+ const v = c_ret_vector_8_f64();
+ try expect(v[0] == 81);
+ try expect(v[1] == 82);
+ try expect(v[2] == 83);
+ try expect(v[3] == 84);
+ try expect(v[4] == 85);
+ try expect(v[5] == 86);
+ try expect(v[6] == 87);
+ try expect(v[7] == 88);
+ c_vector_8_f64(.{ 89, 90, 91, 92, 93, 94, 95, 96 }, 8);
+ c_test_vector_8_f64();
+}
+
+export fn zig_ret_vector_12_f64() @Vector(12, f64) {
+ return .{ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108 };
+}
+export fn zig_vector_12_f64(v: @Vector(12, f64), i: usize) void {
+ expect(v[0] == 109) catch @panic("test failure");
+ expect(v[1] == 110) catch @panic("test failure");
+ expect(v[2] == 111) catch @panic("test failure");
+ expect(v[3] == 112) catch @panic("test failure");
+ expect(v[4] == 113) catch @panic("test failure");
+ expect(v[5] == 114) catch @panic("test failure");
+ expect(v[6] == 115) catch @panic("test failure");
+ expect(v[7] == 116) catch @panic("test failure");
+ expect(v[8] == 117) catch @panic("test failure");
+ expect(v[9] == 118) catch @panic("test failure");
+ expect(v[10] == 119) catch @panic("test failure");
+ expect(v[11] == 120) catch @panic("test failure");
+ expect(i == 12) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_12_f64() @Vector(12, f64);
+extern fn c_vector_12_f64(@Vector(12, f64), usize) void;
+extern fn c_test_vector_12_f64() void;
+
+test "@Vector(12, f64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_12_f64();
+ try expect(v[0] == 121);
+ try expect(v[1] == 122);
+ try expect(v[2] == 123);
+ try expect(v[3] == 124);
+ try expect(v[4] == 125);
+ try expect(v[5] == 126);
+ try expect(v[6] == 127);
+ try expect(v[7] == 128);
+ try expect(v[8] == 129);
+ try expect(v[9] == 130);
+ try expect(v[10] == 131);
+ try expect(v[11] == 132);
+ c_vector_12_f64(.{ 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144 }, 12);
+ c_test_vector_12_f64();
+}
+
+export fn zig_ret_vector_16_f64() @Vector(16, f64) {
+ return .{ 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160 };
+}
+export fn zig_vector_16_f64(v: @Vector(16, f64), i: usize) void {
+ expect(v[0] == 161) catch @panic("test failure");
+ expect(v[1] == 162) catch @panic("test failure");
+ expect(v[2] == 163) catch @panic("test failure");
+ expect(v[3] == 164) catch @panic("test failure");
+ expect(v[4] == 165) catch @panic("test failure");
+ expect(v[5] == 166) catch @panic("test failure");
+ expect(v[6] == 167) catch @panic("test failure");
+ expect(v[7] == 168) catch @panic("test failure");
+ expect(v[8] == 169) catch @panic("test failure");
+ expect(v[9] == 170) catch @panic("test failure");
+ expect(v[10] == 171) catch @panic("test failure");
+ expect(v[11] == 172) catch @panic("test failure");
+ expect(v[12] == 173) catch @panic("test failure");
+ expect(v[13] == 174) catch @panic("test failure");
+ expect(v[14] == 175) catch @panic("test failure");
+ expect(v[15] == 176) catch @panic("test failure");
+ expect(i == 16) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_16_f64() @Vector(16, f64);
+extern fn c_vector_16_f64(@Vector(16, f64), usize) void;
+extern fn c_test_vector_16_f64() void;
+
+test "@Vector(16, f64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_16_f64();
+ try expect(v[0] == 177);
+ try expect(v[1] == 178);
+ try expect(v[2] == 179);
+ try expect(v[3] == 180);
+ try expect(v[4] == 181);
+ try expect(v[5] == 182);
+ try expect(v[6] == 183);
+ try expect(v[7] == 184);
+ try expect(v[8] == 185);
+ try expect(v[9] == 186);
+ try expect(v[10] == 187);
+ try expect(v[11] == 188);
+ try expect(v[12] == 189);
+ try expect(v[13] == 190);
+ try expect(v[14] == 191);
+ try expect(v[15] == 192);
+ c_vector_16_f64(.{ 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208 }, 16);
+ c_test_vector_16_f64();
+}
+
+export fn zig_ret_vector_24_f64() @Vector(24, f64) {
+ return .{
+ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
+ 225, 226, 227, 228, 229, 230, 231, 232,
+ };
+}
+export fn zig_vector_24_f64(v: @Vector(24, f64), i: usize) void {
+ expect(v[0] == 233) catch @panic("test failure");
+ expect(v[1] == 234) catch @panic("test failure");
+ expect(v[2] == 235) catch @panic("test failure");
+ expect(v[3] == 236) catch @panic("test failure");
+ expect(v[4] == 237) catch @panic("test failure");
+ expect(v[5] == 238) catch @panic("test failure");
+ expect(v[6] == 239) catch @panic("test failure");
+ expect(v[7] == 240) catch @panic("test failure");
+ expect(v[8] == 241) catch @panic("test failure");
+ expect(v[9] == 242) catch @panic("test failure");
+ expect(v[10] == 243) catch @panic("test failure");
+ expect(v[11] == 244) catch @panic("test failure");
+ expect(v[12] == 245) catch @panic("test failure");
+ expect(v[13] == 246) catch @panic("test failure");
+ expect(v[14] == 247) catch @panic("test failure");
+ expect(v[15] == 248) catch @panic("test failure");
+ expect(v[16] == 249) catch @panic("test failure");
+ expect(v[17] == 250) catch @panic("test failure");
+ expect(v[18] == 251) catch @panic("test failure");
+ expect(v[19] == 252) catch @panic("test failure");
+ expect(v[20] == 253) catch @panic("test failure");
+ expect(v[21] == 254) catch @panic("test failure");
+ expect(v[22] == 255) catch @panic("test failure");
+ expect(v[23] == 256) catch @panic("test failure");
+ expect(i == 24) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_24_f64() @Vector(24, f64);
+extern fn c_vector_24_f64(@Vector(24, f64), usize) void;
+extern fn c_test_vector_24_f64() void;
+
+test "@Vector(24, f64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_24_f64();
+ try expect(v[0] == 257);
+ try expect(v[1] == 258);
+ try expect(v[2] == 259);
+ try expect(v[3] == 260);
+ try expect(v[4] == 261);
+ try expect(v[5] == 262);
+ try expect(v[6] == 263);
+ try expect(v[7] == 264);
+ try expect(v[8] == 265);
+ try expect(v[9] == 266);
+ try expect(v[10] == 267);
+ try expect(v[11] == 268);
+ try expect(v[12] == 269);
+ try expect(v[13] == 270);
+ try expect(v[14] == 271);
+ try expect(v[15] == 272);
+ try expect(v[16] == 273);
+ try expect(v[17] == 274);
+ try expect(v[18] == 275);
+ try expect(v[19] == 276);
+ try expect(v[20] == 277);
+ try expect(v[21] == 278);
+ try expect(v[22] == 279);
+ try expect(v[23] == 280);
+ c_vector_24_f64(.{
+ 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296,
+ 297, 298, 299, 300, 301, 302, 303, 304,
+ }, 24);
+ c_test_vector_24_f64();
+}
+
+export fn zig_ret_vector_32_f64() @Vector(32, f64) {
+ return .{
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320,
+ 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
+ };
+}
+export fn zig_vector_32_f64(v: @Vector(32, f64), i: usize) void {
+ expect(v[0] == 337) catch @panic("test failure");
+ expect(v[1] == 338) catch @panic("test failure");
+ expect(v[2] == 339) catch @panic("test failure");
+ expect(v[3] == 340) catch @panic("test failure");
+ expect(v[4] == 341) catch @panic("test failure");
+ expect(v[5] == 342) catch @panic("test failure");
+ expect(v[6] == 343) catch @panic("test failure");
+ expect(v[7] == 344) catch @panic("test failure");
+ expect(v[8] == 345) catch @panic("test failure");
+ expect(v[9] == 346) catch @panic("test failure");
+ expect(v[10] == 347) catch @panic("test failure");
+ expect(v[11] == 348) catch @panic("test failure");
+ expect(v[12] == 349) catch @panic("test failure");
+ expect(v[13] == 350) catch @panic("test failure");
+ expect(v[14] == 351) catch @panic("test failure");
+ expect(v[15] == 352) catch @panic("test failure");
+ expect(v[16] == 353) catch @panic("test failure");
+ expect(v[17] == 354) catch @panic("test failure");
+ expect(v[18] == 355) catch @panic("test failure");
+ expect(v[19] == 356) catch @panic("test failure");
+ expect(v[20] == 357) catch @panic("test failure");
+ expect(v[21] == 358) catch @panic("test failure");
+ expect(v[22] == 359) catch @panic("test failure");
+ expect(v[23] == 360) catch @panic("test failure");
+ expect(v[24] == 361) catch @panic("test failure");
+ expect(v[25] == 362) catch @panic("test failure");
+ expect(v[26] == 363) catch @panic("test failure");
+ expect(v[27] == 364) catch @panic("test failure");
+ expect(v[28] == 365) catch @panic("test failure");
+ expect(v[29] == 366) catch @panic("test failure");
+ expect(v[30] == 367) catch @panic("test failure");
+ expect(v[31] == 368) catch @panic("test failure");
+ expect(i == 32) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_32_f64() @Vector(32, f64);
+extern fn c_vector_32_f64(@Vector(32, f64), usize) void;
+extern fn c_test_vector_32_f64() void;
+
+test "@Vector(32, f64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_32_f64();
+ try expect(v[0] == 369);
+ try expect(v[1] == 370);
+ try expect(v[2] == 371);
+ try expect(v[3] == 372);
+ try expect(v[4] == 373);
+ try expect(v[5] == 374);
+ try expect(v[6] == 375);
+ try expect(v[7] == 376);
+ try expect(v[8] == 377);
+ try expect(v[9] == 378);
+ try expect(v[10] == 379);
+ try expect(v[11] == 380);
+ try expect(v[12] == 381);
+ try expect(v[13] == 382);
+ try expect(v[14] == 383);
+ try expect(v[15] == 384);
+ try expect(v[16] == 385);
+ try expect(v[17] == 386);
+ try expect(v[18] == 387);
+ try expect(v[19] == 388);
+ try expect(v[20] == 389);
+ try expect(v[21] == 390);
+ try expect(v[22] == 391);
+ try expect(v[23] == 392);
+ try expect(v[24] == 393);
+ try expect(v[25] == 394);
+ try expect(v[26] == 395);
+ try expect(v[27] == 396);
+ try expect(v[28] == 397);
+ try expect(v[29] == 398);
+ try expect(v[30] == 399);
+ try expect(v[31] == 400);
+ c_vector_32_f64(.{
+ 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416,
+ 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432,
+ }, 32);
+ c_test_vector_32_f64();
+}
+
+export fn zig_ret_vector_48_f64() @Vector(48, f64) {
+ return .{
+ 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448,
+ 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464,
+ 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480,
+ };
+}
+export fn zig_vector_48_f64(v: @Vector(48, f64), i: usize) void {
+ expect(v[0] == 481) catch @panic("test failure");
+ expect(v[1] == 482) catch @panic("test failure");
+ expect(v[2] == 483) catch @panic("test failure");
+ expect(v[3] == 484) catch @panic("test failure");
+ expect(v[4] == 485) catch @panic("test failure");
+ expect(v[5] == 486) catch @panic("test failure");
+ expect(v[6] == 487) catch @panic("test failure");
+ expect(v[7] == 488) catch @panic("test failure");
+ expect(v[8] == 489) catch @panic("test failure");
+ expect(v[9] == 490) catch @panic("test failure");
+ expect(v[10] == 491) catch @panic("test failure");
+ expect(v[11] == 492) catch @panic("test failure");
+ expect(v[12] == 493) catch @panic("test failure");
+ expect(v[13] == 494) catch @panic("test failure");
+ expect(v[14] == 495) catch @panic("test failure");
+ expect(v[15] == 496) catch @panic("test failure");
+ expect(v[16] == 497) catch @panic("test failure");
+ expect(v[17] == 498) catch @panic("test failure");
+ expect(v[18] == 499) catch @panic("test failure");
+ expect(v[19] == 500) catch @panic("test failure");
+ expect(v[20] == 501) catch @panic("test failure");
+ expect(v[21] == 502) catch @panic("test failure");
+ expect(v[22] == 503) catch @panic("test failure");
+ expect(v[23] == 504) catch @panic("test failure");
+ expect(v[24] == 505) catch @panic("test failure");
+ expect(v[25] == 506) catch @panic("test failure");
+ expect(v[26] == 507) catch @panic("test failure");
+ expect(v[27] == 508) catch @panic("test failure");
+ expect(v[28] == 509) catch @panic("test failure");
+ expect(v[29] == 510) catch @panic("test failure");
+ expect(v[30] == 511) catch @panic("test failure");
+ expect(v[31] == 512) catch @panic("test failure");
+ expect(v[32] == 513) catch @panic("test failure");
+ expect(v[33] == 514) catch @panic("test failure");
+ expect(v[34] == 515) catch @panic("test failure");
+ expect(v[35] == 516) catch @panic("test failure");
+ expect(v[36] == 517) catch @panic("test failure");
+ expect(v[37] == 518) catch @panic("test failure");
+ expect(v[38] == 519) catch @panic("test failure");
+ expect(v[39] == 520) catch @panic("test failure");
+ expect(v[40] == 521) catch @panic("test failure");
+ expect(v[41] == 522) catch @panic("test failure");
+ expect(v[42] == 523) catch @panic("test failure");
+ expect(v[43] == 524) catch @panic("test failure");
+ expect(v[44] == 525) catch @panic("test failure");
+ expect(v[45] == 526) catch @panic("test failure");
+ expect(v[46] == 527) catch @panic("test failure");
+ expect(v[47] == 528) catch @panic("test failure");
+ expect(i == 48) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_48_f64() @Vector(48, f64);
+extern fn c_vector_48_f64(@Vector(48, f64), usize) void;
+extern fn c_test_vector_48_f64() void;
+
+test "@Vector(48, f64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_48_f64();
+ try expect(v[0] == 529);
+ try expect(v[1] == 530);
+ try expect(v[2] == 531);
+ try expect(v[3] == 532);
+ try expect(v[4] == 533);
+ try expect(v[5] == 534);
+ try expect(v[6] == 535);
+ try expect(v[7] == 536);
+ try expect(v[8] == 537);
+ try expect(v[9] == 538);
+ try expect(v[10] == 539);
+ try expect(v[11] == 540);
+ try expect(v[12] == 541);
+ try expect(v[13] == 542);
+ try expect(v[14] == 543);
+ try expect(v[15] == 544);
+ try expect(v[16] == 545);
+ try expect(v[17] == 546);
+ try expect(v[18] == 547);
+ try expect(v[19] == 548);
+ try expect(v[20] == 549);
+ try expect(v[21] == 550);
+ try expect(v[22] == 551);
+ try expect(v[23] == 552);
+ try expect(v[24] == 553);
+ try expect(v[25] == 554);
+ try expect(v[26] == 555);
+ try expect(v[27] == 556);
+ try expect(v[28] == 557);
+ try expect(v[29] == 558);
+ try expect(v[30] == 559);
+ try expect(v[31] == 560);
+ try expect(v[32] == 561);
+ try expect(v[33] == 562);
+ try expect(v[34] == 563);
+ try expect(v[35] == 564);
+ try expect(v[36] == 565);
+ try expect(v[37] == 566);
+ try expect(v[38] == 567);
+ try expect(v[39] == 568);
+ try expect(v[40] == 569);
+ try expect(v[41] == 570);
+ try expect(v[42] == 571);
+ try expect(v[43] == 572);
+ try expect(v[44] == 573);
+ try expect(v[45] == 574);
+ try expect(v[46] == 575);
+ try expect(v[47] == 576);
+ c_vector_48_f64(.{
+ 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592,
+ 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608,
+ 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624,
+ }, 48);
+ c_test_vector_48_f64();
+}
+
+export fn zig_ret_vector_64_f64() @Vector(64, f64) {
+ return .{
+ 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640,
+ 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656,
+ 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672,
+ 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688,
+ };
+}
+export fn zig_vector_64_f64(v: @Vector(64, f64), i: usize) void {
+ expect(v[0] == 689) catch @panic("test failure");
+ expect(v[1] == 690) catch @panic("test failure");
+ expect(v[2] == 691) catch @panic("test failure");
+ expect(v[3] == 692) catch @panic("test failure");
+ expect(v[4] == 693) catch @panic("test failure");
+ expect(v[5] == 694) catch @panic("test failure");
+ expect(v[6] == 695) catch @panic("test failure");
+ expect(v[7] == 696) catch @panic("test failure");
+ expect(v[8] == 697) catch @panic("test failure");
+ expect(v[9] == 698) catch @panic("test failure");
+ expect(v[10] == 699) catch @panic("test failure");
+ expect(v[11] == 700) catch @panic("test failure");
+ expect(v[12] == 701) catch @panic("test failure");
+ expect(v[13] == 702) catch @panic("test failure");
+ expect(v[14] == 703) catch @panic("test failure");
+ expect(v[15] == 704) catch @panic("test failure");
+ expect(v[16] == 705) catch @panic("test failure");
+ expect(v[17] == 706) catch @panic("test failure");
+ expect(v[18] == 707) catch @panic("test failure");
+ expect(v[19] == 708) catch @panic("test failure");
+ expect(v[20] == 709) catch @panic("test failure");
+ expect(v[21] == 710) catch @panic("test failure");
+ expect(v[22] == 711) catch @panic("test failure");
+ expect(v[23] == 712) catch @panic("test failure");
+ expect(v[24] == 713) catch @panic("test failure");
+ expect(v[25] == 714) catch @panic("test failure");
+ expect(v[26] == 715) catch @panic("test failure");
+ expect(v[27] == 716) catch @panic("test failure");
+ expect(v[28] == 717) catch @panic("test failure");
+ expect(v[29] == 718) catch @panic("test failure");
+ expect(v[30] == 719) catch @panic("test failure");
+ expect(v[31] == 720) catch @panic("test failure");
+ expect(v[32] == 721) catch @panic("test failure");
+ expect(v[33] == 722) catch @panic("test failure");
+ expect(v[34] == 723) catch @panic("test failure");
+ expect(v[35] == 724) catch @panic("test failure");
+ expect(v[36] == 725) catch @panic("test failure");
+ expect(v[37] == 726) catch @panic("test failure");
+ expect(v[38] == 727) catch @panic("test failure");
+ expect(v[39] == 728) catch @panic("test failure");
+ expect(v[40] == 729) catch @panic("test failure");
+ expect(v[41] == 730) catch @panic("test failure");
+ expect(v[42] == 731) catch @panic("test failure");
+ expect(v[43] == 732) catch @panic("test failure");
+ expect(v[44] == 733) catch @panic("test failure");
+ expect(v[45] == 734) catch @panic("test failure");
+ expect(v[46] == 735) catch @panic("test failure");
+ expect(v[47] == 736) catch @panic("test failure");
+ expect(v[48] == 737) catch @panic("test failure");
+ expect(v[49] == 738) catch @panic("test failure");
+ expect(v[50] == 739) catch @panic("test failure");
+ expect(v[51] == 740) catch @panic("test failure");
+ expect(v[52] == 741) catch @panic("test failure");
+ expect(v[53] == 742) catch @panic("test failure");
+ expect(v[54] == 743) catch @panic("test failure");
+ expect(v[55] == 744) catch @panic("test failure");
+ expect(v[56] == 745) catch @panic("test failure");
+ expect(v[57] == 746) catch @panic("test failure");
+ expect(v[58] == 747) catch @panic("test failure");
+ expect(v[59] == 748) catch @panic("test failure");
+ expect(v[60] == 749) catch @panic("test failure");
+ expect(v[61] == 750) catch @panic("test failure");
+ expect(v[62] == 751) catch @panic("test failure");
+ expect(v[63] == 752) catch @panic("test failure");
+ expect(i == 64) catch @panic("test failure");
+}
+
+extern fn c_ret_vector_64_f64() @Vector(64, f64);
+extern fn c_vector_64_f64(@Vector(64, f64), usize) void;
+extern fn c_test_vector_64_f64() void;
+
+test "@Vector(64, f64)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const v = c_ret_vector_64_f64();
+ try expect(v[0] == 753);
+ try expect(v[1] == 754);
+ try expect(v[2] == 755);
+ try expect(v[3] == 756);
+ try expect(v[4] == 757);
+ try expect(v[5] == 758);
+ try expect(v[6] == 759);
+ try expect(v[7] == 760);
+ try expect(v[8] == 761);
+ try expect(v[9] == 762);
+ try expect(v[10] == 763);
+ try expect(v[11] == 764);
+ try expect(v[12] == 765);
+ try expect(v[13] == 766);
+ try expect(v[14] == 767);
+ try expect(v[15] == 768);
+ try expect(v[16] == 769);
+ try expect(v[17] == 770);
+ try expect(v[18] == 771);
+ try expect(v[19] == 772);
+ try expect(v[20] == 773);
+ try expect(v[21] == 774);
+ try expect(v[22] == 775);
+ try expect(v[23] == 776);
+ try expect(v[24] == 777);
+ try expect(v[25] == 778);
+ try expect(v[26] == 779);
+ try expect(v[27] == 780);
+ try expect(v[28] == 781);
+ try expect(v[29] == 782);
+ try expect(v[30] == 783);
+ try expect(v[31] == 784);
+ try expect(v[32] == 785);
+ try expect(v[33] == 786);
+ try expect(v[34] == 787);
+ try expect(v[35] == 788);
+ try expect(v[36] == 789);
+ try expect(v[37] == 790);
+ try expect(v[38] == 791);
+ try expect(v[39] == 792);
+ try expect(v[40] == 793);
+ try expect(v[41] == 794);
+ try expect(v[42] == 795);
+ try expect(v[43] == 796);
+ try expect(v[44] == 797);
+ try expect(v[45] == 798);
+ try expect(v[46] == 799);
+ try expect(v[47] == 800);
+ try expect(v[48] == 801);
+ try expect(v[49] == 802);
+ try expect(v[50] == 803);
+ try expect(v[51] == 804);
+ try expect(v[52] == 805);
+ try expect(v[53] == 806);
+ try expect(v[54] == 807);
+ try expect(v[55] == 808);
+ try expect(v[56] == 809);
+ try expect(v[57] == 810);
+ try expect(v[58] == 811);
+ try expect(v[59] == 812);
+ try expect(v[60] == 813);
+ try expect(v[61] == 814);
+ try expect(v[62] == 815);
+ try expect(v[63] == 816);
+ c_vector_64_f64(.{
+ 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832,
+ 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848,
+ 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864,
+ 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880,
+ }, 64);
+ c_test_vector_64_f64();
+}
+
+const Struct_u8 = extern struct {
+ a: u8,
+};
+
+export fn zig_ret_struct_u8() Struct_u8 {
+ return .{ .a = 1 };
+}
+export fn zig_struct_u8(s: Struct_u8, i: usize) void {
+ expect(s.a == 2) catch @panic("test failure");
+ expect(i == 3) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u8() Struct_u8;
+extern fn c_struct_u8(Struct_u8, usize) void;
+extern fn c_test_struct_u8() void;
+
+test "struct u8" {
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
+
+ const s = c_ret_struct_u8();
+ try expect(s.a == 4);
+ c_struct_u8(.{ .a = 5 }, 6);
+ c_test_struct_u8();
+}
+
+const Struct_u8_u8 = extern struct {
+ a: u8,
+ b: u8,
+};
+
+export fn zig_ret_struct_u8_u8() Struct_u8_u8 {
+ return .{ .a = 1, .b = 2 };
+}
+export fn zig_struct_u8_u8(s: Struct_u8_u8, i: usize) void {
+ expect(s.a == 3) catch @panic("test failure");
+ expect(s.b == 4) catch @panic("test failure");
+ expect(i == 5) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u8_u8() Struct_u8_u8;
+extern fn c_struct_u8_u8(Struct_u8_u8, usize) void;
+extern fn c_test_struct_u8_u8() void;
+
+test "struct u8, u8" {
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86) return error.SkipZigTest;
+
+ const s = c_ret_struct_u8_u8();
+ try expect(s.a == 6);
+ try expect(s.b == 7);
+ c_struct_u8_u8(.{ .a = 8, .b = 9 }, 10);
+ c_test_struct_u8_u8();
+}
+
+const Struct_u8_u8_u8 = extern struct {
+ a: u8,
+ b: u8,
+ c: u8,
+};
+
+export fn zig_ret_struct_u8_u8_u8() Struct_u8_u8_u8 {
+ return .{ .a = 1, .b = 2, .c = 3 };
+}
+export fn zig_struct_u8_u8_u8(s: Struct_u8_u8_u8, i: usize) void {
+ expect(s.a == 4) catch @panic("test failure");
+ expect(s.b == 5) catch @panic("test failure");
+ expect(s.c == 6) catch @panic("test failure");
+ expect(i == 7) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u8_u8_u8() Struct_u8_u8_u8;
+extern fn c_struct_u8_u8_u8(Struct_u8_u8_u8, usize) void;
+extern fn c_test_struct_u8_u8_u8() void;
+
+test "struct u8, u8, u8" {
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86) return error.SkipZigTest;
+
+ const s = c_ret_struct_u8_u8_u8();
+ try expect(s.a == 8);
+ try expect(s.b == 9);
+ try expect(s.c == 10);
+ c_struct_u8_u8_u8(.{ .a = 11, .b = 12, .c = 13 }, 14);
+ c_test_struct_u8_u8_u8();
+}
+
+const Struct_u8_u8_u8_u8 = extern struct {
+ a: u8,
+ b: u8,
+ c: u8,
+ d: u8,
+};
+
+export fn zig_ret_struct_u8_u8_u8_u8() Struct_u8_u8_u8_u8 {
+ return .{ .a = 1, .b = 2, .c = 3, .d = 4 };
+}
+export fn zig_struct_u8_u8_u8_u8(s: Struct_u8_u8_u8_u8, i: usize) void {
+ expect(s.a == 5) catch @panic("test failure");
+ expect(s.b == 6) catch @panic("test failure");
+ expect(s.c == 7) catch @panic("test failure");
+ expect(s.d == 8) catch @panic("test failure");
+ expect(i == 9) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u8_u8_u8_u8() Struct_u8_u8_u8_u8;
+extern fn c_struct_u8_u8_u8_u8(Struct_u8_u8_u8_u8, usize) void;
+extern fn c_test_struct_u8_u8_u8_u8() void;
+
+test "struct u8, u8, u8, u8" {
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86) return error.SkipZigTest;
+
+ const s = c_ret_struct_u8_u8_u8_u8();
+ try expect(s.a == 10);
+ try expect(s.b == 11);
+ try expect(s.c == 12);
+ try expect(s.d == 13);
+ c_struct_u8_u8_u8_u8(.{ .a = 14, .b = 15, .c = 16, .d = 17 }, 18);
+ c_test_struct_u8_u8_u8_u8();
+}
+
+const Struct_u16 = extern struct {
+ a: u16,
+};
+
+export fn zig_ret_struct_u16() Struct_u16 {
+ return .{ .a = 1 };
+}
+export fn zig_struct_u16(s: Struct_u16, i: usize) void {
+ expect(s.a == 2) catch @panic("test failure");
+ expect(i == 3) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u16() Struct_u16;
+extern fn c_struct_u16(Struct_u16, usize) void;
+extern fn c_test_struct_u16() void;
+
+test "struct u16" {
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
+
+ const s = c_ret_struct_u16();
+ try expect(s.a == 4);
+ c_struct_u16(.{ .a = 5 }, 6);
+ c_test_struct_u16();
+}
+
+const Struct_u16_u16 = extern struct {
+ a: u16,
+ b: u16,
+};
+
+export fn zig_ret_struct_u16_u16() Struct_u16_u16 {
+ return .{ .a = 1, .b = 2 };
+}
+export fn zig_struct_u16_u16(s: Struct_u16_u16, i: usize) void {
+ expect(s.a == 3) catch @panic("test failure");
+ expect(s.b == 4) catch @panic("test failure");
+ expect(i == 5) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u16_u16() Struct_u16_u16;
+extern fn c_struct_u16_u16(Struct_u16_u16, usize) void;
+extern fn c_test_struct_u16_u16() void;
+
+test "struct u16, u16" {
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86) return error.SkipZigTest;
+
+ const s = c_ret_struct_u16_u16();
+ try expect(s.a == 6);
+ try expect(s.b == 7);
+ c_struct_u16_u16(.{ .a = 8, .b = 9 }, 10);
+ c_test_struct_u16_u16();
+}
+
+const Struct_u16_u16_u16 = extern struct {
+ a: u16,
+ b: u16,
+ c: u16,
+};
+
+export fn zig_ret_struct_u16_u16_u16() Struct_u16_u16_u16 {
+ return .{ .a = 1, .b = 2, .c = 3 };
+}
+export fn zig_struct_u16_u16_u16(s: Struct_u16_u16_u16, i: usize) void {
+ expect(s.a == 4) catch @panic("test failure");
+ expect(s.b == 5) catch @panic("test failure");
+ expect(s.c == 6) catch @panic("test failure");
+ expect(i == 7) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u16_u16_u16() Struct_u16_u16_u16;
+extern fn c_struct_u16_u16_u16(Struct_u16_u16_u16, usize) void;
+extern fn c_test_struct_u16_u16_u16() void;
+
+test "struct u16, u16, u16" {
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86) return error.SkipZigTest;
+
+ const s = c_ret_struct_u16_u16_u16();
+ try expect(s.a == 8);
+ try expect(s.b == 9);
+ try expect(s.c == 10);
+ c_struct_u16_u16_u16(.{ .a = 11, .b = 12, .c = 13 }, 14);
+ c_test_struct_u16_u16_u16();
+}
+
+const Struct_u16_u16_u16_u16 = extern struct {
+ a: u16,
+ b: u16,
+ c: u16,
+ d: u16,
+};
+
+export fn zig_ret_struct_u16_u16_u16_u16() Struct_u16_u16_u16_u16 {
+ return .{ .a = 1, .b = 2, .c = 3, .d = 4 };
+}
+export fn zig_struct_u16_u16_u16_u16(s: Struct_u16_u16_u16_u16, i: usize) void {
+ expect(s.a == 5) catch @panic("test failure");
+ expect(s.b == 6) catch @panic("test failure");
+ expect(s.c == 7) catch @panic("test failure");
+ expect(s.d == 8) catch @panic("test failure");
+ expect(i == 9) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u16_u16_u16_u16() Struct_u16_u16_u16_u16;
+extern fn c_struct_u16_u16_u16_u16(Struct_u16_u16_u16_u16, usize) void;
+extern fn c_test_struct_u16_u16_u16_u16() void;
+
+test "struct u16, u16, u16, u16" {
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86) return error.SkipZigTest;
+
+ const s = c_ret_struct_u16_u16_u16_u16();
+ try expect(s.a == 10);
+ try expect(s.b == 11);
+ try expect(s.c == 12);
+ try expect(s.d == 13);
+ c_struct_u16_u16_u16_u16(.{ .a = 14, .b = 15, .c = 16, .d = 17 }, 18);
+ c_test_struct_u16_u16_u16_u16();
+}
+
+const Struct_u32 = extern struct {
+ a: u32,
+};
+
+export fn zig_ret_struct_u32() Struct_u32 {
+ return .{ .a = 1 };
+}
+export fn zig_struct_u32(s: Struct_u32, i: usize) void {
+ expect(s.a == 2) catch @panic("test failure");
+ expect(i == 3) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u32() Struct_u32;
+extern fn c_struct_u32(Struct_u32, usize) void;
+extern fn c_test_struct_u32() void;
+
+test "struct u32" {
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
+
+ const s = c_ret_struct_u32();
+ try expect(s.a == 4);
+ c_struct_u32(.{ .a = 5 }, 6);
+ c_test_struct_u32();
+}
+
+const Struct_u32_u32 = extern struct {
+ a: u32,
+ b: u32,
+};
+
+export fn zig_ret_struct_u32_u32() Struct_u32_u32 {
+ return .{ .a = 1, .b = 2 };
+}
+export fn zig_struct_u32_u32(s: Struct_u32_u32, i: usize) void {
+ expect(s.a == 3) catch @panic("test failure");
+ expect(s.b == 4) catch @panic("test failure");
+ expect(i == 5) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u32_u32() Struct_u32_u32;
+extern fn c_struct_u32_u32(Struct_u32_u32, usize) void;
+extern fn c_test_struct_u32_u32() void;
+
+test "struct u32, u32" {
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
+
+ const s = c_ret_struct_u32_u32();
+ try expect(s.a == 6);
+ try expect(s.b == 7);
+ c_struct_u32_u32(.{ .a = 8, .b = 9 }, 10);
+ c_test_struct_u32_u32();
+}
+
+const Struct_u32_u32_u32 = extern struct {
+ a: u32,
+ b: u32,
+ c: u32,
+};
+
+export fn zig_ret_struct_u32_u32_u32() Struct_u32_u32_u32 {
+ return .{ .a = 1, .b = 2, .c = 3 };
+}
+export fn zig_struct_u32_u32_u32(s: Struct_u32_u32_u32, i: usize) void {
+ expect(s.a == 4) catch @panic("test failure");
+ expect(s.b == 5) catch @panic("test failure");
+ expect(s.c == 6) catch @panic("test failure");
+ expect(i == 7) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u32_u32_u32() Struct_u32_u32_u32;
+extern fn c_struct_u32_u32_u32(Struct_u32_u32_u32, usize) void;
+extern fn c_test_struct_u32_u32_u32() void;
+
+test "struct u32, u32, u32" {
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = c_ret_struct_u32_u32_u32();
+ try expect(s.a == 8);
+ try expect(s.b == 9);
+ try expect(s.c == 10);
+ c_struct_u32_u32_u32(.{ .a = 11, .b = 12, .c = 13 }, 14);
+ c_test_struct_u32_u32_u32();
+}
+
+const Struct_u32_u32_u32_u32 = extern struct {
+ a: u32,
+ b: u32,
+ c: u32,
+ d: u32,
+};
+
+export fn zig_ret_struct_u32_u32_u32_u32() Struct_u32_u32_u32_u32 {
+ return .{ .a = 1, .b = 2, .c = 3, .d = 4 };
+}
+export fn zig_struct_u32_u32_u32_u32(s: Struct_u32_u32_u32_u32, i: usize) void {
+ expect(s.a == 5) catch @panic("test failure");
+ expect(s.b == 6) catch @panic("test failure");
+ expect(s.c == 7) catch @panic("test failure");
+ expect(s.d == 8) catch @panic("test failure");
+ expect(i == 9) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u32_u32_u32_u32() Struct_u32_u32_u32_u32;
+extern fn c_struct_u32_u32_u32_u32(Struct_u32_u32_u32_u32, usize) void;
+extern fn c_test_struct_u32_u32_u32_u32() void;
+
+test "struct u32, u32, u32, u32" {
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = c_ret_struct_u32_u32_u32_u32();
+ try expect(s.a == 10);
+ try expect(s.b == 11);
+ try expect(s.c == 12);
+ try expect(s.d == 13);
+ c_struct_u32_u32_u32_u32(.{ .a = 14, .b = 15, .c = 16, .d = 17 }, 18);
+ c_test_struct_u32_u32_u32_u32();
+}
+
+const Struct_u64 = extern struct {
+ a: u64,
+};
+
+export fn zig_ret_struct_u64() Struct_u64 {
+ return .{ .a = 1 };
+}
+export fn zig_struct_u64(s: Struct_u64, i: usize) void {
+ expect(s.a == 2) catch @panic("test failure");
+ expect(i == 3) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u64() Struct_u64;
+extern fn c_struct_u64(Struct_u64, usize) void;
+extern fn c_test_struct_u64() void;
+
+test "struct u64" {
+ if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
+
+ const s = c_ret_struct_u64();
+ try expect(s.a == 4);
+ c_struct_u64(.{ .a = 5 }, 6);
+ c_test_struct_u64();
+}
+
+const Struct_u64_u64 = extern struct {
+ a: u64,
+ b: u64,
+};
+
+export fn zig_ret_struct_u64_u64() Struct_u64_u64 {
+ return .{ .a = 1, .b = 2 };
+}
+export fn zig_struct_u64_u64(s: Struct_u64_u64, i: usize) void {
+ expect(s.a == 3) catch @panic("test failure");
+ expect(s.b == 4) catch @panic("test failure");
+ expect(i == 1) catch @panic("test failure");
+}
+export fn zig_1_struct_u64_u64(_: usize, s: Struct_u64_u64, i: usize) void {
+ expect(s.a == 5) catch @panic("test failure");
+ expect(s.b == 6) catch @panic("test failure");
+ expect(i == 2) catch @panic("test failure");
+}
+export fn zig_2_struct_u64_u64(_: usize, _: usize, s: Struct_u64_u64, i: usize) void {
+ expect(s.a == 7) catch @panic("test failure");
+ expect(s.b == 8) catch @panic("test failure");
+ expect(i == 3) catch @panic("test failure");
+}
+export fn zig_3_struct_u64_u64(_: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
+ expect(s.a == 9) catch @panic("test failure");
+ expect(s.b == 10) catch @panic("test failure");
+ expect(i == 4) catch @panic("test failure");
+}
+export fn zig_4_struct_u64_u64(_: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
+ expect(s.a == 11) catch @panic("test failure");
+ expect(s.b == 12) catch @panic("test failure");
+ expect(i == 5) catch @panic("test failure");
+}
+export fn zig_5_struct_u64_u64(_: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
+ expect(s.a == 13) catch @panic("test failure");
+ expect(s.b == 14) catch @panic("test failure");
+ expect(i == 6) catch @panic("test failure");
+}
+export fn zig_6_struct_u64_u64(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
+ expect(s.a == 15) catch @panic("test failure");
+ expect(s.b == 16) catch @panic("test failure");
+ expect(i == 7) catch @panic("test failure");
+}
+export fn zig_7_struct_u64_u64(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
+ expect(s.a == 17) catch @panic("test failure");
+ expect(s.b == 18) catch @panic("test failure");
+ expect(i == 8) catch @panic("test failure");
+}
+export fn zig_8_struct_u64_u64(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
+ expect(s.a == 19) catch @panic("test failure");
+ expect(s.b == 20) catch @panic("test failure");
+ expect(i == 9) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u64_u64() Struct_u64_u64;
+extern fn c_struct_u64_u64(Struct_u64_u64, usize) void;
+extern fn c_1_struct_u64_u64(usize, Struct_u64_u64, usize) void;
+extern fn c_2_struct_u64_u64(usize, usize, Struct_u64_u64, usize) void;
+extern fn c_3_struct_u64_u64(usize, usize, usize, Struct_u64_u64, usize) void;
+extern fn c_4_struct_u64_u64(usize, usize, usize, usize, Struct_u64_u64, usize) void;
+extern fn c_5_struct_u64_u64(usize, usize, usize, usize, usize, Struct_u64_u64, usize) void;
+extern fn c_6_struct_u64_u64(usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void;
+extern fn c_7_struct_u64_u64(usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void;
+extern fn c_8_struct_u64_u64(usize, usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void;
+extern fn c_test_struct_u64_u64() void;
+
+test "struct u64, u64" {
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = c_ret_struct_u64_u64();
+ try expect(s.a == 21);
+ try expect(s.b == 22);
+ c_struct_u64_u64(.{ .a = 23, .b = 24 }, 1);
+ c_1_struct_u64_u64(0, .{ .a = 25, .b = 26 }, 2);
+ c_2_struct_u64_u64(0, 1, .{ .a = 27, .b = 28 }, 3);
+ c_3_struct_u64_u64(0, 1, 2, .{ .a = 29, .b = 30 }, 4);
+ c_4_struct_u64_u64(0, 1, 2, 3, .{ .a = 31, .b = 32 }, 5);
+ c_5_struct_u64_u64(0, 1, 2, 3, 4, .{ .a = 33, .b = 34 }, 6);
+ c_6_struct_u64_u64(0, 1, 2, 3, 4, 5, .{ .a = 35, .b = 36 }, 7);
+ c_7_struct_u64_u64(0, 1, 2, 3, 4, 5, 6, .{ .a = 37, .b = 38 }, 8);
+ c_8_struct_u64_u64(0, 1, 2, 3, 4, 5, 6, 7, .{ .a = 39, .b = 40 }, 9);
+ c_test_struct_u64_u64();
+}
+
+const Struct_u64_u64_u64 = extern struct {
+ a: u64,
+ b: u64,
+ c: u64,
+};
+
+export fn zig_ret_struct_u64_u64_u64() Struct_u64_u64_u64 {
+ return .{ .a = 1, .b = 2, .c = 3 };
+}
+export fn zig_struct_u64_u64_u64(s: Struct_u64_u64_u64, i: usize) void {
+ expect(s.a == 4) catch @panic("test failure");
+ expect(s.b == 5) catch @panic("test failure");
+ expect(s.c == 6) catch @panic("test failure");
+ expect(i == 7) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u64_u64_u64() Struct_u64_u64_u64;
+extern fn c_struct_u64_u64_u64(Struct_u64_u64_u64, usize) void;
+extern fn c_test_struct_u64_u64_u64() void;
+
+test "struct u64, u64, u64" {
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = c_ret_struct_u64_u64_u64();
+ try expect(s.a == 8);
+ try expect(s.b == 9);
+ try expect(s.c == 10);
+ c_struct_u64_u64_u64(.{ .a = 11, .b = 12, .c = 13 }, 14);
+ c_test_struct_u64_u64_u64();
+}
+
+const Struct_u64_u64_u64_u64 = extern struct {
+ a: u64,
+ b: u64,
+ c: u64,
+ d: u64,
+};
+
+export fn zig_ret_struct_u64_u64_u64_u64() Struct_u64_u64_u64_u64 {
+ return .{ .a = 1, .b = 2, .c = 3, .d = 4 };
+}
+export fn zig_struct_u64_u64_u64_u64(s: Struct_u64_u64_u64_u64, i: usize) void {
+ expect(s.a == 5) catch @panic("test failure");
+ expect(s.b == 6) catch @panic("test failure");
+ expect(s.c == 7) catch @panic("test failure");
+ expect(s.d == 8) catch @panic("test failure");
+ expect(i == 9) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u64_u64_u64_u64() Struct_u64_u64_u64_u64;
+extern fn c_struct_u64_u64_u64_u64(Struct_u64_u64_u64_u64, usize) void;
+extern fn c_test_struct_u64_u64_u64_u64() void;
+
+test "struct u64, u64, u64, u64" {
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = c_ret_struct_u64_u64_u64_u64();
+ try expect(s.a == 10);
+ try expect(s.b == 11);
+ try expect(s.c == 12);
+ try expect(s.d == 13);
+ c_struct_u64_u64_u64_u64(.{ .a = 14, .b = 15, .c = 16, .d = 17 }, 18);
+ c_test_struct_u64_u64_u64_u64();
+}
+
+const Struct_f32 = extern struct {
+ a: f32,
+};
+
+export fn zig_ret_struct_f32() Struct_f32 {
+ return .{ .a = 1 };
+}
+export fn zig_struct_f32(s: Struct_f32, i: usize) void {
+ expect(s.a == 2) catch @panic("test failure");
+ expect(i == 3) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_f32() Struct_f32;
+extern fn c_struct_f32(Struct_f32, usize) void;
+extern fn c_test_struct_f32() void;
+
+test "struct f32" {
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
+
+ const s = c_ret_struct_f32();
+ try expect(s.a == 4);
+ c_struct_f32(.{ .a = 5 }, 6);
+ c_test_struct_f32();
+}
+
+const Struct_f32_f32 = extern struct {
+ a: f32,
+ b: f32,
+};
+
+export fn zig_ret_struct_f32_f32() Struct_f32_f32 {
+ return .{ .a = 1, .b = 2 };
+}
+export fn zig_struct_f32_f32(s: Struct_f32_f32, i: usize) void {
+ expect(s.a == 3) catch @panic("test failure");
+ expect(s.b == 4) catch @panic("test failure");
+ expect(i == 5) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_f32_f32() Struct_f32_f32;
+extern fn c_struct_f32_f32(Struct_f32_f32, usize) void;
+extern fn c_test_struct_f32_f32() void;
+
+test "struct f32, f32" {
+ if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
+
+ const s = c_ret_struct_f32_f32();
+ try expect(s.a == 6);
+ try expect(s.b == 7);
+ c_struct_f32_f32(.{ .a = 8, .b = 9 }, 10);
+ c_test_struct_f32_f32();
+}
+
+const Struct_f32_f32_f32 = extern struct {
+ a: f32,
+ b: f32,
+ c: f32,
+};
+
+export fn zig_ret_struct_f32_f32_f32() Struct_f32_f32_f32 {
+ return .{ .a = 1, .b = 2, .c = 3 };
+}
+export fn zig_struct_f32_f32_f32(s: Struct_f32_f32_f32, i: usize) void {
+ expect(s.a == 4) catch @panic("test failure");
+ expect(s.b == 5) catch @panic("test failure");
+ expect(s.c == 6) catch @panic("test failure");
+ expect(i == 7) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_f32_f32_f32() Struct_f32_f32_f32;
+extern fn c_struct_f32_f32_f32(Struct_f32_f32_f32, usize) void;
+extern fn c_test_struct_f32_f32_f32() void;
+
+test "struct f32, f32, f32" {
+ if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = c_ret_struct_f32_f32_f32();
+ try expect(s.a == 8);
+ try expect(s.b == 9);
+ try expect(s.c == 10);
+ c_struct_f32_f32_f32(.{ .a = 11, .b = 12, .c = 13 }, 14);
+ c_test_struct_f32_f32_f32();
+}
+
+const Struct_f32_f32_f32_f32 = extern struct {
+ a: f32,
+ b: f32,
+ c: f32,
+ d: f32,
+};
+
+export fn zig_ret_struct_f32_f32_f32_f32() Struct_f32_f32_f32_f32 {
+ return .{ .a = 1, .b = 2, .c = 3, .d = 4 };
+}
+export fn zig_struct_f32_f32_f32_f32(s: Struct_f32_f32_f32_f32, i: usize) void {
+ expect(s.a == 5) catch @panic("test failure");
+ expect(s.b == 6) catch @panic("test failure");
+ expect(s.c == 7) catch @panic("test failure");
+ expect(s.d == 8) catch @panic("test failure");
+ expect(i == 9) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_f32_f32_f32_f32() Struct_f32_f32_f32_f32;
+extern fn c_struct_f32_f32_f32_f32(Struct_f32_f32_f32_f32, usize) void;
+extern fn c_test_struct_f32_f32_f32_f32() void;
+
+test "struct f32, f32, f32, f32" {
+ if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = c_ret_struct_f32_f32_f32_f32();
+ try expect(s.a == 10);
+ try expect(s.b == 11);
+ try expect(s.c == 12);
+ try expect(s.d == 13);
+ c_struct_f32_f32_f32_f32(.{ .a = 14, .b = 15, .c = 16, .d = 17 }, 18);
+ c_test_struct_f32_f32_f32_f32();
+}
+
+const Struct_f32_f32_f32_f32_f32 = extern struct {
+ a: f32,
+ b: f32,
+ c: f32,
+ d: f32,
+ e: f32,
+};
+
+export fn zig_ret_struct_f32_f32_f32_f32_f32() Struct_f32_f32_f32_f32_f32 {
+ return .{ .a = 1, .b = 2, .c = 3, .d = 4, .e = 5 };
+}
+export fn zig_struct_f32_f32_f32_f32_f32(s: Struct_f32_f32_f32_f32_f32, i: usize) void {
+ expect(s.a == 6) catch @panic("test failure");
+ expect(s.b == 7) catch @panic("test failure");
+ expect(s.c == 8) catch @panic("test failure");
+ expect(s.d == 9) catch @panic("test failure");
+ expect(s.e == 10) catch @panic("test failure");
+ expect(i == 11) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_f32_f32_f32_f32_f32() Struct_f32_f32_f32_f32_f32;
+extern fn c_struct_f32_f32_f32_f32_f32(Struct_f32_f32_f32_f32_f32, usize) void;
+extern fn c_test_struct_f32_f32_f32_f32_f32() void;
+
+test "struct f32, f32, f32, f32, f32" {
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = c_ret_struct_f32_f32_f32_f32_f32();
+ try expect(s.a == 12);
+ try expect(s.b == 13);
+ try expect(s.c == 14);
+ try expect(s.d == 15);
+ try expect(s.e == 16);
+ c_struct_f32_f32_f32_f32_f32(.{ .a = 17, .b = 18, .c = 19, .d = 20, .e = 21 }, 22);
+ c_test_struct_f32_f32_f32_f32_f32();
+}
+
+const Struct_f32a8 = extern struct {
+ a: f32 align(8),
+};
+
+export fn zig_ret_struct_f32a8() Struct_f32a8 {
+ return .{ .a = 1.25 };
+}
+export fn zig_struct_f32a8(s: Struct_f32a8, f: f32) void {
+ expect(s.a == 2.75) catch @panic("test failure");
+ expect(f == 3.5) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_f32a8() Struct_f32a8;
+extern fn c_struct_f32a8(Struct_f32a8, f32) void;
+extern fn c_test_struct_f32a8() void;
+
+test "struct f32 align(8)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86) return error.SkipZigTest;
+
+ const s = c_ret_struct_f32a8();
+ try expect(s.a == 4.125);
+ c_struct_f32a8(.{ .a = 5.375 }, 6.5);
+ c_test_struct_f32a8();
+}
+
+const Struct_f32a8_f32a8 = extern struct {
+ a: f32 align(8),
+ b: f32 align(8),
+};
+
+export fn zig_ret_struct_f32a8_f32a8() Struct_f32a8_f32a8 {
+ return .{ .a = 1.25, .b = 2.75 };
+}
+export fn zig_struct_f32a8_f32a8(s: Struct_f32a8_f32a8, f: f32) void {
+ expect(s.a == 3.125) catch @panic("test failure");
+ expect(s.b == 4.375) catch @panic("test failure");
+ expect(f == 5.5) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_f32a8_f32a8() Struct_f32a8_f32a8;
+extern fn c_struct_f32a8_f32a8(Struct_f32a8_f32a8, f32) void;
+extern fn c_test_struct_f32a8_f32a8() void;
+
+test "struct f32 align(8), f32 align(8)" {
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86) return error.SkipZigTest;
+
+ const s = c_ret_struct_f32a8_f32a8();
+ try expect(s.a == 6.625);
+ try expect(s.b == 7.875);
+ c_struct_f32a8_f32a8(.{ .a = 8.0625, .b = 9.1875 }, 10.5);
+ c_test_struct_f32a8_f32a8();
+}
+
+const Struct_f32f32_f32 = extern struct {
+ a: extern struct { b: f32, c: f32 },
+ d: f32,
+};
+
+export fn zig_ret_struct_f32f32_f32() Struct_f32f32_f32 {
+ return .{ .a = .{ .b = 1.0, .c = 2.0 }, .d = 3.0 };
+}
+export fn zig_struct_f32f32_f32(s: Struct_f32f32_f32) void {
+ expect(s.a.b == 1.0) catch @panic("test failure");
+ expect(s.a.c == 2.0) catch @panic("test failure");
+ expect(s.d == 3.0) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_f32f32_f32() Struct_f32f32_f32;
+extern fn c_struct_f32f32_f32(Struct_f32f32_f32) void;
+extern fn c_test_struct_f32f32_f32() void;
+
+test "struct {f32, f32}, f32" {
+ if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = c_ret_struct_f32f32_f32();
+ try expect(s.a.b == 1.0);
+ try expect(s.a.c == 2.0);
+ try expect(s.d == 3.0);
+ c_struct_f32f32_f32(.{ .a = .{ .b = 1.0, .c = 2.0 }, .d = 3.0 });
+ c_test_struct_f32f32_f32();
+}
+
+const Struct_f32_f32f32 = extern struct {
+ a: f32,
+ b: extern struct { c: f32, d: f32 },
+};
+
+export fn zig_ret_struct_f32_f32f32() Struct_f32_f32f32 {
+ return .{ .a = 1.0, .b = .{ .c = 2.0, .d = 3.0 } };
+}
+export fn zig_struct_f32_f32f32(s: Struct_f32_f32f32) void {
+ expect(s.a == 1.0) catch @panic("test failure");
+ expect(s.b.c == 2.0) catch @panic("test failure");
+ expect(s.b.d == 3.0) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_f32_f32f32() Struct_f32_f32f32;
+extern fn c_struct_f32_f32f32(Struct_f32_f32f32) void;
+extern fn c_test_struct_f32_f32f32() void;
+
+test "struct f32, {f32, f32}" {
+ if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = c_ret_struct_f32_f32f32();
+ try expect(s.a == 1.0);
+ try expect(s.b.c == 2.0);
+ try expect(s.b.d == 3.0);
+ c_struct_f32_f32f32(.{ .a = 1.0, .b = .{ .c = 2.0, .d = 3.0 } });
+ c_test_struct_f32_f32f32();
+}
+
+const Struct_f64 = extern struct {
+ a: f64,
+};
+
+export fn zig_ret_struct_f64() Struct_f64 {
+ return .{ .a = 1 };
+}
+export fn zig_struct_f64(s: Struct_f64, i: usize) void {
+ expect(s.a == 2) catch @panic("test failure");
+ expect(i == 3) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_f64() Struct_f64;
+extern fn c_struct_f64(Struct_f64, usize) void;
+extern fn c_test_struct_f64() void;
+
+test "struct f64" {
+ if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+ if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
+
+ const s = c_ret_struct_f64();
+ try expect(s.a == 4);
+ c_struct_f64(.{ .a = 5 }, 6);
+ c_test_struct_f64();
+}
+
+const Struct_f64_f64 = extern struct {
+ a: f64,
+ b: f64,
+};
+
+export fn zig_ret_struct_f64_f64() Struct_f64_f64 {
+ return .{ .a = 1, .b = 2 };
+}
+export fn zig_struct_f64_f64(s: Struct_f64_f64, i: usize) void {
+ expect(s.a == 3) catch @panic("test failure");
+ expect(s.b == 4) catch @panic("test failure");
+ expect(i == 5) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_f64_f64() Struct_f64_f64;
+extern fn c_struct_f64_f64(Struct_f64_f64, usize) void;
+extern fn c_test_struct_f64_f64() void;
+
+test "struct f64, f64" {
if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
- if (builtin.cpu.arch.isLoongArch() and builtin.abi.float() == .soft) return error.SkipZigTest;
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = c_ret_struct_f64_f64();
+ try expect(s.a == 6);
+ try expect(s.b == 7);
+ c_struct_f64_f64(.{ .a = 8, .b = 9 }, 10);
+ c_test_struct_f64_f64();
+}
+
+const Struct_f64_f64_f64 = extern struct {
+ a: f64,
+ b: f64,
+ c: f64,
+};
+
+export fn zig_ret_struct_f64_f64_f64() Struct_f64_f64_f64 {
+ return .{ .a = 1, .b = 2, .c = 3 };
+}
+export fn zig_struct_f64_f64_f64(s: Struct_f64_f64_f64, i: usize) void {
+ expect(s.a == 4) catch @panic("test failure");
+ expect(s.b == 5) catch @panic("test failure");
+ expect(s.c == 6) catch @panic("test failure");
+ expect(i == 7) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_f64_f64_f64() Struct_f64_f64_f64;
+extern fn c_struct_f64_f64_f64(Struct_f64_f64_f64, usize) void;
+extern fn c_test_struct_f64_f64_f64() void;
+
+test "struct f64, f64, f64" {
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = c_ret_struct_f64_f64_f64();
+ try expect(s.a == 8);
+ try expect(s.b == 9);
+ try expect(s.c == 10);
+ c_struct_f64_f64_f64(.{ .a = 11, .b = 12, .c = 13 }, 14);
+ c_test_struct_f64_f64_f64();
+}
+
+const Struct_f64_f64_f64_f64 = extern struct {
+ a: f64,
+ b: f64,
+ c: f64,
+ d: f64,
+};
+
+export fn zig_ret_struct_f64_f64_f64_f64() Struct_f64_f64_f64_f64 {
+ return .{ .a = 1, .b = 2, .c = 3, .d = 4 };
+}
+export fn zig_struct_f64_f64_f64_f64(s: Struct_f64_f64_f64_f64, i: usize) void {
+ expect(s.a == 5) catch @panic("test failure");
+ expect(s.b == 6) catch @panic("test failure");
+ expect(s.c == 7) catch @panic("test failure");
+ expect(s.d == 8) catch @panic("test failure");
+ expect(i == 9) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_f64_f64_f64_f64() Struct_f64_f64_f64_f64;
+extern fn c_struct_f64_f64_f64_f64(Struct_f64_f64_f64_f64, usize) void;
+extern fn c_test_struct_f64_f64_f64_f64() void;
+
+test "struct f64, f64, f64, f64" {
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = c_ret_struct_f64_f64_f64_f64();
+ try expect(s.a == 10);
+ try expect(s.b == 11);
+ try expect(s.c == 12);
+ try expect(s.d == 13);
+ c_struct_f64_f64_f64_f64(.{ .a = 14, .b = 15, .c = 16, .d = 17 }, 18);
+ c_test_struct_f64_f64_f64_f64();
+}
+
+const Struct_f64_f64_f64_f64_f64 = extern struct {
+ a: f64,
+ b: f64,
+ c: f64,
+ d: f64,
+ e: f64,
+};
+
+export fn zig_ret_struct_f64_f64_f64_f64_f64() Struct_f64_f64_f64_f64_f64 {
+ return .{ .a = 1, .b = 2, .c = 3, .d = 4, .e = 5 };
+}
+export fn zig_struct_f64_f64_f64_f64_f64(s: Struct_f64_f64_f64_f64_f64, i: usize) void {
+ expect(s.a == 6) catch @panic("test failure");
+ expect(s.b == 7) catch @panic("test failure");
+ expect(s.c == 8) catch @panic("test failure");
+ expect(s.d == 9) catch @panic("test failure");
+ expect(s.e == 10) catch @panic("test failure");
+ expect(i == 11) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_f64_f64_f64_f64_f64() Struct_f64_f64_f64_f64_f64;
+extern fn c_struct_f64_f64_f64_f64_f64(Struct_f64_f64_f64_f64_f64, usize) void;
+extern fn c_test_struct_f64_f64_f64_f64_f64() void;
+
+test "struct f64, f64, f64, f64, f64" {
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = c_ret_struct_f64_f64_f64_f64_f64();
+ try expect(s.a == 12);
+ try expect(s.b == 13);
+ try expect(s.c == 14);
+ try expect(s.d == 15);
+ try expect(s.e == 16);
+ c_struct_f64_f64_f64_f64_f64(.{ .a = 17, .b = 18, .c = 19, .d = 20, .e = 21 }, 22);
+ c_test_struct_f64_f64_f64_f64_f64();
+}
+
+const Struct_u32_Union_u32_u32u32 = extern struct {
+ a: u32,
+ b: extern union {
+ c: extern struct {
+ d: u32,
+ e: u32,
+ },
+ },
+};
+
+export fn zig_ret_struct_u32_union_u32_u32u32() Struct_u32_Union_u32_u32u32 {
+ return .{ .a = 1, .b = .{ .c = .{ .d = 2, .e = 3 } } };
+}
+export fn zig_struct_u32_union_u32_u32u32(s: Struct_u32_Union_u32_u32u32) void {
+ expect(s.a == 1) catch @panic("test failure");
+ expect(s.b.c.d == 2) catch @panic("test failure");
+ expect(s.b.c.e == 3) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_u32_union_u32_u32u32() Struct_u32_Union_u32_u32u32;
+extern fn c_struct_u32_union_u32_u32u32(Struct_u32_Union_u32_u32u32) void;
+extern fn c_test_struct_u32_union_u32_u32u32() void;
+
+test "struct{u32,union{u32,struct{u32,u32}}}" {
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = c_ret_struct_u32_union_u32_u32u32();
+ try expect(s.a == 1);
+ try expect(s.b.c.d == 2);
+ try expect(s.b.c.e == 3);
+ c_struct_u32_union_u32_u32u32(.{ .a = 1, .b = .{ .c = .{ .d = 2, .e = 3 } } });
+ c_test_struct_u32_union_u32_u32u32();
+}
+
+const Struct_i32_i32 = extern struct {
+ a: i32,
+ b: i32,
+};
+extern fn c_mut_struct_i32_i32(Struct_i32_i32) Struct_i32_i32;
+extern fn c_struct_i32_i32(Struct_i32_i32) void;
+
+test "struct i32 i32" {
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
- c_ptr_size_float_struct(.{ .x = 1, .y = 2 });
+ const s: Struct_i32_i32 = .{
+ .a = 1,
+ .b = 2,
+ };
+ const mut_res = c_mut_struct_i32_i32(s);
+ try expect(s.a == 1);
+ try expect(s.b == 2);
+ try expect(mut_res.a == 101);
+ try expect(mut_res.b == 252);
+ c_struct_i32_i32(s);
+}
+
+export fn zig_struct_i32_i32(s: Struct_i32_i32) void {
+ expect(s.a == 1) catch @panic("test failure: zig_struct_i32_i32 1");
+ expect(s.b == 2) catch @panic("test failure: zig_struct_i32_i32 2");
+}
+
+const BigStruct = extern struct {
+ a: u64,
+ b: u64,
+ c: u64,
+ d: u64,
+ e: u8,
+};
+extern fn c_big_struct(BigStruct) void;
+
+test "big struct" {
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = BigStruct{
+ .a = 1,
+ .b = 2,
+ .c = 3,
+ .d = 4,
+ .e = 5,
+ };
+ c_big_struct(s);
+}
+
+export fn zig_big_struct(x: BigStruct) void {
+ expect(x.a == 1) catch @panic("test failure: zig_big_struct 1");
+ expect(x.b == 2) catch @panic("test failure: zig_big_struct 2");
+ expect(x.c == 3) catch @panic("test failure: zig_big_struct 3");
+ expect(x.d == 4) catch @panic("test failure: zig_big_struct 4");
+ expect(x.e == 5) catch @panic("test failure: zig_big_struct 5");
+}
+
+const BigUnion = extern union {
+ a: BigStruct,
+};
+extern fn c_big_union(BigUnion) void;
+
+test "big union" {
+ if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const x = BigUnion{
+ .a = BigStruct{
+ .a = 1,
+ .b = 2,
+ .c = 3,
+ .d = 4,
+ .e = 5,
+ },
+ };
+ c_big_union(x);
+}
+
+export fn zig_big_union(x: BigUnion) void {
+ expect(x.a.a == 1) catch @panic("test failure: zig_big_union a");
+ expect(x.a.b == 2) catch @panic("test failure: zig_big_union b");
+ expect(x.a.c == 3) catch @panic("test failure: zig_big_union c");
+ expect(x.a.d == 4) catch @panic("test failure: zig_big_union d");
+ expect(x.a.e == 5) catch @panic("test failure: zig_big_union e");
+}
+
+const MedStructMixed = extern struct {
+ a: u32,
+ b: f32,
+ c: f32,
+ d: u32 = 0,
+};
+extern fn c_med_struct_mixed(MedStructMixed) void;
+extern fn c_ret_med_struct_mixed() MedStructMixed;
+
+test "medium struct of ints and floats" {
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = MedStructMixed{
+ .a = 1234,
+ .b = 100.0,
+ .c = 1337.0,
+ };
+ c_med_struct_mixed(s);
+ const s2 = c_ret_med_struct_mixed();
+ try expect(s2.a == 1234);
+ try expect(s2.b == 100.0);
+ try expect(s2.c == 1337.0);
+}
+
+export fn zig_med_struct_mixed(x: MedStructMixed) void {
+ expect(x.a == 1234) catch @panic("test failure");
+ expect(x.b == 100.0) catch @panic("test failure");
+ expect(x.c == 1337.0) catch @panic("test failure");
+}
+
+const SmallPackedStruct = packed struct(u8) {
+ a: u2,
+ b: u2,
+ c: u2,
+ d: u2,
+};
+extern fn c_small_packed_struct(SmallPackedStruct) void;
+extern fn c_ret_small_packed_struct() SmallPackedStruct;
+
+export fn zig_small_packed_struct(x: SmallPackedStruct) void {
+ expect(x.a == 0) catch @panic("test failure");
+ expect(x.b == 1) catch @panic("test failure");
+ expect(x.c == 2) catch @panic("test failure");
+ expect(x.d == 3) catch @panic("test failure");
+}
+
+test "small packed struct" {
+ const s = SmallPackedStruct{ .a = 0, .b = 1, .c = 2, .d = 3 };
+ c_small_packed_struct(s);
+ const s2 = c_ret_small_packed_struct();
+ try expect(s2.a == 0);
+ try expect(s2.b == 1);
+ try expect(s2.c == 2);
+ try expect(s2.d == 3);
+}
+
+const BigPackedStruct = packed struct(u128) {
+ a: u64,
+ b: u64,
+};
+extern fn c_big_packed_struct(BigPackedStruct) void;
+extern fn c_ret_big_packed_struct() BigPackedStruct;
+
+export fn zig_big_packed_struct(x: BigPackedStruct) void {
+ expect(x.a == 1) catch @panic("test failure");
+ expect(x.b == 2) catch @panic("test failure");
+}
+
+test "big packed struct" {
+ if (!have_i128) return error.SkipZigTest;
+
+ const s = BigPackedStruct{ .a = 1, .b = 2 };
+ c_big_packed_struct(s);
+ const s2 = c_ret_big_packed_struct();
+ try expect(s2.a == 1);
+ try expect(s2.b == 2);
+}
+
+const SplitStructInt = extern struct {
+ a: u64,
+ b: u8,
+ c: u32,
+};
+extern fn c_split_struct_ints(SplitStructInt) void;
+
+test "split struct of ints" {
+ if (builtin.cpu.arch == .x86) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = SplitStructInt{
+ .a = 1234,
+ .b = 100,
+ .c = 1337,
+ };
+ c_split_struct_ints(s);
+}
+
+export fn zig_split_struct_ints(x: SplitStructInt) void {
+ expect(x.a == 1234) catch @panic("test failure");
+ expect(x.b == 100) catch @panic("test failure");
+ expect(x.c == 1337) catch @panic("test failure");
+}
+
+const SplitStructMixed = extern struct {
+ a: u64,
+ b: u8,
+ c: f32,
+};
+extern fn c_split_struct_mixed(SplitStructMixed) void;
+extern fn c_ret_split_struct_mixed() SplitStructMixed;
+
+test "split struct of ints and floats" {
+ if (builtin.cpu.arch == .x86) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = SplitStructMixed{
+ .a = 1234,
+ .b = 100,
+ .c = 1337.0,
+ };
+ c_split_struct_mixed(s);
+ const s2 = c_ret_split_struct_mixed();
+ try expect(s2.a == 1234);
+ try expect(s2.b == 100);
+ try expect(s2.c == 1337.0);
+}
+
+export fn zig_split_struct_mixed(x: SplitStructMixed) void {
+ expect(x.a == 1234) catch @panic("test failure");
+ expect(x.b == 100) catch @panic("test failure");
+ expect(x.c == 1337.0) catch @panic("test failure");
+}
+
+extern fn c_big_struct_both(BigStruct) BigStruct;
+
+test "sret and byval together" {
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ const s = BigStruct{
+ .a = 1,
+ .b = 2,
+ .c = 3,
+ .d = 4,
+ .e = 5,
+ };
+ const y = c_big_struct_both(s);
+ try expect(y.a == 10);
+ try expect(y.b == 11);
+ try expect(y.c == 12);
+ try expect(y.d == 13);
+ try expect(y.e == 14);
+}
+
+export fn zig_big_struct_both(x: BigStruct) BigStruct {
+ expect(x.a == 30) catch @panic("test failure");
+ expect(x.b == 31) catch @panic("test failure");
+ expect(x.c == 32) catch @panic("test failure");
+ expect(x.d == 33) catch @panic("test failure");
+ expect(x.e == 34) catch @panic("test failure");
+ const s = BigStruct{
+ .a = 20,
+ .b = 21,
+ .c = 22,
+ .d = 23,
+ .e = 24,
+ };
+ return s;
+}
+
+export fn zig_ret_bool() bool {
+ return true;
+}
+export fn zig_ret_u8() u8 {
+ return 0xff;
+}
+export fn zig_ret_u16() u16 {
+ return 0xffff;
+}
+export fn zig_ret_u32() u32 {
+ return 0xffffffff;
+}
+export fn zig_ret_u64() u64 {
+ return 0xffffffffffffffff;
+}
+export fn zig_ret_i8() i8 {
+ return -1;
+}
+export fn zig_ret_i16() i16 {
+ return -1;
+}
+export fn zig_ret_i32() i32 {
+ return -1;
+}
+export fn zig_ret_i64() i64 {
+ return -1;
+}
+
+export fn zig_ret_med_struct_mixed() MedStructMixed {
+ return .{
+ .a = 1234,
+ .b = 100.0,
+ .c = 1337.0,
+ };
+}
+
+export fn zig_ret_split_struct_mixed() SplitStructMixed {
+ return .{
+ .a = 1234,
+ .b = 100,
+ .c = 1337.0,
+ };
+}
+
+extern fn c_ret_bool() bool;
+extern fn c_ret_u8() u8;
+extern fn c_ret_u16() u16;
+extern fn c_ret_u32() u32;
+extern fn c_ret_u64() u64;
+extern fn c_ret_i8() i8;
+extern fn c_ret_i16() i16;
+extern fn c_ret_i32() i32;
+extern fn c_ret_i64() i64;
+
+test "integer return types" {
+ try expect(c_ret_bool() == true);
+
+ try expect(c_ret_u8() == 0xff);
+ try expect(c_ret_u16() == 0xffff);
+ try expect(c_ret_u32() == 0xffffffff);
+ try expect(c_ret_u64() == 0xffffffffffffffff);
+
+ try expect(c_ret_i8() == -1);
+ try expect(c_ret_i16() == -1);
+ try expect(c_ret_i32() == -1);
+ try expect(c_ret_i64() == -1);
+}
+
+const StructWithArray = extern struct {
+ a: i32,
+ padding: [4]u8,
+ b: i64,
+};
+extern fn c_struct_with_array(StructWithArray) void;
+extern fn c_ret_struct_with_array() StructWithArray;
+
+test "Struct with array as padding." {
+ if (builtin.cpu.arch == .x86) return error.SkipZigTest;
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ c_struct_with_array(.{ .a = 1, .padding = undefined, .b = 2 });
+
+ const x = c_ret_struct_with_array();
+ try expect(x.a == 4);
+ try expect(x.b == 155);
+}
+
+const FloatArrayStruct = extern struct {
+ origin: extern struct {
+ x: f64,
+ y: f64,
+ },
+ size: extern struct {
+ width: f64,
+ height: f64,
+ },
+};
+
+extern fn c_float_array_struct(FloatArrayStruct) void;
+extern fn c_ret_float_array_struct() FloatArrayStruct;
+
+test "Float array like struct" {
+ if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
+ if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+ if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+
+ c_float_array_struct(.{
+ .origin = .{
+ .x = 5,
+ .y = 6,
+ },
+ .size = .{
+ .width = 7,
+ .height = 8,
+ },
+ });
- const x = c_ret_ptr_size_float_struct();
- try expect(x.x == 3);
- try expect(x.y == 4);
+ const x = c_ret_float_array_struct();
+ try expect(x.origin.x == 1);
+ try expect(x.origin.y == 2);
+ try expect(x.size.width == 3);
+ try expect(x.size.height == 4);
}
//=== Helpers for struct test ===//
@@ -6135,7 +17111,8 @@ const byval_tail_callsite_attr = struct {
}
fn cast(self: MyRect) struct_Rect {
- return @bitCast(self);
+ const ptr: *const struct_Rect = @ptrCast(&self);
+ return ptr.*;
}
extern fn c_byval_tail_callsite_attr(struct_Rect) f64;
@@ -6161,22 +17138,118 @@ test "byval tail callsite attribute" {
}
test "x86 fastcall calling convention" {
- if (builtin.cpu.arch != .x86) return error.SkipZigTest;
+ if (builtin.cpu.arch != .x86 or builtin.os.tag != .windows or builtin.abi != .msvc) return error.SkipZigTest;
+
const static = struct {
- extern fn c_fastcall_check(a: c_int, b: f32, c: *anyopaque, d: f64, e: c_int) callconv(.{ .x86_fastcall = .{} }) void;
- export fn zig_fastcall_check(a: c_int, b: f32, c: *anyopaque, d: f64, e: c_int) callconv(.{ .x86_fastcall = .{} }) void {
+ const fastcall: std.builtin.CallingConvention = .{ .x86_fastcall = .{} };
+
+ extern fn c_fastcall_check(a: c_int, b: f32, c: *anyopaque, d: f64, e: c_int) callconv(fastcall) void;
+ export fn zig_fastcall_check(a: c_int, b: f32, c: *anyopaque, d: f64, e: c_int) callconv(fastcall) void {
if (a != 1) @panic("test failure");
if (b != 2.0) @panic("test failure");
if (@intFromPtr(c) != 3) @panic("test failure");
if (d != 4.0) @panic("test failure");
if (e != 5) @panic("test failure");
}
+
+ const SRet = extern struct {
+ a: i32,
+ b: i32,
+ c: i32,
+ };
+ extern fn c_fastcall_sret() callconv(fastcall) SRet;
+ export fn zig_fastcall_sret() callconv(fastcall) SRet {
+ return .{
+ .a = 1,
+ .b = 2,
+ .c = 3,
+ };
+ }
+
+ const NoSRet = extern struct {
+ a: i8,
+ b: i16,
+ };
+ extern fn c_fastcall_no_sret() callconv(fastcall) NoSRet;
+ export fn zig_fastcall_no_sret() callconv(fastcall) NoSRet {
+ return .{
+ .a = 1,
+ .b = 2,
+ };
+ }
+
+ const NoSRetF32F32 = extern struct {
+ a: f32,
+ b: f32,
+ };
+ extern fn c_fastcall_no_sret_f32_f32() callconv(fastcall) NoSRetF32F32;
+ export fn zig_fastcall_no_sret_f32_f32() callconv(fastcall) NoSRetF32F32 {
+ return .{
+ .a = 1,
+ .b = 2,
+ };
+ }
+
+ const NoSRetF64 = extern struct {
+ a: f64,
+ };
+ extern fn c_fastcall_no_sret_f64() callconv(fastcall) NoSRetF64;
+ export fn zig_fastcall_no_sret_f64() callconv(fastcall) NoSRetF64 {
+ return .{
+ .a = 1,
+ };
+ }
+
+ extern fn c_fastcall_ret_f32() callconv(fastcall) f32;
+ export fn zig_fastcall_ret_f32() callconv(fastcall) f32 {
+ return 1;
+ }
+
+ extern fn c_fastcall_ret_f64() callconv(fastcall) f64;
+ export fn zig_fastcall_ret_f64() callconv(fastcall) f64 {
+ return 1;
+ }
+
+ extern fn run_c_fastcall_tests() void;
};
+
static.c_fastcall_check(1, 2.0, @ptrFromInt(3), 4.0, 5);
+
+ {
+ const s = static.c_fastcall_sret();
+ try expect(s.a == 1);
+ try expect(s.b == 2);
+ try expect(s.c == 3);
+ }
+ {
+ const s = static.c_fastcall_no_sret();
+ try expect(s.a == 1);
+ try expect(s.b == 2);
+ }
+ {
+ const s = static.c_fastcall_no_sret_f32_f32();
+ try expect(s.a == 1);
+ try expect(s.b == 2);
+ }
+ {
+ const s = static.c_fastcall_no_sret_f64();
+ try expect(s.a == 1);
+ }
+ {
+ const s = static.c_fastcall_ret_f32();
+ try expect(s == 1);
+ }
+ {
+ const s = static.c_fastcall_ret_f64();
+ try expect(s == 1);
+ }
+
+ static.run_c_fastcall_tests();
}
test "x86 vectorcall calling convention" {
- if (builtin.cpu.arch != .x86) return error.SkipZigTest;
+ if (builtin.cpu.arch != .x86 or builtin.os.tag != .windows or builtin.abi != .msvc) return error.SkipZigTest;
+
const static = struct {
extern fn c_vectorcall_check(a: c_int, b: f32, c: f64, d: *anyopaque, e: f32, f: f64, g: f64, h: f32, i: f32, j: c_int) callconv(.{ .x86_vectorcall = .{} }) void;
export fn zig_vectorcall_check(a: c_int, b: f32, c: f64, d: *anyopaque, e: f32, f: f64, g: f64, h: f32, i: f32, j: c_int) callconv(.{ .x86_vectorcall = .{} }) void {
@@ -6194,3 +17267,34 @@ test "x86 vectorcall calling convention" {
};
static.c_vectorcall_check(1, 2.0, 3.0, @ptrFromInt(4), 5.0, 6.0, 7.0, 8.0, 9.0, 10);
}
+
+extern fn c_win64_varargs_u64_f64_u64_f64(...) void;
+extern fn c_win64_varargs_f64_u64_f64_u64(...) void;
+
+test "win64 varargs" {
+ if (builtin.cpu.arch != .x86_64 or builtin.os.tag != .windows) return error.SkipZigTest;
+
+ const Opv = extern struct {};
+ c_win64_varargs_u64_f64_u64_f64(
+ @as(Opv, .{}),
+ @as(f32, 1),
+ @as(Opv, .{}),
+ @as(f32, 2.0),
+ @as(Opv, .{}),
+ @as(f64, 3),
+ @as(Opv, .{}),
+ @as(f64, 4.0),
+ @as(Opv, .{}),
+ );
+ c_win64_varargs_f64_u64_f64_u64(
+ @as(Opv, .{}),
+ @as(f32, 5),
+ @as(Opv, .{}),
+ @as(f32, 6.0),
+ @as(Opv, .{}),
+ @as(f64, 7),
+ @as(Opv, .{}),
+ @as(f64, 8.0),
+ @as(Opv, .{}),
+ );
+}
diff --git a/test/cases/callconv_spirv.zig b/test/cases/callconv_spirv.zig
new file mode 100644
index 0000000000000000000000000000000000000000..25be9d0c27a7493811da50525ce5de0bf696c001
--- /dev/null
+++ b/test/cases/callconv_spirv.zig
@@ -0,0 +1,12 @@
+export fn vert() callconv(.spirv_vertex) void {}
+export fn frag() callconv(.{ .spirv_fragment = .{ .depth_assumption = .greater } }) void {}
+export fn comp() callconv(.{ .spirv_kernel = .{ .x = 8, .y = 8, .z = 1 } }) void {}
+export fn task() callconv(.{ .spirv_task = .{ .x = 1, .y = 1, .z = 1 } }) void {}
+export fn mesh() callconv(.{ .spirv_mesh = .{ .stage_output = .output_lines, .max_primitives = 1, .max_vertices = 2 } }) void {}
+
+// compile
+// output_mode=Obj
+// backend=selfhosted
+// target=spirv32-vulkan
+// cpu_features=vulkan_v1_2+mesh_shading_ext
+// emit_bin=true
diff --git a/test/cases/compile_errors/@breakpoint_comptime_call.zig b/test/cases/compile_errors/@breakpoint_comptime_call.zig
new file mode 100644
index 0000000000000000000000000000000000000000..7183e83dc9a2bb414ef1ddd751f090cd20ada798
--- /dev/null
+++ b/test/cases/compile_errors/@breakpoint_comptime_call.zig
@@ -0,0 +1,7 @@
+export fn entry() void {
+ comptime @breakpoint();
+}
+
+// error
+//
+// :2:14: error: encountered @breakpoint at comptime
diff --git a/test/cases/compile_errors/SpirvType_is_a_compile_error_in_non-SPIRV_targets.zig b/test/cases/compile_errors/SpirvType_is_a_compile_error_in_non-SPIRV_targets.zig
new file mode 100644
index 0000000000000000000000000000000000000000..431c9c1b61297e517a4e414ac40a5963c0204e78
--- /dev/null
+++ b/test/cases/compile_errors/SpirvType_is_a_compile_error_in_non-SPIRV_targets.zig
@@ -0,0 +1,9 @@
+comptime {
+ _ = @SpirvType(.{ .runtime_array = u32 });
+}
+
+// error
+// backend=selfhosted
+// target=x86_64-native
+//
+// :2:9: error: builtin @SpirvType is only available when targeting SPIR-V; targeted CPU architecture is x86_64
diff --git a/test/cases/compile_errors/SpirvType_vulkan_target.zig b/test/cases/compile_errors/SpirvType_vulkan_target.zig
new file mode 100644
index 0000000000000000000000000000000000000000..fdb53678e3139870df23563a9b2ac5494e524cea
--- /dev/null
+++ b/test/cases/compile_errors/SpirvType_vulkan_target.zig
@@ -0,0 +1,56 @@
+comptime {
+ _ = @SpirvType(.{ .image = .{
+ .usage = .{ .storage = u32 },
+ .format = .unknown,
+ .dim = .@"2d",
+ .depth = .unknown,
+ .arrayed = false,
+ .multisampled = false,
+ .access = .read_only,
+ } });
+}
+
+comptime {
+ _ = @SpirvType(.{ .image = .{
+ .usage = .{ .sampled = bool },
+ .format = .unknown,
+ .dim = .@"2d",
+ .depth = .unknown,
+ .arrayed = false,
+ .multisampled = false,
+ .access = .unknown,
+ } });
+}
+
+comptime {
+ _ = @SpirvType(.{ .image = .{
+ .usage = .{ .sampled = void },
+ .format = .unknown,
+ .dim = .@"2d",
+ .depth = .unknown,
+ .arrayed = false,
+ .multisampled = false,
+ .access = .unknown,
+ } });
+}
+
+comptime {
+ _ = @SpirvType(.{ .image = .{
+ .usage = .{ .sampled = u24 },
+ .format = .unknown,
+ .dim = .@"2d",
+ .depth = .unknown,
+ .arrayed = false,
+ .multisampled = false,
+ .access = .unknown,
+ } });
+}
+
+// error
+// backend=selfhosted
+// target=spirv32-vulkan
+//
+// :2:21: error: access qualifier '.read_only' is only valid under the 'opencl' os
+// :14:21: error: invalid 'sampled' field value 'bool'
+// :26:21: error: 'void' type for 'sampled' field is only valid under the 'opencl' os
+// :38:21: error: 'sampled' field value must be a 32-bit int, 64-bit int or 32-bit float under the 'vulkan' os
diff --git a/test/cases/compile_errors/asm_output_type_no_guaranteed_in_memory_layout.zig b/test/cases/compile_errors/asm_output_type_no_guaranteed_in_memory_layout.zig
index 85be7d3c27ba384a96eb7575bdb579e4a3e3bdff..ddb26058d0e73198537b27708602822eb8678555 100644
--- a/test/cases/compile_errors/asm_output_type_no_guaranteed_in_memory_layout.zig
+++ b/test/cases/compile_errors/asm_output_type_no_guaranteed_in_memory_layout.zig
@@ -25,14 +25,38 @@ export fn entry4() void {
: [_] "=r" (u),
);
}
+const ES = extern struct { x: u32 };
+export fn entry5() void {
+ var es: ES = undefined;
+ asm volatile (""
+ : [_] "=r" (es),
+ );
+}
+const EU = extern union { x: u32 };
+export fn entry6() void {
+ var eu: EU = undefined;
+ asm volatile (""
+ : [_] "=r" (eu),
+ );
+}
// error
//
-// :4:24: error: invalid inline assembly output type; 'tmp.S' does not have a guaranteed in-memory layout
+// :4:24: error: invalid inline assembly output type 'tmp.S'
+// :4:24: note: struct types cannot be passed to inline assembly
// :1:11: note: struct declared here
-// :11:21: error: invalid inline assembly output type; 'tmp.S' does not have a guaranteed in-memory layout
+// :11:21: error: invalid inline assembly output type 'tmp.S'
+// :11:21: note: struct types cannot be passed to inline assembly
// :1:11: note: struct declared here
-// :18:24: error: invalid inline assembly output type; 'tmp.U' does not have a guaranteed in-memory layout
+// :18:24: error: invalid inline assembly output type 'tmp.U'
+// :18:24: note: union types cannot be passed to inline assembly
// :15:11: note: union declared here
-// :25:21: error: invalid inline assembly output type; 'tmp.U' does not have a guaranteed in-memory layout
+// :25:21: error: invalid inline assembly output type 'tmp.U'
+// :25:21: note: union types cannot be passed to inline assembly
// :15:11: note: union declared here
+// :32:21: error: invalid inline assembly output type 'tmp.ES'
+// :32:21: note: struct types cannot be passed to inline assembly
+// :28:19: note: struct declared here
+// :39:21: error: invalid inline assembly output type 'tmp.EU'
+// :39:21: note: union types cannot be passed to inline assembly
+// :35:19: note: union declared here
diff --git a/test/cases/compile_errors/bitCast_extern_struct.zig b/test/cases/compile_errors/bitCast_extern_struct.zig
new file mode 100644
index 0000000000000000000000000000000000000000..2c0c9b3cd0fd63ae90fb27bbcd04d7def708373e
--- /dev/null
+++ b/test/cases/compile_errors/bitCast_extern_struct.zig
@@ -0,0 +1,10 @@
+const S = extern struct { x: u32 };
+export fn foo(s: S) void {
+ const as_int: u32 = @bitCast(s);
+ _ = as_int;
+}
+
+// error
+//
+// :3:34: error: cannot @bitCast from 'tmp.S'
+// :1:18: note: struct declared here
diff --git a/test/cases/compile_errors/bitCast_to_enum_type.zig b/test/cases/compile_errors/bitCast_to_enum_type.zig
deleted file mode 100644
index 3ae88d65f95cbd7dc080d56a9fa45c47fb056bc5..0000000000000000000000000000000000000000
--- a/test/cases/compile_errors/bitCast_to_enum_type.zig
+++ /dev/null
@@ -1,10 +0,0 @@
-export fn entry() void {
- const E = enum(u32) { a, b };
- const y: E = @bitCast(@as(u32, 3));
- _ = y;
-}
-
-// error
-//
-// :3:18: error: cannot @bitCast to 'tmp.entry.E'
-// :3:18: note: use @enumFromInt to cast from 'u32'
diff --git a/test/cases/compile_errors/bitCast_vector_of_pointer.zig b/test/cases/compile_errors/bitCast_vector_of_pointer.zig
new file mode 100644
index 0000000000000000000000000000000000000000..d9b5a3f1b3b2f5360215f085c1c48e3aece1d5d4
--- /dev/null
+++ b/test/cases/compile_errors/bitCast_vector_of_pointer.zig
@@ -0,0 +1,9 @@
+export fn foo(p: *u32) void {
+ const vec: @Vector(2, *u32) = .{ p, p };
+ const raw: [2]usize = @bitCast(vec);
+ _ = raw;
+}
+
+// error
+//
+// :3:36: error: cannot @bitCast from '@Vector(2, *u32)'
diff --git a/test/cases/compile_errors/bitCast_with_invalid_array_element_type.zig b/test/cases/compile_errors/bitCast_with_invalid_array_element_type.zig
index bf1bacda487048439166e853a8d5720c1c4f9bc3..bc04258d26921f4543a7b3b962ee57cab82c9aaa 100644
--- a/test/cases/compile_errors/bitCast_with_invalid_array_element_type.zig
+++ b/test/cases/compile_errors/bitCast_with_invalid_array_element_type.zig
@@ -18,9 +18,6 @@ export fn baz() void {
// error
//
-// :5:29: error: cannot @bitCast from '[1]tmp.foo.S'
-// :5:29: note: array element type 'tmp.foo.S' does not have a guaranteed in-memory layout
+// :5:42: error: cannot @bitCast from '[1]tmp.foo.S'
// :12:19: error: cannot @bitCast to '[1]tmp.bar.S'
-// :12:19: note: array element type 'tmp.bar.S' does not have a guaranteed in-memory layout
-// :16:21: error: cannot @bitCast from '[1]comptime_int'
-// :16:21: note: array element type 'comptime_int' does not have a guaranteed in-memory layout
+// :16:45: error: cannot @bitCast from '[1]comptime_int'
diff --git a/test/cases/compile_errors/callconv_spirv_invalid_options.zig b/test/cases/compile_errors/callconv_spirv_invalid_options.zig
new file mode 100644
index 0000000000000000000000000000000000000000..a04646f3c20ccc9387d8aea1c70fd5dbdac951d2
--- /dev/null
+++ b/test/cases/compile_errors/callconv_spirv_invalid_options.zig
@@ -0,0 +1,29 @@
+const F1 = fn () callconv(.{ .spirv_kernel = .{ .x = 0, .y = 1, .z = 1 } }) void;
+const F2 = fn () callconv(.{ .spirv_task = .{ .x = 1, .y = 0, .z = 1 } }) void;
+const F3 = fn () callconv(.{ .spirv_mesh = .{ .max_vertices = 0 } }) void;
+const F4 = fn () callconv(.{ .spirv_fragment = .{ .pixel_centered_integer = true } }) void;
+export fn entry1() void {
+ const a: F1 = undefined;
+ _ = a;
+}
+export fn entry2() void {
+ const a: F2 = undefined;
+ _ = a;
+}
+export fn entry3() void {
+ const a: F3 = undefined;
+ _ = a;
+}
+export fn entry4() void {
+ const a: F4 = undefined;
+ _ = a;
+}
+
+// error
+// backend=selfhosted
+// target=spirv32-vulkan
+//
+// :1:28: error: kernel workgroup dimensions must be at least 1
+// :2:28: error: kernel workgroup dimensions must be at least 1
+// :3:28: error: mesh shader 'max_vertices' and 'max_primitives' must be at least 1
+// :4:28: error: 'pixel_centered_integer' is not supported on this target
diff --git a/test/cases/compile_errors/callconv_spirv_on_unsupported_platform.zig b/test/cases/compile_errors/callconv_spirv_on_unsupported_platform.zig
new file mode 100644
index 0000000000000000000000000000000000000000..1c41095021ad498dce4178d67556f1eb7b45e8d4
--- /dev/null
+++ b/test/cases/compile_errors/callconv_spirv_on_unsupported_platform.zig
@@ -0,0 +1,30 @@
+const F1 = fn () callconv(.{ .spirv_fragment = .{} }) void;
+const F2 = fn () callconv(.spirv_vertex) void;
+const F3 = fn () callconv(.{ .spirv_task = .{ .x = 1, .y = 1, .z = 1 } }) void;
+const F4 = fn () callconv(.{ .spirv_mesh = .{} }) void;
+export fn entry1() void {
+ const a: F1 = undefined;
+ _ = a;
+}
+export fn entry2() void {
+ const a: F2 = undefined;
+ _ = a;
+}
+export fn entry3() void {
+ const a: F3 = undefined;
+ _ = a;
+}
+export fn entry4() void {
+ const a: F4 = undefined;
+ _ = a;
+}
+
+// error
+// backend=selfhosted
+// target=spirv64-opencl
+// cpu_features=opencl_v2+mesh_shading_ext
+//
+// :1:28: error: calling convention 'spirv_fragment' not supported by compiler backend 'stage2_spirv'
+// :2:28: error: calling convention 'spirv_vertex' not supported by compiler backend 'stage2_spirv'
+// :3:28: error: calling convention 'spirv_task' not supported by compiler backend 'stage2_spirv'
+// :4:28: error: calling convention 'spirv_mesh' not supported by compiler backend 'stage2_spirv'
diff --git a/test/cases/compile_errors/callconv_stack_alignment_coerce.zig b/test/cases/compile_errors/callconv_stack_alignment_coerce.zig
new file mode 100644
index 0000000000000000000000000000000000000000..0f09ba230038853d395a5d44dc3699df96960628
--- /dev/null
+++ b/test/cases/compile_errors/callconv_stack_alignment_coerce.zig
@@ -0,0 +1,10 @@
+fn foo() callconv(.{ .x86_64_sysv = .{ .incoming_stack_alignment = 32 } }) void {}
+const Bar = *const fn () callconv(.{ .x86_64_sysv = .{ .incoming_stack_alignment = 16 } }) void;
+export var p: Bar = &foo;
+
+// error
+// target=x86_64-linux-none
+//
+// :3:21: error: expected type '*const fn () callconv(.{ .x86_64_sysv = .{ .incoming_stack_alignment = 16 } }) void', found '*const fn () callconv(.{ .x86_64_sysv = .{ .incoming_stack_alignment = 32 } }) void'
+// :3:21: note: pointer type child 'fn () callconv(.{ .x86_64_sysv = .{ .incoming_stack_alignment = 32 } }) void' cannot cast into pointer type child 'fn () callconv(.{ .x86_64_sysv = .{ .incoming_stack_alignment = 16 } }) void'
+// :3:21: note: calling convention 'x86_64_sysv' cannot cast into calling convention 'x86_64_sysv'
diff --git a/test/cases/compile_errors/comptime_var_referenced_at_runtime.zig b/test/cases/compile_errors/comptime_var_referenced_at_runtime.zig
index 603ce497326d547334cf5a99af0ff4fbb1e2c04d..897c298e6181ff75fd866370674e0ea769f7ae2c 100644
--- a/test/cases/compile_errors/comptime_var_referenced_at_runtime.zig
+++ b/test/cases/compile_errors/comptime_var_referenced_at_runtime.zig
@@ -71,6 +71,12 @@ export fn bax() void {
@memmove(&rt, &x);
}
+export fn qoo(i: u8) void {
+ comptime var x: u32 = 123;
+ const y = .{ .p = &x, .i = i };
+ _ = y;
+}
+
// error
//
// :5:19: error: runtime value contains reference to comptime var
@@ -103,3 +109,6 @@ export fn bax() void {
// :71:19: error: runtime value contains reference to comptime var
// :71:19: note: comptime var pointers are not available at runtime
// :67:14: note: 'runtime_value' points to comptime var declared here
+// :76:19: error: runtime value contains reference to comptime var
+// :76:19: note: comptime var pointers are not available at runtime
+// :75:14: note: 'runtime_value' points to comptime var declared here
diff --git a/test/cases/compile_errors/deref_ptr_to_comptime_only_type.zig b/test/cases/compile_errors/deref_ptr_to_comptime_only_type.zig
new file mode 100644
index 0000000000000000000000000000000000000000..cc453d616fbe4dd836a069a034e61498f1b33dce
--- /dev/null
+++ b/test/cases/compile_errors/deref_ptr_to_comptime_only_type.zig
@@ -0,0 +1,9 @@
+export fn entry(ptr: *anyopaque) void {
+ const ct_only: *type = @ptrCast(ptr);
+ _ = ct_only.*;
+}
+
+// error
+//
+// :3:16: error: cannot load comptime-only type 'type'
+// :3:9: note: pointer of type '*type' is runtime-known
diff --git a/test/cases/compile_errors/directly_embedding_spirv_type_in_struct_and_union.zig b/test/cases/compile_errors/directly_embedding_spirv_type_in_struct_and_union.zig
new file mode 100644
index 0000000000000000000000000000000000000000..732db0b4408883a1e0aaacf019bb6c459d62205f
--- /dev/null
+++ b/test/cases/compile_errors/directly_embedding_spirv_type_in_struct_and_union.zig
@@ -0,0 +1,35 @@
+const Sampler = @SpirvType(.sampler);
+const RuntimeArray = @SpirvType(.{ .runtime_array = u32 });
+const Foo = struct {
+ s: Sampler,
+};
+const Baz = struct {
+ a: RuntimeArray,
+};
+const Qux = extern struct {
+ a: RuntimeArray,
+ b: u32,
+};
+export fn a() void {
+ var foo: Foo = undefined;
+ _ = &foo;
+}
+export fn c() void {
+ var baz: Baz = undefined;
+ _ = &baz;
+}
+export fn d() void {
+ var qux: Qux = undefined;
+ _ = &qux;
+}
+
+// error
+// backend=selfhosted
+// target=spirv32-vulkan
+//
+// :4:8: error: cannot directly embed SPIR-V type 'tmp.Sampler__SpirvType_4' in struct
+// :4:8: note: opaque types have unknown size
+// :6:13: error: non-extern struct cannot contain fields of type 'tmp.RuntimeArray__SpirvType_11'
+// :7:5: note: while checking this field
+// :9:20: error: struct field of type 'tmp.RuntimeArray__SpirvType_11' must be the last field
+// :10:5: note: while checking this field
diff --git a/test/cases/compile_errors/error_in_nested_declaration.zig b/test/cases/compile_errors/error_in_nested_declaration.zig
new file mode 100644
index 0000000000000000000000000000000000000000..d1eb73a0cc878a11ee29c48fdffa6d9fd991ca17
--- /dev/null
+++ b/test/cases/compile_errors/error_in_nested_declaration.zig
@@ -0,0 +1,29 @@
+const S = struct {
+ b: u32,
+ c: i32,
+ a: struct {
+ pub fn str(_: @This(), extra: []u32) []i32 {
+ return @bitCast(extra);
+ }
+ },
+};
+
+pub export fn entry() void {
+ var s: S = undefined;
+ _ = s.a.str(undefined);
+}
+
+const S2 = struct {
+ a: [*c]anyopaque,
+};
+
+pub export fn entry2() void {
+ var s: S2 = undefined;
+ _ = &s;
+}
+
+// error
+//
+// :6:20: error: cannot @bitCast to '[]i32'
+// :6:20: note: use @ptrCast to cast from '[]u32'
+// :17:12: error: indexable pointer to opaque type 'anyopaque' not allowed
diff --git a/test/cases/compile_errors/extern_spirv_decoration_validation.zig b/test/cases/compile_errors/extern_spirv_decoration_validation.zig
new file mode 100644
index 0000000000000000000000000000000000000000..ea51feb3b931f5d6a93d8640a9a8819251bb3cfc
--- /dev/null
+++ b/test/cases/compile_errors/extern_spirv_decoration_validation.zig
@@ -0,0 +1,13 @@
+const x = @extern(*addrspace(.output) u32, .{
+ .name = "x",
+ .decoration = .{ .flat = 0 },
+});
+comptime {
+ _ = x;
+}
+
+// error
+// backend=selfhosted
+// target=spirv32-vulkan
+//
+// :1:45: error: 'flat' decoration requires 'input' address space
diff --git a/test/cases/compile_errors/illegal_operation_on_logical_ptr.zig b/test/cases/compile_errors/illegal_operation_on_logical_ptr.zig
index 85decd8a6c29fb74f56ffefcc5bb99d3fd5e2339..859f0be6d37f1961be9f2bc295daeb330858b3cd 100644
--- a/test/cases/compile_errors/illegal_operation_on_logical_ptr.zig
+++ b/test/cases/compile_errors/illegal_operation_on_logical_ptr.zig
@@ -1,15 +1,3 @@
-export fn elemPtr() void {
- var ptr: [*]u8 = undefined;
- ptr[0] = 0;
-}
-
-export fn elemVal() void {
- var ptr: [*]u8 = undefined;
- var val = ptr[0];
- _ = &ptr;
- _ = &val;
-}
-
export fn intFromPtr() void {
var value: u8 = 0;
_ = @intFromPtr(&value);
@@ -37,15 +25,11 @@ export fn ptrIntArithmetic() void {
// error
// target=spirv64-vulkan
//
-// :3:8: error: illegal operation on logical pointer of type '[*]u8'
-// :3:8: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan
-// :8:18: error: illegal operation on logical pointer of type '[*]u8'
-// :8:18: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan
-// :15:21: error: illegal operation on logical pointer of type '*u8'
-// :15:21: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan
-// :20:20: error: illegal operation on logical pointer of type '*u8'
-// :20:20: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan
-// :28:17: error: illegal operation on logical pointer of type '*u8'
-// :28:17: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan
-// :34:14: error: illegal operation on logical pointer of type '[*]u8'
-// :34:14: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan
+// :3:21: error: illegal operation on logical pointer of type '*u8'
+// :3:21: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan
+// :8:20: error: illegal operation on logical pointer of type '*u8'
+// :8:20: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan
+// :16:17: error: illegal operation on logical pointer of type '*u8'
+// :16:17: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan
+// :22:14: error: illegal operation on logical pointer of type '[*]u8'
+// :22:14: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan
diff --git a/test/cases/compile_errors/indexing_non-tuple_struct.zig b/test/cases/compile_errors/indexing_non-tuple_struct.zig
index b46852c2660836bf2ac6ff063cf9c36d2bb5626c..d3d792f47f609a1c074a5ff6e3b8cb2355c17f85 100644
--- a/test/cases/compile_errors/indexing_non-tuple_struct.zig
+++ b/test/cases/compile_errors/indexing_non-tuple_struct.zig
@@ -8,3 +8,4 @@ export fn a() void {
//
// :4:6: error: type 'tmp.a.S' does not support indexing
// :4:6: note: operand must be an array, slice, tuple, or vector
+// :2:15: note: struct declared here
diff --git a/test/cases/compile_errors/inline_return.zig b/test/cases/compile_errors/inline_return.zig
new file mode 100644
index 0000000000000000000000000000000000000000..e761e78e211d1d26a3040cd8afe30eb549caeb8e
--- /dev/null
+++ b/test/cases/compile_errors/inline_return.zig
@@ -0,0 +1,16 @@
+inline fn select(cond: bool, a: anytype, b: anytype) @TypeOf(a, b) {
+ if (cond) {
+ return a;
+ } else {
+ return b;
+ }
+}
+export fn f(x: u32) u32 {
+ return select(x > 0, 2, 1);
+}
+
+// error
+//
+// :9:18: error: value with comptime-only type 'comptime_int' depends on runtime control flow
+// :2:9: note: runtime control flow here
+// :9:18: note: called inline here
diff --git a/test/cases/compile_errors/primitive_integer_type_with_leading_zero.zig b/test/cases/compile_errors/primitive_integer_type_with_leading_zero.zig
new file mode 100644
index 0000000000000000000000000000000000000000..8492f3444b316338d2d1ad31472e92a589b673d7
--- /dev/null
+++ b/test/cases/compile_errors/primitive_integer_type_with_leading_zero.zig
@@ -0,0 +1,7 @@
+export fn entry1() void {
+ _ = u032;
+}
+
+// error
+//
+// :2:9: error: primitive integer type 'u032' has leading zero
diff --git a/test/cases/compile_errors/runtime_align.zig b/test/cases/compile_errors/runtime_align.zig
new file mode 100644
index 0000000000000000000000000000000000000000..d9356f7a4169f16e37d2155c5a68869a3738eb12
--- /dev/null
+++ b/test/cases/compile_errors/runtime_align.zig
@@ -0,0 +1,46 @@
+var alignment: u29 = 4;
+
+var global: u8 align(alignment) = 0;
+export fn globalWithRuntimeAlign() u8 {
+ return global;
+}
+
+export fn localWithRuntimeAlign() u8 {
+ const local: u8 align(alignment) = 0;
+ return local;
+}
+
+export fn destructureWithRuntimeAlign() u8 {
+ const de: u8 align(alignment), const structure align(alignment) = .{ 0, 0 };
+ return de | structure;
+}
+
+export fn structFieldWithRuntimeAlign() u8 {
+ const @"struct": struct { field: u8 align(alignment) } = .{ .field = 0 };
+ return @"struct".field;
+}
+
+export fn unionFieldWithRuntimeAlign() u8 {
+ const @"union": union { field: u8 align(alignment) } = .{ .field = 0 };
+ return @"union".field;
+}
+
+export fn pointerWithRuntimeAlign() u8 {
+ const ptr: *align(alignment) u8 = &global;
+ return ptr.*;
+}
+
+// error
+//
+// :3:22: error: unable to resolve comptime value
+// :3:22: note: alignment must be comptime-known
+// :9:27: error: unable to resolve comptime value
+// :9:27: note: alignment must be comptime-known
+// :14:24: error: unable to resolve comptime value
+// :14:24: note: alignment must be comptime-known
+// :19:47: error: unable to resolve comptime value
+// :19:47: note: alignment must be comptime-known
+// :24:45: error: unable to resolve comptime value
+// :24:45: note: alignment must be comptime-known
+// :29:23: error: unable to resolve comptime value
+// :29:23: note: alignment must be comptime-known
diff --git a/test/cases/compile_errors/runtime_bound_arg_with_comptime_param.zig b/test/cases/compile_errors/runtime_bound_arg_with_comptime_param.zig
new file mode 100644
index 0000000000000000000000000000000000000000..398d6c77c89b58f2a6106119999c2f922b23d3d8
--- /dev/null
+++ b/test/cases/compile_errors/runtime_bound_arg_with_comptime_param.zig
@@ -0,0 +1,22 @@
+pub const A = enum {
+ a1,
+ a2,
+
+ pub fn x(comptime _: A) usize {
+ return 0;
+ }
+
+ pub fn y(self: A) usize {
+ return self.x();
+ }
+};
+
+pub fn main() void {
+ _ = A.y(.a1);
+}
+
+// error
+//
+// :10:20: error: unable to resolve comptime value
+// :10:20: note: argument to comptime parameter must be comptime-known
+// :5:14: note: parameter declared comptime here
diff --git a/test/cases/compile_errors/spirv_merge_logical_pointers.zig b/test/cases/compile_errors/spirv_merge_logical_pointers.zig
index 09ee6dd78cfc9509b5bb3cb3067119ed886ce75c..ccceef8097c8418dcfc363f6baa87c0e04073b3c 100644
--- a/test/cases/compile_errors/spirv_merge_logical_pointers.zig
+++ b/test/cases/compile_errors/spirv_merge_logical_pointers.zig
@@ -11,8 +11,8 @@ export fn a() void {
}
// error
-// target=spirv64-vulkan
+// target=spirv32-vulkan
//
// :9:13: error: value with non-mergable pointer type '*i32' depends on runtime control flow
// :9:17: note: runtime control flow here
-// :9:13: note: pointers with address space 'generic' cannot be returned from a branch on target spirv-vulkan by compiler backend stage2_spirv
+// :9:13: note: pointers with address space 'generic' cannot be returned from a branch on target 'spirv-vulkan' by compiler backend 'stage2_spirv'
diff --git a/test/cases/compile_errors/switch_with_overlapping_case_ranges.zig b/test/cases/compile_errors/switch_with_overlapping_case_ranges.zig
index 5b272e5c84a8d9295697add83d0627a7b22c5fc9..619875c7970ba869cb84ac43cdd1f0789724ec4f 100644
--- a/test/cases/compile_errors/switch_with_overlapping_case_ranges.zig
+++ b/test/cases/compile_errors/switch_with_overlapping_case_ranges.zig
@@ -1,12 +1,40 @@
-export fn entry() void {
- var q: u8 = 0;
- switch ((&q).*) {
+export fn entry1(x: u8) void {
+ switch (x) {
1...2 => {},
0...255 => {},
}
}
+export fn entry2(x: i8) void {
+ switch (x) {
+ -128...5 => {},
+ 5...127 => {},
+ }
+}
+
+export fn entry3(x: u8) void {
+ switch (x) {
+ 0...5 => {},
+ 5 => {},
+ 6...255 => {},
+ }
+}
+
+export fn entry4(x: u8) void {
+ switch (x) {
+ 0...5 => {},
+ 6 => {},
+ 6...255 => {},
+ }
+}
+
// error
//
-// :5:10: error: duplicate switch value
-// :4:10: note: previous value here
+// :4:10: error: duplicate switch value
+// :3:10: note: previous value here
+// :11:10: error: duplicate switch value
+// :10:13: note: previous value here
+// :17:10: error: duplicate switch value
+// :18:9: note: previous value here
+// :27:10: error: duplicate switch value
+// :26:9: note: previous value here
diff --git a/test/cases/error_in_nested_declaration.zig b/test/cases/error_in_nested_declaration.zig
deleted file mode 100644
index 92759cd151c8e4ef5d97fc2391f8b2cfcbe48010..0000000000000000000000000000000000000000
--- a/test/cases/error_in_nested_declaration.zig
+++ /dev/null
@@ -1,30 +0,0 @@
-const S = struct {
- b: u32,
- c: i32,
- a: struct {
- pub fn str(_: @This(), extra: []u32) []i32 {
- return @bitCast(extra);
- }
- },
-};
-
-pub export fn entry() void {
- var s: S = undefined;
- _ = s.a.str(undefined);
-}
-
-const S2 = struct {
- a: [*c]anyopaque,
-};
-
-pub export fn entry2() void {
- var s: S2 = undefined;
- _ = &s;
-}
-
-// error
-// backend=selfhosted,llvm
-//
-// :6:20: error: cannot @bitCast to '[]i32'
-// :6:20: note: use @ptrCast to cast from '[]u32'
-// :17:12: error: indexable pointer to opaque type 'anyopaque' not allowed
diff --git a/test/cases/image_sampling_spirv.zig b/test/cases/image_sampling_spirv.zig
new file mode 100644
index 0000000000000000000000000000000000000000..030727e95c106b6b2521ab72d07bb608b58a22a8
--- /dev/null
+++ b/test/cases/image_sampling_spirv.zig
@@ -0,0 +1,42 @@
+pub const Image = @SpirvType(.{ .image = .{
+ .usage = .{ .sampled = f32 },
+ .format = .unknown,
+ .dim = .@"2d",
+ .depth = .not_depth,
+ .arrayed = false,
+ .multisampled = false,
+ .access = .unknown,
+} });
+pub const SampledImage = @SpirvType(.{ .sampled_image = Image });
+
+const image_in = @extern(*addrspace(.constant) const SampledImage, .{
+ .name = "image_in",
+ .decoration = .{ .descriptor = .{ .set = 2, .binding = 0 } },
+});
+const uv_in = @extern(*addrspace(.input) @Vector(2, f32), .{ .name = "uv", .decoration = .{ .location = 0 } });
+const color_out = @extern(*addrspace(.output) @Vector(4, f32), .{ .name = "color", .decoration = .{ .location = 0 } });
+
+export fn main() callconv(.{ .spirv_fragment = .{} }) void {
+ color_out.* = imageSample(image_in, uv_in.*);
+}
+
+fn imageSample(
+ sampled_image: *addrspace(.constant) const SampledImage,
+ uv: @Vector(2, f32),
+) @Vector(4, f32) {
+ return asm volatile (
+ \\%loaded_sampler = OpLoad %SampledImage %sampled_image
+ \\%ret = OpImageSampleImplicitLod %Result %loaded_sampler %uv
+ : [ret] "" (-> @Vector(4, f32)),
+ : [SampledImage] "t" (SampledImage),
+ [sampled_image] "" (sampled_image),
+ [Result] "t" (@Vector(4, f32)),
+ [uv] "" (uv),
+ );
+}
+
+// compile
+// output_mode=Exe
+// backend=selfhosted
+// target=spirv32-vulkan
+// emit_bin=true
diff --git a/test/cases/safety/@intCast negative to u0.zig b/test/cases/safety/@intCast negative to u0.zig
new file mode 100644
index 0000000000000000000000000000000000000000..a445f755b7b8edb1e2a8f85375d92be95a8875aa
--- /dev/null
+++ b/test/cases/safety/@intCast negative to u0.zig
@@ -0,0 +1,22 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "integer does not fit in destination type")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+pub fn main() !void {
+ bar(1, -1);
+ return error.TestFailed;
+}
+
+fn bar(one: u1, not_zero: i32) void {
+ const x = one << @intCast(not_zero);
+ _ = x;
+}
+// run
+// backend=selfhosted,llvm
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/@intCast positive to u0.zig b/test/cases/safety/@intCast positive to u0.zig
new file mode 100644
index 0000000000000000000000000000000000000000..180ee78512fccc28ba1b33ef2b78e0570f0044cb
--- /dev/null
+++ b/test/cases/safety/@intCast positive to u0.zig
@@ -0,0 +1,22 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "integer does not fit in destination type")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+pub fn main() !void {
+ bar(1, 1);
+ return error.TestFailed;
+}
+
+fn bar(one: u1, not_zero: i32) void {
+ const x = one << @intCast(not_zero);
+ _ = x;
+}
+// run
+// backend=selfhosted,llvm
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/@intCast to u0.zig b/test/cases/safety/@intCast to u0.zig
deleted file mode 100644
index 180ee78512fccc28ba1b33ef2b78e0570f0044cb..0000000000000000000000000000000000000000
--- a/test/cases/safety/@intCast to u0.zig
+++ /dev/null
@@ -1,22 +0,0 @@
-const std = @import("std");
-
-pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
- _ = stack_trace;
- if (std.mem.eql(u8, message, "integer does not fit in destination type")) {
- std.process.exit(0);
- }
- std.process.exit(1);
-}
-
-pub fn main() !void {
- bar(1, 1);
- return error.TestFailed;
-}
-
-fn bar(one: u1, not_zero: i32) void {
- const x = one << @intCast(not_zero);
- _ = x;
-}
-// run
-// backend=selfhosted,llvm
-// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/deref_null_c_pointer.zig b/test/cases/safety/deref_null_c_pointer.zig
new file mode 100644
index 0000000000000000000000000000000000000000..31f81cf76401aa267a5778735b92639d4a74a411
--- /dev/null
+++ b/test/cases/safety/deref_null_c_pointer.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "attempt to use null value")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+pub fn main() !void {
+ const p: [*c]u8 = null;
+ _ = p.*;
+}
+
+// run
+// backend=selfhosted,llvm
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/ref_deref_null_c_pointer.zig b/test/cases/safety/ref_deref_null_c_pointer.zig
new file mode 100644
index 0000000000000000000000000000000000000000..60b6601d0deae3848aa7a4725f04a74dd4552712
--- /dev/null
+++ b/test/cases/safety/ref_deref_null_c_pointer.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "attempt to use null value")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+pub fn main() !void {
+ const p: [*c]u8 = null;
+ _ = &p.*;
+}
+
+// run
+// backend=selfhosted,llvm
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/spirv_mergable_pointers.zig b/test/cases/spirv_mergable_pointers.zig
index 106ee8efbe2f1ba588ca830d7a5e67bda95d8ee3..e44c1b53cf7ec89926218ceb4fb16b55adfd72b8 100644
--- a/test/cases/spirv_mergable_pointers.zig
+++ b/test/cases/spirv_mergable_pointers.zig
@@ -13,5 +13,5 @@ export fn a() void {
// compile
// output_mode=Obj
// backend=selfhosted
-// target=spirv64-vulkan
-// emit_bin=false
+// target=spirv32-vulkan
+// emit_bin=true
diff --git a/test/incremental/increase_array_field_length b/test/incremental/increase_array_field_length
new file mode 100644
index 0000000000000000000000000000000000000000..714473dd8302d57b0b2644a90f73442d47e9db2d
--- /dev/null
+++ b/test/incremental/increase_array_field_length
@@ -0,0 +1,31 @@
+#update=initial version
+#file=main.zig
+const Big = struct { arr: [10]u8 };
+pub fn main(init: std.process.Init) !void {
+ var big: Big = undefined;
+ big = .{ .arr = @splat(123) };
+ var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{});
+ const index = big.arr.len - 1;
+ big.arr[index] = 234;
+ stdout_writer.interface.print("arr[{d}] = {d}\n", .{ index, big.arr[index] }) catch |err| switch (err) {
+ error.WriteFailed => return stdout_writer.err.?,
+ };
+}
+const std = @import("std");
+#expect_stdout="arr[9] = 234\n"
+
+#update=increase array length
+#file=main.zig
+const Big = struct { arr: [1000]u8 };
+pub fn main(init: std.process.Init) !void {
+ var big: Big = undefined;
+ big = .{ .arr = @splat(123) };
+ var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{});
+ const index = big.arr.len - 1;
+ big.arr[index] = 234;
+ stdout_writer.interface.print("arr[{d}] = {d}\n", .{ index, big.arr[index] }) catch |err| switch (err) {
+ error.WriteFailed => return stdout_writer.err.?,
+ };
+}
+const std = @import("std");
+#expect_stdout="arr[999] = 234\n"
diff --git a/test/libc.zig b/test/libc.zig
index ee72cab75302935780851d8a7caf98775c9f4397..6f5590a543fe9966cd82cc3ed5241ae03f6566b6 100644
--- a/test/libc.zig
+++ b/test/libc.zig
@@ -151,9 +151,9 @@ pub fn addCases(cases: *tests.LibcContext) void {
// cases.addLibcTestCase("math/asinhl.c", true, .{});
cases.addLibcTestCase("math/asinl.c", true, .{});
cases.addLibcTestCase("math/atan.c", true, .{});
- // cases.addLibcTestCase("math/atan2.c", true, .{});
- // cases.addLibcTestCase("math/atan2f.c", true, .{});
- // cases.addLibcTestCase("math/atan2l.c", true, .{});
+ cases.addLibcTestCase("math/atan2.c", true, .{});
+ cases.addLibcTestCase("math/atan2f.c", true, .{});
+ cases.addLibcTestCase("math/atan2l.c", true, .{});
cases.addLibcTestCase("math/atanf.c", true, .{});
cases.addLibcTestCase("math/atanh.c", true, .{});
cases.addLibcTestCase("math/atanhf.c", true, .{});
diff --git a/test/link.zig b/test/link.zig
new file mode 100644
index 0000000000000000000000000000000000000000..1dc75f4d0df843be0431092a06dbdcb067cd0ab1
--- /dev/null
+++ b/test/link.zig
@@ -0,0 +1,341 @@
+pub fn addCases(ctx: *LinkContext) void {
+ if (ctx.target.result.isMinGW())
+ @import("link/mingw.zig").addCases(ctx);
+
+ if (ctx.includeTest("static-lib")) |case| {
+ const obj1 = case.addObject(.{
+ .name = "obj1",
+ .name_prefix = false,
+ .name_target = false,
+ .use_llvm = true,
+ .use_lld = true,
+ .c_source_bytes =
+ \\int foo1 = 1;
+ \\int foo2 = 2;
+ \\unsigned int fooBar() {
+ \\ return foo1 + foo2;
+ \\}
+ ,
+ });
+ const obj2 = case.addObject(.{
+ .name = "this_is_a_long_name",
+ .name_prefix = false,
+ .name_target = false,
+ .zig_source_bytes =
+ \\fn fooWeak() callconv(.c) usize {
+ \\ return 0xaabbccddaabbccdd;
+ \\}
+ \\export var foo_array: [2]u16 = .{ 0xffff, 0xabcd };
+ \\export var foo_strong: usize = 0x1122334411223344;
+ \\comptime {
+ \\ @export(&fooWeak, .{ .name = "fooWeak", .linkage = .weak });
+ \\ @export(&foo_strong, .{ .name = "foo_strong_alias", .linkage = .strong });
+ \\}
+ ,
+ });
+
+ const lib = case.addLibrary(.static, .{
+ .name = "lib",
+ .name_prefix = false,
+ .name_target = false,
+ });
+ lib.root_module.addObject(obj1);
+ lib.root_module.addObject(obj2);
+
+ case.verifyObjdump(lib.getEmittedBin(), &.{
+ "-s",
+ "--elements=file-type",
+ "--symbols",
+ "--only-symbol=foo",
+ }, .{ .use_llvm = true });
+
+ const exe = case.addExecutable(.{
+ .name = "test",
+ .zig_source_bytes =
+ \\extern fn fooBar() c_uint;
+ \\extern fn fooWeak() usize;
+ \\extern var foo_array: [2]u16;
+ \\extern var foo_strong: usize;
+ \\extern var foo_strong_alias: usize;
+ \\pub fn main() !u8 {
+ \\ return @intFromBool(0xcd003365cd00df35 != fooBar() +
+ \\ fooWeak() +
+ \\ foo_array[1] +
+ \\ foo_strong +
+ \\ foo_strong_alias);
+ \\}
+ ,
+ });
+ exe.root_module.linkLibrary(lib);
+
+ const run = case.addRunArtifact(exe);
+ run.addCheck(.{ .expect_term = .{ .exited = 0 } });
+ }
+
+ if (ctx.includeTest("tls")) |case| {
+ const obj = case.addObject(.{
+ .name = "obj",
+ .zig_source_bytes =
+ \\threadlocal var threadlocal_var: u32 = 1234;
+ \\threadlocal var threadlocal_arr: [4]u16 = .{ 0x1111, 0x2222, 0x3333, 0x4444, };
+ \\export fn threadlocal_read(a: *u32, b: *u16) void {
+ \\ a.* = threadlocal_var;
+ \\ b.* = threadlocal_arr[3];
+ \\}
+ \\export fn threadlocal_write(a: u32, b: u16) void {
+ \\ threadlocal_var = a;
+ \\ threadlocal_arr[3] = b;
+ \\}
+ ,
+ });
+
+ case.verifyObjdump(obj.getEmittedBin(), &.{
+ "-s",
+ "--symbols",
+ "--only-symbol=threadlocal",
+ "--only-symbol=tls",
+ }, .{ .use_llvm = true });
+
+ const exe = case.addExecutable(.{
+ .name = "test",
+ .zig_source_bytes =
+ \\extern fn threadlocal_read(a: *u32, b: *u16) void;
+ \\extern fn threadlocal_write(a: u32, b: u16) void;
+ \\threadlocal var threadlocal_foo: u64 = 0xcafecafecafecafe;
+ \\pub fn main() !u8 {
+ \\ var a: u32 = undefined;
+ \\ var b: u16 = undefined;
+ \\ threadlocal_read(&a, &b);
+ \\ if (a != 1234 or b != 0x4444) return 1;
+ \\ if (threadlocal_foo != 0xcafecafecafecafe) return 2;
+ \\ threadlocal_write(0xabcdabcd, 0x5555);
+ \\ threadlocal_foo = 1;
+ \\ threadlocal_read(&a, &b);
+ \\ if (a != 0xabcdabcd or b != 0x5555) return 3;
+ \\ if (threadlocal_foo != 1) return 4;
+ \\ return 0;
+ \\}
+ ,
+ });
+ exe.root_module.addObject(obj);
+
+ const run = case.addRunArtifact(exe);
+ run.addCheck(.{ .expect_term = .{ .exited = 0 } });
+ }
+
+ if (ctx.includeTest("dynamic-lib-code")) |case| {
+ const lib = case.addLibrary(.dynamic, .{
+ .name = "lib",
+ .name_target = false,
+ .zig_source_bytes =
+ \\export fn foo1() callconv(.c) u64 {
+ \\ return 0x1122334411223344;
+ \\}
+ \\export fn foo2() callconv(.c) u64 {
+ \\ return 0xaabbccddaabbccdd;
+ \\}
+ ,
+ });
+
+ case.verifyObjdump(lib.getEmittedBin(), &.{
+ "-s",
+ "--exports",
+ "--only-symbol=foo",
+ }, .{ .os = true });
+
+ if (ctx.target.result.os.tag == .windows) {
+ case.verifyObjdump(lib.getEmittedImplib(), &.{
+ "-s",
+ "--exports=sort",
+ "--only-symbol=foo",
+ }, .{ .sub_name = "implib", .os = true, .arch = true });
+ }
+
+ const exe = case.addExecutable(.{
+ .name = "test",
+ .zig_source_bytes =
+ \\extern fn foo1() u64;
+ \\pub fn main() !u8 {
+ \\ const foo2 = @extern(
+ \\ *const fn () callconv(.c) u64,
+ \\ .{ .name = "foo2", .is_dll_import = true },
+ \\ );
+ \\ return @intFromBool(0xbbde0021bbde0021 != foo1() + foo2());
+ \\}
+ ,
+ });
+ exe.root_module.linkLibrary(lib);
+
+ const run = case.addRunArtifact(exe);
+ run.addCheck(.{ .expect_term = .{ .exited = 0 } });
+ }
+
+ if (ctx.includeTest("dynamic-lib-data")) |case| {
+ const lib = case.addLibrary(.dynamic, .{
+ .name = "lib",
+ .name_target = false,
+ .zig_source_bytes =
+ \\export var foo_array: [2]u16 = .{ 0xffff, 0xabcd };
+ \\export var foo_strong: usize = 0x1122334411223344;
+ \\comptime {
+ \\ @export(&foo_strong, .{ .name = "foo_strong_alias", .linkage = .strong });
+ \\}
+ ,
+ });
+
+ case.verifyObjdump(lib.getEmittedBin(), &.{
+ "-s",
+ "--exports",
+ "--only-symbol=foo",
+ }, .{});
+
+ if (ctx.target.result.os.tag == .windows) {
+ case.verifyObjdump(lib.getEmittedImplib(), &.{
+ "-s",
+ "--exports=sort",
+ "--only-symbol=foo",
+ }, .{ .sub_name = "implib", .os = true, .arch = true });
+ }
+
+ const exe = case.addExecutable(.{
+ .name = "test",
+ .zig_source_bytes =
+ \\pub fn main() !u8 {
+ \\ const foo_array = @extern(*[2]u16, .{ .name = "foo_array", .is_dll_import = true });
+ \\ const foo_strong = @extern(*usize, .{ .name = "foo_strong", .is_dll_import = true });
+ \\ const foo_strong_alias = @extern(*usize, .{ .name = "foo_strong_alias", .is_dll_import = true });
+ \\ return @intFromBool(0x2244668822451255 !=
+ \\ foo_array[1] +
+ \\ foo_strong.* +
+ \\ foo_strong_alias.*);
+ \\}
+ ,
+ });
+ exe.root_module.linkLibrary(lib);
+
+ const run = case.addRunArtifact(exe);
+ run.addCheck(.{ .expect_term = .{ .exited = 0 } });
+ }
+
+ if (ctx.includeTest("abs-symbol")) |case| {
+ const abs = case.addObject(.{
+ .name = "abs",
+ .use_llvm = true, // TODO: .globl not supported on self-hosted
+ .use_lld = true,
+ .asm_source_bytes =
+ \\.globl foo
+ \\foo = 0xcafecafe
+ \\
+ ,
+ });
+
+ const abs_reloc = case.addObject(.{
+ .name = "abs_reloc",
+ .use_llvm = true, // TODO: .globl not supported on self-hosted
+ .use_lld = true,
+ .asm_source_bytes =
+ \\.data
+ \\.globl foo_copy
+ \\foo_copy:
+ \\.long foo
+ ,
+ });
+
+ case.verifyObjdump(abs_reloc.getEmittedBin(), &.{
+ "-s",
+ "--relocs",
+ }, .{ .arch = true });
+
+ const exe = case.addExecutable(.{
+ .name = "test",
+ .zig_source_bytes =
+ \\extern var foo_copy: u32;
+ \\pub fn main() !u8 {
+ \\ return @intFromBool(foo_copy != 0xcafecafe);
+ \\}
+ ,
+ });
+ exe.root_module.addObject(abs);
+ exe.root_module.addObject(abs_reloc);
+
+ const run = case.addRunArtifact(exe);
+ run.addCheck(.{ .expect_term = .{ .exited = 0 } });
+
+ if (!ctx.use_llvm) {
+ const exe_reloc_err = case.addExecutable(.{
+ .name = "test-reloc-err",
+ .zig_source_bytes =
+ \\extern const foo: u32;
+ \\pub fn main() !u8 {
+ \\ return @intFromBool(foo != 0xcafecafe);
+ \\}
+ ,
+ });
+ exe_reloc_err.root_module.addObject(abs);
+ case.expectLinkErrors(exe_reloc_err, .{
+ .contains = "error: absolute symbol 'foo' targeted by invalid relocation type: /?/",
+ });
+ }
+ }
+
+ if (ctx.includeTest("explicit-extern-lib-name")) |case| {
+ // TODO: Lld.zig does not look at explicit inputs to resolve explicit extern lib names
+ if (ctx.use_llvm) return;
+
+ const lib1 = case.addLibrary(.dynamic, .{
+ .name = "lib1",
+ .name_target = false,
+ .zig_source_bytes =
+ \\export fn foo() u8 {
+ \\ return 43;
+ \\}
+ ,
+ });
+
+ const lib2 = case.addLibrary(.dynamic, .{
+ .name = "lib2",
+ .name_target = false,
+ .zig_source_bytes =
+ \\export fn foo() u8 {
+ \\ return 42;
+ \\}
+ ,
+ });
+
+ const lib3 = case.addLibrary(.static, .{
+ .name = "lib3",
+ .zig_source_bytes =
+ \\extern fn foo() u8;
+ \\export fn callFoo() u8 {
+ \\ return foo();
+ \\}
+ ,
+ });
+
+ const exe = case.addExecutable(.{
+ .name = "test",
+ .zig_source_bytes =
+ \\extern "explicit-extern-lib-name-lib2" fn foo() u8;
+ \\extern fn callFoo() u8;
+ \\pub fn main() !u8 {
+ \\ return foo() + callFoo();
+ \\}
+ ,
+ });
+ exe.root_module.linkLibrary(lib1);
+ exe.root_module.linkLibrary(lib2);
+ // exe.root_module.addLibraryPath(.{
+ // .generated = .{
+ // .index = lib2.getEmittedBin().generated.index,
+ // .up = 1,
+ // },
+ // });
+ exe.root_module.linkLibrary(lib3);
+
+ const run = case.addRunArtifact(exe);
+ run.addCheck(.{ .expect_term = .{ .exited = 84 } });
+ }
+}
+
+const LinkContext = @import("tests.zig").LinkContext;
+const std = @import("std");
diff --git a/test/link/exports.zig b/test/link/exports.zig
new file mode 100644
index 0000000000000000000000000000000000000000..3f5e4734f45cc1e29472480174beb1d3d90e23cb
--- /dev/null
+++ b/test/link/exports.zig
@@ -0,0 +1,9 @@
+export fn foo_fn() void {}
+var foo_var: u32 = 1234;
+comptime {
+ @export(&foo_var, .{ .name = "foo_var", .linkage = .strong });
+}
+const foo_const: u64 = 5678;
+comptime {
+ @export(&foo_const, .{ .name = "foo_const", .linkage = .strong });
+}
diff --git a/test/link/mingw.zig b/test/link/mingw.zig
new file mode 100644
index 0000000000000000000000000000000000000000..e584709de04f5fc21ac2283d2356226c4c0ec36c
--- /dev/null
+++ b/test/link/mingw.zig
@@ -0,0 +1,48 @@
+pub fn addCases(ctx: *LinkContext) void {
+ if (ctx.includeTest("ctor-dtor")) |case| {
+ if (!ctx.link_libc) return;
+
+ const obj = case.addObject(.{
+ .name = "obj",
+ .use_llvm = true,
+ .use_lld = true,
+ .c_source_bytes =
+ \\#include
+ \\int foo;
+ \\__attribute__((constructor))
+ \\static void init_foo() {
+ \\ foo = 42;
+ \\}
+ \\__attribute__((destructor))
+ \\static void deinit_foo() {
+ \\ exit(42);
+ \\}
+ ,
+ });
+
+ const lib = case.addLibrary(.static, .{
+ .name = "lib",
+ .name_prefix = false,
+ .name_target = false,
+ });
+ lib.root_module.addObject(obj);
+
+ const exe = case.addExecutable(.{
+ .name = "test",
+ .zig_source_bytes =
+ \\extern var foo: u32;
+ \\pub fn main() !u8 {
+ \\ if (foo != 42) return 1;
+ \\ return 2;
+ \\}
+ ,
+ });
+ exe.root_module.addObject(obj);
+
+ const run = case.addRunArtifact(exe);
+ run.addCheck(.{ .expect_term = .{ .exited = 42 } });
+ }
+}
+
+const LinkContext = @import("../tests.zig").LinkContext;
+const std = @import("std");
diff --git a/test/link/snapshots/.gitattributes b/test/link/snapshots/.gitattributes
new file mode 100644
index 0000000000000000000000000000000000000000..699baaf03a7db7fe3ff3dcc2c4986c32e1aa52c3
--- /dev/null
+++ b/test/link/snapshots/.gitattributes
@@ -0,0 +1 @@
+*.dmp eol=lf
diff --git a/test/link/snapshots/abs-symbol.x86_64.dmp b/test/link/snapshots/abs-symbol.x86_64.dmp
new file mode 100644
index 0000000000000000000000000000000000000000..747546649b082633b0097b1be311a382e0b98e2b
--- /dev/null
+++ b/test/link/snapshots/abs-symbol.x86_64.dmp
@@ -0,0 +1 @@
+xxxxxxxx ADDR32 xxxxxxxx UNDEF | foo
diff --git a/test/link/snapshots/dynamic-lib-code.implib-x86_64-windows.dmp b/test/link/snapshots/dynamic-lib-code.implib-x86_64-windows.dmp
new file mode 100644
index 0000000000000000000000000000000000000000..eed30ce985f4c8ab00f7534716ab5bed343edd8d
--- /dev/null
+++ b/test/link/snapshots/dynamic-lib-code.implib-x86_64-windows.dmp
@@ -0,0 +1,32 @@
+ 0 date
+ 0 user_id
+ 0 group_id
+ 0 file_mode
+xxxxxxxxxxxxxxxx size
+ second_linker type
+ | x symbols
+ | x members
+xxxxxxxx __imp_foo1
+xxxxxxxx __imp_foo2
+xxxxxxxx foo1
+xxxxxxxx foo2
+ 0 version
+ 8664 machine (AMD64)
+ 0 time_date_stamp
+xxxxxxxxxxxxxxxx size_of_data
+xxxxxxxxxxxxxxxx hint
+ CODE import_type
+ NAME name_type
+ symbol name | foo1
+ import name | foo1
+ dll | dynamic-lib-code-lib.dll
+ 0 version
+ 8664 machine (AMD64)
+ 0 time_date_stamp
+xxxxxxxxxxxxxxxx size_of_data
+xxxxxxxxxxxxxxxx hint
+ CODE import_type
+ NAME name_type
+ symbol name | foo2
+ import name | foo2
+ dll | dynamic-lib-code-lib.dll
diff --git a/test/link/snapshots/dynamic-lib-code.windows.dmp b/test/link/snapshots/dynamic-lib-code.windows.dmp
new file mode 100644
index 0000000000000000000000000000000000000000..a9396675f8f34175fc4b3a5f488a003cc60bc63d
--- /dev/null
+++ b/test/link/snapshots/dynamic-lib-code.windows.dmp
@@ -0,0 +1,13 @@
+Export directory:
+ 0 flags
+ 0 time_date_stamp
+ 0.00 version
+xxxxxxxxxxxxxxxx name_rva
+ 1 ordinal_base
+xxxxxxxxxxxxxxxx number_of_entries
+xxxxxxxxxxxxxxxx number_of_names
+xxxxxxxxxxxxxxxx export_address_table_rva
+xxxxxxxxxxxxxxxx name_pointer_table_rva
+xxxxxxxxxxxxxxxx ordinal_table_rva
+xxxx xxxx xxxxxxxx | foo1
+xxxx xxxx xxxxxxxx | foo2
diff --git a/test/link/snapshots/dynamic-lib-data.dmp b/test/link/snapshots/dynamic-lib-data.dmp
new file mode 100644
index 0000000000000000000000000000000000000000..480b7107582590491d4e1094ff69f39ae9d44a61
--- /dev/null
+++ b/test/link/snapshots/dynamic-lib-data.dmp
@@ -0,0 +1,14 @@
+Export directory:
+ 0 flags
+ 0 time_date_stamp
+ 0.00 version
+xxxxxxxxxxxxxxxx name_rva
+ 1 ordinal_base
+xxxxxxxxxxxxxxxx number_of_entries
+xxxxxxxxxxxxxxxx number_of_names
+xxxxxxxxxxxxxxxx export_address_table_rva
+xxxxxxxxxxxxxxxx name_pointer_table_rva
+xxxxxxxxxxxxxxxx ordinal_table_rva
+xxxx xxxx xxxxxxxx | foo_array
+xxxx xxxx xxxxxxxx | foo_strong
+xxxx xxxx xxxxxxxx | foo_strong_alias
diff --git a/test/link/snapshots/dynamic-lib-data.implib-x86_64-windows.dmp b/test/link/snapshots/dynamic-lib-data.implib-x86_64-windows.dmp
new file mode 100644
index 0000000000000000000000000000000000000000..b273ef44e475ff353e37271a9ec3777332082d5a
--- /dev/null
+++ b/test/link/snapshots/dynamic-lib-data.implib-x86_64-windows.dmp
@@ -0,0 +1,41 @@
+ 0 date
+ 0 user_id
+ 0 group_id
+ 0 file_mode
+xxxxxxxxxxxxxxxx size
+ second_linker type
+ | x symbols
+ | x members
+xxxxxxxx __imp_foo_array
+xxxxxxxx __imp_foo_strong
+xxxxxxxx __imp_foo_strong_alias
+ 0 version
+ 8664 machine (AMD64)
+ 0 time_date_stamp
+xxxxxxxxxxxxxxxx size_of_data
+xxxxxxxxxxxxxxxx hint
+ DATA import_type
+ NAME name_type
+ symbol name | foo_array
+ import name | foo_array
+ dll | dynamic-lib-data-lib.dll
+ 0 version
+ 8664 machine (AMD64)
+ 0 time_date_stamp
+xxxxxxxxxxxxxxxx size_of_data
+xxxxxxxxxxxxxxxx hint
+ DATA import_type
+ NAME name_type
+ symbol name | foo_strong
+ import name | foo_strong
+ dll | dynamic-lib-data-lib.dll
+ 0 version
+ 8664 machine (AMD64)
+ 0 time_date_stamp
+xxxxxxxxxxxxxxxx size_of_data
+xxxxxxxxxxxxxxxx hint
+ DATA import_type
+ NAME name_type
+ symbol name | foo_strong_alias
+ import name | foo_strong_alias
+ dll | dynamic-lib-data-lib.dll
diff --git a/test/link/snapshots/static-lib.llvm.dmp b/test/link/snapshots/static-lib.llvm.dmp
new file mode 100644
index 0000000000000000000000000000000000000000..f64e76be1134c735e77bb6e2e10d0983a8858d35
--- /dev/null
+++ b/test/link/snapshots/static-lib.llvm.dmp
@@ -0,0 +1,15 @@
+lib.lib: COFF archive
+lib.lib(obj1.obj): COFF object
+xxxx 00000000 1 NULL() EXTERNAL | fooBar
+xxxx 00000000 2 NULL EXTERNAL | foo1
+xxxx 00000004 2 NULL EXTERNAL | foo2
+lib.lib(this_is_a_long_name.obj): COFF object
+xxxx 00000000 1 NULL() STATIC | this_is_a_long_name.fooWeak
+xxxx 00000000 2 NULL STATIC | this_is_a_long_name.foo_strong
+xxxx 00000008 2 NULL STATIC | this_is_a_long_name.foo_array
+xxxx 00000000 2 NULL EXTERNAL | foo_strong
+xxxx 00000000 2 NULL EXTERNAL | foo_strong_alias
+xxxx 00000008 2 NULL EXTERNAL | foo_array
+xxxx 00000000 UNDEF NULL WEAK_EXTERNAL | fooWeak
+ | Weak External [falls back to relative ordinal 000000+2 via SEARCH_ALIAS]
+xxxx 00000000 1 NULL() EXTERNAL | .weak.fooWeak.default.foo_strong
diff --git a/test/link/snapshots/static-lib.no-llvm.dmp b/test/link/snapshots/static-lib.no-llvm.dmp
new file mode 100644
index 0000000000000000000000000000000000000000..07e2219bfd57889557bd5eda680dc5de4ba62e42
--- /dev/null
+++ b/test/link/snapshots/static-lib.no-llvm.dmp
@@ -0,0 +1,12 @@
+lib.lib: COFF archive
+lib.lib(obj1.obj): COFF object
+xxxx 00000000 1 NULL() EXTERNAL | fooBar
+xxxx 00000000 2 NULL EXTERNAL | foo1
+xxxx 00000004 2 NULL EXTERNAL | foo2
+lib.lib(this_is_a_long_name.obj): COFF object
+xxxx 00000000 4 NULL() EXTERNAL | this_is_a_long_name.fooWeak
+xxxx 00000000 2 NULL EXTERNAL | foo_strong
+xxxx 00000000 2 NULL EXTERNAL | foo_strong_alias
+xxxx 00000010 2 NULL EXTERNAL | foo_array
+xxxx 00000000 UNDEF NULL() WEAK_EXTERNAL | fooWeak
+ | Weak External [falls back to relative ordinal 000000-4 via SEARCH_ALIAS]
diff --git a/test/link/snapshots/tls.llvm.dmp b/test/link/snapshots/tls.llvm.dmp
new file mode 100644
index 0000000000000000000000000000000000000000..8e70edb3acc79d3559d05451ab555d01d621d26a
--- /dev/null
+++ b/test/link/snapshots/tls.llvm.dmp
@@ -0,0 +1,9 @@
+xxxx 00000000 6 NULL STATIC | .tls$
+ | Section [size xxxxxxxx chksum a194a569 relocs 0000 lines 0000]
+xxxx 00000000 1 NULL() STATIC | obj.threadlocal_write
+xxxx 00000000 UNDEF NULL EXTERNAL | _tls_index
+xxxx 00000000 6 NULL STATIC | obj.threadlocal_var
+xxxx 00000004 6 NULL STATIC | obj.threadlocal_arr
+xxxx 00000040 1 NULL() STATIC | obj.threadlocal_read
+xxxx 00000000 1 NULL() EXTERNAL | threadlocal_write
+xxxx 00000040 1 NULL() EXTERNAL | threadlocal_read
diff --git a/test/link/snapshots/tls.no-llvm.dmp b/test/link/snapshots/tls.no-llvm.dmp
new file mode 100644
index 0000000000000000000000000000000000000000..02ae0d78df3fa5cddafaed1d3dc49a50debf7247
--- /dev/null
+++ b/test/link/snapshots/tls.no-llvm.dmp
@@ -0,0 +1,7 @@
+xxxx 00000000 5 NULL STATIC | .tls$
+ | Section [size xxxxxxxx chksum 00000000 relocs 0000 lines 0000]
+xxxx 00000000 5 NULL STATIC | obj.threadlocal_var
+xxxx 00000008 5 NULL STATIC | obj.threadlocal_arr
+xxxx 00000000 UNDEF NULL EXTERNAL | _tls_index
+xxxx 00000000 4 NULL() EXTERNAL | threadlocal_write
+xxxx 00000060 4 NULL() EXTERNAL | threadlocal_read
diff --git a/test/llvm_targets.zig b/test/llvm_targets.zig
index 4f9159eaebc3a49ef97bb742b5870e0e068ddbfd..cbbf4aff7d01adeb6cfbd22a51402f35759b1ea4 100644
--- a/test/llvm_targets.zig
+++ b/test/llvm_targets.zig
@@ -154,11 +154,13 @@ const targets = [_]std.Target.Query{
.{ .cpu_arch = .mipsel, .os_tag = .linux, .abi = .musleabihf },
.{ .cpu_arch = .mipsel, .os_tag = .netbsd, .abi = .eabi },
.{ .cpu_arch = .mipsel, .os_tag = .netbsd, .abi = .eabihf },
+ // .{ .cpu_arch = .mipsel, .os_tag = .psx, .abi = .eabi },
.{ .cpu_arch = .mipsel, .os_tag = .psp, .abi = .eabihf },
.{ .cpu_arch = .mipsel, .os_tag = .rtems, .abi = .eabi },
.{ .cpu_arch = .mipsel, .os_tag = .rtems, .abi = .eabihf },
.{ .cpu_arch = .mips64, .os_tag = .freestanding, .abi = .none },
+ .{ .cpu_arch = .mips64, .os_tag = .linux, .abi = .abin32 },
.{ .cpu_arch = .mips64, .os_tag = .linux, .abi = .gnuabi64 },
.{ .cpu_arch = .mips64, .os_tag = .linux, .abi = .gnuabin32 },
.{ .cpu_arch = .mips64, .os_tag = .linux, .abi = .muslabi64 },
@@ -167,6 +169,7 @@ const targets = [_]std.Target.Query{
.{ .cpu_arch = .mips64, .os_tag = .openbsd, .abi = .none },
.{ .cpu_arch = .mips64el, .os_tag = .freestanding, .abi = .none },
+ .{ .cpu_arch = .mips64el, .os_tag = .linux, .abi = .abin32 },
.{ .cpu_arch = .mips64el, .os_tag = .linux, .abi = .gnuabi64 },
.{ .cpu_arch = .mips64el, .os_tag = .linux, .abi = .gnuabin32 },
.{ .cpu_arch = .mips64el, .os_tag = .linux, .abi = .muslabi64 },
@@ -192,6 +195,7 @@ const targets = [_]std.Target.Query{
.{ .cpu_arch = .powerpc, .os_tag = .openbsd, .abi = .eabihf },
.{ .cpu_arch = .powerpc, .os_tag = .rtems, .abi = .eabi },
.{ .cpu_arch = .powerpc, .os_tag = .rtems, .abi = .eabihf },
+ .{ .cpu_arch = .powerpc, .os_tag = .wiiu, .abi = .eabihf },
.{ .cpu_arch = .powerpcle, .os_tag = .freestanding, .abi = .eabi },
.{ .cpu_arch = .powerpcle, .os_tag = .freestanding, .abi = .eabihf },
@@ -330,6 +334,7 @@ const targets = [_]std.Target.Query{
.{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .muslx32 },
.{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .none },
.{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .ohos },
+ .{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .x32 },
.{ .cpu_arch = .x86_64, .os_tag = .maccatalyst, .abi = .none },
.{ .cpu_arch = .x86_64, .os_tag = .macos, .abi = .none },
.{ .cpu_arch = .x86_64, .os_tag = .netbsd, .abi = .none },
diff --git a/test/src/Cases.zig b/test/src/Cases.zig
index 9ffc5ec61645f2ecc6364389b63b58e2b5717935..f321d15851e117539f78f38681bd20cb8e06b1c4 100644
--- a/test/src/Cases.zig
+++ b/test/src/Cases.zig
@@ -357,7 +357,15 @@ fn addFromDirInner(
var manifest = try TestManifest.parse(ctx.arena, src);
const backends = try manifest.getConfigForKeyAlloc(ctx.arena, "backend", Backend);
- const targets = try manifest.getConfigForKeyAlloc(ctx.arena, "target", std.Target.Query);
+ const target_strs = try manifest.getConfigForKeyAlloc(ctx.arena, "target", []const u8);
+ const cpu_features_str = manifest.config_map.get("cpu_features") orelse "";
+ const targets = try ctx.arena.alloc(std.Target.Query, target_strs.len);
+ for (targets, target_strs) |*query, target_str| {
+ query.* = try std.Target.Query.parse(.{
+ .arch_os_abi = target_str,
+ .cpu_features = if (cpu_features_str.len == 0) null else cpu_features_str,
+ });
+ }
const is_test = try manifest.getConfigForKeyAssertSingle("is_test", bool);
const link_libc = try manifest.getConfigForKeyAssertSingle("link_libc", bool);
const output_mode = try manifest.getConfigForKeyAssertSingle("output_mode", std.builtin.OutputMode);
@@ -707,6 +715,8 @@ const TestManifestConfigDefaults = struct {
return "null";
} else if (std.mem.eql(u8, key, "imports")) {
return "";
+ } else if (std.mem.eql(u8, key, "cpu_features")) {
+ return "";
} else unreachable;
}
};
@@ -739,6 +749,7 @@ const TestManifest = struct {
.{ "is_test", {} },
.{ "output_mode", {} },
.{ "target", {} },
+ .{ "cpu_features", {} },
.{ "c_frontend", {} },
.{ "link_libc", {} },
.{ "backend", {} },
diff --git a/test/src/Link.zig b/test/src/Link.zig
new file mode 100644
index 0000000000000000000000000000000000000000..16c7dbdf83ace21ba7d92ef0c88ba54e0efb42fa
--- /dev/null
+++ b/test/src/Link.zig
@@ -0,0 +1,281 @@
+b: *Build,
+step: *Step,
+optimize: std.builtin.OptimizeMode,
+target: std.Build.ResolvedTarget,
+target_desc: []const u8,
+use_llvm: bool,
+use_lld: bool,
+link_libc: bool,
+test_filters: []const []const u8,
+update_step: ?*Step.UpdateSourceFiles,
+updated_snapshots: std.StringArrayHashMapUnmanaged(void),
+max_rss: usize,
+
+pub fn includeTest(self: *Link, prefix: []const u8) ?Case {
+ if (for (self.test_filters) |filter| {
+ if (std.mem.containsAtLeast(u8, prefix, 1, filter)) break false;
+ } else self.test_filters.len > 0) return null;
+
+ return .{
+ .ctx = self,
+ .prefix = prefix,
+ };
+}
+
+pub fn sourcePath(self: *const Link, sub_path: []const u8) std.Build.LazyPath {
+ return self.b.path(self.b.pathJoin(&.{ "test/link", sub_path }));
+}
+
+pub const Case = struct {
+ ctx: *Link,
+ prefix: []const u8,
+
+ fn resolveName(self: *const Case, overlay: *const OverlayOptions) []const u8 {
+ if (!overlay.name_prefix and !overlay.name_target)
+ return overlay.name;
+
+ if (overlay.name_prefix == overlay.name_target)
+ return self.ctx.b.fmt("{s}-{s}-{s}", .{ self.prefix, overlay.name, self.ctx.target_desc })
+ else if (overlay.name_prefix)
+ return self.ctx.b.fmt("{s}-{s}", .{ self.prefix, overlay.name })
+ else
+ return self.ctx.b.fmt("{s}-{s}", .{ overlay.name, self.ctx.target_desc });
+ }
+
+ pub fn addLibrary(
+ self: *const Case,
+ linkage: std.builtin.LinkMode,
+ overlay: OverlayOptions,
+ ) *Step.Compile {
+ return self.ctx.b.addLibrary(.{
+ .linkage = linkage,
+ .name = self.resolveName(&overlay),
+ .root_module = self.ctx.createModule(overlay),
+ .use_llvm = overlay.use_llvm orelse self.ctx.use_llvm,
+ .use_lld = overlay.use_lld orelse self.ctx.use_lld,
+ });
+ }
+
+ pub fn addExecutable(
+ self: *const Case,
+ overlay: OverlayOptions,
+ ) *Step.Compile {
+ return self.ctx.b.addExecutable(.{
+ .name = self.resolveName(&overlay),
+ .root_module = self.ctx.createModule(overlay),
+ .use_llvm = overlay.use_llvm orelse self.ctx.use_llvm,
+ .use_lld = overlay.use_lld orelse self.ctx.use_lld,
+ });
+ }
+
+ pub fn addRunArtifact(
+ self: *const Case,
+ exe: *Step.Compile,
+ ) *Step.Run {
+ const run_step = self.ctx.b.addRunArtifact(exe);
+ run_step.skip_foreign_checks = true;
+ self.ctx.step.dependOn(&run_step.step);
+ return run_step;
+ }
+
+ pub fn addObject(
+ self: *const Case,
+ overlay: OverlayOptions,
+ ) *Step.Compile {
+ return self.ctx.b.addObject(.{
+ .name = self.resolveName(&overlay),
+ .root_module = self.ctx.createModule(overlay),
+ .use_llvm = overlay.use_llvm orelse self.ctx.use_llvm,
+ .use_lld = overlay.use_lld orelse self.ctx.use_lld,
+ });
+ }
+
+ pub fn expectLinkErrors(
+ self: *const Case,
+ comp: *Step.Compile,
+ expected_errors: Step.Compile.ExpectedCompileErrors,
+ ) void {
+ comp.expect_errors = expected_errors;
+ const bin_file = comp.getEmittedBin();
+ bin_file.addStepDependencies(self.ctx.step);
+ }
+
+ const SnapshotScope = struct {
+ /// If a test case has multiple verifyObjdump calls, `opt_sub_name` should
+ /// be used to differentiate them.
+ sub_name: ?[]const u8 = null,
+ arch: bool = false,
+ os: bool = false,
+ abi: bool = false,
+ optimize: bool = false,
+ use_llvm: bool = false,
+ use_lld: bool = false,
+ link_libc: bool = false,
+ };
+
+ /// Verify the results of a `zig objdump` call against a snapshot, which
+ /// contains the expected output. Snapshots alias between all build
+ /// configurations by default, but by specifying fields in `scope`,
+ /// unique snapshot names are generated for each value of that field.
+ pub fn verifyObjdump(
+ self: *const Case,
+ file: Build.LazyPath,
+ args: []const []const u8,
+ scope: SnapshotScope,
+ ) void {
+ const ctx = self.ctx;
+ const snapshot_name = self.snapshotName(scope) catch @panic("OOM");
+ const snapshot_sub_path = ctx.b.pathJoin(&.{ "test/link/snapshots/", snapshot_name });
+
+ // Many tests may read the same snapshot, so only use the first one to update.
+ // If there are differences in output, they will show up on the next test run.
+ if (ctx.update_step != null) {
+ const gop = ctx.updated_snapshots.getOrPut(ctx.b.allocator, snapshot_sub_path) catch @panic("OOM");
+ if (gop.found_existing) return;
+ }
+
+ const run_step = Step.Run.create(ctx.b, ctx.b.fmt(
+ "objdump {s} {s}",
+ .{ snapshot_name, ctx.target_desc },
+ ));
+ run_step.addArgs(&.{ ctx.b.graph.zig_exe, "objdump" });
+ run_step.addFileArg(file);
+ run_step.addArgs(args);
+ run_step.addCheck(.{ .expect_term = .{ .exited = 0 } });
+
+ if (ctx.update_step) |update_step| {
+ // Workaround for the build system not realizing objdump itself has changed
+ run_step.has_side_effects = true;
+
+ const snapshot_update_path = run_step.captureStdOut(.{});
+ update_step.addCopyFileToSource(snapshot_update_path, snapshot_sub_path);
+ } else {
+ run_step.addCheck(.{ .expect_stdout_snapshot = ctx.b.path(snapshot_sub_path) });
+ }
+
+ ctx.step.dependOn(&run_step.step);
+ }
+
+ fn snapshotName(
+ self: *const Case,
+ scope: SnapshotScope,
+ ) ![]const u8 {
+ const ctx = self.ctx;
+ var snapshot_name: std.Io.Writer.Allocating = .init(ctx.b.allocator);
+ const w = &snapshot_name.writer;
+
+ try w.writeAll(self.prefix);
+ var sep: u8 = '.';
+
+ if (try snapshotNameInner(w, scope.sub_name != null, &sep))
+ try w.writeAll(scope.sub_name.?);
+ if (try snapshotNameInner(w, scope.arch, &sep))
+ try w.print("{t}", .{ctx.target.result.cpu.arch});
+ if (try snapshotNameInner(w, scope.os, &sep))
+ try w.print("{t}", .{ctx.target.result.os.tag});
+ if (try snapshotNameInner(w, scope.abi, &sep))
+ try w.print("{t}", .{ctx.target.result.abi});
+ if (try snapshotNameInner(w, scope.optimize, &sep))
+ try w.print("{t}", .{ctx.optimize});
+ if (try snapshotNameInner(w, scope.use_llvm, &sep))
+ try w.writeAll(if (ctx.use_llvm) "llvm" else "no-llvm");
+ if (try snapshotNameInner(w, scope.use_lld, &sep))
+ try w.writeAll(if (ctx.use_lld) "lld" else "no-lld");
+ if (try snapshotNameInner(w, scope.link_libc, &sep))
+ try w.writeAll(if (ctx.link_libc) "libc" else "no-libc");
+
+ if (sep == '-') sep = '.';
+ try w.writeByte(sep);
+ try w.writeAll("dmp");
+
+ return try snapshot_name.toOwnedSlice();
+ }
+
+ fn snapshotNameInner(w: *std.Io.Writer, cond: bool, sep: *u8) !bool {
+ if (cond) {
+ try w.writeByte(sep.*);
+ sep.* = '-';
+ }
+
+ return cond;
+ }
+};
+
+fn createModule(self: *const Link, overlay: OverlayOptions) *Build.Module {
+ const write_files = self.b.addWriteFiles();
+
+ const mod = self.b.createModule(.{
+ .target = self.target,
+ .optimize = self.optimize,
+ .root_source_file = overlay.zig_source_file orelse rsf: {
+ const bytes = overlay.zig_source_bytes orelse break :rsf null;
+ const name = self.b.fmt("{s}.zig", .{overlay.name});
+ break :rsf write_files.add(name, bytes);
+ },
+ .link_libc = self.link_libc, // TODO: Should this be in overlay instead?
+ .pic = overlay.pic,
+ .strip = overlay.strip,
+ });
+
+ if (overlay.objcpp_source_bytes) |bytes| {
+ mod.addCSourceFile(.{
+ .file = write_files.add("a.mm", bytes),
+ .flags = overlay.objcpp_source_flags,
+ });
+ }
+ if (overlay.objc_source_bytes) |bytes| {
+ mod.addCSourceFile(.{
+ .file = write_files.add("a.m", bytes),
+ .flags = overlay.objc_source_flags,
+ });
+ }
+ if (overlay.cpp_source_bytes) |bytes| {
+ mod.addCSourceFile(.{
+ .file = write_files.add("a.cpp", bytes),
+ .flags = overlay.cpp_source_flags,
+ });
+ }
+ if (overlay.c_source_bytes) |bytes| {
+ mod.addCSourceFile(.{
+ .file = write_files.add("a.c", bytes),
+ .flags = overlay.c_source_flags,
+ });
+ }
+ if (overlay.asm_source_bytes) |bytes| {
+ mod.addAssemblyFile(write_files.add("a.s", bytes));
+ }
+
+ return mod;
+}
+
+const OverlayOptions = struct {
+ name: []const u8,
+ /// Prefix the name with the test case prefix.
+ /// Unset if names with specific lengths are needed.
+ name_prefix: bool = true,
+ /// Prefix the name with `target_desc`.
+ /// Can be unset when the snapshot needs to contain the name,
+ /// so that snapshots can alias between targets.
+ name_target: bool = true,
+ asm_source_bytes: ?[]const u8 = null,
+ c_source_bytes: ?[]const u8 = null,
+ c_source_flags: []const []const u8 = &.{},
+ cpp_source_bytes: ?[]const u8 = null,
+ cpp_source_flags: []const []const u8 = &.{},
+ objc_source_bytes: ?[]const u8 = null,
+ objc_source_flags: []const []const u8 = &.{},
+ objcpp_source_bytes: ?[]const u8 = null,
+ objcpp_source_flags: []const []const u8 = &.{},
+ zig_source_bytes: ?[]const u8 = null,
+ zig_source_file: ?std.Build.LazyPath = null,
+ pic: ?bool = null,
+ strip: ?bool = null,
+ use_llvm: ?bool = null,
+ use_lld: ?bool = null,
+};
+
+const std = @import("std");
+const Build = std.Build;
+const Step = Build.Step;
+
+const Link = @This();
diff --git a/test/standalone/build.zig b/test/standalone/build.zig
index e36e802979d5fcb3bf593399413c835f91938af8..c5376b2e0df839ff498ad712c657b624611d34bd 100644
--- a/test/standalone/build.zig
+++ b/test/standalone/build.zig
@@ -31,6 +31,7 @@ pub fn build(b: *std.Build) void {
const tools_target = b.resolveTargetQuery(.{});
for ([_][]const u8{
// Alphabetically sorted. No need to build `tools/spirv/grammar.zig`.
+ "../../tools/check_mingw.zig",
"../../tools/dump-cov.zig",
"../../tools/fetch_them_macos_headers.zig",
"../../tools/gen_macos_headers_c.zig",
@@ -61,6 +62,21 @@ pub fn build(b: *std.Build) void {
.target = tools_target,
}),
});
+ if (std.mem.endsWith(u8, tool_src_path, "check_mingw.zig")) {
+ const mingw_preprocessor_mod = b.createModule(.{
+ .root_source_file = b.path("../../src/libs/mingw/Preprocessor.zig"),
+ .target = tools_target,
+ });
+ tool.root_module.addImport("preprocessor", mingw_preprocessor_mod);
+ }
+ if (std.mem.endsWith(u8, tool_src_path, "update_cpu_features.zig")) {
+ const spirv_spec = b.createModule(.{
+ .root_source_file = b.path("../../src/codegen/spirv/spec.zig"),
+ .target = tools_target,
+ });
+ tool.root_module.addImport("spirv_spec", spirv_spec);
+ }
+
tools_tests_step.dependOn(&tool.step);
}
for ([_][]const u8{
diff --git a/test/standalone/build.zig.zon b/test/standalone/build.zig.zon
index de1b97d60bdbe995992a69fe4eb9f55d99e7e3c8..190394704ae48cd28406511353905a2f8675dd63 100644
--- a/test/standalone/build.zig.zon
+++ b/test/standalone/build.zig.zon
@@ -193,6 +193,9 @@
.elf2 = .{
.path = "elf2",
},
+ .run_args = .{
+ .path = "run_args",
+ },
},
.paths = .{
"build.zig",
diff --git a/test/standalone/load_dynamic_library/add.zig b/test/standalone/load_dynamic_library/add.zig
deleted file mode 100644
index a04ec1544dc82e27afb137de2672a48d726a72fc..0000000000000000000000000000000000000000
--- a/test/standalone/load_dynamic_library/add.zig
+++ /dev/null
@@ -1,3 +0,0 @@
-export fn add(a: i32, b: i32) i32 {
- return a + b;
-}
diff --git a/test/standalone/load_dynamic_library/build.zig b/test/standalone/load_dynamic_library/build.zig
index 2160b2b3e474a558725d9f2c39eb98f7a1be9d8a..8af976e9929eef069673e71c0bb1c1a738ef4e7d 100644
--- a/test/standalone/load_dynamic_library/build.zig
+++ b/test/standalone/load_dynamic_library/build.zig
@@ -11,12 +11,16 @@ pub fn build(b: *std.Build) void {
if (builtin.os.tag == .wasi) return;
if (builtin.os.tag == .windows) return;
+ // ld and lld do not agree on the format of the .hash section
+ // Tracked by https://codeberg.org/ziglang/zig/issues/35746
+ if (builtin.cpu.arch == .s390x and builtin.os.tag == .linux) return;
+
const lib = b.addLibrary(.{
.linkage = .dynamic,
- .name = "add",
+ .name = "lib",
.version = .{ .major = 1, .minor = 0, .patch = 0 },
.root_module = b.createModule(.{
- .root_source_file = b.path("add.zig"),
+ .root_source_file = b.path("lib.zig"),
.optimize = optimize,
.target = target,
}),
diff --git a/test/standalone/load_dynamic_library/lib.zig b/test/standalone/load_dynamic_library/lib.zig
new file mode 100644
index 0000000000000000000000000000000000000000..d5f45bce7ccb715ed1ef1902780caaf65b1a5875
--- /dev/null
+++ b/test/standalone/load_dynamic_library/lib.zig
@@ -0,0 +1,8 @@
+export fn addInts(a: i32, b: i32) i32 {
+ return a + b;
+}
+
+var forty_two: i32 = 42;
+export fn fortyTwo() i32 {
+ return forty_two;
+}
diff --git a/test/standalone/load_dynamic_library/main.zig b/test/standalone/load_dynamic_library/main.zig
index ac64e67cdaddf18d0904f5ecff78306542930fef..a8e9e9b6d6661a8536178be3148347ea7448c634 100644
--- a/test/standalone/load_dynamic_library/main.zig
+++ b/test/standalone/load_dynamic_library/main.zig
@@ -8,9 +8,11 @@ pub fn main(init: std.process.Init) !void {
var lib = try std.DynLib.open(dynlib_name);
defer lib.close();
- const Add = *const fn (i32, i32) callconv(.c) i32;
- const addFn = lib.lookup(Add, "add") orelse return error.SymbolNotFound;
+ const AddInts = *const fn (i32, i32) callconv(.c) i32;
+ const addInts = lib.lookup(AddInts, "addInts").?;
+ std.debug.assert(addInts(12, 34) == 46);
- const result = addFn(12, 34);
- std.debug.assert(result == 46);
+ const FortyTwo = *const fn () callconv(.c) i32;
+ const fortyTwo = lib.lookup(FortyTwo, "fortyTwo").?;
+ std.debug.assert(fortyTwo() == 42);
}
diff --git a/test/standalone/run_args/build.zig b/test/standalone/run_args/build.zig
new file mode 100644
index 0000000000000000000000000000000000000000..fdc3c1f0237743329edaaf7b0c15f8c4ea8a134c
--- /dev/null
+++ b/test/standalone/run_args/build.zig
@@ -0,0 +1,160 @@
+const std = @import("std");
+
+/// Tests that args are passed to run steps correctly.
+///
+/// Note that when `make_absolute` is true we make sure the resulting path argument is absolute, but
+/// when it is false we allow either absolute or relative paths. This is because the maker receives
+/// absolute paths when build is run from anywhere other than the build root.
+pub fn build(b: *std.Build) !void {
+ const step = b.step("test", "Run artifact args standalone test cases");
+ b.default_step = step;
+
+ const exe = b.addExecutable(.{
+ .name = "exe",
+ .root_module = b.createModule(.{
+ .root_source_file = b.path("main.zig"),
+ .target = b.graph.host,
+ }),
+ });
+
+ // Arg
+ {
+ const run = b.addRunArtifact(exe);
+ step.dependOn(&run.step);
+ run.addArg("arg1");
+ run.expectStdErrEqual("arg1\n");
+ }
+
+ // Args
+ {
+ const run = b.addRunArtifact(exe);
+ step.dependOn(&run.step);
+ run.addArgs(&.{ "arg1", "arg2" });
+ run.expectStdErrEqual("arg1\narg2\n");
+ }
+
+ // Artifact Args
+ {
+ // Absolute
+ {
+ const run = b.addRunArtifact(exe);
+ step.dependOn(&run.step);
+ _ = run.addArtifactArg2(exe, .{ .prefix = "path^", .make_absolute = true, .suffix = "$" });
+ run.expectStdErrMatch("abs exe");
+ }
+ // Relative
+ {
+ const run = b.addRunArtifact(exe);
+ step.dependOn(&run.step);
+ _ = run.addArtifactArg2(exe, .{ .prefix = "path^", .make_absolute = false, .suffix = "$" });
+ run.expectStdErrMatch("exe\n");
+ }
+ }
+
+ // File Args
+ {
+ const write_files = b.addWriteFiles();
+ const file = write_files.add("file", "");
+
+ // Absolute
+ {
+ const run = b.addRunArtifact(exe);
+ step.dependOn(&run.step);
+ _ = run.addFileArg2(file, .{ .prefix = "path^", .make_absolute = true, .suffix = "$" });
+ run.expectStdErrEqual("abs file\n");
+ }
+ // Relative
+ {
+ const run = b.addRunArtifact(exe);
+ step.dependOn(&run.step);
+ _ = run.addFileArg2(file, .{ .prefix = "path^", .make_absolute = false, .suffix = "$" });
+ run.expectStdErrMatch("file\n");
+ }
+ }
+
+ // File Content
+ {
+ const write_files = b.addWriteFiles();
+ const file = write_files.add("file", "foo bar baz");
+
+ const run = b.addRunArtifact(exe);
+ step.dependOn(&run.step);
+ _ = run.addFileContentArg2(file, .{ .prefix = "content-prefix ", .suffix = " content-suffix" });
+ run.expectStdErrEqual("content-prefix foo bar baz content-suffix\n");
+ }
+
+ // Output File Args
+ {
+ // Absolute
+ {
+ const run = b.addRunArtifact(exe);
+ step.dependOn(&run.step);
+ _ = run.addOutputFileArg2("output-file", .{ .prefix = "path^", .make_absolute = true, .suffix = "$" });
+ run.expectStdErrEqual("abs output-file\n");
+ }
+ // Relative
+ {
+ const run = b.addRunArtifact(exe);
+ step.dependOn(&run.step);
+ _ = run.addOutputFileArg2("output-file", .{ .prefix = "path^", .make_absolute = false, .suffix = "$" });
+ run.expectStdErrMatch("output-file\n");
+ }
+ }
+
+ // Output Directory Args
+ {
+ // Absolute
+ {
+ const run = b.addRunArtifact(exe);
+ step.dependOn(&run.step);
+ _ = run.addOutputDirectoryArg2("output-dir", .{ .prefix = "path^", .make_absolute = true, .suffix = "$" });
+ run.expectStdErrEqual("abs output-dir\n");
+ }
+ // Relative
+ {
+ const run = b.addRunArtifact(exe);
+ step.dependOn(&run.step);
+ _ = run.addOutputDirectoryArg2("output-dir", .{ .prefix = "path^", .make_absolute = false, .suffix = "$" });
+ run.expectStdErrMatch("output-dir\n");
+ }
+ }
+
+ // Directory Args
+ {
+ const write_files = b.addWriteFiles();
+ const directory = try write_files.getDirectory().join(b.graph.arena, "dir");
+
+ // Absolute
+ {
+ const run = b.addRunArtifact(exe);
+ step.dependOn(&run.step);
+ _ = run.addDirectoryArg2(directory, .{ .prefix = "path^", .make_absolute = true, .suffix = "$" });
+ run.expectStdErrEqual("abs dir\n");
+ }
+ // Relative
+ {
+ const run = b.addRunArtifact(exe);
+ step.dependOn(&run.step);
+ _ = run.addDirectoryArg2(directory, .{ .prefix = "path^", .make_absolute = false, .suffix = "$" });
+ run.expectStdErrMatch("dir\n");
+ }
+ }
+
+ // Dep File Args
+ {
+ // Absolute
+ {
+ const run = b.addRunArtifact(exe);
+ step.dependOn(&run.step);
+ _ = run.addDepFileOutputArg2("deps.d", .{ .prefix = "path^", .make_absolute = true, .suffix = "$" });
+ run.expectStdErrEqual("abs deps.d\n");
+ }
+ // Relative
+ {
+ const run = b.addRunArtifact(exe);
+ step.dependOn(&run.step);
+ _ = run.addDepFileOutputArg2("deps.d", .{ .prefix = "path^", .make_absolute = false, .suffix = "$" });
+ run.expectStdErrMatch("deps.d\n");
+ }
+ }
+}
diff --git a/test/standalone/run_args/main.zig b/test/standalone/run_args/main.zig
new file mode 100644
index 0000000000000000000000000000000000000000..008f9dd57676baf6d8d960b796a1972aed2c672f
--- /dev/null
+++ b/test/standalone/run_args/main.zig
@@ -0,0 +1,32 @@
+const std = @import("std");
+
+pub fn main(init: std.process.Init) !void {
+ const io = init.io;
+ const arena = init.arena.allocator();
+
+ var iter = try init.minimal.args.iterateAllocator(arena);
+ std.debug.assert(iter.skip());
+ while (iter.next()) |arg| {
+ const path_prefix = "path^";
+ const path_suffix = "$";
+ if (std.mem.startsWith(u8, arg, path_prefix) and std.mem.endsWith(u8, arg, path_suffix)) {
+ // If we're a path, log whether we're absolute or relative, and log the basename
+ const path = arg[path_prefix.len..][0 .. arg.len - path_prefix.len - path_suffix.len];
+ if (std.fs.path.isAbsolute(path)) {
+ std.debug.print("abs ", .{});
+ } else {
+ std.debug.print("rel ", .{});
+ }
+ std.debug.print("{s}\n", .{std.fs.path.basename(path)});
+
+ // Create an empty dep file if necessary
+ if (std.mem.endsWith(u8, path, ".d")) {
+ const file = try std.Io.Dir.cwd().createFile(io, path, .{});
+ defer file.close(io);
+ }
+ } else {
+ // If it's not a path, log the arg as is
+ std.debug.print("{s}\n", .{arg});
+ }
+ }
+}
diff --git a/test/standalone/shared_library/build.zig b/test/standalone/shared_library/build.zig
index 444f5fd7bc7d2415a309958671b5c565383f52cd..20b9df685f8b58798eec82a8d2559b07689e66e4 100644
--- a/test/standalone/shared_library/build.zig
+++ b/test/standalone/shared_library/build.zig
@@ -7,11 +7,47 @@ pub fn build(b: *std.Build) void {
const optimize: std.builtin.OptimizeMode = .Debug;
const target = b.standardTargetOptions(.{});
- const exe_names: []const []const u8 = &.{ "test", "test-dync" };
- const lib_names: []const []const u8 = &.{ "mathtest", "mathtest-dync" };
- const lib_link_libc: []const bool = &.{ false, true };
+ const exe_names: []const []const u8 = &.{
+ "test",
+ "test-dync",
+ "test-no-llvm",
+ "test-no-llvm-dync",
+ "test-exe-no-llvm",
+ "test-dync-exe-no-llvm",
+ "test-no-llvm-exe-no-llvm",
+ "test-no-llvm-dync-exe-no-llvm",
+ };
+ const lib_names: []const []const u8 = &.{
+ "mathtest",
+ "mathtest-dync",
+ "mathtest-no-llvm",
+ "mathtest-no-llvm-dync",
+ "mathtest-exe-no-llvm",
+ "mathtest-dync-exe-no-llvm",
+ "mathtest-no-llvm-exe-no-llvm",
+ "mathtest-no-llvm-dync-exe-no-llvm",
+ };
+ const lib_link_libc: []const bool = &.{ false, true, false, true, false, true, false, true };
+ const lib_use_llvm: []const bool = &.{ true, true, false, false, true, true, false, false };
+ const exe_use_llvm: []const bool = &.{ true, true, true, true, false, false, false, false };
+
+ for (
+ exe_names,
+ lib_names,
+ lib_link_libc,
+ lib_use_llvm,
+ exe_use_llvm,
+ ) |exe_name, lib_name, dyn_libc, lib_llvm, exe_llvm| {
+ const no_llvm = !lib_llvm or !exe_llvm;
+ if (no_llvm and target.result.os.tag == .macos) continue; // TODO
+ if (no_llvm and target.result.os.tag == .freebsd) continue; // TODO
+ if (no_llvm and target.result.os.tag == .netbsd) continue; // TODO
+ if (no_llvm and target.result.os.tag == .openbsd) continue; // TODO
+ if (no_llvm and target.result.cpu.arch == .aarch64) continue; // TODO
+ if (no_llvm and target.result.cpu.arch == .loongarch64) continue; // TODO
+ if (no_llvm and target.result.cpu.arch == .powerpc64le) continue; // TODO
+ if (no_llvm and target.result.cpu.arch == .s390x) continue; // TODO
- for (exe_names, lib_names, lib_link_libc) |exe_name, lib_name, dyn_libc| {
const lib = b.addLibrary(.{
.linkage = .dynamic,
.name = lib_name,
@@ -22,6 +58,7 @@ pub fn build(b: *std.Build) void {
.optimize = optimize,
.link_libc = dyn_libc,
}),
+ .use_llvm = lib_llvm,
});
const exe = b.addExecutable(.{
@@ -32,6 +69,7 @@ pub fn build(b: *std.Build) void {
.optimize = optimize,
.link_libc = true,
}),
+ .use_llvm = exe_llvm,
});
exe.root_module.addCSourceFile(.{
.file = b.path("test.c"),
diff --git a/test/standalone/shared_library/mathtest.zig b/test/standalone/shared_library/mathtest.zig
index a04ec1544dc82e27afb137de2672a48d726a72fc..9c33bf8370c44ea1ec3b59fcd24f1d5a1765608a 100644
--- a/test/standalone/shared_library/mathtest.zig
+++ b/test/standalone/shared_library/mathtest.zig
@@ -1,3 +1,5 @@
+export var exported_var: i32 = 9999;
+
export fn add(a: i32, b: i32) i32 {
return a + b;
}
diff --git a/test/standalone/shared_library/test.c b/test/standalone/shared_library/test.c
index f178f78b4583339b65ae51a14fdb58830b0015db..b1b3672d0a48c9c521e98dbdf14f1f52610a9655 100644
--- a/test/standalone/shared_library/test.c
+++ b/test/standalone/shared_library/test.c
@@ -7,7 +7,16 @@
#include
int32_t add(int32_t a, int32_t b);
+#if _WIN32
+#define IMPORT __declspec(dllimport)
+#else
+#define IMPORT
+#endif
+
+extern IMPORT int32_t exported_var;
+
int main(int argc, char **argv) {
assert(add(42, 1337) == 1379);
+ assert(exported_var == 9999);
return 0;
}
diff --git a/test/standalone/static_c_lib/build.zig b/test/standalone/static_c_lib/build.zig
index 4bed5cdefa5f496c702b60a051646d9e8979b177..5b35871dceca1a00abbac632adab8f0edc4add69 100644
--- a/test/standalone/static_c_lib/build.zig
+++ b/test/standalone/static_c_lib/build.zig
@@ -5,26 +5,76 @@ pub fn build(b: *std.Build) void {
b.default_step = test_step;
const optimize: std.builtin.OptimizeMode = .Debug;
+ const target = b.standardTargetOptions(.{});
- const foo = b.addLibrary(.{
- .linkage = .static,
- .name = "foo",
- .root_module = b.createModule(.{
- .root_source_file = null,
- .optimize = optimize,
- .target = b.graph.host,
- }),
- });
- foo.root_module.addCSourceFile(.{ .file = b.path("foo.c"), .flags = &[_][]const u8{} });
- foo.root_module.addIncludePath(b.path("."));
+ const exe_names: []const []const u8 = &.{
+ "test",
+ "test-dync",
+ "test-no-llvm",
+ "test-no-llvm-dync",
+ "test-exe-no-llvm",
+ "test-dync-exe-no-llvm",
+ "test-no-llvm-exe-no-llvm",
+ "test-no-llvm-dync-exe-no-llvm",
+ };
+ const lib_names: []const []const u8 = &.{
+ "foo",
+ "foo-dync",
+ "foo-no-llvm",
+ "foo-no-llvm-dync",
+ "foo-exe-no-llvm",
+ "foo-dync-exe-no-llvm",
+ "foo-no-llvm-exe-no-llvm",
+ "foo-no-llvm-dync-exe-no-llvm",
+ };
+ const lib_link_libc: []const bool = &.{ false, true, false, true, false, true, false, true };
+ const lib_use_llvm: []const bool = &.{ true, true, false, false, true, true, false, false };
+ const exe_use_llvm: []const bool = &.{ true, true, true, true, false, false, false, false };
- const test_exe = b.addTest(.{ .root_module = b.createModule(.{
- .root_source_file = b.path("foo.zig"),
- .target = b.graph.host,
- .optimize = optimize,
- }) });
- test_exe.root_module.linkLibrary(foo);
- test_exe.root_module.addIncludePath(b.path("."));
+ for (
+ exe_names,
+ lib_names,
+ lib_link_libc,
+ lib_use_llvm,
+ exe_use_llvm,
+ ) |exe_name, lib_name, dyn_libc, lib_llvm, exe_llvm| {
+ const no_llvm = !lib_llvm or !exe_llvm;
+ if (no_llvm and target.result.os.tag == .macos) continue; // TODO
+ if (no_llvm and target.result.os.tag == .freebsd) continue; // TODO
+ if (no_llvm and target.result.os.tag == .netbsd) continue; // TODO
+ if (no_llvm and target.result.os.tag == .openbsd) continue; // TODO
+ if (no_llvm and target.result.cpu.arch == .aarch64) continue; // TODO
+ if (no_llvm and target.result.cpu.arch == .loongarch64) continue; // TODO
+ if (no_llvm and target.result.cpu.arch == .powerpc64le) continue; // TODO
+ if (no_llvm and target.result.cpu.arch == .s390x) continue; // TODO
- test_step.dependOn(&b.addRunArtifact(test_exe).step);
+ const foo = b.addLibrary(.{
+ .linkage = .static,
+ .name = lib_name,
+ .root_module = b.createModule(.{
+ .root_source_file = null,
+ .optimize = optimize,
+ .target = target,
+ .link_libc = dyn_libc,
+ }),
+ .use_llvm = lib_llvm,
+ });
+ foo.root_module.addCSourceFile(.{ .file = b.path("foo.c"), .flags = &[_][]const u8{} });
+ foo.root_module.addIncludePath(b.path("."));
+
+ const test_exe = b.addTest(.{
+ .name = exe_name,
+ .root_module = b.createModule(.{
+ .root_source_file = b.path("foo.zig"),
+ .target = target,
+ .optimize = optimize,
+ .link_libc = dyn_libc,
+ }),
+ .use_llvm = exe_llvm,
+ });
+ test_exe.root_module.linkLibrary(foo);
+ test_exe.root_module.addIncludePath(b.path("."));
+
+ test_step.dependOn(&b.addRunArtifact(test_exe).step);
+ }
}
diff --git a/test/tests.zig b/test/tests.zig
index 9136d1434f11e13087d163a31058e6ae5f5ba895..6166444b9b33bdcafc034cfb26bc55aa9c48a916 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -10,6 +10,7 @@ const error_traces = @import("error_traces.zig");
const stack_traces = @import("stack_traces.zig");
const llvm_ir = @import("llvm_ir.zig");
const libc = @import("libc.zig");
+const link = @import("link.zig");
// Implementations
pub const ErrorTracesContext = @import("src/ErrorTrace.zig");
@@ -17,6 +18,7 @@ pub const StackTracesContext = @import("src/StackTrace.zig");
pub const DebuggerContext = @import("src/Debugger.zig");
pub const LlvmIrContext = @import("src/LlvmIr.zig");
pub const LibcContext = @import("src/Libc.zig");
+pub const LinkContext = @import("src/Link.zig");
const ModuleTestTarget = struct {
linkage: ?std.builtin.LinkMode = null,
@@ -272,36 +274,34 @@ const module_test_targets = blk: {
},
.link_libc = true,
},
- // Crashes in weird ways when applying relocations.
- // .{
- // .target = .{
- // .cpu_arch = .arm,
- // .os_tag = .linux,
- // .abi = .musleabi,
- // },
- // .linkage = .dynamic,
- // .link_libc = true,
- // .extra_target = true,
- // },
+ .{
+ .target = .{
+ .cpu_arch = .arm,
+ .os_tag = .linux,
+ .abi = .musleabi,
+ },
+ .linkage = .dynamic,
+ .link_libc = true,
+ .extra_target = true,
+ },
+ .{
+ .target = .{
+ .cpu_arch = .arm,
+ .os_tag = .linux,
+ .abi = .musleabihf,
+ },
+ .link_libc = true,
+ },
.{
.target = .{
.cpu_arch = .arm,
.os_tag = .linux,
.abi = .musleabihf,
},
+ .linkage = .dynamic,
.link_libc = true,
+ .extra_target = true,
},
- // Crashes in weird ways when applying relocations.
- // .{
- // .target = .{
- // .cpu_arch = .arm,
- // .os_tag = .linux,
- // .abi = .musleabihf,
- // },
- // .linkage = .dynamic,
- // .link_libc = true,
- // .extra_target = true,
- // },
.{
.target = .{
.cpu_arch = .arm,
@@ -623,6 +623,13 @@ const module_test_targets = blk: {
.abi = .none,
},
},
+ .{
+ .target = .{
+ .cpu_arch = .mips64,
+ .os_tag = .linux,
+ .abi = .abin32,
+ },
+ },
.{
.target = .{
.cpu_arch = .mips64,
@@ -648,7 +655,6 @@ const module_test_targets = blk: {
.abi = .muslabin32,
},
.link_libc = true,
- .extra_target = true,
},
.{
.target = .{
@@ -675,7 +681,6 @@ const module_test_targets = blk: {
.abi = .gnuabin32,
},
.link_libc = true,
- .extra_target = true,
},
.{
@@ -685,6 +690,14 @@ const module_test_targets = blk: {
.abi = .none,
},
},
+ .{
+ .target = .{
+ .cpu_arch = .mips64el,
+ .os_tag = .linux,
+ .abi = .abin32,
+ },
+ .extra_target = true,
+ },
.{
.target = .{
.cpu_arch = .mips64el,
@@ -1147,6 +1160,59 @@ const module_test_targets = blk: {
.use_llvm = true,
.use_lld = true,
},
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .linux,
+ .abi = .x32,
+ },
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .linux,
+ .abi = .musl,
+ },
+ .link_libc = true,
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .linux,
+ .abi = .musl,
+ },
+ .linkage = .dynamic,
+ .link_libc = true,
+ .extra_target = true,
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .linux,
+ .abi = .musl,
+ },
+ .link_libc = true,
+ .use_llvm = true,
+ .use_lld = false,
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .linux,
+ .abi = .muslx32,
+ },
+ .link_libc = true,
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .linux,
+ .abi = .muslx32,
+ },
+ .linkage = .dynamic,
+ .link_libc = true,
+ .extra_target = true,
+ },
.{
.target = .{
.cpu_arch = .x86_64,
@@ -1162,54 +1228,6 @@ const module_test_targets = blk: {
.abi = .gnux32,
},
.link_libc = true,
- .extra_target = true,
- },
- .{
- .target = .{
- .cpu_arch = .x86_64,
- .os_tag = .linux,
- .abi = .musl,
- },
- .link_libc = true,
- },
- .{
- .target = .{
- .cpu_arch = .x86_64,
- .os_tag = .linux,
- .abi = .musl,
- },
- .linkage = .dynamic,
- .link_libc = true,
- .extra_target = true,
- },
- .{
- .target = .{
- .cpu_arch = .x86_64,
- .os_tag = .linux,
- .abi = .muslx32,
- },
- .link_libc = true,
- .extra_target = true,
- },
- .{
- .target = .{
- .cpu_arch = .x86_64,
- .os_tag = .linux,
- .abi = .muslx32,
- },
- .linkage = .dynamic,
- .link_libc = true,
- .extra_target = true,
- },
- .{
- .target = .{
- .cpu_arch = .x86_64,
- .os_tag = .linux,
- .abi = .musl,
- },
- .link_libc = true,
- .use_llvm = true,
- .use_lld = false,
},
// Darwin Targets
@@ -2002,12 +2020,133 @@ const c_abi_targets = blk: {
.abi = .gnu,
},
},
+
.{
.target = .{
.cpu_arch = .x86_64,
.os_tag = .windows,
.abi = .gnu,
},
+ .use_llvm = false,
+ .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .cpu_model = .{ .explicit = &std.Target.x86.cpu.x86_64_v2 },
+ .os_tag = .windows,
+ .abi = .gnu,
+ },
+ .use_llvm = false,
+ .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .cpu_model = .{ .explicit = &std.Target.x86.cpu.x86_64_v3 },
+ .os_tag = .windows,
+ .abi = .gnu,
+ },
+ .use_llvm = false,
+ .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"},
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .windows,
+ .abi = .gnu,
+ },
+ .use_llvm = true,
+ },
+ };
+};
+
+const LinkTarget = struct {
+ target: std.Target.Query = .{},
+ optimize_mode: std.builtin.OptimizeMode = .Debug,
+ link_libc: bool = false,
+ use_llvm: bool = false,
+ use_lld: bool = false,
+};
+
+const link_targets = blk: {
+ @setEvalBranchQuota(30000);
+ break :blk [_]LinkTarget{
+ // Native Targets
+
+ // .{
+ // .use_llvm = true,
+ // },
+
+ // Windows Targets
+
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .windows,
+ .abi = .gnu,
+ },
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .windows,
+ .abi = .gnu,
+ },
+ .link_libc = true,
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .windows,
+ .abi = .gnu,
+ },
+ .use_llvm = true,
+ .use_lld = true,
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .windows,
+ .abi = .gnu,
+ },
+ .link_libc = true,
+ .use_llvm = true,
+ .use_lld = true,
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .windows,
+ .abi = .msvc,
+ },
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .windows,
+ .abi = .msvc,
+ },
+ .link_libc = true,
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .windows,
+ .abi = .msvc,
+ },
+ .use_llvm = true,
+ .use_lld = true,
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .windows,
+ .abi = .msvc,
+ },
+ .link_libc = true,
+ .use_llvm = true,
+ .use_lld = true,
},
};
};
@@ -3036,6 +3175,77 @@ pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step {
return step;
}
+const LinkTestOptions = struct {
+ test_target_filters: []const []const u8,
+ test_filters: []const []const u8,
+ optimize_modes: []const OptimizeMode,
+ skip_non_native: bool,
+ skip_windows: bool,
+ skip_llvm: bool,
+ max_rss: usize,
+};
+
+pub fn addLinkTests(b: *std.Build, options: LinkTestOptions) *Step {
+ const step = b.step("test-link", "Run the linker tests");
+ const update_snapshots = b.option(
+ bool,
+ "link-snapshot-update",
+ "Update linker test snapshots in-place instead of testing against them",
+ ) orelse false;
+
+ for (link_targets) |link_target| {
+ if (options.skip_non_native and !link_target.target.isNative()) continue;
+ if (options.skip_windows and link_target.target.os_tag == .windows) continue;
+
+ const resolved_target = b.resolveTargetQuery(link_target.target);
+ const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM");
+ const target = &resolved_target.result;
+
+ if (options.test_target_filters.len > 0) {
+ for (options.test_target_filters) |filter| {
+ if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
+ } else continue;
+ }
+
+ for (options.optimize_modes) |optimize_mode| {
+ if (link_target.optimize_mode != optimize_mode) continue;
+ if (link_target.link_libc and target.abi == .msvc and b.graph.host.result.os.tag != .windows) continue;
+ const would_use_llvm = wouldUseLlvm(link_target.use_llvm, link_target.target, optimize_mode);
+ if (options.skip_llvm and would_use_llvm) continue;
+
+ const opt_update_step = if (update_snapshots) update: {
+ const update_step = Step.UpdateSourceFiles.create(b);
+ step.dependOn(&update_step.step);
+ break :update update_step;
+ } else null;
+
+ var context: LinkContext = .{
+ .b = b,
+ .step = step,
+ .optimize = optimize_mode,
+ .target = resolved_target,
+ .target_desc = std.fmt.allocPrint(b.allocator, "{s}-{t}{s}{s}{s}", .{
+ target.zigTriple(b.allocator) catch @panic("OOM"),
+ optimize_mode,
+ if (link_target.use_llvm) "-llvm" else "",
+ if (link_target.use_lld) "-lld" else "",
+ if (link_target.link_libc) "-libc" else "",
+ }) catch @panic("OOM"),
+ .use_llvm = link_target.use_llvm,
+ .use_lld = link_target.use_lld,
+ .link_libc = link_target.link_libc,
+ .test_filters = options.test_filters,
+ .update_step = opt_update_step,
+ .updated_snapshots = .empty,
+ .max_rss = options.max_rss,
+ };
+
+ link.addCases(&context);
+ }
+ }
+ return step;
+}
+
pub fn addCases(
b: *std.Build,
parent_step: *Step,
diff --git a/tools/check_mingw.zig b/tools/check_mingw.zig
new file mode 100644
index 0000000000000000000000000000000000000000..c67b3f2599efaa9592cc238b866a44d2b3e1bf45
--- /dev/null
+++ b/tools/check_mingw.zig
@@ -0,0 +1,124 @@
+const std = @import("std");
+const Io = std.Io;
+const Dir = Io.Dir;
+const Preprocessor = @import("preprocessor");
+
+pub fn main(init: std.process.Init) !void {
+ const arena = init.arena.allocator();
+ const io = init.io;
+ const args = try init.minimal.args.toSlice(arena);
+
+ const zig_src_mingw_lib_path = args[1];
+
+ const mingw_include_path = try Dir.path.join(arena, &.{
+ zig_src_mingw_lib_path, "def-include",
+ });
+ const mingw_libcommon_path = try Dir.path.join(arena, &.{
+ zig_src_mingw_lib_path, "lib-common",
+ });
+
+ var mingw_libcommon_dir = Dir.cwd().openDir(io, mingw_libcommon_path, .{ .iterate = true }) catch |err| {
+ std.log.err("unable to open directory {s}: {t}", .{ mingw_libcommon_path, err });
+ std.process.exit(1);
+ };
+ defer mingw_libcommon_dir.close(io);
+
+ var walker = try mingw_libcommon_dir.walk(arena);
+ defer walker.deinit();
+
+ while (try walker.next(io)) |entry| {
+ if (entry.kind != .file) continue;
+ // Only .def.in files need preprocessing
+ if (!std.mem.endsWith(u8, entry.basename, ".def.in")) continue;
+
+ var fail = false;
+ for (&targets) |*target| {
+ var target_arena: std.heap.ArenaAllocator = .init(init.gpa);
+ defer target_arena.deinit();
+
+ const pp_arena = target_arena.allocator();
+ const file_path = try Dir.path.join(pp_arena, &.{ mingw_libcommon_path, entry.path });
+
+ const aro = pp: {
+ const target_triple = try target.zigTriple(pp_arena);
+ const target_arg = try std.fmt.allocPrint(pp_arena, "--target={s}", .{target_triple});
+ const result = std.process.run(pp_arena, io, .{
+ .argv = &.{
+ "arocc",
+ "-E",
+ target_arg,
+ "--no-line-commands",
+ "-nostdinc",
+ "-I",
+ mingw_include_path,
+ file_path,
+ },
+ }) catch |err| {
+ std.log.err("unable to execute arocc: {t}", .{err});
+ std.process.exit(1);
+ };
+ if (result.term.exited != 0) {
+ std.log.err("error executing arocc: {s}", .{result.stderr});
+ std.process.exit(result.term.exited);
+ }
+ break :pp result.stdout;
+ };
+
+ const native = pp: {
+ var aw: Io.Writer.Allocating = .init(pp_arena);
+ errdefer aw.deinit();
+
+ var pp: Preprocessor = .{
+ .io = io,
+ .arena = pp_arena,
+ .include_dir = mingw_include_path,
+ .target = target,
+ };
+
+ pp.preprocess(file_path) catch |err| {
+ std.log.err("error preprocessing file {s} for target {t}: {t}", .{ entry.path, target.cpu.arch, err });
+ fail = true;
+ continue;
+ };
+ pp.prettyPrintTokens(&aw.writer) catch |err| {
+ std.log.err("error printing tokens for file {s} for target {t}: {t}", .{ entry.path, target.cpu.arch, err });
+ fail = true;
+ continue;
+ };
+
+ break :pp try aw.toOwnedSliceSentinel(0);
+ };
+
+ try std.testing.expectEqualStrings(aro, native);
+ }
+
+ if (fail) std.process.exit(1);
+ }
+}
+
+const targets = [_]std.Target{
+ .{
+ .ofmt = .coff,
+ .abi = .gnu,
+ .os = .{ .tag = .windows, .version_range = .default(.thumb, .windows, .gnu) },
+ .cpu = .{ .arch = .thumb, .model = .generic(.thumb), .features = .empty },
+ },
+ .{
+ .ofmt = .coff,
+ .abi = .gnu,
+ .os = .{ .tag = .windows, .version_range = .default(.aarch64, .windows, .gnu) },
+ .cpu = .{ .arch = .aarch64, .model = .generic(.aarch64), .features = .empty },
+ },
+ .{
+ .ofmt = .coff,
+ .abi = .gnu,
+ .os = .{ .tag = .windows, .version_range = .default(.x86, .windows, .gnu) },
+ .cpu = .{ .arch = .x86, .model = .generic(.x86), .features = .empty },
+ },
+ .{
+ .ofmt = .coff,
+ .abi = .gnu,
+ .os = .{ .tag = .windows, .version_range = .default(.x86_64, .windows, .gnu) },
+ .cpu = .{ .arch = .x86_64, .model = .generic(.x86_64), .features = .empty },
+ },
+};
diff --git a/tools/dump-cov.zig b/tools/dump-cov.zig
index 4a54d9f5199299a75dd8fcae46a7d3506ee53d50..c9a8aa8a32ccbe2fc063d30bda143f772bef0e19 100644
--- a/tools/dump-cov.zig
+++ b/tools/dump-cov.zig
@@ -67,7 +67,7 @@ pub fn main(init: std.process.Init) !void {
try stdout.print("{any}\n", .{header.*});
const pcs = header.pcAddrs();
- var indexed_pcs: std.AutoArrayHashMapUnmanaged(usize, void) = .empty;
+ var indexed_pcs: std.array_hash_map.Auto(usize, void) = .empty;
try indexed_pcs.entries.resize(arena, pcs.len);
@memcpy(indexed_pcs.entries.items(.key), pcs);
try indexed_pcs.reIndex(arena);
diff --git a/tools/gen_spirv_spec.zig b/tools/gen_spirv_spec.zig
index 57e1a64471218d40a49314a1ba44d3a6e846e43c..fbf8fa167ae6fc0ae5dcba040a87046b66d34c5c 100644
--- a/tools/gen_spirv_spec.zig
+++ b/tools/gen_spirv_spec.zig
@@ -13,6 +13,33 @@ const Operand = g.Operand;
const ExtendedStructSet = std.StringHashMap(void);
+const allowed_vendors = [_][]const u8{
+ "KHR",
+ "EXT",
+};
+
+fn isAllowedCapability(name: []const u8) bool {
+ // core capabilities (no vendor suffix) end in a lowercase letter or digit.
+ const last = name[name.len - 1];
+ if (std.ascii.isLower(last) or std.ascii.isDigit(last)) return true;
+ for (allowed_vendors) |vendor| {
+ if (std.mem.endsWith(u8, name, vendor)) return true;
+ }
+ return false;
+}
+
+fn isAllowedExtension(name: []const u8) bool {
+ const spv_prefix = "SPV_";
+ if (!std.mem.startsWith(u8, name, spv_prefix)) return false;
+ const tail = name[spv_prefix.len..];
+ for (allowed_vendors) |vendor| {
+ if (std.mem.startsWith(u8, tail, vendor) and
+ tail.len > vendor.len and tail[vendor.len] == '_')
+ return true;
+ }
+ return false;
+}
+
const Extension = struct {
name: []const u8,
opcode_name: []const u8,
@@ -325,6 +352,43 @@ fn render(
try renderOperandKinds(arena, writer, all_operand_kinds.values(), extended_structs);
try renderInstructionSet(writer, registry, extensions, all_operand_kinds);
+ try renderExtension(arena, writer, all_operand_kinds.values());
+}
+
+fn renderExtension(
+ arena: Allocator,
+ writer: *std.Io.Writer,
+ kinds: []const OperandKind,
+) !void {
+ try writer.writeAll(
+ \\pub const Extension = enum {
+ \\v1_0,
+ \\v1_1,
+ \\v1_2,
+ \\v1_3,
+ \\v1_4,
+ \\v1_5,
+ \\v1_6,
+ \\
+ );
+
+ var seen_extensions: std.StringHashMapUnmanaged(void) = .empty;
+ defer seen_extensions.deinit(arena);
+
+ for (kinds) |kind| {
+ if (std.mem.eql(u8, "Capability", kind.kind)) {
+ for (kind.enumerants.?) |enumerant| {
+ if (!isAllowedCapability(enumerant.enumerant)) continue;
+ for (enumerant.extensions) |ext| {
+ if (!isAllowedExtension(ext)) continue;
+ if (seen_extensions.contains(ext)) continue;
+ try seen_extensions.put(arena, ext, {});
+ try writer.print("{s},\n", .{ext});
+ }
+ }
+ }
+ }
+ try writer.writeAll("};\n");
}
fn renderInstructionSet(
@@ -687,10 +751,13 @@ fn renderValueEnum(
const enum_indices = enum_map.values();
+ const is_capability = std.mem.eql(u8, "Capability", enumeration.kind);
+
try writer.print("pub const {f} = enum(u32) {{\n", .{std.zig.fmtId(enumeration.kind)});
for (enum_indices) |i| {
const enumerant = enumerants[i];
+ if (is_capability and !isAllowedCapability(enumerant.enumerant)) continue;
// if (enumerant.value != .int) return error.InvalidRegistry;
switch (enumerant.value) {
@@ -702,6 +769,8 @@ fn renderValueEnum(
try writer.writeByte('\n');
for (aliases.items) |alias| {
+ if (is_capability and (!isAllowedCapability(enumerants[alias.enumerant].enumerant) or
+ !isAllowedCapability(enumerants[alias.alias].enumerant))) continue;
try writer.print("pub const {f} = {f}.{f};\n", .{
formatId(enumerants[alias.enumerant].enumerant),
std.zig.fmtId(enumeration.kind),
@@ -709,6 +778,41 @@ fn renderValueEnum(
});
}
+ if (is_capability) {
+ try writer.writeAll(
+ \\
+ \\pub fn dependencies(self: Capability) []const Extension {
+ \\ return switch (self) {
+ );
+
+ for (enum_indices) |i| {
+ const enumerant = enumerants[i];
+ if (!isAllowedCapability(enumerant.enumerant)) continue;
+
+ // Convert version to enum.
+ // None is for reserved
+ // Example: "None" -> .v1_0
+ // Example: "1.5" -> .v1_5
+ const enum_version = enumerant.version.?;
+ const version: [4]u8 = .{ 'v', '1', '_', if (enum_version[0] == 'N') '0' else enum_version[2] };
+
+ try writer.print("\n.{f} => &.{{.{s},", .{ formatId(enumerant.enumerant), version });
+ for (enumerant.extensions) |extension| {
+ if (!isAllowedExtension(extension)) continue;
+ try writer.print(".{s},", .{extension});
+ }
+ try writer.writeAll("},");
+ }
+
+ try writer.writeAll(
+ \\};
+ \\}
+ \\};
+ \\
+ );
+ return;
+ }
+
if (!extended_structs.contains(enumeration.kind)) {
try writer.writeAll("};\n");
return;
diff --git a/tools/update_cpu_features.zig b/tools/update_cpu_features.zig
index ea6a659507a972c3c95492817ac6779a4ced05ba..42432c0c36f48c831524773b882d1da75caaa723 100644
--- a/tools/update_cpu_features.zig
+++ b/tools/update_cpu_features.zig
@@ -1,4 +1,5 @@
const builtin = @import("builtin");
+const spirv_spec = @import("spirv_spec");
const std = @import("std");
const Io = std.Io;
@@ -49,6 +50,43 @@ const ArchTarget = struct {
branch_quota: ?usize = null,
};
+const spirv_extra_features = blk: {
+ const caps_info = @typeInfo(spirv_spec.Capability).@"enum";
+ const exts_info = @typeInfo(spirv_spec.Extension).@"enum";
+ const caps_len = caps_info.field_names.len;
+ const exts_len = exts_info.field_names.len;
+
+ var features: [caps_len + exts_len]Feature = undefined;
+ for (
+ caps_info.field_names,
+ caps_info.field_values,
+ features[0..caps_len],
+ ) |name, value, *feature| {
+ feature.* = .{
+ .zig_name = name,
+ .desc = "Enable " ++ name ++ " capability",
+ .deps = &struct {
+ const extensions = spirv_spec.Capability.dependencies(@enumFromInt(value));
+ const deps: [extensions.len][]const u8 = inner: {
+ var out: [extensions.len][]const u8 = undefined;
+ for (extensions, 0..) |ext, i| out[i] = @tagName(ext);
+ break :inner out;
+ };
+ }.deps,
+ };
+ }
+
+ for (exts_info.field_names, features[caps_len..]) |name, *feature| {
+ feature.* = .{
+ .zig_name = name,
+ .desc = "Enable " ++ name ++ " extension",
+ .deps = &.{},
+ };
+ }
+
+ break :blk features;
+};
+
const targets = [_]ArchTarget{
.{
.zig_name = "aarch64",
@@ -1358,6 +1396,15 @@ const targets = [_]ArchTarget{
},
},
.extra_cpus = &.{
+ .{
+ .llvm_name = null,
+ .zig_name = "r3000a",
+ .features = &.{
+ "mips1",
+ "soft_float",
+ "notraps",
+ },
+ },
.{
.llvm_name = null,
.zig_name = "allegrex",
@@ -1434,83 +1481,7 @@ const targets = [_]ArchTarget{
.td_name = "SPIRV",
},
.branch_quota = 2000,
- .extra_features = &.{
- .{
- .zig_name = "v1_0",
- .desc = "Enable version 1.0",
- .deps = &.{},
- },
- .{
- .zig_name = "v1_1",
- .desc = "Enable version 1.1",
- .deps = &.{"v1_0"},
- },
- .{
- .zig_name = "v1_2",
- .desc = "Enable version 1.2",
- .deps = &.{"v1_1"},
- },
- .{
- .zig_name = "v1_3",
- .desc = "Enable version 1.3",
- .deps = &.{"v1_2"},
- },
- .{
- .zig_name = "v1_4",
- .desc = "Enable version 1.4",
- .deps = &.{"v1_3"},
- },
- .{
- .zig_name = "v1_5",
- .desc = "Enable version 1.5",
- .deps = &.{"v1_4"},
- },
- .{
- .zig_name = "v1_6",
- .desc = "Enable version 1.6",
- .deps = &.{"v1_5"},
- },
- .{
- .zig_name = "int64",
- .desc = "Enable Int64 capability",
- .deps = &.{"v1_0"},
- },
- .{
- .zig_name = "float16",
- .desc = "Enable Float16 capability",
- .deps = &.{"v1_0"},
- },
- .{
- .zig_name = "float64",
- .desc = "Enable Float64 capability",
- .deps = &.{"v1_0"},
- },
- .{
- .zig_name = "storage_push_constant16",
- .desc = "Enable SPV_KHR_16bit_storage extension and the StoragePushConstant16 capability",
- .deps = &.{"v1_3"},
- },
- .{
- .zig_name = "arbitrary_precision_integers",
- .desc = "Enable SPV_INTEL_arbitrary_precision_integers extension and the ArbitraryPrecisionIntegersINTEL capability",
- .deps = &.{"v1_5"},
- },
- .{
- .zig_name = "generic_pointer",
- .desc = "Enable GenericPointer capability",
- .deps = &.{"v1_0"},
- },
- .{
- .zig_name = "vector16",
- .desc = "Enable Vector16 capability",
- .deps = &.{"v1_0"},
- },
- .{
- .zig_name = "variable_pointers",
- .desc = "Enable SPV_KHR_variable_pointers extension and the VariablePointers capability",
- .deps = &.{"v1_0"},
- },
- },
+ .extra_features = &spirv_extra_features,
.extra_cpus = &.{
.{
.llvm_name = null,
diff --git a/tools/update_crc_catalog.zig b/tools/update_crc_catalog.zig
index 57eedf375b29c1195dcfbf4dcea1f42f1235a192..55f51ce92b4f4a36f51fd176b681487de16d1621 100644
--- a/tools/update_crc_catalog.zig
+++ b/tools/update_crc_catalog.zig
@@ -2,7 +2,6 @@ const std = @import("std");
const Io = std.Io;
const Dir = std.Io.Dir;
const mem = std.mem;
-const ascii = std.ascii;
const catalog_txt = @embedFile("crc/catalog.txt");
@@ -32,6 +31,7 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8)
var zig_code_file = try hash_target_dir.createFile(io, "crc.zig", .{});
defer zig_code_file.close(io);
+
var zig_code_file_buffer: [4096]u8 = undefined;
var zig_code_file_writer = zig_code_file.writer(io, &zig_code_file_buffer);
const code_writer = &zig_code_file_writer.interface;
@@ -39,23 +39,13 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8)
try code_writer.writeAll(
\\//! This file is auto-generated by tools/update_crc_catalog.zig.
\\
- \\const impl = @import("crc/impl.zig");
- \\
- \\pub const Crc = impl.Crc;
- \\pub const Polynomial = impl.Polynomial;
- \\pub const Crc32WithPoly = impl.Crc32WithPoly;
- \\pub const Crc32SmallWithPoly = impl.Crc32SmallWithPoly;
- \\
- \\pub const Crc32 = Crc32IsoHdlc;
- \\
- \\test {
- \\ _ = @import("crc/test.zig");
- \\}
+ \\const builtin = @import("builtin");
\\
);
var zig_test_file = try crc_target_dir.createFile(io, "test.zig", .{});
defer zig_test_file.close(io);
+
var zig_test_file_buffer: [4096]u8 = undefined;
var zig_test_file_writer = zig_test_file.writer(io, &zig_test_file_buffer);
const test_writer = &zig_test_file_writer.interface;
@@ -69,24 +59,24 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8)
\\const crc = @import("../crc.zig");
\\
\\test "crc32 ieee regression" {
- \\ const crc32 = crc.Crc32IsoHdlc;
- \\ try testing.expectEqual(crc32.hash(""), 0x00000000);
- \\ try testing.expectEqual(crc32.hash("a"), 0xe8b7be43);
- \\ try testing.expectEqual(crc32.hash("abc"), 0x352441c2);
+ \\ const Crc = crc.@"CRC-32/ISO-HDLC";
+ \\ try testing.expectEqual(Crc.hash(""), 0x00000000);
+ \\ try testing.expectEqual(Crc.hash("a"), 0xe8b7be43);
+ \\ try testing.expectEqual(Crc.hash("abc"), 0x352441c2);
\\}
\\
\\test "crc32 castagnoli regression" {
- \\ const crc32 = crc.Crc32Iscsi;
- \\ try testing.expectEqual(crc32.hash(""), 0x00000000);
- \\ try testing.expectEqual(crc32.hash("a"), 0xc1d04330);
- \\ try testing.expectEqual(crc32.hash("abc"), 0x364b3fb7);
+ \\ const Crc = crc.@"CRC-32/ISCSI";
+ \\ try testing.expectEqual(Crc.hash(""), 0x00000000);
+ \\ try testing.expectEqual(Crc.hash("a"), 0xc1d04330);
+ \\ try testing.expectEqual(Crc.hash("abc"), 0x364b3fb7);
\\}
\\
\\test "crc32 koopman regression" {
- \\ const crc32 = crc.Koopman;
- \\ try testing.expectEqual(crc32.hash(""), 0x00000000);
- \\ try testing.expectEqual(crc32.hash("a"), 0x0da2aa8a);
- \\ try testing.expectEqual(crc32.hash("abc"), 0xba2322ac);
+ \\ const Crc = crc.@"CRC-32/KOOPMAN";
+ \\ try testing.expectEqual(Crc.hash(""), 0x00000000);
+ \\ try testing.expectEqual(Crc.hash("a"), 0x0da2aa8a);
+ \\ try testing.expectEqual(Crc.hash("abc"), 0xba2322ac);
\\}
\\
);
@@ -135,59 +125,154 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8)
}
}
- const snakecase = try ascii.allocLowerString(arena, name);
- defer arena.free(snakecase);
-
- _ = mem.replace(u8, snakecase, "-", "_", snakecase);
- _ = mem.replace(u8, snakecase, "/", "_", snakecase);
-
- var buf = try std.array_list.Managed(u8).initCapacity(arena, snakecase.len);
- defer buf.deinit();
-
- var prev: u8 = 0;
- for (snakecase, 0..) |c, i| {
- if (c == '_') {
- // do nothing
- } else if (i == 0) {
- buf.appendAssumeCapacity(ascii.toUpper(c));
- } else if (prev == '_') {
- buf.appendAssumeCapacity(ascii.toUpper(c));
- } else {
- buf.appendAssumeCapacity(c);
- }
- prev = c;
+ if (mem.eql(u8, name, "CRC-32/ISCSI")) {
+ try code_writer.print(
+ \\
+ \\pub const {f} = if (builtin.cpu.hasAll(.x86, &.{{ .@"64bit", .crc32 }}))
+ \\ @import("crc/Crc32c.zig")
+ \\else
+ \\ Generic(u{s}, .{{
+ \\ .polynomial = {s},
+ \\ .initial = {s},
+ \\ .reflect_input = {s},
+ \\ .reflect_output = {s},
+ \\ .xor_output = {s},
+ \\ }});
+ \\
+ , .{ std.zig.fmtId(name), width, poly, init, refin, refout, xorout });
+ } else {
+ try code_writer.print(
+ \\
+ \\pub const {f} = Generic(u{s}, .{{
+ \\ .polynomial = {s},
+ \\ .initial = {s},
+ \\ .reflect_input = {s},
+ \\ .reflect_output = {s},
+ \\ .xor_output = {s},
+ \\}});
+ \\
+ , .{ std.zig.fmtId(name), width, poly, init, refin, refout, xorout });
}
- const camelcase = buf.items;
-
- try code_writer.writeAll(try std.fmt.allocPrint(arena,
- \\
- \\pub const {s} = Crc(u{s}, .{{
- \\ .polynomial = {s},
- \\ .initial = {s},
- \\ .reflect_input = {s},
- \\ .reflect_output = {s},
- \\ .xor_output = {s},
- \\}});
- \\
- , .{ camelcase, width, poly, init, refin, refout, xorout }));
-
- try test_writer.writeAll(try std.fmt.allocPrint(arena,
+ try test_writer.print(
\\
\\test "{0s}" {{
- \\ const {1s} = crc.{1s};
+ \\ const Crc = crc.{1f};
\\
- \\ try testing.expectEqual(@as(u{2s}, {3s}), {1s}.hash("123456789"));
+ \\ try testing.expectEqual(@as(u{2s}, {3s}), Crc.hash("123456789"));
\\
- \\ var c = {1s}.init();
+ \\ var c = Crc.init();
\\ c.update("1234");
\\ c.update("56789");
\\ try testing.expectEqual(@as(u{2s}, {3s}), c.final());
\\}}
\\
- , .{ name, camelcase, width, check }));
+ , .{ name, std.zig.fmtId(name), width, check });
}
+ try code_writer.writeAll(
+ \\
+ \\pub fn Algorithm(comptime W: type) type {
+ \\ return struct {
+ \\ polynomial: W,
+ \\ initial: W,
+ \\ reflect_input: bool,
+ \\ reflect_output: bool,
+ \\ xor_output: W,
+ \\ };
+ \\}
+ \\
+ \\pub fn Generic(comptime W: type, comptime algorithm: Algorithm(W)) type {
+ \\ return struct {
+ \\ const Self = @This();
+ \\ const I = if (@bitSizeOf(W) < 8) u8 else W;
+ \\ const lookup_table = blk: {
+ \\ @setEvalBranchQuota(2500);
+ \\ const poly = reflect(algorithm.polynomial);
+ \\ var table: [256]I = undefined;
+ \\ for (&table, 0..) |*e, i| {
+ \\ var crc: I = i;
+ \\ if (algorithm.reflect_input) {
+ \\ var j: usize = 0;
+ \\ while (j < 8) : (j += 1) {
+ \\ crc = (crc >> 1) ^ ((crc & 1) * poly);
+ \\ }
+ \\ } else {
+ \\ crc <<= @bitSizeOf(I) - 8;
+ \\ var j: usize = 0;
+ \\ while (j < 8) : (j += 1) {
+ \\ crc = (crc << 1) ^ (((crc >> (@bitSizeOf(I) - 1)) & 1) * poly);
+ \\ }
+ \\ }
+ \\ e.* = crc;
+ \\ }
+ \\ break :blk table;
+ \\ };
+ \\
+ \\ crc: I,
+ \\
+ \\ pub fn init() Self {
+ \\ const initial = reflect(algorithm.initial);
+ \\ return .{ .crc = initial };
+ \\ }
+ \\
+ \\ inline fn tableEntry(index: I) I {
+ \\ const short: u8 = @truncate(index);
+ \\ return lookup_table[short];
+ \\ }
+ \\
+ \\ pub fn update(self: *Self, bytes: []const u8) void {
+ \\ var i: usize = 0;
+ \\ if (@bitSizeOf(I) <= 8) {
+ \\ while (i < bytes.len) : (i += 1) {
+ \\ self.crc = tableEntry(self.crc ^ bytes[i]);
+ \\ }
+ \\ } else if (algorithm.reflect_input) {
+ \\ while (i < bytes.len) : (i += 1) {
+ \\ const table_index = self.crc ^ bytes[i];
+ \\ self.crc = tableEntry(table_index) ^ (self.crc >> 8);
+ \\ }
+ \\ } else {
+ \\ while (i < bytes.len) : (i += 1) {
+ \\ const table_index = (self.crc >> (@bitSizeOf(I) - 8)) ^ bytes[i];
+ \\ self.crc = tableEntry(table_index) ^ (self.crc << 8);
+ \\ }
+ \\ }
+ \\ }
+ \\
+ \\ pub fn final(self: Self) W {
+ \\ var c = self.crc;
+ \\ if (algorithm.reflect_input != algorithm.reflect_output) {
+ \\ c = @bitReverse(c);
+ \\ }
+ \\ if (!algorithm.reflect_output) {
+ \\ c >>= @bitSizeOf(I) - @bitSizeOf(W);
+ \\ }
+ \\ return @intCast(c ^ algorithm.xor_output);
+ \\ }
+ \\
+ \\ pub fn hash(bytes: []const u8) W {
+ \\ var c = Self.init();
+ \\ c.update(bytes);
+ \\ return c.final();
+ \\ }
+ \\
+ \\ fn reflect(x: I) I {
+ \\ const offset = @bitSizeOf(I) - @bitSizeOf(W);
+ \\ if (algorithm.reflect_input)
+ \\ return @bitReverse(x) >> offset
+ \\ else
+ \\ return x << offset;
+ \\ }
+ \\ };
+ \\}
+ \\
+ \\test {
+ \\ _ = @import("crc/test.zig");
+ \\}
+ \\
+ );
+
try code_writer.flush();
try test_writer.flush();
}