| author | |
| committer | |
| log | 597082adf45cebbf2c6a81c3f732b6d2ce4a1435 |
| tree | 9309977e204cceaac2c18efbea2153a69f86d1f4 |
| parent | 07606d12daabe8c201dba3d5b27e702ce58d0ffb |
| parent | d98e39fa6864f287bc50f265f98b7195849afa68 |
Conflicts:
* build.zig
* src/Compilation.zig
* src/codegen/spirv/spec.zig
* src/link/SpirV.zig
* test/stage2/darwin.zig
- this one might be problematic; start.zig looks for `main` in the
root source file, not `_main`. Not sure why there is an underscore
there in master branch.48 files changed, 3668 insertions(+), 907 deletions(-)
build.zig+70-22| ... | @@ -228,6 +228,7 @@ pub fn build(b: *Builder) !void { | ... | @@ -228,6 +228,7 @@ pub fn build(b: *Builder) !void { |
| 228 | const is_wine_enabled = b.option(bool, "enable-wine", "Use Wine to run cross compiled Windows tests") orelse false; | 228 | const is_wine_enabled = b.option(bool, "enable-wine", "Use Wine to run cross compiled Windows tests") orelse false; |
| 229 | const is_qemu_enabled = b.option(bool, "enable-qemu", "Use QEMU to run cross compiled foreign architecture tests") orelse false; | 229 | const is_qemu_enabled = b.option(bool, "enable-qemu", "Use QEMU to run cross compiled foreign architecture tests") orelse false; |
| 230 | const is_wasmtime_enabled = b.option(bool, "enable-wasmtime", "Use Wasmtime to enable and run WASI libstd tests") orelse false; | 230 | const is_wasmtime_enabled = b.option(bool, "enable-wasmtime", "Use Wasmtime to enable and run WASI libstd tests") orelse false; |
| 231 | const is_darling_enabled = b.option(bool, "enable-darling", "[Experimental] Use Darling to run cross compiled macOS tests") orelse false; | ||
| 231 | const glibc_multi_dir = b.option([]const u8, "enable-foreign-glibc", "Provide directory with glibc installations to run cross compiled tests that link glibc"); | 232 | const glibc_multi_dir = b.option([]const u8, "enable-foreign-glibc", "Provide directory with glibc installations to run cross compiled tests that link glibc"); |
| 232 | 233 | ||
| 233 | test_stage2.addBuildOption(bool, "skip_non_native", skip_non_native); | 234 | test_stage2.addBuildOption(bool, "skip_non_native", skip_non_native); |
| ... | @@ -238,6 +239,7 @@ pub fn build(b: *Builder) !void { | ... | @@ -238,6 +239,7 @@ pub fn build(b: *Builder) !void { |
| 238 | test_stage2.addBuildOption(bool, "enable_wine", is_wine_enabled); | 239 | test_stage2.addBuildOption(bool, "enable_wine", is_wine_enabled); |
| 239 | test_stage2.addBuildOption(bool, "enable_wasmtime", is_wasmtime_enabled); | 240 | test_stage2.addBuildOption(bool, "enable_wasmtime", is_wasmtime_enabled); |
| 240 | test_stage2.addBuildOption(u32, "mem_leak_frames", mem_leak_frames * 2); | 241 | test_stage2.addBuildOption(u32, "mem_leak_frames", mem_leak_frames * 2); |
| 242 | test_stage2.addBuildOption(bool, "enable_darling", is_darling_enabled); | ||
| 241 | test_stage2.addBuildOption(?[]const u8, "glibc_multi_install_dir", glibc_multi_dir); | 243 | test_stage2.addBuildOption(?[]const u8, "glibc_multi_install_dir", glibc_multi_dir); |
| 242 | test_stage2.addBuildOption([]const u8, "version", version); | 244 | test_stage2.addBuildOption([]const u8, "version", version); |
| 243 | 245 | ||
| ... | @@ -272,11 +274,56 @@ pub fn build(b: *Builder) !void { | ... | @@ -272,11 +274,56 @@ pub fn build(b: *Builder) !void { |
| 272 | const fmt_step = b.step("test-fmt", "Run zig fmt against build.zig to make sure it works"); | 274 | const fmt_step = b.step("test-fmt", "Run zig fmt against build.zig to make sure it works"); |
| 273 | fmt_step.dependOn(&fmt_build_zig.step); | 275 | fmt_step.dependOn(&fmt_build_zig.step); |
| 274 | 276 | ||
| 275 | // TODO for the moment, skip wasm32-wasi until bugs are sorted out. | 277 | toolchain_step.dependOn(tests.addPkgTests( |
| 276 | toolchain_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", modes, false, skip_non_native, skip_libc, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir)); | 278 | b, |
| 277 | 279 | test_filter, | |
| 278 | toolchain_step.dependOn(tests.addPkgTests(b, test_filter, "lib/std/special/compiler_rt.zig", "compiler-rt", "Run the compiler_rt tests", modes, true, skip_non_native, true, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir)); | 280 | "test/behavior.zig", |
| 279 | toolchain_step.dependOn(tests.addPkgTests(b, test_filter, "lib/std/special/c.zig", "minilibc", "Run the mini libc tests", modes, true, skip_non_native, true, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir)); | 281 | "behavior", |
| 282 | "Run the behavior tests", | ||
| 283 | modes, | ||
| 284 | false, | ||
| 285 | skip_non_native, | ||
| 286 | skip_libc, | ||
| 287 | is_wine_enabled, | ||
| 288 | is_qemu_enabled, | ||
| 289 | is_wasmtime_enabled, | ||
| 290 | is_darling_enabled, | ||
| 291 | glibc_multi_dir, | ||
| 292 | )); | ||
| 293 | |||
| 294 | toolchain_step.dependOn(tests.addPkgTests( | ||
| 295 | b, | ||
| 296 | test_filter, | ||
| 297 | "lib/std/special/compiler_rt.zig", | ||
| 298 | "compiler-rt", | ||
| 299 | "Run the compiler_rt tests", | ||
| 300 | modes, | ||
| 301 | true, | ||
| 302 | skip_non_native, | ||
| 303 | true, | ||
| 304 | is_wine_enabled, | ||
| 305 | is_qemu_enabled, | ||
| 306 | is_wasmtime_enabled, | ||
| 307 | is_darling_enabled, | ||
| 308 | glibc_multi_dir, | ||
| 309 | )); | ||
| 310 | |||
| 311 | toolchain_step.dependOn(tests.addPkgTests( | ||
| 312 | b, | ||
| 313 | test_filter, | ||
| 314 | "lib/std/special/c.zig", | ||
| 315 | "minilibc", | ||
| 316 | "Run the mini libc tests", | ||
| 317 | modes, | ||
| 318 | true, | ||
| 319 | skip_non_native, | ||
| 320 | true, | ||
| 321 | is_wine_enabled, | ||
| 322 | is_qemu_enabled, | ||
| 323 | is_wasmtime_enabled, | ||
| 324 | is_darling_enabled, | ||
| 325 | glibc_multi_dir, | ||
| 326 | )); | ||
| 280 | 327 | ||
| 281 | toolchain_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes)); | 328 | toolchain_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes)); |
| 282 | toolchain_step.dependOn(tests.addStandaloneTests(b, test_filter, modes)); | 329 | toolchain_step.dependOn(tests.addStandaloneTests(b, test_filter, modes)); |
| ... | @@ -294,7 +341,22 @@ pub fn build(b: *Builder) !void { | ... | @@ -294,7 +341,22 @@ pub fn build(b: *Builder) !void { |
| 294 | toolchain_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes)); | 341 | toolchain_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes)); |
| 295 | } | 342 | } |
| 296 | 343 | ||
| 297 | const std_step = tests.addPkgTests(b, test_filter, "lib/std/std.zig", "std", "Run the standard library tests", modes, false, skip_non_native, skip_libc, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir); | 344 | const std_step = tests.addPkgTests( |
| 345 | b, | ||
| 346 | test_filter, | ||
| 347 | "lib/std/std.zig", | ||
| 348 | "std", | ||
| 349 | "Run the standard library tests", | ||
| 350 | modes, | ||
| 351 | false, | ||
| 352 | skip_non_native, | ||
| 353 | skip_libc, | ||
| 354 | is_wine_enabled, | ||
| 355 | is_qemu_enabled, | ||
| 356 | is_wasmtime_enabled, | ||
| 357 | is_darling_enabled, | ||
| 358 | glibc_multi_dir, | ||
| 359 | ); | ||
| 298 | 360 | ||
| 299 | const test_step = b.step("test", "Run all the tests"); | 361 | const test_step = b.step("test", "Run all the tests"); |
| 300 | test_step.dependOn(toolchain_step); | 362 | test_step.dependOn(toolchain_step); |
| ... | @@ -346,8 +408,7 @@ fn addCmakeCfgOptionsToExe( | ... | @@ -346,8 +408,7 @@ fn addCmakeCfgOptionsToExe( |
| 346 | }, | 408 | }, |
| 347 | else => |e| return e, | 409 | else => |e| return e, |
| 348 | }; | 410 | }; |
| 349 | 411 | exe.linkSystemLibrary("unwind"); | |
| 350 | exe.linkSystemLibrary("pthread"); | ||
| 351 | } else if (exe.target.isFreeBSD()) { | 412 | } else if (exe.target.isFreeBSD()) { |
| 352 | try addCxxKnownPath(b, cfg, exe, "libc++.a", null, need_cpp_includes); | 413 | try addCxxKnownPath(b, cfg, exe, "libc++.a", null, need_cpp_includes); |
| 353 | exe.linkSystemLibrary("pthread"); | 414 | exe.linkSystemLibrary("pthread"); |
| ... | @@ -355,20 +416,7 @@ fn addCmakeCfgOptionsToExe( | ... | @@ -355,20 +416,7 @@ fn addCmakeCfgOptionsToExe( |
| 355 | try addCxxKnownPath(b, cfg, exe, "libc++.a", null, need_cpp_includes); | 416 | try addCxxKnownPath(b, cfg, exe, "libc++.a", null, need_cpp_includes); |
| 356 | try addCxxKnownPath(b, cfg, exe, "libc++abi.a", null, need_cpp_includes); | 417 | try addCxxKnownPath(b, cfg, exe, "libc++abi.a", null, need_cpp_includes); |
| 357 | } else if (exe.target.isDarwin()) { | 418 | } else if (exe.target.isDarwin()) { |
| 358 | if (addCxxKnownPath(b, cfg, exe, "libgcc_eh.a", "", need_cpp_includes)) { | 419 | exe.linkSystemLibrary("c++"); |
| 359 | // Compiler is GCC. | ||
| 360 | try addCxxKnownPath(b, cfg, exe, "libstdc++.a", null, need_cpp_includes); | ||
| 361 | exe.linkSystemLibrary("pthread"); | ||
| 362 | // TODO LLD cannot perform this link. | ||
| 363 | // Set ZIG_SYSTEM_LINKER_HACK env var to use system linker ld instead. | ||
| 364 | // See https://github.com/ziglang/zig/issues/1535 | ||
| 365 | } else |err| switch (err) { | ||
| 366 | error.RequiredLibraryNotFound => { | ||
| 367 | // System compiler, not gcc. | ||
| 368 | exe.linkSystemLibrary("c++"); | ||
| 369 | }, | ||
| 370 | else => |e| return e, | ||
| 371 | } | ||
| 372 | } | 420 | } |
| 373 | 421 | ||
| 374 | if (cfg.dia_guids_lib.len != 0) { | 422 | if (cfg.dia_guids_lib.len != 0) { |
lib/libc/glibc/sysdeps/sparc/nptl/bits/pthreadtypes-arch.h deleted-81| ... | @@ -1,81 +0,0 @@ | ||
| 1 | /* Machine-specific pthread type layouts. SPARC version. | ||
| 2 | Copyright (C) 2003-2019 Free Software Foundation, Inc. | ||
| 3 | This file is part of the GNU C Library. | ||
| 4 | |||
| 5 | The GNU C Library is free software; you can redistribute it and/or | ||
| 6 | modify it under the terms of the GNU Lesser General Public | ||
| 7 | License as published by the Free Software Foundation; either | ||
| 8 | version 2.1 of the License, or (at your option) any later version. | ||
| 9 | |||
| 10 | The GNU C Library is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 13 | Lesser General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU Lesser General Public | ||
| 16 | License along with the GNU C Library; if not, see | ||
| 17 | <http://www.gnu.org/licenses/>. */ | ||
| 18 | |||
| 19 | #ifndef _BITS_PTHREADTYPES_ARCH_H | ||
| 20 | #define _BITS_PTHREADTYPES_ARCH_H	1 | ||
| 21 | |||
| 22 | #include <bits/wordsize.h> | ||
| 23 | |||
| 24 | #if __WORDSIZE == 64 | ||
| 25 | # define __SIZEOF_PTHREAD_ATTR_T 56 | ||
| 26 | # define __SIZEOF_PTHREAD_MUTEX_T 40 | ||
| 27 | # define __SIZEOF_PTHREAD_CONDATTR_T 4 | ||
| 28 | # define __SIZEOF_PTHREAD_RWLOCK_T 56 | ||
| 29 | # define __SIZEOF_PTHREAD_BARRIER_T 32 | ||
| 30 | #else | ||
| 31 | # define __SIZEOF_PTHREAD_ATTR_T 36 | ||
| 32 | # define __SIZEOF_PTHREAD_MUTEX_T 24 | ||
| 33 | # define __SIZEOF_PTHREAD_CONDATTR_T 4 | ||
| 34 | # define __SIZEOF_PTHREAD_RWLOCK_T 32 | ||
| 35 | # define __SIZEOF_PTHREAD_BARRIER_T 20 | ||
| 36 | #endif | ||
| 37 | #define __SIZEOF_PTHREAD_MUTEXATTR_T 4 | ||
| 38 | #define __SIZEOF_PTHREAD_COND_T 48 | ||
| 39 | #define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 | ||
| 40 | #define __SIZEOF_PTHREAD_BARRIERATTR_T 4 | ||
| 41 | |||
| 42 | /* Definitions for internal mutex struct. */ | ||
| 43 | #define __PTHREAD_COMPAT_PADDING_MID | ||
| 44 | #define __PTHREAD_COMPAT_PADDING_END | ||
| 45 | #define __PTHREAD_MUTEX_LOCK_ELISION 0 | ||
| 46 | #define __PTHREAD_MUTEX_NUSERS_AFTER_KIND (__WORDSIZE != 64) | ||
| 47 | #define __PTHREAD_MUTEX_USE_UNION (__WORDSIZE != 64) | ||
| 48 | |||
| 49 | #define __LOCK_ALIGNMENT | ||
| 50 | #define __ONCE_ALIGNMENT | ||
| 51 | |||
| 52 | struct __pthread_rwlock_arch_t | ||
| 53 | { | ||
| 54 | unsigned int __readers; | ||
| 55 | unsigned int __writers; | ||
| 56 | unsigned int __wrphase_futex; | ||
| 57 | unsigned int __writers_futex; | ||
| 58 | unsigned int __pad3; | ||
| 59 | unsigned int __pad4; | ||
| 60 | #if __WORDSIZE == 64 | ||
| 61 | int __cur_writer; | ||
| 62 | int __shared; | ||
| 63 | unsigned long int __pad1; | ||
| 64 | unsigned long int __pad2; | ||
| 65 | /* FLAGS must stay at this position in the structure to maintain | ||
| 66 | binary compatibility. */ | ||
| 67 | unsigned int __flags; | ||
| 68 | #else | ||
| 69 | unsigned char __pad1; | ||
| 70 | unsigned char __pad2; | ||
| 71 | unsigned char __shared; | ||
| 72 | /* FLAGS must stay at this position in the structure to maintain | ||
| 73 | binary compatibility. */ | ||
| 74 | unsigned char __flags; | ||
| 75 | int __cur_writer; | ||
| 76 | #endif | ||
| 77 | }; | ||
| 78 | |||
| 79 | #define __PTHREAD_RWLOCK_ELISION_EXTRA 0 | ||
| 80 | |||
| 81 | #endif	/* bits/pthreadtypes.h */ | ||
lib/std/build.zig+8| ... | @@ -1398,6 +1398,9 @@ pub const LibExeObjStep = struct { | ... | @@ -1398,6 +1398,9 @@ pub const LibExeObjStep = struct { |
| 1398 | /// Uses system Wasmtime installation to run cross compiled wasm/wasi build artifacts. | 1398 | /// Uses system Wasmtime installation to run cross compiled wasm/wasi build artifacts. |
| 1399 | enable_wasmtime: bool = false, | 1399 | enable_wasmtime: bool = false, |
| 1400 | 1400 | ||
| 1401 | /// Experimental. Uses system Darling installation to run cross compiled macOS build artifacts. | ||
| 1402 | enable_darling: bool = false, | ||
| 1403 | |||
| 1401 | /// After following the steps in https://github.com/ziglang/zig/wiki/Updating-libc#glibc, | 1404 | /// After following the steps in https://github.com/ziglang/zig/wiki/Updating-libc#glibc, |
| 1402 | /// this will be the directory $glibc-build-dir/install/glibcs | 1405 | /// this will be the directory $glibc-build-dir/install/glibcs |
| 1403 | /// Given the example of the aarch64 target, this is the directory | 1406 | /// Given the example of the aarch64 target, this is the directory |
| ... | @@ -2514,6 +2517,11 @@ pub const LibExeObjStep = struct { | ... | @@ -2514,6 +2517,11 @@ pub const LibExeObjStep = struct { |
| 2514 | try zig_args.append("--dir=."); | 2517 | try zig_args.append("--dir=."); |
| 2515 | try zig_args.append("--test-cmd-bin"); | 2518 | try zig_args.append("--test-cmd-bin"); |
| 2516 | }, | 2519 | }, |
| 2520 | .darling => |bin_name| if (self.enable_darling) { | ||
| 2521 | try zig_args.append("--test-cmd"); | ||
| 2522 | try zig_args.append(bin_name); | ||
| 2523 | try zig_args.append("--test-cmd-bin"); | ||
| 2524 | }, | ||
| 2517 | } | 2525 | } |
| 2518 | 2526 | ||
| 2519 | for (self.packages.items) |pkg| { | 2527 | for (self.packages.items) |pkg| { |
lib/std/debug.zig+4-2| ... | @@ -309,6 +309,7 @@ const RED = "\x1b[31;1m"; | ... | @@ -309,6 +309,7 @@ const RED = "\x1b[31;1m"; |
| 309 | const GREEN = "\x1b[32;1m"; | 309 | const GREEN = "\x1b[32;1m"; |
| 310 | const CYAN = "\x1b[36;1m"; | 310 | const CYAN = "\x1b[36;1m"; |
| 311 | const WHITE = "\x1b[37;1m"; | 311 | const WHITE = "\x1b[37;1m"; |
| 312 | const BOLD = "\x1b[1m"; | ||
| 312 | const DIM = "\x1b[2m"; | 313 | const DIM = "\x1b[2m"; |
| 313 | const RESET = "\x1b[0m"; | 314 | const RESET = "\x1b[0m"; |
| 314 | 315 | ||
| ... | @@ -479,8 +480,9 @@ pub const TTY = struct { | ... | @@ -479,8 +480,9 @@ pub const TTY = struct { |
| 479 | .Red => out_stream.writeAll(RED) catch return, | 480 | .Red => out_stream.writeAll(RED) catch return, |
| 480 | .Green => out_stream.writeAll(GREEN) catch return, | 481 | .Green => out_stream.writeAll(GREEN) catch return, |
| 481 | .Cyan => out_stream.writeAll(CYAN) catch return, | 482 | .Cyan => out_stream.writeAll(CYAN) catch return, |
| 482 | .White, .Bold => out_stream.writeAll(WHITE) catch return, | 483 | .White => out_stream.writeAll(WHITE) catch return, |
| 483 | .Dim => out_stream.writeAll(DIM) catch return, | 484 | .Dim => out_stream.writeAll(DIM) catch return, |
| 485 | .Bold => out_stream.writeAll(BOLD) catch return, | ||
| 484 | .Reset => out_stream.writeAll(RESET) catch return, | 486 | .Reset => out_stream.writeAll(RESET) catch return, |
| 485 | }, | 487 | }, |
| 486 | .windows_api => if (native_os == .windows) { | 488 | .windows_api => if (native_os == .windows) { |
| ... | @@ -632,7 +634,7 @@ fn printLineInfo( | ... | @@ -632,7 +634,7 @@ fn printLineInfo( |
| 632 | comptime printLineFromFile: anytype, | 634 | comptime printLineFromFile: anytype, |
| 633 | ) !void { | 635 | ) !void { |
| 634 | nosuspend { | 636 | nosuspend { |
| 635 | tty_config.setColor(out_stream, .White); | 637 | tty_config.setColor(out_stream, .Bold); |
| 636 | 638 | ||
| 637 | if (line_info) |*li| { | 639 | if (line_info) |*li| { |
| 638 | try out_stream.print("{s}:{d}:{d}", .{ li.file_name, li.line, li.column }); | 640 | try out_stream.print("{s}:{d}:{d}", .{ li.file_name, li.line, li.column }); |
lib/std/fs.zig+3-1| ... | @@ -501,7 +501,9 @@ pub const Dir = struct { | ... | @@ -501,7 +501,9 @@ pub const Dir = struct { |
| 501 | }, | 501 | }, |
| 502 | .linux => struct { | 502 | .linux => struct { |
| 503 | dir: Dir, | 503 | dir: Dir, |
| 504 | buf: [8192]u8, // TODO align(@alignOf(os.dirent64)), | 504 | // The if guard is solely there to prevent compile errors from missing `os.linux.dirent64` |
| 505 | // definition when compiling for other OSes. It doesn't do anything when compiling for Linux. | ||
| 506 | buf: [8192]u8 align(if (builtin.os.tag != .linux) 1 else @alignOf(os.linux.dirent64)), | ||
| 505 | index: usize, | 507 | index: usize, |
| 506 | end_index: usize, | 508 | end_index: usize, |
| 507 | 509 |
lib/std/hash_map.zig+13-12| ... | @@ -303,29 +303,32 @@ pub fn HashMapUnmanaged( | ... | @@ -303,29 +303,32 @@ pub fn HashMapUnmanaged( |
| 303 | /// Metadata for a slot. It can be in three states: empty, used or | 303 | /// Metadata for a slot. It can be in three states: empty, used or |
| 304 | /// tombstone. Tombstones indicate that an entry was previously used, | 304 | /// tombstone. Tombstones indicate that an entry was previously used, |
| 305 | /// they are a simple way to handle removal. | 305 | /// they are a simple way to handle removal. |
| 306 | /// To this state, we add 6 bits from the slot's key hash. These are | 306 | /// To this state, we add 7 bits from the slot's key hash. These are |
| 307 | /// used as a fast way to disambiguate between entries without | 307 | /// used as a fast way to disambiguate between entries without |
| 308 | /// having to use the equality function. If two fingerprints are | 308 | /// having to use the equality function. If two fingerprints are |
| 309 | /// different, we know that we don't have to compare the keys at all. | 309 | /// different, we know that we don't have to compare the keys at all. |
| 310 | /// The 6 bits are the highest ones from a 64 bit hash. This way, not | 310 | /// The 7 bits are the highest ones from a 64 bit hash. This way, not |
| 311 | /// only we use the `log2(capacity)` lowest bits from the hash to determine | 311 | /// only we use the `log2(capacity)` lowest bits from the hash to determine |
| 312 | /// a slot index, but we use 6 more bits to quickly resolve collisions | 312 | /// a slot index, but we use 7 more bits to quickly resolve collisions |
| 313 | /// when multiple elements with different hashes end up wanting to be in / the same slot. | 313 | /// when multiple elements with different hashes end up wanting to be in the same slot. |
| 314 | /// Not using the equality function means we don't have to read into | 314 | /// Not using the equality function means we don't have to read into |
| 315 | /// the entries array, avoiding a likely cache miss. | 315 | /// the entries array, likely avoiding a cache miss and a potentially |
| 316 | /// costly function call. | ||
| 316 | const Metadata = packed struct { | 317 | const Metadata = packed struct { |
| 317 | const FingerPrint = u6; | 318 | const FingerPrint = u7; |
| 318 | 319 | ||
| 320 | const free: FingerPrint = 0; | ||
| 321 | const tombstone: FingerPrint = 1; | ||
| 322 | |||
| 323 | fingerprint: FingerPrint = free, | ||
| 319 | used: u1 = 0, | 324 | used: u1 = 0, |
| 320 | tombstone: u1 = 0, | ||
| 321 | fingerprint: FingerPrint = 0, | ||
| 322 | 325 | ||
| 323 | pub fn isUsed(self: Metadata) bool { | 326 | pub fn isUsed(self: Metadata) bool { |
| 324 | return self.used == 1; | 327 | return self.used == 1; |
| 325 | } | 328 | } |
| 326 | 329 | ||
| 327 | pub fn isTombstone(self: Metadata) bool { | 330 | pub fn isTombstone(self: Metadata) bool { |
| 328 | return self.tombstone == 1; | 331 | return !self.isUsed() and self.fingerprint == tombstone; |
| 329 | } | 332 | } |
| 330 | 333 | ||
| 331 | pub fn takeFingerprint(hash: Hash) FingerPrint { | 334 | pub fn takeFingerprint(hash: Hash) FingerPrint { |
| ... | @@ -336,14 +339,12 @@ pub fn HashMapUnmanaged( | ... | @@ -336,14 +339,12 @@ pub fn HashMapUnmanaged( |
| 336 | 339 | ||
| 337 | pub fn fill(self: *Metadata, fp: FingerPrint) void { | 340 | pub fn fill(self: *Metadata, fp: FingerPrint) void { |
| 338 | self.used = 1; | 341 | self.used = 1; |
| 339 | self.tombstone = 0; | ||
| 340 | self.fingerprint = fp; | 342 | self.fingerprint = fp; |
| 341 | } | 343 | } |
| 342 | 344 | ||
| 343 | pub fn remove(self: *Metadata) void { | 345 | pub fn remove(self: *Metadata) void { |
| 344 | self.used = 0; | 346 | self.used = 0; |
| 345 | self.tombstone = 1; | 347 | self.fingerprint = tombstone; |
| 346 | self.fingerprint = 0; | ||
| 347 | } | 348 | } |
| 348 | }; | 349 | }; |
| 349 | 350 |
lib/std/json.zig+45-10| ... | @@ -623,7 +623,7 @@ pub const StreamingParser = struct { | ... | @@ -623,7 +623,7 @@ pub const StreamingParser = struct { |
| 623 | 623 | ||
| 624 | .ObjectSeparator => switch (c) { | 624 | .ObjectSeparator => switch (c) { |
| 625 | ':' => { | 625 | ':' => { |
| 626 | p.state = .ValueBegin; | 626 | p.state = .ValueBeginNoClosing; |
| 627 | p.after_string_state = .ValueEnd; | 627 | p.after_string_state = .ValueEnd; |
| 628 | }, | 628 | }, |
| 629 | 0x09, 0x0A, 0x0D, 0x20 => { | 629 | 0x09, 0x0A, 0x0D, 0x20 => { |
| ... | @@ -1205,6 +1205,13 @@ test "json.token mismatched close" { | ... | @@ -1205,6 +1205,13 @@ test "json.token mismatched close" { |
| 1205 | try testing.expectError(error.UnexpectedClosingBrace, p.next()); | 1205 | try testing.expectError(error.UnexpectedClosingBrace, p.next()); |
| 1206 | } | 1206 | } |
| 1207 | 1207 | ||
| 1208 | test "json.token premature object close" { | ||
| 1209 | var p = TokenStream.init("{ \"key\": }"); | ||
| 1210 | try checkNext(&p, .ObjectBegin); | ||
| 1211 | try checkNext(&p, .String); | ||
| 1212 | try testing.expectError(error.InvalidValueBegin, p.next()); | ||
| 1213 | } | ||
| 1214 | |||
| 1208 | /// Validate a JSON string. This does not limit number precision so a decoder may not necessarily | 1215 | /// Validate a JSON string. This does not limit number precision so a decoder may not necessarily |
| 1209 | /// be able to decode the string even if this returns true. | 1216 | /// be able to decode the string even if this returns true. |
| 1210 | pub fn validate(s: []const u8) bool { | 1217 | pub fn validate(s: []const u8) bool { |
| ... | @@ -1566,11 +1573,16 @@ fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options: | ... | @@ -1566,11 +1573,16 @@ fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options: |
| 1566 | // .UseLast => {}, | 1573 | // .UseLast => {}, |
| 1567 | // } | 1574 | // } |
| 1568 | if (options.duplicate_field_behavior == .UseFirst) { | 1575 | if (options.duplicate_field_behavior == .UseFirst) { |
| 1576 | // unconditonally ignore value. for comptime fields, this skips check against default_value | ||
| 1577 | parseFree(field.field_type, try parse(field.field_type, tokens, options), options); | ||
| 1578 | found = true; | ||
| 1569 | break; | 1579 | break; |
| 1570 | } else if (options.duplicate_field_behavior == .Error) { | 1580 | } else if (options.duplicate_field_behavior == .Error) { |
| 1571 | return error.DuplicateJSONField; | 1581 | return error.DuplicateJSONField; |
| 1572 | } else if (options.duplicate_field_behavior == .UseLast) { | 1582 | } else if (options.duplicate_field_behavior == .UseLast) { |
| 1573 | parseFree(field.field_type, @field(r, field.name), options); | 1583 | if (!field.is_comptime) { |
| 1584 | parseFree(field.field_type, @field(r, field.name), options); | ||
| 1585 | } | ||
| 1574 | fields_seen[i] = false; | 1586 | fields_seen[i] = false; |
| 1575 | } | 1587 | } |
| 1576 | } | 1588 | } |
| ... | @@ -1724,7 +1736,9 @@ pub fn parseFree(comptime T: type, value: T, options: ParseOptions) void { | ... | @@ -1724,7 +1736,9 @@ pub fn parseFree(comptime T: type, value: T, options: ParseOptions) void { |
| 1724 | }, | 1736 | }, |
| 1725 | .Struct => |structInfo| { | 1737 | .Struct => |structInfo| { |
| 1726 | inline for (structInfo.fields) |field| { | 1738 | inline for (structInfo.fields) |field| { |
| 1727 | parseFree(field.field_type, @field(value, field.name), options); | 1739 | if (!field.is_comptime) { |
| 1740 | parseFree(field.field_type, @field(value, field.name), options); | ||
| 1741 | } | ||
| 1728 | } | 1742 | } |
| 1729 | }, | 1743 | }, |
| 1730 | .Array => |arrayInfo| { | 1744 | .Array => |arrayInfo| { |
| ... | @@ -1901,14 +1915,19 @@ test "parse with comptime field" { | ... | @@ -1901,14 +1915,19 @@ test "parse with comptime field" { |
| 1901 | }, | 1915 | }, |
| 1902 | }; | 1916 | }; |
| 1903 | 1917 | ||
| 1904 | const r = try std.json.parse(T, &std.json.TokenStream.init( | 1918 | const options = ParseOptions{ |
| 1919 | .allocator = std.testing.allocator, | ||
| 1920 | }; | ||
| 1921 | |||
| 1922 | const r = try parse(T, &TokenStream.init( | ||
| 1905 | \\{ | 1923 | \\{ |
| 1906 | \\ "kind": "float", | 1924 | \\ "kind": "float", |
| 1907 | \\ "b": 1.0 | 1925 | \\ "b": 1.0 |
| 1908 | \\} | 1926 | \\} |
| 1909 | ), .{ | 1927 | ), options); |
| 1910 | .allocator = std.testing.allocator, | 1928 | |
| 1911 | }); | 1929 | // check that parseFree doesn't try to free comptime fields |
| 1930 | parseFree(T, r, options); | ||
| 1912 | } | 1931 | } |
| 1913 | } | 1932 | } |
| 1914 | 1933 | ||
| ... | @@ -1995,17 +2014,33 @@ test "parse into struct with duplicate field" { | ... | @@ -1995,17 +2014,33 @@ test "parse into struct with duplicate field" { |
| 1995 | const ballast = try testing.allocator.alloc(u64, 1); | 2014 | const ballast = try testing.allocator.alloc(u64, 1); |
| 1996 | defer testing.allocator.free(ballast); | 2015 | defer testing.allocator.free(ballast); |
| 1997 | 2016 | ||
| 1998 | const options = ParseOptions{ | 2017 | const options_first = ParseOptions{ |
| 2018 | .allocator = testing.allocator, | ||
| 2019 | .duplicate_field_behavior = .UseFirst | ||
| 2020 | }; | ||
| 2021 | |||
| 2022 | const options_last = ParseOptions{ | ||
| 1999 | .allocator = testing.allocator, | 2023 | .allocator = testing.allocator, |
| 2000 | .duplicate_field_behavior = .UseLast, | 2024 | .duplicate_field_behavior = .UseLast, |
| 2001 | }; | 2025 | }; |
| 2026 | |||
| 2002 | const str = "{ \"a\": 1, \"a\": 0.25 }"; | 2027 | const str = "{ \"a\": 1, \"a\": 0.25 }"; |
| 2003 | 2028 | ||
| 2004 | const T1 = struct { a: *u64 }; | 2029 | const T1 = struct { a: *u64 }; |
| 2005 | try testing.expectError(error.UnexpectedToken, parse(T1, &TokenStream.init(str), options)); | 2030 | // both .UseFirst and .UseLast should fail because second "a" value isn't a u64 |
| 2031 | try testing.expectError(error.UnexpectedToken, parse(T1, &TokenStream.init(str), options_first)); | ||
| 2032 | try testing.expectError(error.UnexpectedToken, parse(T1, &TokenStream.init(str), options_last)); | ||
| 2006 | 2033 | ||
| 2007 | const T2 = struct { a: f64 }; | 2034 | const T2 = struct { a: f64 }; |
| 2008 | try testing.expectEqual(T2{ .a = 0.25 }, try parse(T2, &TokenStream.init(str), options)); | 2035 | try testing.expectEqual(T2{ .a = 1.0 }, try parse(T2, &TokenStream.init(str), options_first)); |
| 2036 | try testing.expectEqual(T2{ .a = 0.25 }, try parse(T2, &TokenStream.init(str), options_last)); | ||
| 2037 | |||
| 2038 | const T3 = struct { comptime a: f64 = 1.0 }; | ||
| 2039 | // .UseFirst should succeed because second "a" value is unconditionally ignored (even though != 1.0) | ||
| 2040 | const t3 = T3{ .a = 1.0 }; | ||
| 2041 | try testing.expectEqual(t3, try parse(T3, &TokenStream.init(str), options_first)); | ||
| 2042 | // .UseLast should fail because second "a" value is 0.25 which is not equal to default value of 1.0 | ||
| 2043 | try testing.expectError(error.UnexpectedValue, parse(T3, &TokenStream.init(str), options_last)); | ||
| 2009 | } | 2044 | } |
| 2010 | 2045 | ||
| 2011 | /// A non-stream JSON parser which constructs a tree of Value's. | 2046 | /// A non-stream JSON parser which constructs a tree of Value's. |
lib/std/json/test.zig+6| ... | @@ -76,6 +76,12 @@ test "y_trailing_comma_after_empty" { | ... | @@ -76,6 +76,12 @@ test "y_trailing_comma_after_empty" { |
| 76 | ); | 76 | ); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | test "n_object_closed_missing_value" { | ||
| 80 | try err( | ||
| 81 | \\{"a":} | ||
| 82 | ); | ||
| 83 | } | ||
| 84 | |||
| 79 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 85 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 80 | 86 | ||
| 81 | test "y_array_arraysWithSpaces" { | 87 | test "y_array_arraysWithSpaces" { |
lib/std/math/isnormal.zig+9-2| ... | @@ -14,16 +14,20 @@ pub fn isNormal(x: anytype) bool { | ... | @@ -14,16 +14,20 @@ pub fn isNormal(x: anytype) bool { |
| 14 | switch (T) { | 14 | switch (T) { |
| 15 | f16 => { | 15 | f16 => { |
| 16 | const bits = @bitCast(u16, x); | 16 | const bits = @bitCast(u16, x); |
| 17 | return (bits + 1024) & 0x7FFF >= 2048; | 17 | return (bits + (1 << 10)) & (maxInt(u16) >> 1) >= (1 << 11); |
| 18 | }, | 18 | }, |
| 19 | f32 => { | 19 | f32 => { |
| 20 | const bits = @bitCast(u32, x); | 20 | const bits = @bitCast(u32, x); |
| 21 | return (bits + 0x00800000) & 0x7FFFFFFF >= 0x01000000; | 21 | return (bits + (1 << 23)) & (maxInt(u32) >> 1) >= (1 << 24); |
| 22 | }, | 22 | }, |
| 23 | f64 => { | 23 | f64 => { |
| 24 | const bits = @bitCast(u64, x); | 24 | const bits = @bitCast(u64, x); |
| 25 | return (bits + (1 << 52)) & (maxInt(u64) >> 1) >= (1 << 53); | 25 | return (bits + (1 << 52)) & (maxInt(u64) >> 1) >= (1 << 53); |
| 26 | }, | 26 | }, |
| 27 | f128 => { | ||
| 28 | const bits = @bitCast(u128, x); | ||
| 29 | return (bits + (1 << 112)) & (maxInt(u128) >> 1) >= (1 << 113); | ||
| 30 | }, | ||
| 27 | else => { | 31 | else => { |
| 28 | @compileError("isNormal not implemented for " ++ @typeName(T)); | 32 | @compileError("isNormal not implemented for " ++ @typeName(T)); |
| 29 | }, | 33 | }, |
| ... | @@ -34,10 +38,13 @@ test "math.isNormal" { | ... | @@ -34,10 +38,13 @@ test "math.isNormal" { |
| 34 | try expect(!isNormal(math.nan(f16))); | 38 | try expect(!isNormal(math.nan(f16))); |
| 35 | try expect(!isNormal(math.nan(f32))); | 39 | try expect(!isNormal(math.nan(f32))); |
| 36 | try expect(!isNormal(math.nan(f64))); | 40 | try expect(!isNormal(math.nan(f64))); |
| 41 | try expect(!isNormal(math.nan(f128))); | ||
| 37 | try expect(!isNormal(@as(f16, 0))); | 42 | try expect(!isNormal(@as(f16, 0))); |
| 38 | try expect(!isNormal(@as(f32, 0))); | 43 | try expect(!isNormal(@as(f32, 0))); |
| 39 | try expect(!isNormal(@as(f64, 0))); | 44 | try expect(!isNormal(@as(f64, 0))); |
| 45 | try expect(!isNormal(@as(f128, 0))); | ||
| 40 | try expect(isNormal(@as(f16, 1.0))); | 46 | try expect(isNormal(@as(f16, 1.0))); |
| 41 | try expect(isNormal(@as(f32, 1.0))); | 47 | try expect(isNormal(@as(f32, 1.0))); |
| 42 | try expect(isNormal(@as(f64, 1.0))); | 48 | try expect(isNormal(@as(f64, 1.0))); |
| 49 | try expect(isNormal(@as(f128, 1.0))); | ||
| 43 | } | 50 | } |
lib/std/math/scalbn.zig+66-66| ... | @@ -9,89 +9,89 @@ | ... | @@ -9,89 +9,89 @@ |
| 9 | // https://git.musl-libc.org/cgit/musl/tree/src/math/scalbnf.c | 9 | // https://git.musl-libc.org/cgit/musl/tree/src/math/scalbnf.c |
| 10 | // https://git.musl-libc.org/cgit/musl/tree/src/math/scalbn.c | 10 | // https://git.musl-libc.org/cgit/musl/tree/src/math/scalbn.c |
| 11 | 11 | ||
| 12 | const std = @import("../std.zig"); | 12 | const std = @import("std"); |
| 13 | const math = std.math; | 13 | const math = std.math; |
| 14 | const assert = std.debug.assert; | ||
| 14 | const expect = std.testing.expect; | 15 | const expect = std.testing.expect; |
| 15 | 16 | ||
| 16 | /// Returns x * 2^n. | 17 | /// Returns x * 2^n. |
| 17 | pub fn scalbn(x: anytype, n: i32) @TypeOf(x) { | 18 | pub fn scalbn(x: anytype, n: i32) @TypeOf(x) { |
| 18 | const T = @TypeOf(x); | 19 | var base = x; |
| 19 | return switch (T) { | 20 | var shift = n; |
| 20 | f32 => scalbn32(x, n), | ||
| 21 | f64 => scalbn64(x, n), | ||
| 22 | else => @compileError("scalbn not implemented for " ++ @typeName(T)), | ||
| 23 | }; | ||
| 24 | } | ||
| 25 | |||
| 26 | fn scalbn32(x: f32, n_: i32) f32 { | ||
| 27 | var y = x; | ||
| 28 | var n = n_; | ||
| 29 | 21 | ||
| 30 | if (n > 127) { | 22 | const T = @TypeOf(base); |
| 31 | y *= 0x1.0p127; | 23 | const IntT = std.meta.Int(.unsigned, @bitSizeOf(T)); |
| 32 | n -= 127; | 24 | if (@typeInfo(T) != .Float) { |
| 33 | if (n > 1023) { | 25 | @compileError("scalbn not implemented for " ++ @typeName(T)); |
| 34 | y *= 0x1.0p127; | ||
| 35 | n -= 127; | ||
| 36 | if (n > 127) { | ||
| 37 | n = 127; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | } else if (n < -126) { | ||
| 41 | y *= 0x1.0p-126 * 0x1.0p24; | ||
| 42 | n += 126 - 24; | ||
| 43 | if (n < -126) { | ||
| 44 | y *= 0x1.0p-126 * 0x1.0p24; | ||
| 45 | n += 126 - 24; | ||
| 46 | if (n < -126) { | ||
| 47 | n = -126; | ||
| 48 | } | ||
| 49 | } | ||
| 50 | } | 26 | } |
| 51 | 27 | ||
| 52 | const u = @intCast(u32, n +% 0x7F) << 23; | 28 | const mantissa_bits = math.floatMantissaBits(T); |
| 53 | return y * @bitCast(f32, u); | 29 | const exponent_bits = math.floatExponentBits(T); |
| 54 | } | 30 | const exponent_bias = (1 << (exponent_bits - 1)) - 1; |
| 31 | const exponent_min = 1 - exponent_bias; | ||
| 32 | const exponent_max = exponent_bias; | ||
| 55 | 33 | ||
| 56 | fn scalbn64(x: f64, n_: i32) f64 { | 34 | // fix double rounding errors in subnormal ranges |
| 57 | var y = x; | 35 | // https://git.musl-libc.org/cgit/musl/commit/src/math/scalbn.c?id=8c44a060243f04283ca68dad199aab90336141db |
| 58 | var n = n_; | 36 | const scale_min_expo = exponent_min + mantissa_bits + 1; |
| 37 | const scale_min = @bitCast(T, @as(IntT, scale_min_expo + exponent_bias) << mantissa_bits); | ||
| 38 | const scale_max = @bitCast(T, @intCast(IntT, exponent_max + exponent_bias) << mantissa_bits); | ||
| 59 | 39 | ||
| 60 | if (n > 1023) { | 40 | // scale `shift` within floating point limits, if possible |
| 61 | y *= 0x1.0p1023; | 41 | // second pass is possible due to subnormal range |
| 62 | n -= 1023; | 42 | // third pass always results in +/-0.0 or +/-inf |
| 63 | if (n > 1023) { | 43 | if (shift > exponent_max) { |
| 64 | y *= 0x1.0p1023; | 44 | base *= scale_max; |
| 65 | n -= 1023; | 45 | shift -= exponent_max; |
| 66 | if (n > 1023) { | 46 | if (shift > exponent_max) { |
| 67 | n = 1023; | 47 | base *= scale_max; |
| 68 | } | 48 | shift -= exponent_max; |
| 49 | if (shift > exponent_max) shift = exponent_max; | ||
| 69 | } | 50 | } |
| 70 | } else if (n < -1022) { | 51 | } else if (shift < exponent_min) { |
| 71 | y *= 0x1.0p-1022 * 0x1.0p53; | 52 | base *= scale_min; |
| 72 | n += 1022 - 53; | 53 | shift -= scale_min_expo; |
| 73 | if (n < -1022) { | 54 | if (shift < exponent_min) { |
| 74 | y *= 0x1.0p-1022 * 0x1.0p53; | 55 | base *= scale_min; |
| 75 | n += 1022 - 53; | 56 | shift -= scale_min_expo; |
| 76 | if (n < -1022) { | 57 | if (shift < exponent_min) shift = exponent_min; |
| 77 | n = -1022; | ||
| 78 | } | ||
| 79 | } | 58 | } |
| 80 | } | 59 | } |
| 81 | 60 | ||
| 82 | const u = @intCast(u64, n +% 0x3FF) << 52; | 61 | return base * @bitCast(T, @intCast(IntT, shift + exponent_bias) << mantissa_bits); |
| 83 | return y * @bitCast(f64, u); | ||
| 84 | } | 62 | } |
| 85 | 63 | ||
| 86 | test "math.scalbn" { | 64 | test "math.scalbn" { |
| 87 | try expect(scalbn(@as(f32, 1.5), 4) == scalbn32(1.5, 4)); | 65 | // basic usage |
| 88 | try expect(scalbn(@as(f64, 1.5), 4) == scalbn64(1.5, 4)); | 66 | try expect(scalbn(@as(f16, 1.5), 4) == 24.0); |
| 89 | } | 67 | try expect(scalbn(@as(f32, 1.5), 4) == 24.0); |
| 68 | try expect(scalbn(@as(f64, 1.5), 4) == 24.0); | ||
| 69 | try expect(scalbn(@as(f128, 1.5), 4) == 24.0); | ||
| 90 | 70 | ||
| 91 | test "math.scalbn32" { | 71 | // subnormals |
| 92 | try expect(scalbn32(1.5, 4) == 24.0); | 72 | try expect(math.isNormal(scalbn(@as(f16, 1.0), -14))); |
| 93 | } | 73 | try expect(!math.isNormal(scalbn(@as(f16, 1.0), -15))); |
| 74 | try expect(math.isNormal(scalbn(@as(f32, 1.0), -126))); | ||
| 75 | try expect(!math.isNormal(scalbn(@as(f32, 1.0), -127))); | ||
| 76 | try expect(math.isNormal(scalbn(@as(f64, 1.0), -1022))); | ||
| 77 | try expect(!math.isNormal(scalbn(@as(f64, 1.0), -1023))); | ||
| 78 | try expect(math.isNormal(scalbn(@as(f128, 1.0), -16382))); | ||
| 79 | try expect(!math.isNormal(scalbn(@as(f128, 1.0), -16383))); | ||
| 80 | // unreliable due to lack of native f16 support, see talk on PR #8733 | ||
| 81 | // try expect(scalbn(@as(f16, 0x1.1FFp-1), -14 - 9) == math.f16_true_min); | ||
| 82 | try expect(scalbn(@as(f32, 0x1.3FFFFFp-1), -126 - 22) == math.f32_true_min); | ||
| 83 | try expect(scalbn(@as(f64, 0x1.7FFFFFFFFFFFFp-1), -1022 - 51) == math.f64_true_min); | ||
| 84 | try expect(scalbn(@as(f128, 0x1.7FFFFFFFFFFFFFFFFFFFFFFFFFFFp-1), -16382 - 111) == math.f128_true_min); | ||
| 94 | 85 | ||
| 95 | test "math.scalbn64" { | 86 | // float limits |
| 96 | try expect(scalbn64(1.5, 4) == 24.0); | 87 | try expect(scalbn(@as(f32, math.f32_max), -128 - 149) > 0.0); |
| 88 | try expect(scalbn(@as(f32, math.f32_max), -128 - 149 - 1) == 0.0); | ||
| 89 | try expect(!math.isPositiveInf(scalbn(@as(f16, math.f16_true_min), 15 + 24))); | ||
| 90 | try expect(math.isPositiveInf(scalbn(@as(f16, math.f16_true_min), 15 + 24 + 1))); | ||
| 91 | try expect(!math.isPositiveInf(scalbn(@as(f32, math.f32_true_min), 127 + 149))); | ||
| 92 | try expect(math.isPositiveInf(scalbn(@as(f32, math.f32_true_min), 127 + 149 + 1))); | ||
| 93 | try expect(!math.isPositiveInf(scalbn(@as(f64, math.f64_true_min), 1023 + 1074))); | ||
| 94 | try expect(math.isPositiveInf(scalbn(@as(f64, math.f64_true_min), 1023 + 1074 + 1))); | ||
| 95 | try expect(!math.isPositiveInf(scalbn(@as(f128, math.f128_true_min), 16383 + 16494))); | ||
| 96 | try expect(math.isPositiveInf(scalbn(@as(f128, math.f128_true_min), 16383 + 16494 + 1))); | ||
| 97 | } | 97 | } |
lib/std/os/bits/linux/errno-sparc.zig+1| ... | @@ -52,6 +52,7 @@ pub const ENOPROTOOPT = 42; | ... | @@ -52,6 +52,7 @@ pub const ENOPROTOOPT = 42; |
| 52 | pub const EPROTONOSUPPORT = 43; | 52 | pub const EPROTONOSUPPORT = 43; |
| 53 | pub const ESOCKTNOSUPPORT = 44; | 53 | pub const ESOCKTNOSUPPORT = 44; |
| 54 | pub const EOPNOTSUPP = 45; | 54 | pub const EOPNOTSUPP = 45; |
| 55 | pub const ENOTSUP = EOPNOTSUPP; | ||
| 55 | pub const EPFNOSUPPORT = 46; | 56 | pub const EPFNOSUPPORT = 46; |
| 56 | pub const EAFNOSUPPORT = 47; | 57 | pub const EAFNOSUPPORT = 47; |
| 57 | pub const EADDRINUSE = 48; | 58 | pub const EADDRINUSE = 48; |
lib/std/special/compiler_rt.zig+10| ... | @@ -297,7 +297,17 @@ comptime { | ... | @@ -297,7 +297,17 @@ comptime { |
| 297 | @export(@import("compiler_rt/sparc.zig")._Qp_fgt, .{ .name = "_Qp_fgt", .linkage = linkage }); | 297 | @export(@import("compiler_rt/sparc.zig")._Qp_fgt, .{ .name = "_Qp_fgt", .linkage = linkage }); |
| 298 | @export(@import("compiler_rt/sparc.zig")._Qp_fge, .{ .name = "_Qp_fge", .linkage = linkage }); | 298 | @export(@import("compiler_rt/sparc.zig")._Qp_fge, .{ .name = "_Qp_fge", .linkage = linkage }); |
| 299 | 299 | ||
| 300 | @export(@import("compiler_rt/sparc.zig")._Qp_itoq, .{ .name = "_Qp_itoq", .linkage = linkage }); | ||
| 301 | @export(@import("compiler_rt/sparc.zig")._Qp_uitoq, .{ .name = "_Qp_uitoq", .linkage = linkage }); | ||
| 302 | @export(@import("compiler_rt/sparc.zig")._Qp_xtoq, .{ .name = "_Qp_xtoq", .linkage = linkage }); | ||
| 303 | @export(@import("compiler_rt/sparc.zig")._Qp_uxtoq, .{ .name = "_Qp_uxtoq", .linkage = linkage }); | ||
| 304 | @export(@import("compiler_rt/sparc.zig")._Qp_stoq, .{ .name = "_Qp_stoq", .linkage = linkage }); | ||
| 300 | @export(@import("compiler_rt/sparc.zig")._Qp_dtoq, .{ .name = "_Qp_dtoq", .linkage = linkage }); | 305 | @export(@import("compiler_rt/sparc.zig")._Qp_dtoq, .{ .name = "_Qp_dtoq", .linkage = linkage }); |
| 306 | @export(@import("compiler_rt/sparc.zig")._Qp_qtoi, .{ .name = "_Qp_qtoi", .linkage = linkage }); | ||
| 307 | @export(@import("compiler_rt/sparc.zig")._Qp_qtoui, .{ .name = "_Qp_qtoui", .linkage = linkage }); | ||
| 308 | @export(@import("compiler_rt/sparc.zig")._Qp_qtox, .{ .name = "_Qp_qtox", .linkage = linkage }); | ||
| 309 | @export(@import("compiler_rt/sparc.zig")._Qp_qtoux, .{ .name = "_Qp_qtoux", .linkage = linkage }); | ||
| 310 | @export(@import("compiler_rt/sparc.zig")._Qp_qtos, .{ .name = "_Qp_qtos", .linkage = linkage }); | ||
| 301 | @export(@import("compiler_rt/sparc.zig")._Qp_qtod, .{ .name = "_Qp_qtod", .linkage = linkage }); | 311 | @export(@import("compiler_rt/sparc.zig")._Qp_qtod, .{ .name = "_Qp_qtod", .linkage = linkage }); |
| 302 | } | 312 | } |
| 303 | 313 |
lib/std/special/compiler_rt/mulXf3.zig+6-6| ... | @@ -98,8 +98,8 @@ fn mulXf3(comptime T: type, a: T, b: T) T { | ... | @@ -98,8 +98,8 @@ fn mulXf3(comptime T: type, a: T, b: T) T { |
| 98 | // one or both of a or b is denormal, the other (if applicable) is a | 98 | // one or both of a or b is denormal, the other (if applicable) is a |
| 99 | // normal number. Renormalize one or both of a and b, and set scale to | 99 | // normal number. Renormalize one or both of a and b, and set scale to |
| 100 | // include the necessary exponent adjustment. | 100 | // include the necessary exponent adjustment. |
| 101 | if (aAbs < implicitBit) scale +%= normalize(T, &aSignificand); | 101 | if (aAbs < implicitBit) scale += normalize(T, &aSignificand); |
| 102 | if (bAbs < implicitBit) scale +%= normalize(T, &bSignificand); | 102 | if (bAbs < implicitBit) scale += normalize(T, &bSignificand); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | // Or in the implicit significand bit. (If we fell through from the | 105 | // Or in the implicit significand bit. (If we fell through from the |
| ... | @@ -277,7 +277,7 @@ fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeInfo(T | ... | @@ -277,7 +277,7 @@ fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeInfo(T |
| 277 | 277 | ||
| 278 | const shift = @clz(Z, significand.*) - @clz(Z, implicitBit); | 278 | const shift = @clz(Z, significand.*) - @clz(Z, implicitBit); |
| 279 | significand.* <<= @intCast(std.math.Log2Int(Z), shift); | 279 | significand.* <<= @intCast(std.math.Log2Int(Z), shift); |
| 280 | return 1 - shift; | 280 | return @as(i32, 1) - shift; |
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | fn wideRightShiftWithSticky(comptime Z: type, hi: *Z, lo: *Z, count: u32) void { | 283 | fn wideRightShiftWithSticky(comptime Z: type, hi: *Z, lo: *Z, count: u32) void { |
| ... | @@ -285,15 +285,15 @@ fn wideRightShiftWithSticky(comptime Z: type, hi: *Z, lo: *Z, count: u32) void { | ... | @@ -285,15 +285,15 @@ fn wideRightShiftWithSticky(comptime Z: type, hi: *Z, lo: *Z, count: u32) void { |
| 285 | const typeWidth = @typeInfo(Z).Int.bits; | 285 | const typeWidth = @typeInfo(Z).Int.bits; |
| 286 | const S = std.math.Log2Int(Z); | 286 | const S = std.math.Log2Int(Z); |
| 287 | if (count < typeWidth) { | 287 | if (count < typeWidth) { |
| 288 | const sticky = @truncate(u8, lo.* << @intCast(S, typeWidth -% count)); | 288 | const sticky = @boolToInt((lo.* << @intCast(S, typeWidth -% count)) != 0); |
| 289 | lo.* = (hi.* << @intCast(S, typeWidth -% count)) | (lo.* >> @intCast(S, count)) | sticky; | 289 | lo.* = (hi.* << @intCast(S, typeWidth -% count)) | (lo.* >> @intCast(S, count)) | sticky; |
| 290 | hi.* = hi.* >> @intCast(S, count); | 290 | hi.* = hi.* >> @intCast(S, count); |
| 291 | } else if (count < 2 * typeWidth) { | 291 | } else if (count < 2 * typeWidth) { |
| 292 | const sticky = @truncate(u8, hi.* << @intCast(S, 2 * typeWidth -% count) | lo.*); | 292 | const sticky = @boolToInt((hi.* << @intCast(S, 2 * typeWidth -% count) | lo.*) != 0); |
| 293 | lo.* = hi.* >> @intCast(S, count -% typeWidth) | sticky; | 293 | lo.* = hi.* >> @intCast(S, count -% typeWidth) | sticky; |
| 294 | hi.* = 0; | 294 | hi.* = 0; |
| 295 | } else { | 295 | } else { |
| 296 | const sticky = @truncate(u8, hi.* | lo.*); | 296 | const sticky = @boolToInt((hi.* | lo.*) != 0); |
| 297 | lo.* = sticky; | 297 | lo.* = sticky; |
| 298 | hi.* = 0; | 298 | hi.* = 0; |
| 299 | } | 299 | } |
lib/std/special/compiler_rt/mulXf3_test.zig+14| ... | @@ -88,4 +88,18 @@ test "multf3" { | ... | @@ -88,4 +88,18 @@ test "multf3" { |
| 88 | ); | 88 | ); |
| 89 | 89 | ||
| 90 | try test__multf3(0x1.23456734245345p-10000, 0x1.edcba524498724p-6497, 0x0, 0x0); | 90 | try test__multf3(0x1.23456734245345p-10000, 0x1.edcba524498724p-6497, 0x0, 0x0); |
| 91 | |||
| 92 | // Denormal operands. | ||
| 93 | try test__multf3( | ||
| 94 | 0x0.0000000000000000000000000001p-16382, | ||
| 95 | 0x1.p16383, | ||
| 96 | 0x3f90000000000000, | ||
| 97 | 0x0, | ||
| 98 | ); | ||
| 99 | try test__multf3( | ||
| 100 | 0x1.p16383, | ||
| 101 | 0x0.0000000000000000000000000001p-16382, | ||
| 102 | 0x3f90000000000000, | ||
| 103 | 0x0, | ||
| 104 | ); | ||
| 91 | } | 105 | } |
lib/std/special/compiler_rt/sparc.zig+41-1| ... | @@ -68,12 +68,52 @@ pub fn _Qp_fge(a: *f128, b: *f128) callconv(.C) bool { | ... | @@ -68,12 +68,52 @@ pub fn _Qp_fge(a: *f128, b: *f128) callconv(.C) bool { |
| 68 | return cmp == @enumToInt(FCMP.Greater) or cmp == @enumToInt(FCMP.Equal); | 68 | return cmp == @enumToInt(FCMP.Greater) or cmp == @enumToInt(FCMP.Equal); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | // Casting | 71 | // Conversion |
| 72 | |||
| 73 | pub fn _Qp_itoq(c: *f128, a: i32) callconv(.C) void { | ||
| 74 | c.* = @import("floatsiXf.zig").__floatsitf(a); | ||
| 75 | } | ||
| 76 | |||
| 77 | pub fn _Qp_uitoq(c: *f128, a: u32) callconv(.C) void { | ||
| 78 | c.* = @import("floatunsitf.zig").__floatunsitf(a); | ||
| 79 | } | ||
| 80 | |||
| 81 | pub fn _Qp_xtoq(c: *f128, a: i64) callconv(.C) void { | ||
| 82 | c.* = @import("floatditf.zig").__floatditf(a); | ||
| 83 | } | ||
| 84 | |||
| 85 | pub fn _Qp_uxtoq(c: *f128, a: u64) callconv(.C) void { | ||
| 86 | c.* = @import("floatunditf.zig").__floatunditf(a); | ||
| 87 | } | ||
| 88 | |||
| 89 | pub fn _Qp_stoq(c: *f128, a: f32) callconv(.C) void { | ||
| 90 | c.* = @import("extendXfYf2.zig").__extendsftf2(a); | ||
| 91 | } | ||
| 72 | 92 | ||
| 73 | pub fn _Qp_dtoq(c: *f128, a: f64) callconv(.C) void { | 93 | pub fn _Qp_dtoq(c: *f128, a: f64) callconv(.C) void { |
| 74 | c.* = @import("extendXfYf2.zig").__extenddftf2(a); | 94 | c.* = @import("extendXfYf2.zig").__extenddftf2(a); |
| 75 | } | 95 | } |
| 76 | 96 | ||
| 97 | pub fn _Qp_qtoi(a: *f128) callconv(.C) i32 { | ||
| 98 | return @import("fixtfsi.zig").__fixtfsi(a.*); | ||
| 99 | } | ||
| 100 | |||
| 101 | pub fn _Qp_qtoui(a: *f128) callconv(.C) u32 { | ||
| 102 | return @import("fixunstfsi.zig").__fixunstfsi(a.*); | ||
| 103 | } | ||
| 104 | |||
| 105 | pub fn _Qp_qtox(a: *f128) callconv(.C) i64 { | ||
| 106 | return @import("fixtfdi.zig").__fixtfdi(a.*); | ||
| 107 | } | ||
| 108 | |||
| 109 | pub fn _Qp_qtoux(a: *f128) callconv(.C) u64 { | ||
| 110 | return @import("fixunstfdi.zig").__fixunstfdi(a.*); | ||
| 111 | } | ||
| 112 | |||
| 113 | pub fn _Qp_qtos(a: *f128) callconv(.C) f32 { | ||
| 114 | return @import("truncXfYf2.zig").__trunctfsf2(a.*); | ||
| 115 | } | ||
| 116 | |||
| 77 | pub fn _Qp_qtod(a: *f128) callconv(.C) f64 { | 117 | pub fn _Qp_qtod(a: *f128) callconv(.C) f64 { |
| 78 | return @import("truncXfYf2.zig").__trunctfdf2(a.*); | 118 | return @import("truncXfYf2.zig").__trunctfdf2(a.*); |
| 79 | } | 119 | } |
lib/std/start.zig+1-1| ... | @@ -46,7 +46,7 @@ comptime { | ... | @@ -46,7 +46,7 @@ comptime { |
| 46 | } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) { | 46 | } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) { |
| 47 | if (builtin.link_libc and @hasDecl(root, "main")) { | 47 | if (builtin.link_libc and @hasDecl(root, "main")) { |
| 48 | if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) { | 48 | if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) { |
| 49 | @export(main, .{ .name = "main", .linkage = .Weak }); | 49 | @export(main, .{ .name = "main" }); |
| 50 | } | 50 | } |
| 51 | } else if (native_os == .windows) { | 51 | } else if (native_os == .windows) { |
| 52 | if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and | 52 | if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and |
lib/std/target.zig+13-1| ... | @@ -431,6 +431,7 @@ pub const Target = struct { | ... | @@ -431,6 +431,7 @@ pub const Target = struct { |
| 431 | pub const powerpc = @import("target/powerpc.zig"); | 431 | pub const powerpc = @import("target/powerpc.zig"); |
| 432 | pub const riscv = @import("target/riscv.zig"); | 432 | pub const riscv = @import("target/riscv.zig"); |
| 433 | pub const sparc = @import("target/sparc.zig"); | 433 | pub const sparc = @import("target/sparc.zig"); |
| 434 | pub const spirv = @import("target/spirv.zig"); | ||
| 434 | pub const systemz = @import("target/systemz.zig"); | 435 | pub const systemz = @import("target/systemz.zig"); |
| 435 | pub const ve = @import("target/ve.zig"); | 436 | pub const ve = @import("target/ve.zig"); |
| 436 | pub const wasm = @import("target/wasm.zig"); | 437 | pub const wasm = @import("target/wasm.zig"); |
| ... | @@ -594,7 +595,7 @@ pub const Target = struct { | ... | @@ -594,7 +595,7 @@ pub const Target = struct { |
| 594 | pub const Set = struct { | 595 | pub const Set = struct { |
| 595 | ints: [usize_count]usize, | 596 | ints: [usize_count]usize, |
| 596 | 597 | ||
| 597 | pub const needed_bit_count = 172; | 598 | pub const needed_bit_count = 288; |
| 598 | pub const byte_count = (needed_bit_count + 7) / 8; | 599 | pub const byte_count = (needed_bit_count + 7) / 8; |
| 599 | pub const usize_count = (byte_count + (@sizeOf(usize) - 1)) / @sizeOf(usize); | 600 | pub const usize_count = (byte_count + (@sizeOf(usize) - 1)) / @sizeOf(usize); |
| 600 | pub const Index = std.math.Log2Int(std.meta.Int(.unsigned, usize_count * @bitSizeOf(usize))); | 601 | pub const Index = std.math.Log2Int(std.meta.Int(.unsigned, usize_count * @bitSizeOf(usize))); |
| ... | @@ -822,6 +823,13 @@ pub const Target = struct { | ... | @@ -822,6 +823,13 @@ pub const Target = struct { |
| 822 | }; | 823 | }; |
| 823 | } | 824 | } |
| 824 | 825 | ||
| 826 | pub fn isSPIRV(arch: Arch) bool { | ||
| 827 | return switch (arch) { | ||
| 828 | .spirv32, .spirv64 => true, | ||
| 829 | else => false, | ||
| 830 | }; | ||
| 831 | } | ||
| 832 | |||
| 825 | pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model { | 833 | pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model { |
| 826 | for (arch.allCpuModels()) |cpu| { | 834 | for (arch.allCpuModels()) |cpu| { |
| 827 | if (mem.eql(u8, cpu_name, cpu.name)) { | 835 | if (mem.eql(u8, cpu_name, cpu.name)) { |
| ... | @@ -1116,6 +1124,7 @@ pub const Target = struct { | ... | @@ -1116,6 +1124,7 @@ pub const Target = struct { |
| 1116 | .amdgcn => &amdgpu.all_features, | 1124 | .amdgcn => &amdgpu.all_features, |
| 1117 | .riscv32, .riscv64 => &riscv.all_features, | 1125 | .riscv32, .riscv64 => &riscv.all_features, |
| 1118 | .sparc, .sparcv9, .sparcel => &sparc.all_features, | 1126 | .sparc, .sparcv9, .sparcel => &sparc.all_features, |
| 1127 | .spirv32, .spirv64 => &spirv.all_features, | ||
| 1119 | .s390x => &systemz.all_features, | 1128 | .s390x => &systemz.all_features, |
| 1120 | .i386, .x86_64 => &x86.all_features, | 1129 | .i386, .x86_64 => &x86.all_features, |
| 1121 | .nvptx, .nvptx64 => &nvptx.all_features, | 1130 | .nvptx, .nvptx64 => &nvptx.all_features, |
| ... | @@ -1320,6 +1329,9 @@ pub const Target = struct { | ... | @@ -1320,6 +1329,9 @@ pub const Target = struct { |
| 1320 | if (cpu_arch.isWasm()) { | 1329 | if (cpu_arch.isWasm()) { |
| 1321 | return .wasm; | 1330 | return .wasm; |
| 1322 | } | 1331 | } |
| 1332 | if (cpu_arch.isSPIRV()) { | ||
| 1333 | return .spirv; | ||
| 1334 | } | ||
| 1323 | return .elf; | 1335 | return .elf; |
| 1324 | } | 1336 | } |
| 1325 | 1337 |
lib/std/target/spirv.zig created+2135| ... | @@ -0,0 +1,2135 @@ | ||
| 1 | //! This file is auto-generated by tools/update_spirv_features.zig. | ||
| 2 | //! TODO: Dependencies of capabilities on extensions. | ||
| 3 | //! TODO: Dependencies of extensions on extensions. | ||
| 4 | //! TODO: Dependencies of extensions on versions. | ||
| 5 | |||
| 6 | const std = @import("../std.zig"); | ||
| 7 | const CpuFeature = std.Target.Cpu.Feature; | ||
| 8 | const CpuModel = std.Target.Cpu.Model; | ||
| 9 | |||
| 10 | pub const Feature = enum { | ||
| 11 | v1_1, | ||
| 12 | v1_2, | ||
| 13 | v1_3, | ||
| 14 | v1_4, | ||
| 15 | v1_5, | ||
| 16 | SPV_AMD_shader_fragment_mask, | ||
| 17 | SPV_AMD_gpu_shader_int16, | ||
| 18 | SPV_AMD_gpu_shader_half_float, | ||
| 19 | SPV_AMD_texture_gather_bias_lod, | ||
| 20 | SPV_AMD_shader_ballot, | ||
| 21 | SPV_AMD_gcn_shader, | ||
| 22 | SPV_AMD_shader_image_load_store_lod, | ||
| 23 | SPV_AMD_shader_explicit_vertex_parameter, | ||
| 24 | SPV_AMD_shader_trinary_minmax, | ||
| 25 | SPV_AMD_gpu_shader_half_float_fetch, | ||
| 26 | SPV_GOOGLE_hlsl_functionality1, | ||
| 27 | SPV_GOOGLE_user_type, | ||
| 28 | SPV_GOOGLE_decorate_string, | ||
| 29 | SPV_EXT_demote_to_helper_invocation, | ||
| 30 | SPV_EXT_descriptor_indexing, | ||
| 31 | SPV_EXT_fragment_fully_covered, | ||
| 32 | SPV_EXT_shader_stencil_export, | ||
| 33 | SPV_EXT_physical_storage_buffer, | ||
| 34 | SPV_EXT_shader_atomic_float_add, | ||
| 35 | SPV_EXT_shader_atomic_float_min_max, | ||
| 36 | SPV_EXT_shader_image_int64, | ||
| 37 | SPV_EXT_fragment_shader_interlock, | ||
| 38 | SPV_EXT_fragment_invocation_density, | ||
| 39 | SPV_EXT_shader_viewport_index_layer, | ||
| 40 | SPV_INTEL_loop_fuse, | ||
| 41 | SPV_INTEL_fpga_dsp_control, | ||
| 42 | SPV_INTEL_fpga_reg, | ||
| 43 | SPV_INTEL_fpga_memory_accesses, | ||
| 44 | SPV_INTEL_fpga_loop_controls, | ||
| 45 | SPV_INTEL_io_pipes, | ||
| 46 | SPV_INTEL_unstructured_loop_controls, | ||
| 47 | SPV_INTEL_blocking_pipes, | ||
| 48 | SPV_INTEL_device_side_avc_motion_estimation, | ||
| 49 | SPV_INTEL_fpga_memory_attributes, | ||
| 50 | SPV_INTEL_fp_fast_math_mode, | ||
| 51 | SPV_INTEL_media_block_io, | ||
| 52 | SPV_INTEL_shader_integer_functions2, | ||
| 53 | SPV_INTEL_subgroups, | ||
| 54 | SPV_INTEL_fpga_cluster_attributes, | ||
| 55 | SPV_INTEL_kernel_attributes, | ||
| 56 | SPV_INTEL_arbitrary_precision_integers, | ||
| 57 | SPV_KHR_8bit_storage, | ||
| 58 | SPV_KHR_shader_clock, | ||
| 59 | SPV_KHR_device_group, | ||
| 60 | SPV_KHR_16bit_storage, | ||
| 61 | SPV_KHR_variable_pointers, | ||
| 62 | SPV_KHR_no_integer_wrap_decoration, | ||
| 63 | SPV_KHR_subgroup_vote, | ||
| 64 | SPV_KHR_multiview, | ||
| 65 | SPV_KHR_shader_ballot, | ||
| 66 | SPV_KHR_vulkan_memory_model, | ||
| 67 | SPV_KHR_physical_storage_buffer, | ||
| 68 | SPV_KHR_workgroup_memory_explicit_layout, | ||
| 69 | SPV_KHR_fragment_shading_rate, | ||
| 70 | SPV_KHR_shader_atomic_counter_ops, | ||
| 71 | SPV_KHR_shader_draw_parameters, | ||
| 72 | SPV_KHR_storage_buffer_storage_class, | ||
| 73 | SPV_KHR_linkonce_odr, | ||
| 74 | SPV_KHR_terminate_invocation, | ||
| 75 | SPV_KHR_non_semantic_info, | ||
| 76 | SPV_KHR_post_depth_coverage, | ||
| 77 | SPV_KHR_expect_assume, | ||
| 78 | SPV_KHR_ray_tracing, | ||
| 79 | SPV_KHR_ray_query, | ||
| 80 | SPV_KHR_float_controls, | ||
| 81 | SPV_NV_viewport_array2, | ||
| 82 | SPV_NV_shader_subgroup_partitioned, | ||
| 83 | SPV_NVX_multiview_per_view_attributes, | ||
| 84 | SPV_NV_ray_tracing, | ||
| 85 | SPV_NV_shader_image_footprint, | ||
| 86 | SPV_NV_shading_rate, | ||
| 87 | SPV_NV_stereo_view_rendering, | ||
| 88 | SPV_NV_compute_shader_derivatives, | ||
| 89 | SPV_NV_shader_sm_builtins, | ||
| 90 | SPV_NV_mesh_shader, | ||
| 91 | SPV_NV_geometry_shader_passthrough, | ||
| 92 | SPV_NV_fragment_shader_barycentric, | ||
| 93 | SPV_NV_cooperative_matrix, | ||
| 94 | SPV_NV_sample_mask_override_coverage, | ||
| 95 | Matrix, | ||
| 96 | Shader, | ||
| 97 | Geometry, | ||
| 98 | Tessellation, | ||
| 99 | Addresses, | ||
| 100 | Linkage, | ||
| 101 | Kernel, | ||
| 102 | Vector16, | ||
| 103 | Float16Buffer, | ||
| 104 | Float16, | ||
| 105 | Float64, | ||
| 106 | Int64, | ||
| 107 | Int64Atomics, | ||
| 108 | ImageBasic, | ||
| 109 | ImageReadWrite, | ||
| 110 | ImageMipmap, | ||
| 111 | Pipes, | ||
| 112 | Groups, | ||
| 113 | DeviceEnqueue, | ||
| 114 | LiteralSampler, | ||
| 115 | AtomicStorage, | ||
| 116 | Int16, | ||
| 117 | TessellationPointSize, | ||
| 118 | GeometryPointSize, | ||
| 119 | ImageGatherExtended, | ||
| 120 | StorageImageMultisample, | ||
| 121 | UniformBufferArrayDynamicIndexing, | ||
| 122 | SampledImageArrayDynamicIndexing, | ||
| 123 | StorageBufferArrayDynamicIndexing, | ||
| 124 | StorageImageArrayDynamicIndexing, | ||
| 125 | ClipDistance, | ||
| 126 | CullDistance, | ||
| 127 | ImageCubeArray, | ||
| 128 | SampleRateShading, | ||
| 129 | ImageRect, | ||
| 130 | SampledRect, | ||
| 131 | GenericPointer, | ||
| 132 | Int8, | ||
| 133 | InputAttachment, | ||
| 134 | SparseResidency, | ||
| 135 | MinLod, | ||
| 136 | Sampled1D, | ||
| 137 | Image1D, | ||
| 138 | SampledCubeArray, | ||
| 139 | SampledBuffer, | ||
| 140 | ImageBuffer, | ||
| 141 | ImageMSArray, | ||
| 142 | StorageImageExtendedFormats, | ||
| 143 | ImageQuery, | ||
| 144 | DerivativeControl, | ||
| 145 | InterpolationFunction, | ||
| 146 | TransformFeedback, | ||
| 147 | GeometryStreams, | ||
| 148 | StorageImageReadWithoutFormat, | ||
| 149 | StorageImageWriteWithoutFormat, | ||
| 150 | MultiViewport, | ||
| 151 | SubgroupDispatch, | ||
| 152 | NamedBarrier, | ||
| 153 | PipeStorage, | ||
| 154 | GroupNonUniform, | ||
| 155 | GroupNonUniformVote, | ||
| 156 | GroupNonUniformArithmetic, | ||
| 157 | GroupNonUniformBallot, | ||
| 158 | GroupNonUniformShuffle, | ||
| 159 | GroupNonUniformShuffleRelative, | ||
| 160 | GroupNonUniformClustered, | ||
| 161 | GroupNonUniformQuad, | ||
| 162 | ShaderLayer, | ||
| 163 | ShaderViewportIndex, | ||
| 164 | FragmentShadingRateKHR, | ||
| 165 | SubgroupBallotKHR, | ||
| 166 | DrawParameters, | ||
| 167 | WorkgroupMemoryExplicitLayoutKHR, | ||
| 168 | WorkgroupMemoryExplicitLayout8BitAccessKHR, | ||
| 169 | WorkgroupMemoryExplicitLayout16BitAccessKHR, | ||
| 170 | SubgroupVoteKHR, | ||
| 171 | StorageBuffer16BitAccess, | ||
| 172 | StorageUniformBufferBlock16, | ||
| 173 | UniformAndStorageBuffer16BitAccess, | ||
| 174 | StorageUniform16, | ||
| 175 | StoragePushConstant16, | ||
| 176 | StorageInputOutput16, | ||
| 177 | DeviceGroup, | ||
| 178 | MultiView, | ||
| 179 | VariablePointersStorageBuffer, | ||
| 180 | VariablePointers, | ||
| 181 | AtomicStorageOps, | ||
| 182 | SampleMaskPostDepthCoverage, | ||
| 183 | StorageBuffer8BitAccess, | ||
| 184 | UniformAndStorageBuffer8BitAccess, | ||
| 185 | StoragePushConstant8, | ||
| 186 | DenormPreserve, | ||
| 187 | DenormFlushToZero, | ||
| 188 | SignedZeroInfNanPreserve, | ||
| 189 | RoundingModeRTE, | ||
| 190 | RoundingModeRTZ, | ||
| 191 | RayQueryProvisionalKHR, | ||
| 192 | RayQueryKHR, | ||
| 193 | RayTraversalPrimitiveCullingKHR, | ||
| 194 | RayTracingKHR, | ||
| 195 | Float16ImageAMD, | ||
| 196 | ImageGatherBiasLodAMD, | ||
| 197 | FragmentMaskAMD, | ||
| 198 | StencilExportEXT, | ||
| 199 | ImageReadWriteLodAMD, | ||
| 200 | Int64ImageEXT, | ||
| 201 | ShaderClockKHR, | ||
| 202 | SampleMaskOverrideCoverageNV, | ||
| 203 | GeometryShaderPassthroughNV, | ||
| 204 | ShaderViewportIndexLayerEXT, | ||
| 205 | ShaderViewportIndexLayerNV, | ||
| 206 | ShaderViewportMaskNV, | ||
| 207 | ShaderStereoViewNV, | ||
| 208 | PerViewAttributesNV, | ||
| 209 | FragmentFullyCoveredEXT, | ||
| 210 | MeshShadingNV, | ||
| 211 | ImageFootprintNV, | ||
| 212 | FragmentBarycentricNV, | ||
| 213 | ComputeDerivativeGroupQuadsNV, | ||
| 214 | FragmentDensityEXT, | ||
| 215 | ShadingRateNV, | ||
| 216 | GroupNonUniformPartitionedNV, | ||
| 217 | ShaderNonUniform, | ||
| 218 | ShaderNonUniformEXT, | ||
| 219 | RuntimeDescriptorArray, | ||
| 220 | RuntimeDescriptorArrayEXT, | ||
| 221 | InputAttachmentArrayDynamicIndexing, | ||
| 222 | InputAttachmentArrayDynamicIndexingEXT, | ||
| 223 | UniformTexelBufferArrayDynamicIndexing, | ||
| 224 | UniformTexelBufferArrayDynamicIndexingEXT, | ||
| 225 | StorageTexelBufferArrayDynamicIndexing, | ||
| 226 | StorageTexelBufferArrayDynamicIndexingEXT, | ||
| 227 | UniformBufferArrayNonUniformIndexing, | ||
| 228 | UniformBufferArrayNonUniformIndexingEXT, | ||
| 229 | SampledImageArrayNonUniformIndexing, | ||
| 230 | SampledImageArrayNonUniformIndexingEXT, | ||
| 231 | StorageBufferArrayNonUniformIndexing, | ||
| 232 | StorageBufferArrayNonUniformIndexingEXT, | ||
| 233 | StorageImageArrayNonUniformIndexing, | ||
| 234 | StorageImageArrayNonUniformIndexingEXT, | ||
| 235 | InputAttachmentArrayNonUniformIndexing, | ||
| 236 | InputAttachmentArrayNonUniformIndexingEXT, | ||
| 237 | UniformTexelBufferArrayNonUniformIndexing, | ||
| 238 | UniformTexelBufferArrayNonUniformIndexingEXT, | ||
| 239 | StorageTexelBufferArrayNonUniformIndexing, | ||
| 240 | StorageTexelBufferArrayNonUniformIndexingEXT, | ||
| 241 | RayTracingNV, | ||
| 242 | VulkanMemoryModel, | ||
| 243 | VulkanMemoryModelKHR, | ||
| 244 | VulkanMemoryModelDeviceScope, | ||
| 245 | VulkanMemoryModelDeviceScopeKHR, | ||
| 246 | PhysicalStorageBufferAddresses, | ||
| 247 | PhysicalStorageBufferAddressesEXT, | ||
| 248 | ComputeDerivativeGroupLinearNV, | ||
| 249 | RayTracingProvisionalKHR, | ||
| 250 | CooperativeMatrixNV, | ||
| 251 | FragmentShaderSampleInterlockEXT, | ||
| 252 | FragmentShaderShadingRateInterlockEXT, | ||
| 253 | ShaderSMBuiltinsNV, | ||
| 254 | FragmentShaderPixelInterlockEXT, | ||
| 255 | DemoteToHelperInvocationEXT, | ||
| 256 | SubgroupShuffleINTEL, | ||
| 257 | SubgroupBufferBlockIOINTEL, | ||
| 258 | SubgroupImageBlockIOINTEL, | ||
| 259 | SubgroupImageMediaBlockIOINTEL, | ||
| 260 | RoundToInfinityINTEL, | ||
| 261 | FloatingPointModeINTEL, | ||
| 262 | IntegerFunctions2INTEL, | ||
| 263 | FunctionPointersINTEL, | ||
| 264 | IndirectReferencesINTEL, | ||
| 265 | AsmINTEL, | ||
| 266 | AtomicFloat32MinMaxEXT, | ||
| 267 | AtomicFloat64MinMaxEXT, | ||
| 268 | AtomicFloat16MinMaxEXT, | ||
| 269 | VectorComputeINTEL, | ||
| 270 | VectorAnyINTEL, | ||
| 271 | ExpectAssumeKHR, | ||
| 272 | SubgroupAvcMotionEstimationINTEL, | ||
| 273 | SubgroupAvcMotionEstimationIntraINTEL, | ||
| 274 | SubgroupAvcMotionEstimationChromaINTEL, | ||
| 275 | VariableLengthArrayINTEL, | ||
| 276 | FunctionFloatControlINTEL, | ||
| 277 | FPGAMemoryAttributesINTEL, | ||
| 278 | FPFastMathModeINTEL, | ||
| 279 | ArbitraryPrecisionIntegersINTEL, | ||
| 280 | UnstructuredLoopControlsINTEL, | ||
| 281 | FPGALoopControlsINTEL, | ||
| 282 | KernelAttributesINTEL, | ||
| 283 | FPGAKernelAttributesINTEL, | ||
| 284 | FPGAMemoryAccessesINTEL, | ||
| 285 | FPGAClusterAttributesINTEL, | ||
| 286 | LoopFuseINTEL, | ||
| 287 | FPGABufferLocationINTEL, | ||
| 288 | USMStorageClassesINTEL, | ||
| 289 | IOPipesINTEL, | ||
| 290 | BlockingPipesINTEL, | ||
| 291 | FPGARegINTEL, | ||
| 292 | AtomicFloat32AddEXT, | ||
| 293 | AtomicFloat64AddEXT, | ||
| 294 | LongConstantCompositeINTEL, | ||
| 295 | }; | ||
| 296 | |||
| 297 | pub usingnamespace CpuFeature.feature_set_fns(Feature); | ||
| 298 | |||
| 299 | pub const all_features = blk: { | ||
| 300 | @setEvalBranchQuota(2000); | ||
| 301 | const len = @typeInfo(Feature).Enum.fields.len; | ||
| 302 | std.debug.assert(len <= CpuFeature.Set.needed_bit_count); | ||
| 303 | var result: [len]CpuFeature = undefined; | ||
| 304 | result[@enumToInt(Feature.v1_1)] = .{ | ||
| 305 | .llvm_name = null, | ||
| 306 | .description = "SPIR-V version 1.1", | ||
| 307 | .dependencies = featureSet(&[_]Feature{}), | ||
| 308 | }; | ||
| 309 | result[@enumToInt(Feature.v1_2)] = .{ | ||
| 310 | .llvm_name = null, | ||
| 311 | .description = "SPIR-V version 1.2", | ||
| 312 | .dependencies = featureSet(&[_]Feature{ | ||
| 313 | .v1_1, | ||
| 314 | }), | ||
| 315 | }; | ||
| 316 | result[@enumToInt(Feature.v1_3)] = .{ | ||
| 317 | .llvm_name = null, | ||
| 318 | .description = "SPIR-V version 1.3", | ||
| 319 | .dependencies = featureSet(&[_]Feature{ | ||
| 320 | .v1_2, | ||
| 321 | }), | ||
| 322 | }; | ||
| 323 | result[@enumToInt(Feature.v1_4)] = .{ | ||
| 324 | .llvm_name = null, | ||
| 325 | .description = "SPIR-V version 1.4", | ||
| 326 | .dependencies = featureSet(&[_]Feature{ | ||
| 327 | .v1_3, | ||
| 328 | }), | ||
| 329 | }; | ||
| 330 | result[@enumToInt(Feature.v1_5)] = .{ | ||
| 331 | .llvm_name = null, | ||
| 332 | .description = "SPIR-V version 1.5", | ||
| 333 | .dependencies = featureSet(&[_]Feature{ | ||
| 334 | .v1_4, | ||
| 335 | }), | ||
| 336 | }; | ||
| 337 | result[@enumToInt(Feature.SPV_AMD_shader_fragment_mask)] = .{ | ||
| 338 | .llvm_name = null, | ||
| 339 | .description = "SPIR-V extension SPV_AMD_shader_fragment_mask", | ||
| 340 | .dependencies = featureSet(&[_]Feature{}), | ||
| 341 | }; | ||
| 342 | result[@enumToInt(Feature.SPV_AMD_gpu_shader_int16)] = .{ | ||
| 343 | .llvm_name = null, | ||
| 344 | .description = "SPIR-V extension SPV_AMD_gpu_shader_int16", | ||
| 345 | .dependencies = featureSet(&[_]Feature{}), | ||
| 346 | }; | ||
| 347 | result[@enumToInt(Feature.SPV_AMD_gpu_shader_half_float)] = .{ | ||
| 348 | .llvm_name = null, | ||
| 349 | .description = "SPIR-V extension SPV_AMD_gpu_shader_half_float", | ||
| 350 | .dependencies = featureSet(&[_]Feature{}), | ||
| 351 | }; | ||
| 352 | result[@enumToInt(Feature.SPV_AMD_texture_gather_bias_lod)] = .{ | ||
| 353 | .llvm_name = null, | ||
| 354 | .description = "SPIR-V extension SPV_AMD_texture_gather_bias_lod", | ||
| 355 | .dependencies = featureSet(&[_]Feature{}), | ||
| 356 | }; | ||
| 357 | result[@enumToInt(Feature.SPV_AMD_shader_ballot)] = .{ | ||
| 358 | .llvm_name = null, | ||
| 359 | .description = "SPIR-V extension SPV_AMD_shader_ballot", | ||
| 360 | .dependencies = featureSet(&[_]Feature{}), | ||
| 361 | }; | ||
| 362 | result[@enumToInt(Feature.SPV_AMD_gcn_shader)] = .{ | ||
| 363 | .llvm_name = null, | ||
| 364 | .description = "SPIR-V extension SPV_AMD_gcn_shader", | ||
| 365 | .dependencies = featureSet(&[_]Feature{}), | ||
| 366 | }; | ||
| 367 | result[@enumToInt(Feature.SPV_AMD_shader_image_load_store_lod)] = .{ | ||
| 368 | .llvm_name = null, | ||
| 369 | .description = "SPIR-V extension SPV_AMD_shader_image_load_store_lod", | ||
| 370 | .dependencies = featureSet(&[_]Feature{}), | ||
| 371 | }; | ||
| 372 | result[@enumToInt(Feature.SPV_AMD_shader_explicit_vertex_parameter)] = .{ | ||
| 373 | .llvm_name = null, | ||
| 374 | .description = "SPIR-V extension SPV_AMD_shader_explicit_vertex_parameter", | ||
| 375 | .dependencies = featureSet(&[_]Feature{}), | ||
| 376 | }; | ||
| 377 | result[@enumToInt(Feature.SPV_AMD_shader_trinary_minmax)] = .{ | ||
| 378 | .llvm_name = null, | ||
| 379 | .description = "SPIR-V extension SPV_AMD_shader_trinary_minmax", | ||
| 380 | .dependencies = featureSet(&[_]Feature{}), | ||
| 381 | }; | ||
| 382 | result[@enumToInt(Feature.SPV_AMD_gpu_shader_half_float_fetch)] = .{ | ||
| 383 | .llvm_name = null, | ||
| 384 | .description = "SPIR-V extension SPV_AMD_gpu_shader_half_float_fetch", | ||
| 385 | .dependencies = featureSet(&[_]Feature{}), | ||
| 386 | }; | ||
| 387 | result[@enumToInt(Feature.SPV_GOOGLE_hlsl_functionality1)] = .{ | ||
| 388 | .llvm_name = null, | ||
| 389 | .description = "SPIR-V extension SPV_GOOGLE_hlsl_functionality1", | ||
| 390 | .dependencies = featureSet(&[_]Feature{}), | ||
| 391 | }; | ||
| 392 | result[@enumToInt(Feature.SPV_GOOGLE_user_type)] = .{ | ||
| 393 | .llvm_name = null, | ||
| 394 | .description = "SPIR-V extension SPV_GOOGLE_user_type", | ||
| 395 | .dependencies = featureSet(&[_]Feature{}), | ||
| 396 | }; | ||
| 397 | result[@enumToInt(Feature.SPV_GOOGLE_decorate_string)] = .{ | ||
| 398 | .llvm_name = null, | ||
| 399 | .description = "SPIR-V extension SPV_GOOGLE_decorate_string", | ||
| 400 | .dependencies = featureSet(&[_]Feature{}), | ||
| 401 | }; | ||
| 402 | result[@enumToInt(Feature.SPV_EXT_demote_to_helper_invocation)] = .{ | ||
| 403 | .llvm_name = null, | ||
| 404 | .description = "SPIR-V extension SPV_EXT_demote_to_helper_invocation", | ||
| 405 | .dependencies = featureSet(&[_]Feature{}), | ||
| 406 | }; | ||
| 407 | result[@enumToInt(Feature.SPV_EXT_descriptor_indexing)] = .{ | ||
| 408 | .llvm_name = null, | ||
| 409 | .description = "SPIR-V extension SPV_EXT_descriptor_indexing", | ||
| 410 | .dependencies = featureSet(&[_]Feature{}), | ||
| 411 | }; | ||
| 412 | result[@enumToInt(Feature.SPV_EXT_fragment_fully_covered)] = .{ | ||
| 413 | .llvm_name = null, | ||
| 414 | .description = "SPIR-V extension SPV_EXT_fragment_fully_covered", | ||
| 415 | .dependencies = featureSet(&[_]Feature{}), | ||
| 416 | }; | ||
| 417 | result[@enumToInt(Feature.SPV_EXT_shader_stencil_export)] = .{ | ||
| 418 | .llvm_name = null, | ||
| 419 | .description = "SPIR-V extension SPV_EXT_shader_stencil_export", | ||
| 420 | .dependencies = featureSet(&[_]Feature{}), | ||
| 421 | }; | ||
| 422 | result[@enumToInt(Feature.SPV_EXT_physical_storage_buffer)] = .{ | ||
| 423 | .llvm_name = null, | ||
| 424 | .description = "SPIR-V extension SPV_EXT_physical_storage_buffer", | ||
| 425 | .dependencies = featureSet(&[_]Feature{}), | ||
| 426 | }; | ||
| 427 | result[@enumToInt(Feature.SPV_EXT_shader_atomic_float_add)] = .{ | ||
| 428 | .llvm_name = null, | ||
| 429 | .description = "SPIR-V extension SPV_EXT_shader_atomic_float_add", | ||
| 430 | .dependencies = featureSet(&[_]Feature{}), | ||
| 431 | }; | ||
| 432 | result[@enumToInt(Feature.SPV_EXT_shader_atomic_float_min_max)] = .{ | ||
| 433 | .llvm_name = null, | ||
| 434 | .description = "SPIR-V extension SPV_EXT_shader_atomic_float_min_max", | ||
| 435 | .dependencies = featureSet(&[_]Feature{}), | ||
| 436 | }; | ||
| 437 | result[@enumToInt(Feature.SPV_EXT_shader_image_int64)] = .{ | ||
| 438 | .llvm_name = null, | ||
| 439 | .description = "SPIR-V extension SPV_EXT_shader_image_int64", | ||
| 440 | .dependencies = featureSet(&[_]Feature{}), | ||
| 441 | }; | ||
| 442 | result[@enumToInt(Feature.SPV_EXT_fragment_shader_interlock)] = .{ | ||
| 443 | .llvm_name = null, | ||
| 444 | .description = "SPIR-V extension SPV_EXT_fragment_shader_interlock", | ||
| 445 | .dependencies = featureSet(&[_]Feature{}), | ||
| 446 | }; | ||
| 447 | result[@enumToInt(Feature.SPV_EXT_fragment_invocation_density)] = .{ | ||
| 448 | .llvm_name = null, | ||
| 449 | .description = "SPIR-V extension SPV_EXT_fragment_invocation_density", | ||
| 450 | .dependencies = featureSet(&[_]Feature{}), | ||
| 451 | }; | ||
| 452 | result[@enumToInt(Feature.SPV_EXT_shader_viewport_index_layer)] = .{ | ||
| 453 | .llvm_name = null, | ||
| 454 | .description = "SPIR-V extension SPV_EXT_shader_viewport_index_layer", | ||
| 455 | .dependencies = featureSet(&[_]Feature{}), | ||
| 456 | }; | ||
| 457 | result[@enumToInt(Feature.SPV_INTEL_loop_fuse)] = .{ | ||
| 458 | .llvm_name = null, | ||
| 459 | .description = "SPIR-V extension SPV_INTEL_loop_fuse", | ||
| 460 | .dependencies = featureSet(&[_]Feature{}), | ||
| 461 | }; | ||
| 462 | result[@enumToInt(Feature.SPV_INTEL_fpga_dsp_control)] = .{ | ||
| 463 | .llvm_name = null, | ||
| 464 | .description = "SPIR-V extension SPV_INTEL_fpga_dsp_control", | ||
| 465 | .dependencies = featureSet(&[_]Feature{}), | ||
| 466 | }; | ||
| 467 | result[@enumToInt(Feature.SPV_INTEL_fpga_reg)] = .{ | ||
| 468 | .llvm_name = null, | ||
| 469 | .description = "SPIR-V extension SPV_INTEL_fpga_reg", | ||
| 470 | .dependencies = featureSet(&[_]Feature{}), | ||
| 471 | }; | ||
| 472 | result[@enumToInt(Feature.SPV_INTEL_fpga_memory_accesses)] = .{ | ||
| 473 | .llvm_name = null, | ||
| 474 | .description = "SPIR-V extension SPV_INTEL_fpga_memory_accesses", | ||
| 475 | .dependencies = featureSet(&[_]Feature{}), | ||
| 476 | }; | ||
| 477 | result[@enumToInt(Feature.SPV_INTEL_fpga_loop_controls)] = .{ | ||
| 478 | .llvm_name = null, | ||
| 479 | .description = "SPIR-V extension SPV_INTEL_fpga_loop_controls", | ||
| 480 | .dependencies = featureSet(&[_]Feature{}), | ||
| 481 | }; | ||
| 482 | result[@enumToInt(Feature.SPV_INTEL_io_pipes)] = .{ | ||
| 483 | .llvm_name = null, | ||
| 484 | .description = "SPIR-V extension SPV_INTEL_io_pipes", | ||
| 485 | .dependencies = featureSet(&[_]Feature{}), | ||
| 486 | }; | ||
| 487 | result[@enumToInt(Feature.SPV_INTEL_unstructured_loop_controls)] = .{ | ||
| 488 | .llvm_name = null, | ||
| 489 | .description = "SPIR-V extension SPV_INTEL_unstructured_loop_controls", | ||
| 490 | .dependencies = featureSet(&[_]Feature{}), | ||
| 491 | }; | ||
| 492 | result[@enumToInt(Feature.SPV_INTEL_blocking_pipes)] = .{ | ||
| 493 | .llvm_name = null, | ||
| 494 | .description = "SPIR-V extension SPV_INTEL_blocking_pipes", | ||
| 495 | .dependencies = featureSet(&[_]Feature{}), | ||
| 496 | }; | ||
| 497 | result[@enumToInt(Feature.SPV_INTEL_device_side_avc_motion_estimation)] = .{ | ||
| 498 | .llvm_name = null, | ||
| 499 | .description = "SPIR-V extension SPV_INTEL_device_side_avc_motion_estimation", | ||
| 500 | .dependencies = featureSet(&[_]Feature{}), | ||
| 501 | }; | ||
| 502 | result[@enumToInt(Feature.SPV_INTEL_fpga_memory_attributes)] = .{ | ||
| 503 | .llvm_name = null, | ||
| 504 | .description = "SPIR-V extension SPV_INTEL_fpga_memory_attributes", | ||
| 505 | .dependencies = featureSet(&[_]Feature{}), | ||
| 506 | }; | ||
| 507 | result[@enumToInt(Feature.SPV_INTEL_fp_fast_math_mode)] = .{ | ||
| 508 | .llvm_name = null, | ||
| 509 | .description = "SPIR-V extension SPV_INTEL_fp_fast_math_mode", | ||
| 510 | .dependencies = featureSet(&[_]Feature{}), | ||
| 511 | }; | ||
| 512 | result[@enumToInt(Feature.SPV_INTEL_media_block_io)] = .{ | ||
| 513 | .llvm_name = null, | ||
| 514 | .description = "SPIR-V extension SPV_INTEL_media_block_io", | ||
| 515 | .dependencies = featureSet(&[_]Feature{}), | ||
| 516 | }; | ||
| 517 | result[@enumToInt(Feature.SPV_INTEL_shader_integer_functions2)] = .{ | ||
| 518 | .llvm_name = null, | ||
| 519 | .description = "SPIR-V extension SPV_INTEL_shader_integer_functions2", | ||
| 520 | .dependencies = featureSet(&[_]Feature{}), | ||
| 521 | }; | ||
| 522 | result[@enumToInt(Feature.SPV_INTEL_subgroups)] = .{ | ||
| 523 | .llvm_name = null, | ||
| 524 | .description = "SPIR-V extension SPV_INTEL_subgroups", | ||
| 525 | .dependencies = featureSet(&[_]Feature{}), | ||
| 526 | }; | ||
| 527 | result[@enumToInt(Feature.SPV_INTEL_fpga_cluster_attributes)] = .{ | ||
| 528 | .llvm_name = null, | ||
| 529 | .description = "SPIR-V extension SPV_INTEL_fpga_cluster_attributes", | ||
| 530 | .dependencies = featureSet(&[_]Feature{}), | ||
| 531 | }; | ||
| 532 | result[@enumToInt(Feature.SPV_INTEL_kernel_attributes)] = .{ | ||
| 533 | .llvm_name = null, | ||
| 534 | .description = "SPIR-V extension SPV_INTEL_kernel_attributes", | ||
| 535 | .dependencies = featureSet(&[_]Feature{}), | ||
| 536 | }; | ||
| 537 | result[@enumToInt(Feature.SPV_INTEL_arbitrary_precision_integers)] = .{ | ||
| 538 | .llvm_name = null, | ||
| 539 | .description = "SPIR-V extension SPV_INTEL_arbitrary_precision_integers", | ||
| 540 | .dependencies = featureSet(&[_]Feature{}), | ||
| 541 | }; | ||
| 542 | result[@enumToInt(Feature.SPV_KHR_8bit_storage)] = .{ | ||
| 543 | .llvm_name = null, | ||
| 544 | .description = "SPIR-V extension SPV_KHR_8bit_storage", | ||
| 545 | .dependencies = featureSet(&[_]Feature{}), | ||
| 546 | }; | ||
| 547 | result[@enumToInt(Feature.SPV_KHR_shader_clock)] = .{ | ||
| 548 | .llvm_name = null, | ||
| 549 | .description = "SPIR-V extension SPV_KHR_shader_clock", | ||
| 550 | .dependencies = featureSet(&[_]Feature{}), | ||
| 551 | }; | ||
| 552 | result[@enumToInt(Feature.SPV_KHR_device_group)] = .{ | ||
| 553 | .llvm_name = null, | ||
| 554 | .description = "SPIR-V extension SPV_KHR_device_group", | ||
| 555 | .dependencies = featureSet(&[_]Feature{}), | ||
| 556 | }; | ||
| 557 | result[@enumToInt(Feature.SPV_KHR_16bit_storage)] = .{ | ||
| 558 | .llvm_name = null, | ||
| 559 | .description = "SPIR-V extension SPV_KHR_16bit_storage", | ||
| 560 | .dependencies = featureSet(&[_]Feature{}), | ||
| 561 | }; | ||
| 562 | result[@enumToInt(Feature.SPV_KHR_variable_pointers)] = .{ | ||
| 563 | .llvm_name = null, | ||
| 564 | .description = "SPIR-V extension SPV_KHR_variable_pointers", | ||
| 565 | .dependencies = featureSet(&[_]Feature{}), | ||
| 566 | }; | ||
| 567 | result[@enumToInt(Feature.SPV_KHR_no_integer_wrap_decoration)] = .{ | ||
| 568 | .llvm_name = null, | ||
| 569 | .description = "SPIR-V extension SPV_KHR_no_integer_wrap_decoration", | ||
| 570 | .dependencies = featureSet(&[_]Feature{}), | ||
| 571 | }; | ||
| 572 | result[@enumToInt(Feature.SPV_KHR_subgroup_vote)] = .{ | ||
| 573 | .llvm_name = null, | ||
| 574 | .description = "SPIR-V extension SPV_KHR_subgroup_vote", | ||
| 575 | .dependencies = featureSet(&[_]Feature{}), | ||
| 576 | }; | ||
| 577 | result[@enumToInt(Feature.SPV_KHR_multiview)] = .{ | ||
| 578 | .llvm_name = null, | ||
| 579 | .description = "SPIR-V extension SPV_KHR_multiview", | ||
| 580 | .dependencies = featureSet(&[_]Feature{}), | ||
| 581 | }; | ||
| 582 | result[@enumToInt(Feature.SPV_KHR_shader_ballot)] = .{ | ||
| 583 | .llvm_name = null, | ||
| 584 | .description = "SPIR-V extension SPV_KHR_shader_ballot", | ||
| 585 | .dependencies = featureSet(&[_]Feature{}), | ||
| 586 | }; | ||
| 587 | result[@enumToInt(Feature.SPV_KHR_vulkan_memory_model)] = .{ | ||
| 588 | .llvm_name = null, | ||
| 589 | .description = "SPIR-V extension SPV_KHR_vulkan_memory_model", | ||
| 590 | .dependencies = featureSet(&[_]Feature{}), | ||
| 591 | }; | ||
| 592 | result[@enumToInt(Feature.SPV_KHR_physical_storage_buffer)] = .{ | ||
| 593 | .llvm_name = null, | ||
| 594 | .description = "SPIR-V extension SPV_KHR_physical_storage_buffer", | ||
| 595 | .dependencies = featureSet(&[_]Feature{}), | ||
| 596 | }; | ||
| 597 | result[@enumToInt(Feature.SPV_KHR_workgroup_memory_explicit_layout)] = .{ | ||
| 598 | .llvm_name = null, | ||
| 599 | .description = "SPIR-V extension SPV_KHR_workgroup_memory_explicit_layout", | ||
| 600 | .dependencies = featureSet(&[_]Feature{}), | ||
| 601 | }; | ||
| 602 | result[@enumToInt(Feature.SPV_KHR_fragment_shading_rate)] = .{ | ||
| 603 | .llvm_name = null, | ||
| 604 | .description = "SPIR-V extension SPV_KHR_fragment_shading_rate", | ||
| 605 | .dependencies = featureSet(&[_]Feature{}), | ||
| 606 | }; | ||
| 607 | result[@enumToInt(Feature.SPV_KHR_shader_atomic_counter_ops)] = .{ | ||
| 608 | .llvm_name = null, | ||
| 609 | .description = "SPIR-V extension SPV_KHR_shader_atomic_counter_ops", | ||
| 610 | .dependencies = featureSet(&[_]Feature{}), | ||
| 611 | }; | ||
| 612 | result[@enumToInt(Feature.SPV_KHR_shader_draw_parameters)] = .{ | ||
| 613 | .llvm_name = null, | ||
| 614 | .description = "SPIR-V extension SPV_KHR_shader_draw_parameters", | ||
| 615 | .dependencies = featureSet(&[_]Feature{}), | ||
| 616 | }; | ||
| 617 | result[@enumToInt(Feature.SPV_KHR_storage_buffer_storage_class)] = .{ | ||
| 618 | .llvm_name = null, | ||
| 619 | .description = "SPIR-V extension SPV_KHR_storage_buffer_storage_class", | ||
| 620 | .dependencies = featureSet(&[_]Feature{}), | ||
| 621 | }; | ||
| 622 | result[@enumToInt(Feature.SPV_KHR_linkonce_odr)] = .{ | ||
| 623 | .llvm_name = null, | ||
| 624 | .description = "SPIR-V extension SPV_KHR_linkonce_odr", | ||
| 625 | .dependencies = featureSet(&[_]Feature{}), | ||
| 626 | }; | ||
| 627 | result[@enumToInt(Feature.SPV_KHR_terminate_invocation)] = .{ | ||
| 628 | .llvm_name = null, | ||
| 629 | .description = "SPIR-V extension SPV_KHR_terminate_invocation", | ||
| 630 | .dependencies = featureSet(&[_]Feature{}), | ||
| 631 | }; | ||
| 632 | result[@enumToInt(Feature.SPV_KHR_non_semantic_info)] = .{ | ||
| 633 | .llvm_name = null, | ||
| 634 | .description = "SPIR-V extension SPV_KHR_non_semantic_info", | ||
| 635 | .dependencies = featureSet(&[_]Feature{}), | ||
| 636 | }; | ||
| 637 | result[@enumToInt(Feature.SPV_KHR_post_depth_coverage)] = .{ | ||
| 638 | .llvm_name = null, | ||
| 639 | .description = "SPIR-V extension SPV_KHR_post_depth_coverage", | ||
| 640 | .dependencies = featureSet(&[_]Feature{}), | ||
| 641 | }; | ||
| 642 | result[@enumToInt(Feature.SPV_KHR_expect_assume)] = .{ | ||
| 643 | .llvm_name = null, | ||
| 644 | .description = "SPIR-V extension SPV_KHR_expect_assume", | ||
| 645 | .dependencies = featureSet(&[_]Feature{}), | ||
| 646 | }; | ||
| 647 | result[@enumToInt(Feature.SPV_KHR_ray_tracing)] = .{ | ||
| 648 | .llvm_name = null, | ||
| 649 | .description = "SPIR-V extension SPV_KHR_ray_tracing", | ||
| 650 | .dependencies = featureSet(&[_]Feature{}), | ||
| 651 | }; | ||
| 652 | result[@enumToInt(Feature.SPV_KHR_ray_query)] = .{ | ||
| 653 | .llvm_name = null, | ||
| 654 | .description = "SPIR-V extension SPV_KHR_ray_query", | ||
| 655 | .dependencies = featureSet(&[_]Feature{}), | ||
| 656 | }; | ||
| 657 | result[@enumToInt(Feature.SPV_KHR_float_controls)] = .{ | ||
| 658 | .llvm_name = null, | ||
| 659 | .description = "SPIR-V extension SPV_KHR_float_controls", | ||
| 660 | .dependencies = featureSet(&[_]Feature{}), | ||
| 661 | }; | ||
| 662 | result[@enumToInt(Feature.SPV_NV_viewport_array2)] = .{ | ||
| 663 | .llvm_name = null, | ||
| 664 | .description = "SPIR-V extension SPV_NV_viewport_array2", | ||
| 665 | .dependencies = featureSet(&[_]Feature{}), | ||
| 666 | }; | ||
| 667 | result[@enumToInt(Feature.SPV_NV_shader_subgroup_partitioned)] = .{ | ||
| 668 | .llvm_name = null, | ||
| 669 | .description = "SPIR-V extension SPV_NV_shader_subgroup_partitioned", | ||
| 670 | .dependencies = featureSet(&[_]Feature{}), | ||
| 671 | }; | ||
| 672 | result[@enumToInt(Feature.SPV_NVX_multiview_per_view_attributes)] = .{ | ||
| 673 | .llvm_name = null, | ||
| 674 | .description = "SPIR-V extension SPV_NVX_multiview_per_view_attributes", | ||
| 675 | .dependencies = featureSet(&[_]Feature{}), | ||
| 676 | }; | ||
| 677 | result[@enumToInt(Feature.SPV_NV_ray_tracing)] = .{ | ||
| 678 | .llvm_name = null, | ||
| 679 | .description = "SPIR-V extension SPV_NV_ray_tracing", | ||
| 680 | .dependencies = featureSet(&[_]Feature{}), | ||
| 681 | }; | ||
| 682 | result[@enumToInt(Feature.SPV_NV_shader_image_footprint)] = .{ | ||
| 683 | .llvm_name = null, | ||
| 684 | .description = "SPIR-V extension SPV_NV_shader_image_footprint", | ||
| 685 | .dependencies = featureSet(&[_]Feature{}), | ||
| 686 | }; | ||
| 687 | result[@enumToInt(Feature.SPV_NV_shading_rate)] = .{ | ||
| 688 | .llvm_name = null, | ||
| 689 | .description = "SPIR-V extension SPV_NV_shading_rate", | ||
| 690 | .dependencies = featureSet(&[_]Feature{}), | ||
| 691 | }; | ||
| 692 | result[@enumToInt(Feature.SPV_NV_stereo_view_rendering)] = .{ | ||
| 693 | .llvm_name = null, | ||
| 694 | .description = "SPIR-V extension SPV_NV_stereo_view_rendering", | ||
| 695 | .dependencies = featureSet(&[_]Feature{}), | ||
| 696 | }; | ||
| 697 | result[@enumToInt(Feature.SPV_NV_compute_shader_derivatives)] = .{ | ||
| 698 | .llvm_name = null, | ||
| 699 | .description = "SPIR-V extension SPV_NV_compute_shader_derivatives", | ||
| 700 | .dependencies = featureSet(&[_]Feature{}), | ||
| 701 | }; | ||
| 702 | result[@enumToInt(Feature.SPV_NV_shader_sm_builtins)] = .{ | ||
| 703 | .llvm_name = null, | ||
| 704 | .description = "SPIR-V extension SPV_NV_shader_sm_builtins", | ||
| 705 | .dependencies = featureSet(&[_]Feature{}), | ||
| 706 | }; | ||
| 707 | result[@enumToInt(Feature.SPV_NV_mesh_shader)] = .{ | ||
| 708 | .llvm_name = null, | ||
| 709 | .description = "SPIR-V extension SPV_NV_mesh_shader", | ||
| 710 | .dependencies = featureSet(&[_]Feature{}), | ||
| 711 | }; | ||
| 712 | result[@enumToInt(Feature.SPV_NV_geometry_shader_passthrough)] = .{ | ||
| 713 | .llvm_name = null, | ||
| 714 | .description = "SPIR-V extension SPV_NV_geometry_shader_passthrough", | ||
| 715 | .dependencies = featureSet(&[_]Feature{}), | ||
| 716 | }; | ||
| 717 | result[@enumToInt(Feature.SPV_NV_fragment_shader_barycentric)] = .{ | ||
| 718 | .llvm_name = null, | ||
| 719 | .description = "SPIR-V extension SPV_NV_fragment_shader_barycentric", | ||
| 720 | .dependencies = featureSet(&[_]Feature{}), | ||
| 721 | }; | ||
| 722 | result[@enumToInt(Feature.SPV_NV_cooperative_matrix)] = .{ | ||
| 723 | .llvm_name = null, | ||
| 724 | .description = "SPIR-V extension SPV_NV_cooperative_matrix", | ||
| 725 | .dependencies = featureSet(&[_]Feature{}), | ||
| 726 | }; | ||
| 727 | result[@enumToInt(Feature.SPV_NV_sample_mask_override_coverage)] = .{ | ||
| 728 | .llvm_name = null, | ||
| 729 | .description = "SPIR-V extension SPV_NV_sample_mask_override_coverage", | ||
| 730 | .dependencies = featureSet(&[_]Feature{}), | ||
| 731 | }; | ||
| 732 | result[@enumToInt(Feature.Matrix)] = .{ | ||
| 733 | .llvm_name = null, | ||
| 734 | .description = "Enable SPIR-V capability Matrix", | ||
| 735 | .dependencies = featureSet(&[_]Feature{ | ||
| 736 | }), | ||
| 737 | }; | ||
| 738 | result[@enumToInt(Feature.Shader)] = .{ | ||
| 739 | .llvm_name = null, | ||
| 740 | .description = "Enable SPIR-V capability Shader", | ||
| 741 | .dependencies = featureSet(&[_]Feature{ | ||
| 742 | .Matrix, | ||
| 743 | }), | ||
| 744 | }; | ||
| 745 | result[@enumToInt(Feature.Geometry)] = .{ | ||
| 746 | .llvm_name = null, | ||
| 747 | .description = "Enable SPIR-V capability Geometry", | ||
| 748 | .dependencies = featureSet(&[_]Feature{ | ||
| 749 | .Shader, | ||
| 750 | }), | ||
| 751 | }; | ||
| 752 | result[@enumToInt(Feature.Tessellation)] = .{ | ||
| 753 | .llvm_name = null, | ||
| 754 | .description = "Enable SPIR-V capability Tessellation", | ||
| 755 | .dependencies = featureSet(&[_]Feature{ | ||
| 756 | .Shader, | ||
| 757 | }), | ||
| 758 | }; | ||
| 759 | result[@enumToInt(Feature.Addresses)] = .{ | ||
| 760 | .llvm_name = null, | ||
| 761 | .description = "Enable SPIR-V capability Addresses", | ||
| 762 | .dependencies = featureSet(&[_]Feature{ | ||
| 763 | }), | ||
| 764 | }; | ||
| 765 | result[@enumToInt(Feature.Linkage)] = .{ | ||
| 766 | .llvm_name = null, | ||
| 767 | .description = "Enable SPIR-V capability Linkage", | ||
| 768 | .dependencies = featureSet(&[_]Feature{ | ||
| 769 | }), | ||
| 770 | }; | ||
| 771 | result[@enumToInt(Feature.Kernel)] = .{ | ||
| 772 | .llvm_name = null, | ||
| 773 | .description = "Enable SPIR-V capability Kernel", | ||
| 774 | .dependencies = featureSet(&[_]Feature{ | ||
| 775 | }), | ||
| 776 | }; | ||
| 777 | result[@enumToInt(Feature.Vector16)] = .{ | ||
| 778 | .llvm_name = null, | ||
| 779 | .description = "Enable SPIR-V capability Vector16", | ||
| 780 | .dependencies = featureSet(&[_]Feature{ | ||
| 781 | .Kernel, | ||
| 782 | }), | ||
| 783 | }; | ||
| 784 | result[@enumToInt(Feature.Float16Buffer)] = .{ | ||
| 785 | .llvm_name = null, | ||
| 786 | .description = "Enable SPIR-V capability Float16Buffer", | ||
| 787 | .dependencies = featureSet(&[_]Feature{ | ||
| 788 | .Kernel, | ||
| 789 | }), | ||
| 790 | }; | ||
| 791 | result[@enumToInt(Feature.Float16)] = .{ | ||
| 792 | .llvm_name = null, | ||
| 793 | .description = "Enable SPIR-V capability Float16", | ||
| 794 | .dependencies = featureSet(&[_]Feature{ | ||
| 795 | }), | ||
| 796 | }; | ||
| 797 | result[@enumToInt(Feature.Float64)] = .{ | ||
| 798 | .llvm_name = null, | ||
| 799 | .description = "Enable SPIR-V capability Float64", | ||
| 800 | .dependencies = featureSet(&[_]Feature{ | ||
| 801 | }), | ||
| 802 | }; | ||
| 803 | result[@enumToInt(Feature.Int64)] = .{ | ||
| 804 | .llvm_name = null, | ||
| 805 | .description = "Enable SPIR-V capability Int64", | ||
| 806 | .dependencies = featureSet(&[_]Feature{ | ||
| 807 | }), | ||
| 808 | }; | ||
| 809 | result[@enumToInt(Feature.Int64Atomics)] = .{ | ||
| 810 | .llvm_name = null, | ||
| 811 | .description = "Enable SPIR-V capability Int64Atomics", | ||
| 812 | .dependencies = featureSet(&[_]Feature{ | ||
| 813 | .Int64, | ||
| 814 | }), | ||
| 815 | }; | ||
| 816 | result[@enumToInt(Feature.ImageBasic)] = .{ | ||
| 817 | .llvm_name = null, | ||
| 818 | .description = "Enable SPIR-V capability ImageBasic", | ||
| 819 | .dependencies = featureSet(&[_]Feature{ | ||
| 820 | .Kernel, | ||
| 821 | }), | ||
| 822 | }; | ||
| 823 | result[@enumToInt(Feature.ImageReadWrite)] = .{ | ||
| 824 | .llvm_name = null, | ||
| 825 | .description = "Enable SPIR-V capability ImageReadWrite", | ||
| 826 | .dependencies = featureSet(&[_]Feature{ | ||
| 827 | .ImageBasic, | ||
| 828 | }), | ||
| 829 | }; | ||
| 830 | result[@enumToInt(Feature.ImageMipmap)] = .{ | ||
| 831 | .llvm_name = null, | ||
| 832 | .description = "Enable SPIR-V capability ImageMipmap", | ||
| 833 | .dependencies = featureSet(&[_]Feature{ | ||
| 834 | .ImageBasic, | ||
| 835 | }), | ||
| 836 | }; | ||
| 837 | result[@enumToInt(Feature.Pipes)] = .{ | ||
| 838 | .llvm_name = null, | ||
| 839 | .description = "Enable SPIR-V capability Pipes", | ||
| 840 | .dependencies = featureSet(&[_]Feature{ | ||
| 841 | .Kernel, | ||
| 842 | }), | ||
| 843 | }; | ||
| 844 | result[@enumToInt(Feature.Groups)] = .{ | ||
| 845 | .llvm_name = null, | ||
| 846 | .description = "Enable SPIR-V capability Groups", | ||
| 847 | .dependencies = featureSet(&[_]Feature{ | ||
| 848 | }), | ||
| 849 | }; | ||
| 850 | result[@enumToInt(Feature.DeviceEnqueue)] = .{ | ||
| 851 | .llvm_name = null, | ||
| 852 | .description = "Enable SPIR-V capability DeviceEnqueue", | ||
| 853 | .dependencies = featureSet(&[_]Feature{ | ||
| 854 | .Kernel, | ||
| 855 | }), | ||
| 856 | }; | ||
| 857 | result[@enumToInt(Feature.LiteralSampler)] = .{ | ||
| 858 | .llvm_name = null, | ||
| 859 | .description = "Enable SPIR-V capability LiteralSampler", | ||
| 860 | .dependencies = featureSet(&[_]Feature{ | ||
| 861 | .Kernel, | ||
| 862 | }), | ||
| 863 | }; | ||
| 864 | result[@enumToInt(Feature.AtomicStorage)] = .{ | ||
| 865 | .llvm_name = null, | ||
| 866 | .description = "Enable SPIR-V capability AtomicStorage", | ||
| 867 | .dependencies = featureSet(&[_]Feature{ | ||
| 868 | .Shader, | ||
| 869 | }), | ||
| 870 | }; | ||
| 871 | result[@enumToInt(Feature.Int16)] = .{ | ||
| 872 | .llvm_name = null, | ||
| 873 | .description = "Enable SPIR-V capability Int16", | ||
| 874 | .dependencies = featureSet(&[_]Feature{ | ||
| 875 | }), | ||
| 876 | }; | ||
| 877 | result[@enumToInt(Feature.TessellationPointSize)] = .{ | ||
| 878 | .llvm_name = null, | ||
| 879 | .description = "Enable SPIR-V capability TessellationPointSize", | ||
| 880 | .dependencies = featureSet(&[_]Feature{ | ||
| 881 | .Tessellation, | ||
| 882 | }), | ||
| 883 | }; | ||
| 884 | result[@enumToInt(Feature.GeometryPointSize)] = .{ | ||
| 885 | .llvm_name = null, | ||
| 886 | .description = "Enable SPIR-V capability GeometryPointSize", | ||
| 887 | .dependencies = featureSet(&[_]Feature{ | ||
| 888 | .Geometry, | ||
| 889 | }), | ||
| 890 | }; | ||
| 891 | result[@enumToInt(Feature.ImageGatherExtended)] = .{ | ||
| 892 | .llvm_name = null, | ||
| 893 | .description = "Enable SPIR-V capability ImageGatherExtended", | ||
| 894 | .dependencies = featureSet(&[_]Feature{ | ||
| 895 | .Shader, | ||
| 896 | }), | ||
| 897 | }; | ||
| 898 | result[@enumToInt(Feature.StorageImageMultisample)] = .{ | ||
| 899 | .llvm_name = null, | ||
| 900 | .description = "Enable SPIR-V capability StorageImageMultisample", | ||
| 901 | .dependencies = featureSet(&[_]Feature{ | ||
| 902 | .Shader, | ||
| 903 | }), | ||
| 904 | }; | ||
| 905 | result[@enumToInt(Feature.UniformBufferArrayDynamicIndexing)] = .{ | ||
| 906 | .llvm_name = null, | ||
| 907 | .description = "Enable SPIR-V capability UniformBufferArrayDynamicIndexing", | ||
| 908 | .dependencies = featureSet(&[_]Feature{ | ||
| 909 | .Shader, | ||
| 910 | }), | ||
| 911 | }; | ||
| 912 | result[@enumToInt(Feature.SampledImageArrayDynamicIndexing)] = .{ | ||
| 913 | .llvm_name = null, | ||
| 914 | .description = "Enable SPIR-V capability SampledImageArrayDynamicIndexing", | ||
| 915 | .dependencies = featureSet(&[_]Feature{ | ||
| 916 | .Shader, | ||
| 917 | }), | ||
| 918 | }; | ||
| 919 | result[@enumToInt(Feature.StorageBufferArrayDynamicIndexing)] = .{ | ||
| 920 | .llvm_name = null, | ||
| 921 | .description = "Enable SPIR-V capability StorageBufferArrayDynamicIndexing", | ||
| 922 | .dependencies = featureSet(&[_]Feature{ | ||
| 923 | .Shader, | ||
| 924 | }), | ||
| 925 | }; | ||
| 926 | result[@enumToInt(Feature.StorageImageArrayDynamicIndexing)] = .{ | ||
| 927 | .llvm_name = null, | ||
| 928 | .description = "Enable SPIR-V capability StorageImageArrayDynamicIndexing", | ||
| 929 | .dependencies = featureSet(&[_]Feature{ | ||
| 930 | .Shader, | ||
| 931 | }), | ||
| 932 | }; | ||
| 933 | result[@enumToInt(Feature.ClipDistance)] = .{ | ||
| 934 | .llvm_name = null, | ||
| 935 | .description = "Enable SPIR-V capability ClipDistance", | ||
| 936 | .dependencies = featureSet(&[_]Feature{ | ||
| 937 | .Shader, | ||
| 938 | }), | ||
| 939 | }; | ||
| 940 | result[@enumToInt(Feature.CullDistance)] = .{ | ||
| 941 | .llvm_name = null, | ||
| 942 | .description = "Enable SPIR-V capability CullDistance", | ||
| 943 | .dependencies = featureSet(&[_]Feature{ | ||
| 944 | .Shader, | ||
| 945 | }), | ||
| 946 | }; | ||
| 947 | result[@enumToInt(Feature.ImageCubeArray)] = .{ | ||
| 948 | .llvm_name = null, | ||
| 949 | .description = "Enable SPIR-V capability ImageCubeArray", | ||
| 950 | .dependencies = featureSet(&[_]Feature{ | ||
| 951 | .SampledCubeArray, | ||
| 952 | }), | ||
| 953 | }; | ||
| 954 | result[@enumToInt(Feature.SampleRateShading)] = .{ | ||
| 955 | .llvm_name = null, | ||
| 956 | .description = "Enable SPIR-V capability SampleRateShading", | ||
| 957 | .dependencies = featureSet(&[_]Feature{ | ||
| 958 | .Shader, | ||
| 959 | }), | ||
| 960 | }; | ||
| 961 | result[@enumToInt(Feature.ImageRect)] = .{ | ||
| 962 | .llvm_name = null, | ||
| 963 | .description = "Enable SPIR-V capability ImageRect", | ||
| 964 | .dependencies = featureSet(&[_]Feature{ | ||
| 965 | .SampledRect, | ||
| 966 | }), | ||
| 967 | }; | ||
| 968 | result[@enumToInt(Feature.SampledRect)] = .{ | ||
| 969 | .llvm_name = null, | ||
| 970 | .description = "Enable SPIR-V capability SampledRect", | ||
| 971 | .dependencies = featureSet(&[_]Feature{ | ||
| 972 | .Shader, | ||
| 973 | }), | ||
| 974 | }; | ||
| 975 | result[@enumToInt(Feature.GenericPointer)] = .{ | ||
| 976 | .llvm_name = null, | ||
| 977 | .description = "Enable SPIR-V capability GenericPointer", | ||
| 978 | .dependencies = featureSet(&[_]Feature{ | ||
| 979 | .Addresses, | ||
| 980 | }), | ||
| 981 | }; | ||
| 982 | result[@enumToInt(Feature.Int8)] = .{ | ||
| 983 | .llvm_name = null, | ||
| 984 | .description = "Enable SPIR-V capability Int8", | ||
| 985 | .dependencies = featureSet(&[_]Feature{ | ||
| 986 | }), | ||
| 987 | }; | ||
| 988 | result[@enumToInt(Feature.InputAttachment)] = .{ | ||
| 989 | .llvm_name = null, | ||
| 990 | .description = "Enable SPIR-V capability InputAttachment", | ||
| 991 | .dependencies = featureSet(&[_]Feature{ | ||
| 992 | .Shader, | ||
| 993 | }), | ||
| 994 | }; | ||
| 995 | result[@enumToInt(Feature.SparseResidency)] = .{ | ||
| 996 | .llvm_name = null, | ||
| 997 | .description = "Enable SPIR-V capability SparseResidency", | ||
| 998 | .dependencies = featureSet(&[_]Feature{ | ||
| 999 | .Shader, | ||
| 1000 | }), | ||
| 1001 | }; | ||
| 1002 | result[@enumToInt(Feature.MinLod)] = .{ | ||
| 1003 | .llvm_name = null, | ||
| 1004 | .description = "Enable SPIR-V capability MinLod", | ||
| 1005 | .dependencies = featureSet(&[_]Feature{ | ||
| 1006 | .Shader, | ||
| 1007 | }), | ||
| 1008 | }; | ||
| 1009 | result[@enumToInt(Feature.Sampled1D)] = .{ | ||
| 1010 | .llvm_name = null, | ||
| 1011 | .description = "Enable SPIR-V capability Sampled1D", | ||
| 1012 | .dependencies = featureSet(&[_]Feature{ | ||
| 1013 | }), | ||
| 1014 | }; | ||
| 1015 | result[@enumToInt(Feature.Image1D)] = .{ | ||
| 1016 | .llvm_name = null, | ||
| 1017 | .description = "Enable SPIR-V capability Image1D", | ||
| 1018 | .dependencies = featureSet(&[_]Feature{ | ||
| 1019 | .Sampled1D, | ||
| 1020 | }), | ||
| 1021 | }; | ||
| 1022 | result[@enumToInt(Feature.SampledCubeArray)] = .{ | ||
| 1023 | .llvm_name = null, | ||
| 1024 | .description = "Enable SPIR-V capability SampledCubeArray", | ||
| 1025 | .dependencies = featureSet(&[_]Feature{ | ||
| 1026 | .Shader, | ||
| 1027 | }), | ||
| 1028 | }; | ||
| 1029 | result[@enumToInt(Feature.SampledBuffer)] = .{ | ||
| 1030 | .llvm_name = null, | ||
| 1031 | .description = "Enable SPIR-V capability SampledBuffer", | ||
| 1032 | .dependencies = featureSet(&[_]Feature{ | ||
| 1033 | }), | ||
| 1034 | }; | ||
| 1035 | result[@enumToInt(Feature.ImageBuffer)] = .{ | ||
| 1036 | .llvm_name = null, | ||
| 1037 | .description = "Enable SPIR-V capability ImageBuffer", | ||
| 1038 | .dependencies = featureSet(&[_]Feature{ | ||
| 1039 | .SampledBuffer, | ||
| 1040 | }), | ||
| 1041 | }; | ||
| 1042 | result[@enumToInt(Feature.ImageMSArray)] = .{ | ||
| 1043 | .llvm_name = null, | ||
| 1044 | .description = "Enable SPIR-V capability ImageMSArray", | ||
| 1045 | .dependencies = featureSet(&[_]Feature{ | ||
| 1046 | .Shader, | ||
| 1047 | }), | ||
| 1048 | }; | ||
| 1049 | result[@enumToInt(Feature.StorageImageExtendedFormats)] = .{ | ||
| 1050 | .llvm_name = null, | ||
| 1051 | .description = "Enable SPIR-V capability StorageImageExtendedFormats", | ||
| 1052 | .dependencies = featureSet(&[_]Feature{ | ||
| 1053 | .Shader, | ||
| 1054 | }), | ||
| 1055 | }; | ||
| 1056 | result[@enumToInt(Feature.ImageQuery)] = .{ | ||
| 1057 | .llvm_name = null, | ||
| 1058 | .description = "Enable SPIR-V capability ImageQuery", | ||
| 1059 | .dependencies = featureSet(&[_]Feature{ | ||
| 1060 | .Shader, | ||
| 1061 | }), | ||
| 1062 | }; | ||
| 1063 | result[@enumToInt(Feature.DerivativeControl)] = .{ | ||
| 1064 | .llvm_name = null, | ||
| 1065 | .description = "Enable SPIR-V capability DerivativeControl", | ||
| 1066 | .dependencies = featureSet(&[_]Feature{ | ||
| 1067 | .Shader, | ||
| 1068 | }), | ||
| 1069 | }; | ||
| 1070 | result[@enumToInt(Feature.InterpolationFunction)] = .{ | ||
| 1071 | .llvm_name = null, | ||
| 1072 | .description = "Enable SPIR-V capability InterpolationFunction", | ||
| 1073 | .dependencies = featureSet(&[_]Feature{ | ||
| 1074 | .Shader, | ||
| 1075 | }), | ||
| 1076 | }; | ||
| 1077 | result[@enumToInt(Feature.TransformFeedback)] = .{ | ||
| 1078 | .llvm_name = null, | ||
| 1079 | .description = "Enable SPIR-V capability TransformFeedback", | ||
| 1080 | .dependencies = featureSet(&[_]Feature{ | ||
| 1081 | .Shader, | ||
| 1082 | }), | ||
| 1083 | }; | ||
| 1084 | result[@enumToInt(Feature.GeometryStreams)] = .{ | ||
| 1085 | .llvm_name = null, | ||
| 1086 | .description = "Enable SPIR-V capability GeometryStreams", | ||
| 1087 | .dependencies = featureSet(&[_]Feature{ | ||
| 1088 | .Geometry, | ||
| 1089 | }), | ||
| 1090 | }; | ||
| 1091 | result[@enumToInt(Feature.StorageImageReadWithoutFormat)] = .{ | ||
| 1092 | .llvm_name = null, | ||
| 1093 | .description = "Enable SPIR-V capability StorageImageReadWithoutFormat", | ||
| 1094 | .dependencies = featureSet(&[_]Feature{ | ||
| 1095 | .Shader, | ||
| 1096 | }), | ||
| 1097 | }; | ||
| 1098 | result[@enumToInt(Feature.StorageImageWriteWithoutFormat)] = .{ | ||
| 1099 | .llvm_name = null, | ||
| 1100 | .description = "Enable SPIR-V capability StorageImageWriteWithoutFormat", | ||
| 1101 | .dependencies = featureSet(&[_]Feature{ | ||
| 1102 | .Shader, | ||
| 1103 | }), | ||
| 1104 | }; | ||
| 1105 | result[@enumToInt(Feature.MultiViewport)] = .{ | ||
| 1106 | .llvm_name = null, | ||
| 1107 | .description = "Enable SPIR-V capability MultiViewport", | ||
| 1108 | .dependencies = featureSet(&[_]Feature{ | ||
| 1109 | .Geometry, | ||
| 1110 | }), | ||
| 1111 | }; | ||
| 1112 | result[@enumToInt(Feature.SubgroupDispatch)] = .{ | ||
| 1113 | .llvm_name = null, | ||
| 1114 | .description = "Enable SPIR-V capability SubgroupDispatch", | ||
| 1115 | .dependencies = featureSet(&[_]Feature{ | ||
| 1116 | .v1_1, | ||
| 1117 | .DeviceEnqueue, | ||
| 1118 | }), | ||
| 1119 | }; | ||
| 1120 | result[@enumToInt(Feature.NamedBarrier)] = .{ | ||
| 1121 | .llvm_name = null, | ||
| 1122 | .description = "Enable SPIR-V capability NamedBarrier", | ||
| 1123 | .dependencies = featureSet(&[_]Feature{ | ||
| 1124 | .v1_1, | ||
| 1125 | .Kernel, | ||
| 1126 | }), | ||
| 1127 | }; | ||
| 1128 | result[@enumToInt(Feature.PipeStorage)] = .{ | ||
| 1129 | .llvm_name = null, | ||
| 1130 | .description = "Enable SPIR-V capability PipeStorage", | ||
| 1131 | .dependencies = featureSet(&[_]Feature{ | ||
| 1132 | .v1_1, | ||
| 1133 | .Pipes, | ||
| 1134 | }), | ||
| 1135 | }; | ||
| 1136 | result[@enumToInt(Feature.GroupNonUniform)] = .{ | ||
| 1137 | .llvm_name = null, | ||
| 1138 | .description = "Enable SPIR-V capability GroupNonUniform", | ||
| 1139 | .dependencies = featureSet(&[_]Feature{ | ||
| 1140 | .v1_3, | ||
| 1141 | }), | ||
| 1142 | }; | ||
| 1143 | result[@enumToInt(Feature.GroupNonUniformVote)] = .{ | ||
| 1144 | .llvm_name = null, | ||
| 1145 | .description = "Enable SPIR-V capability GroupNonUniformVote", | ||
| 1146 | .dependencies = featureSet(&[_]Feature{ | ||
| 1147 | .v1_3, | ||
| 1148 | .GroupNonUniform, | ||
| 1149 | }), | ||
| 1150 | }; | ||
| 1151 | result[@enumToInt(Feature.GroupNonUniformArithmetic)] = .{ | ||
| 1152 | .llvm_name = null, | ||
| 1153 | .description = "Enable SPIR-V capability GroupNonUniformArithmetic", | ||
| 1154 | .dependencies = featureSet(&[_]Feature{ | ||
| 1155 | .v1_3, | ||
| 1156 | .GroupNonUniform, | ||
| 1157 | }), | ||
| 1158 | }; | ||
| 1159 | result[@enumToInt(Feature.GroupNonUniformBallot)] = .{ | ||
| 1160 | .llvm_name = null, | ||
| 1161 | .description = "Enable SPIR-V capability GroupNonUniformBallot", | ||
| 1162 | .dependencies = featureSet(&[_]Feature{ | ||
| 1163 | .v1_3, | ||
| 1164 | .GroupNonUniform, | ||
| 1165 | }), | ||
| 1166 | }; | ||
| 1167 | result[@enumToInt(Feature.GroupNonUniformShuffle)] = .{ | ||
| 1168 | .llvm_name = null, | ||
| 1169 | .description = "Enable SPIR-V capability GroupNonUniformShuffle", | ||
| 1170 | .dependencies = featureSet(&[_]Feature{ | ||
| 1171 | .v1_3, | ||
| 1172 | .GroupNonUniform, | ||
| 1173 | }), | ||
| 1174 | }; | ||
| 1175 | result[@enumToInt(Feature.GroupNonUniformShuffleRelative)] = .{ | ||
| 1176 | .llvm_name = null, | ||
| 1177 | .description = "Enable SPIR-V capability GroupNonUniformShuffleRelative", | ||
| 1178 | .dependencies = featureSet(&[_]Feature{ | ||
| 1179 | .v1_3, | ||
| 1180 | .GroupNonUniform, | ||
| 1181 | }), | ||
| 1182 | }; | ||
| 1183 | result[@enumToInt(Feature.GroupNonUniformClustered)] = .{ | ||
| 1184 | .llvm_name = null, | ||
| 1185 | .description = "Enable SPIR-V capability GroupNonUniformClustered", | ||
| 1186 | .dependencies = featureSet(&[_]Feature{ | ||
| 1187 | .v1_3, | ||
| 1188 | .GroupNonUniform, | ||
| 1189 | }), | ||
| 1190 | }; | ||
| 1191 | result[@enumToInt(Feature.GroupNonUniformQuad)] = .{ | ||
| 1192 | .llvm_name = null, | ||
| 1193 | .description = "Enable SPIR-V capability GroupNonUniformQuad", | ||
| 1194 | .dependencies = featureSet(&[_]Feature{ | ||
| 1195 | .v1_3, | ||
| 1196 | .GroupNonUniform, | ||
| 1197 | }), | ||
| 1198 | }; | ||
| 1199 | result[@enumToInt(Feature.ShaderLayer)] = .{ | ||
| 1200 | .llvm_name = null, | ||
| 1201 | .description = "Enable SPIR-V capability ShaderLayer", | ||
| 1202 | .dependencies = featureSet(&[_]Feature{ | ||
| 1203 | .v1_5, | ||
| 1204 | }), | ||
| 1205 | }; | ||
| 1206 | result[@enumToInt(Feature.ShaderViewportIndex)] = .{ | ||
| 1207 | .llvm_name = null, | ||
| 1208 | .description = "Enable SPIR-V capability ShaderViewportIndex", | ||
| 1209 | .dependencies = featureSet(&[_]Feature{ | ||
| 1210 | .v1_5, | ||
| 1211 | }), | ||
| 1212 | }; | ||
| 1213 | result[@enumToInt(Feature.FragmentShadingRateKHR)] = .{ | ||
| 1214 | .llvm_name = null, | ||
| 1215 | .description = "Enable SPIR-V capability FragmentShadingRateKHR", | ||
| 1216 | .dependencies = featureSet(&[_]Feature{ | ||
| 1217 | .Shader, | ||
| 1218 | }), | ||
| 1219 | }; | ||
| 1220 | result[@enumToInt(Feature.SubgroupBallotKHR)] = .{ | ||
| 1221 | .llvm_name = null, | ||
| 1222 | .description = "Enable SPIR-V capability SubgroupBallotKHR", | ||
| 1223 | .dependencies = featureSet(&[_]Feature{ | ||
| 1224 | }), | ||
| 1225 | }; | ||
| 1226 | result[@enumToInt(Feature.DrawParameters)] = .{ | ||
| 1227 | .llvm_name = null, | ||
| 1228 | .description = "Enable SPIR-V capability DrawParameters", | ||
| 1229 | .dependencies = featureSet(&[_]Feature{ | ||
| 1230 | .v1_3, | ||
| 1231 | .Shader, | ||
| 1232 | }), | ||
| 1233 | }; | ||
| 1234 | result[@enumToInt(Feature.WorkgroupMemoryExplicitLayoutKHR)] = .{ | ||
| 1235 | .llvm_name = null, | ||
| 1236 | .description = "Enable SPIR-V capability WorkgroupMemoryExplicitLayoutKHR", | ||
| 1237 | .dependencies = featureSet(&[_]Feature{ | ||
| 1238 | .Shader, | ||
| 1239 | }), | ||
| 1240 | }; | ||
| 1241 | result[@enumToInt(Feature.WorkgroupMemoryExplicitLayout8BitAccessKHR)] = .{ | ||
| 1242 | .llvm_name = null, | ||
| 1243 | .description = "Enable SPIR-V capability WorkgroupMemoryExplicitLayout8BitAccessKHR", | ||
| 1244 | .dependencies = featureSet(&[_]Feature{ | ||
| 1245 | .WorkgroupMemoryExplicitLayoutKHR, | ||
| 1246 | }), | ||
| 1247 | }; | ||
| 1248 | result[@enumToInt(Feature.WorkgroupMemoryExplicitLayout16BitAccessKHR)] = .{ | ||
| 1249 | .llvm_name = null, | ||
| 1250 | .description = "Enable SPIR-V capability WorkgroupMemoryExplicitLayout16BitAccessKHR", | ||
| 1251 | .dependencies = featureSet(&[_]Feature{ | ||
| 1252 | .Shader, | ||
| 1253 | }), | ||
| 1254 | }; | ||
| 1255 | result[@enumToInt(Feature.SubgroupVoteKHR)] = .{ | ||
| 1256 | .llvm_name = null, | ||
| 1257 | .description = "Enable SPIR-V capability SubgroupVoteKHR", | ||
| 1258 | .dependencies = featureSet(&[_]Feature{ | ||
| 1259 | }), | ||
| 1260 | }; | ||
| 1261 | result[@enumToInt(Feature.StorageBuffer16BitAccess)] = .{ | ||
| 1262 | .llvm_name = null, | ||
| 1263 | .description = "Enable SPIR-V capability StorageBuffer16BitAccess", | ||
| 1264 | .dependencies = featureSet(&[_]Feature{ | ||
| 1265 | .v1_3, | ||
| 1266 | }), | ||
| 1267 | }; | ||
| 1268 | result[@enumToInt(Feature.StorageUniformBufferBlock16)] = .{ | ||
| 1269 | .llvm_name = null, | ||
| 1270 | .description = "Enable SPIR-V capability StorageUniformBufferBlock16", | ||
| 1271 | .dependencies = featureSet(&[_]Feature{ | ||
| 1272 | .v1_3, | ||
| 1273 | }), | ||
| 1274 | }; | ||
| 1275 | result[@enumToInt(Feature.UniformAndStorageBuffer16BitAccess)] = .{ | ||
| 1276 | .llvm_name = null, | ||
| 1277 | .description = "Enable SPIR-V capability UniformAndStorageBuffer16BitAccess", | ||
| 1278 | .dependencies = featureSet(&[_]Feature{ | ||
| 1279 | .v1_3, | ||
| 1280 | .StorageBuffer16BitAccess, | ||
| 1281 | .StorageUniformBufferBlock16, | ||
| 1282 | }), | ||
| 1283 | }; | ||
| 1284 | result[@enumToInt(Feature.StorageUniform16)] = .{ | ||
| 1285 | .llvm_name = null, | ||
| 1286 | .description = "Enable SPIR-V capability StorageUniform16", | ||
| 1287 | .dependencies = featureSet(&[_]Feature{ | ||
| 1288 | .v1_3, | ||
| 1289 | .StorageBuffer16BitAccess, | ||
| 1290 | .StorageUniformBufferBlock16, | ||
| 1291 | }), | ||
| 1292 | }; | ||
| 1293 | result[@enumToInt(Feature.StoragePushConstant16)] = .{ | ||
| 1294 | .llvm_name = null, | ||
| 1295 | .description = "Enable SPIR-V capability StoragePushConstant16", | ||
| 1296 | .dependencies = featureSet(&[_]Feature{ | ||
| 1297 | .v1_3, | ||
| 1298 | }), | ||
| 1299 | }; | ||
| 1300 | result[@enumToInt(Feature.StorageInputOutput16)] = .{ | ||
| 1301 | .llvm_name = null, | ||
| 1302 | .description = "Enable SPIR-V capability StorageInputOutput16", | ||
| 1303 | .dependencies = featureSet(&[_]Feature{ | ||
| 1304 | .v1_3, | ||
| 1305 | }), | ||
| 1306 | }; | ||
| 1307 | result[@enumToInt(Feature.DeviceGroup)] = .{ | ||
| 1308 | .llvm_name = null, | ||
| 1309 | .description = "Enable SPIR-V capability DeviceGroup", | ||
| 1310 | .dependencies = featureSet(&[_]Feature{ | ||
| 1311 | .v1_3, | ||
| 1312 | }), | ||
| 1313 | }; | ||
| 1314 | result[@enumToInt(Feature.MultiView)] = .{ | ||
| 1315 | .llvm_name = null, | ||
| 1316 | .description = "Enable SPIR-V capability MultiView", | ||
| 1317 | .dependencies = featureSet(&[_]Feature{ | ||
| 1318 | .v1_3, | ||
| 1319 | .Shader, | ||
| 1320 | }), | ||
| 1321 | }; | ||
| 1322 | result[@enumToInt(Feature.VariablePointersStorageBuffer)] = .{ | ||
| 1323 | .llvm_name = null, | ||
| 1324 | .description = "Enable SPIR-V capability VariablePointersStorageBuffer", | ||
| 1325 | .dependencies = featureSet(&[_]Feature{ | ||
| 1326 | .v1_3, | ||
| 1327 | .Shader, | ||
| 1328 | }), | ||
| 1329 | }; | ||
| 1330 | result[@enumToInt(Feature.VariablePointers)] = .{ | ||
| 1331 | .llvm_name = null, | ||
| 1332 | .description = "Enable SPIR-V capability VariablePointers", | ||
| 1333 | .dependencies = featureSet(&[_]Feature{ | ||
| 1334 | .v1_3, | ||
| 1335 | .VariablePointersStorageBuffer, | ||
| 1336 | }), | ||
| 1337 | }; | ||
| 1338 | result[@enumToInt(Feature.AtomicStorageOps)] = .{ | ||
| 1339 | .llvm_name = null, | ||
| 1340 | .description = "Enable SPIR-V capability AtomicStorageOps", | ||
| 1341 | .dependencies = featureSet(&[_]Feature{ | ||
| 1342 | }), | ||
| 1343 | }; | ||
| 1344 | result[@enumToInt(Feature.SampleMaskPostDepthCoverage)] = .{ | ||
| 1345 | .llvm_name = null, | ||
| 1346 | .description = "Enable SPIR-V capability SampleMaskPostDepthCoverage", | ||
| 1347 | .dependencies = featureSet(&[_]Feature{ | ||
| 1348 | }), | ||
| 1349 | }; | ||
| 1350 | result[@enumToInt(Feature.StorageBuffer8BitAccess)] = .{ | ||
| 1351 | .llvm_name = null, | ||
| 1352 | .description = "Enable SPIR-V capability StorageBuffer8BitAccess", | ||
| 1353 | .dependencies = featureSet(&[_]Feature{ | ||
| 1354 | .v1_5, | ||
| 1355 | }), | ||
| 1356 | }; | ||
| 1357 | result[@enumToInt(Feature.UniformAndStorageBuffer8BitAccess)] = .{ | ||
| 1358 | .llvm_name = null, | ||
| 1359 | .description = "Enable SPIR-V capability UniformAndStorageBuffer8BitAccess", | ||
| 1360 | .dependencies = featureSet(&[_]Feature{ | ||
| 1361 | .v1_5, | ||
| 1362 | .StorageBuffer8BitAccess, | ||
| 1363 | }), | ||
| 1364 | }; | ||
| 1365 | result[@enumToInt(Feature.StoragePushConstant8)] = .{ | ||
| 1366 | .llvm_name = null, | ||
| 1367 | .description = "Enable SPIR-V capability StoragePushConstant8", | ||
| 1368 | .dependencies = featureSet(&[_]Feature{ | ||
| 1369 | .v1_5, | ||
| 1370 | }), | ||
| 1371 | }; | ||
| 1372 | result[@enumToInt(Feature.DenormPreserve)] = .{ | ||
| 1373 | .llvm_name = null, | ||
| 1374 | .description = "Enable SPIR-V capability DenormPreserve", | ||
| 1375 | .dependencies = featureSet(&[_]Feature{ | ||
| 1376 | .v1_4, | ||
| 1377 | }), | ||
| 1378 | }; | ||
| 1379 | result[@enumToInt(Feature.DenormFlushToZero)] = .{ | ||
| 1380 | .llvm_name = null, | ||
| 1381 | .description = "Enable SPIR-V capability DenormFlushToZero", | ||
| 1382 | .dependencies = featureSet(&[_]Feature{ | ||
| 1383 | .v1_4, | ||
| 1384 | }), | ||
| 1385 | }; | ||
| 1386 | result[@enumToInt(Feature.SignedZeroInfNanPreserve)] = .{ | ||
| 1387 | .llvm_name = null, | ||
| 1388 | .description = "Enable SPIR-V capability SignedZeroInfNanPreserve", | ||
| 1389 | .dependencies = featureSet(&[_]Feature{ | ||
| 1390 | .v1_4, | ||
| 1391 | }), | ||
| 1392 | }; | ||
| 1393 | result[@enumToInt(Feature.RoundingModeRTE)] = .{ | ||
| 1394 | .llvm_name = null, | ||
| 1395 | .description = "Enable SPIR-V capability RoundingModeRTE", | ||
| 1396 | .dependencies = featureSet(&[_]Feature{ | ||
| 1397 | .v1_4, | ||
| 1398 | }), | ||
| 1399 | }; | ||
| 1400 | result[@enumToInt(Feature.RoundingModeRTZ)] = .{ | ||
| 1401 | .llvm_name = null, | ||
| 1402 | .description = "Enable SPIR-V capability RoundingModeRTZ", | ||
| 1403 | .dependencies = featureSet(&[_]Feature{ | ||
| 1404 | .v1_4, | ||
| 1405 | }), | ||
| 1406 | }; | ||
| 1407 | result[@enumToInt(Feature.RayQueryProvisionalKHR)] = .{ | ||
| 1408 | .llvm_name = null, | ||
| 1409 | .description = "Enable SPIR-V capability RayQueryProvisionalKHR", | ||
| 1410 | .dependencies = featureSet(&[_]Feature{ | ||
| 1411 | .Shader, | ||
| 1412 | }), | ||
| 1413 | }; | ||
| 1414 | result[@enumToInt(Feature.RayQueryKHR)] = .{ | ||
| 1415 | .llvm_name = null, | ||
| 1416 | .description = "Enable SPIR-V capability RayQueryKHR", | ||
| 1417 | .dependencies = featureSet(&[_]Feature{ | ||
| 1418 | .Shader, | ||
| 1419 | }), | ||
| 1420 | }; | ||
| 1421 | result[@enumToInt(Feature.RayTraversalPrimitiveCullingKHR)] = .{ | ||
| 1422 | .llvm_name = null, | ||
| 1423 | .description = "Enable SPIR-V capability RayTraversalPrimitiveCullingKHR", | ||
| 1424 | .dependencies = featureSet(&[_]Feature{ | ||
| 1425 | .RayQueryKHR, | ||
| 1426 | .RayTracingKHR, | ||
| 1427 | }), | ||
| 1428 | }; | ||
| 1429 | result[@enumToInt(Feature.RayTracingKHR)] = .{ | ||
| 1430 | .llvm_name = null, | ||
| 1431 | .description = "Enable SPIR-V capability RayTracingKHR", | ||
| 1432 | .dependencies = featureSet(&[_]Feature{ | ||
| 1433 | .Shader, | ||
| 1434 | }), | ||
| 1435 | }; | ||
| 1436 | result[@enumToInt(Feature.Float16ImageAMD)] = .{ | ||
| 1437 | .llvm_name = null, | ||
| 1438 | .description = "Enable SPIR-V capability Float16ImageAMD", | ||
| 1439 | .dependencies = featureSet(&[_]Feature{ | ||
| 1440 | .Shader, | ||
| 1441 | }), | ||
| 1442 | }; | ||
| 1443 | result[@enumToInt(Feature.ImageGatherBiasLodAMD)] = .{ | ||
| 1444 | .llvm_name = null, | ||
| 1445 | .description = "Enable SPIR-V capability ImageGatherBiasLodAMD", | ||
| 1446 | .dependencies = featureSet(&[_]Feature{ | ||
| 1447 | .Shader, | ||
| 1448 | }), | ||
| 1449 | }; | ||
| 1450 | result[@enumToInt(Feature.FragmentMaskAMD)] = .{ | ||
| 1451 | .llvm_name = null, | ||
| 1452 | .description = "Enable SPIR-V capability FragmentMaskAMD", | ||
| 1453 | .dependencies = featureSet(&[_]Feature{ | ||
| 1454 | .Shader, | ||
| 1455 | }), | ||
| 1456 | }; | ||
| 1457 | result[@enumToInt(Feature.StencilExportEXT)] = .{ | ||
| 1458 | .llvm_name = null, | ||
| 1459 | .description = "Enable SPIR-V capability StencilExportEXT", | ||
| 1460 | .dependencies = featureSet(&[_]Feature{ | ||
| 1461 | .Shader, | ||
| 1462 | }), | ||
| 1463 | }; | ||
| 1464 | result[@enumToInt(Feature.ImageReadWriteLodAMD)] = .{ | ||
| 1465 | .llvm_name = null, | ||
| 1466 | .description = "Enable SPIR-V capability ImageReadWriteLodAMD", | ||
| 1467 | .dependencies = featureSet(&[_]Feature{ | ||
| 1468 | .Shader, | ||
| 1469 | }), | ||
| 1470 | }; | ||
| 1471 | result[@enumToInt(Feature.Int64ImageEXT)] = .{ | ||
| 1472 | .llvm_name = null, | ||
| 1473 | .description = "Enable SPIR-V capability Int64ImageEXT", | ||
| 1474 | .dependencies = featureSet(&[_]Feature{ | ||
| 1475 | .Shader, | ||
| 1476 | }), | ||
| 1477 | }; | ||
| 1478 | result[@enumToInt(Feature.ShaderClockKHR)] = .{ | ||
| 1479 | .llvm_name = null, | ||
| 1480 | .description = "Enable SPIR-V capability ShaderClockKHR", | ||
| 1481 | .dependencies = featureSet(&[_]Feature{ | ||
| 1482 | .Shader, | ||
| 1483 | }), | ||
| 1484 | }; | ||
| 1485 | result[@enumToInt(Feature.SampleMaskOverrideCoverageNV)] = .{ | ||
| 1486 | .llvm_name = null, | ||
| 1487 | .description = "Enable SPIR-V capability SampleMaskOverrideCoverageNV", | ||
| 1488 | .dependencies = featureSet(&[_]Feature{ | ||
| 1489 | .SampleRateShading, | ||
| 1490 | }), | ||
| 1491 | }; | ||
| 1492 | result[@enumToInt(Feature.GeometryShaderPassthroughNV)] = .{ | ||
| 1493 | .llvm_name = null, | ||
| 1494 | .description = "Enable SPIR-V capability GeometryShaderPassthroughNV", | ||
| 1495 | .dependencies = featureSet(&[_]Feature{ | ||
| 1496 | .Geometry, | ||
| 1497 | }), | ||
| 1498 | }; | ||
| 1499 | result[@enumToInt(Feature.ShaderViewportIndexLayerEXT)] = .{ | ||
| 1500 | .llvm_name = null, | ||
| 1501 | .description = "Enable SPIR-V capability ShaderViewportIndexLayerEXT", | ||
| 1502 | .dependencies = featureSet(&[_]Feature{ | ||
| 1503 | .MultiViewport, | ||
| 1504 | }), | ||
| 1505 | }; | ||
| 1506 | result[@enumToInt(Feature.ShaderViewportIndexLayerNV)] = .{ | ||
| 1507 | .llvm_name = null, | ||
| 1508 | .description = "Enable SPIR-V capability ShaderViewportIndexLayerNV", | ||
| 1509 | .dependencies = featureSet(&[_]Feature{ | ||
| 1510 | .MultiViewport, | ||
| 1511 | }), | ||
| 1512 | }; | ||
| 1513 | result[@enumToInt(Feature.ShaderViewportMaskNV)] = .{ | ||
| 1514 | .llvm_name = null, | ||
| 1515 | .description = "Enable SPIR-V capability ShaderViewportMaskNV", | ||
| 1516 | .dependencies = featureSet(&[_]Feature{ | ||
| 1517 | .ShaderViewportIndexLayerNV, | ||
| 1518 | }), | ||
| 1519 | }; | ||
| 1520 | result[@enumToInt(Feature.ShaderStereoViewNV)] = .{ | ||
| 1521 | .llvm_name = null, | ||
| 1522 | .description = "Enable SPIR-V capability ShaderStereoViewNV", | ||
| 1523 | .dependencies = featureSet(&[_]Feature{ | ||
| 1524 | .ShaderViewportMaskNV, | ||
| 1525 | }), | ||
| 1526 | }; | ||
| 1527 | result[@enumToInt(Feature.PerViewAttributesNV)] = .{ | ||
| 1528 | .llvm_name = null, | ||
| 1529 | .description = "Enable SPIR-V capability PerViewAttributesNV", | ||
| 1530 | .dependencies = featureSet(&[_]Feature{ | ||
| 1531 | .MultiView, | ||
| 1532 | }), | ||
| 1533 | }; | ||
| 1534 | result[@enumToInt(Feature.FragmentFullyCoveredEXT)] = .{ | ||
| 1535 | .llvm_name = null, | ||
| 1536 | .description = "Enable SPIR-V capability FragmentFullyCoveredEXT", | ||
| 1537 | .dependencies = featureSet(&[_]Feature{ | ||
| 1538 | .Shader, | ||
| 1539 | }), | ||
| 1540 | }; | ||
| 1541 | result[@enumToInt(Feature.MeshShadingNV)] = .{ | ||
| 1542 | .llvm_name = null, | ||
| 1543 | .description = "Enable SPIR-V capability MeshShadingNV", | ||
| 1544 | .dependencies = featureSet(&[_]Feature{ | ||
| 1545 | .Shader, | ||
| 1546 | }), | ||
| 1547 | }; | ||
| 1548 | result[@enumToInt(Feature.ImageFootprintNV)] = .{ | ||
| 1549 | .llvm_name = null, | ||
| 1550 | .description = "Enable SPIR-V capability ImageFootprintNV", | ||
| 1551 | .dependencies = featureSet(&[_]Feature{ | ||
| 1552 | }), | ||
| 1553 | }; | ||
| 1554 | result[@enumToInt(Feature.FragmentBarycentricNV)] = .{ | ||
| 1555 | .llvm_name = null, | ||
| 1556 | .description = "Enable SPIR-V capability FragmentBarycentricNV", | ||
| 1557 | .dependencies = featureSet(&[_]Feature{ | ||
| 1558 | }), | ||
| 1559 | }; | ||
| 1560 | result[@enumToInt(Feature.ComputeDerivativeGroupQuadsNV)] = .{ | ||
| 1561 | .llvm_name = null, | ||
| 1562 | .description = "Enable SPIR-V capability ComputeDerivativeGroupQuadsNV", | ||
| 1563 | .dependencies = featureSet(&[_]Feature{ | ||
| 1564 | }), | ||
| 1565 | }; | ||
| 1566 | result[@enumToInt(Feature.FragmentDensityEXT)] = .{ | ||
| 1567 | .llvm_name = null, | ||
| 1568 | .description = "Enable SPIR-V capability FragmentDensityEXT", | ||
| 1569 | .dependencies = featureSet(&[_]Feature{ | ||
| 1570 | .Shader, | ||
| 1571 | }), | ||
| 1572 | }; | ||
| 1573 | result[@enumToInt(Feature.ShadingRateNV)] = .{ | ||
| 1574 | .llvm_name = null, | ||
| 1575 | .description = "Enable SPIR-V capability ShadingRateNV", | ||
| 1576 | .dependencies = featureSet(&[_]Feature{ | ||
| 1577 | .Shader, | ||
| 1578 | }), | ||
| 1579 | }; | ||
| 1580 | result[@enumToInt(Feature.GroupNonUniformPartitionedNV)] = .{ | ||
| 1581 | .llvm_name = null, | ||
| 1582 | .description = "Enable SPIR-V capability GroupNonUniformPartitionedNV", | ||
| 1583 | .dependencies = featureSet(&[_]Feature{ | ||
| 1584 | }), | ||
| 1585 | }; | ||
| 1586 | result[@enumToInt(Feature.ShaderNonUniform)] = .{ | ||
| 1587 | .llvm_name = null, | ||
| 1588 | .description = "Enable SPIR-V capability ShaderNonUniform", | ||
| 1589 | .dependencies = featureSet(&[_]Feature{ | ||
| 1590 | .v1_5, | ||
| 1591 | .Shader, | ||
| 1592 | }), | ||
| 1593 | }; | ||
| 1594 | result[@enumToInt(Feature.ShaderNonUniformEXT)] = .{ | ||
| 1595 | .llvm_name = null, | ||
| 1596 | .description = "Enable SPIR-V capability ShaderNonUniformEXT", | ||
| 1597 | .dependencies = featureSet(&[_]Feature{ | ||
| 1598 | .v1_5, | ||
| 1599 | .Shader, | ||
| 1600 | }), | ||
| 1601 | }; | ||
| 1602 | result[@enumToInt(Feature.RuntimeDescriptorArray)] = .{ | ||
| 1603 | .llvm_name = null, | ||
| 1604 | .description = "Enable SPIR-V capability RuntimeDescriptorArray", | ||
| 1605 | .dependencies = featureSet(&[_]Feature{ | ||
| 1606 | .v1_5, | ||
| 1607 | .Shader, | ||
| 1608 | }), | ||
| 1609 | }; | ||
| 1610 | result[@enumToInt(Feature.RuntimeDescriptorArrayEXT)] = .{ | ||
| 1611 | .llvm_name = null, | ||
| 1612 | .description = "Enable SPIR-V capability RuntimeDescriptorArrayEXT", | ||
| 1613 | .dependencies = featureSet(&[_]Feature{ | ||
| 1614 | .v1_5, | ||
| 1615 | .Shader, | ||
| 1616 | }), | ||
| 1617 | }; | ||
| 1618 | result[@enumToInt(Feature.InputAttachmentArrayDynamicIndexing)] = .{ | ||
| 1619 | .llvm_name = null, | ||
| 1620 | .description = "Enable SPIR-V capability InputAttachmentArrayDynamicIndexing", | ||
| 1621 | .dependencies = featureSet(&[_]Feature{ | ||
| 1622 | .v1_5, | ||
| 1623 | .InputAttachment, | ||
| 1624 | }), | ||
| 1625 | }; | ||
| 1626 | result[@enumToInt(Feature.InputAttachmentArrayDynamicIndexingEXT)] = .{ | ||
| 1627 | .llvm_name = null, | ||
| 1628 | .description = "Enable SPIR-V capability InputAttachmentArrayDynamicIndexingEXT", | ||
| 1629 | .dependencies = featureSet(&[_]Feature{ | ||
| 1630 | .v1_5, | ||
| 1631 | .InputAttachment, | ||
| 1632 | }), | ||
| 1633 | }; | ||
| 1634 | result[@enumToInt(Feature.UniformTexelBufferArrayDynamicIndexing)] = .{ | ||
| 1635 | .llvm_name = null, | ||
| 1636 | .description = "Enable SPIR-V capability UniformTexelBufferArrayDynamicIndexing", | ||
| 1637 | .dependencies = featureSet(&[_]Feature{ | ||
| 1638 | .v1_5, | ||
| 1639 | .SampledBuffer, | ||
| 1640 | }), | ||
| 1641 | }; | ||
| 1642 | result[@enumToInt(Feature.UniformTexelBufferArrayDynamicIndexingEXT)] = .{ | ||
| 1643 | .llvm_name = null, | ||
| 1644 | .description = "Enable SPIR-V capability UniformTexelBufferArrayDynamicIndexingEXT", | ||
| 1645 | .dependencies = featureSet(&[_]Feature{ | ||
| 1646 | .v1_5, | ||
| 1647 | .SampledBuffer, | ||
| 1648 | }), | ||
| 1649 | }; | ||
| 1650 | result[@enumToInt(Feature.StorageTexelBufferArrayDynamicIndexing)] = .{ | ||
| 1651 | .llvm_name = null, | ||
| 1652 | .description = "Enable SPIR-V capability StorageTexelBufferArrayDynamicIndexing", | ||
| 1653 | .dependencies = featureSet(&[_]Feature{ | ||
| 1654 | .v1_5, | ||
| 1655 | .ImageBuffer, | ||
| 1656 | }), | ||
| 1657 | }; | ||
| 1658 | result[@enumToInt(Feature.StorageTexelBufferArrayDynamicIndexingEXT)] = .{ | ||
| 1659 | .llvm_name = null, | ||
| 1660 | .description = "Enable SPIR-V capability StorageTexelBufferArrayDynamicIndexingEXT", | ||
| 1661 | .dependencies = featureSet(&[_]Feature{ | ||
| 1662 | .v1_5, | ||
| 1663 | .ImageBuffer, | ||
| 1664 | }), | ||
| 1665 | }; | ||
| 1666 | result[@enumToInt(Feature.UniformBufferArrayNonUniformIndexing)] = .{ | ||
| 1667 | .llvm_name = null, | ||
| 1668 | .description = "Enable SPIR-V capability UniformBufferArrayNonUniformIndexing", | ||
| 1669 | .dependencies = featureSet(&[_]Feature{ | ||
| 1670 | .v1_5, | ||
| 1671 | .ShaderNonUniform, | ||
| 1672 | }), | ||
| 1673 | }; | ||
| 1674 | result[@enumToInt(Feature.UniformBufferArrayNonUniformIndexingEXT)] = .{ | ||
| 1675 | .llvm_name = null, | ||
| 1676 | .description = "Enable SPIR-V capability UniformBufferArrayNonUniformIndexingEXT", | ||
| 1677 | .dependencies = featureSet(&[_]Feature{ | ||
| 1678 | .v1_5, | ||
| 1679 | .ShaderNonUniform, | ||
| 1680 | }), | ||
| 1681 | }; | ||
| 1682 | result[@enumToInt(Feature.SampledImageArrayNonUniformIndexing)] = .{ | ||
| 1683 | .llvm_name = null, | ||
| 1684 | .description = "Enable SPIR-V capability SampledImageArrayNonUniformIndexing", | ||
| 1685 | .dependencies = featureSet(&[_]Feature{ | ||
| 1686 | .v1_5, | ||
| 1687 | .ShaderNonUniform, | ||
| 1688 | }), | ||
| 1689 | }; | ||
| 1690 | result[@enumToInt(Feature.SampledImageArrayNonUniformIndexingEXT)] = .{ | ||
| 1691 | .llvm_name = null, | ||
| 1692 | .description = "Enable SPIR-V capability SampledImageArrayNonUniformIndexingEXT", | ||
| 1693 | .dependencies = featureSet(&[_]Feature{ | ||
| 1694 | .v1_5, | ||
| 1695 | .ShaderNonUniform, | ||
| 1696 | }), | ||
| 1697 | }; | ||
| 1698 | result[@enumToInt(Feature.StorageBufferArrayNonUniformIndexing)] = .{ | ||
| 1699 | .llvm_name = null, | ||
| 1700 | .description = "Enable SPIR-V capability StorageBufferArrayNonUniformIndexing", | ||
| 1701 | .dependencies = featureSet(&[_]Feature{ | ||
| 1702 | .v1_5, | ||
| 1703 | .ShaderNonUniform, | ||
| 1704 | }), | ||
| 1705 | }; | ||
| 1706 | result[@enumToInt(Feature.StorageBufferArrayNonUniformIndexingEXT)] = .{ | ||
| 1707 | .llvm_name = null, | ||
| 1708 | .description = "Enable SPIR-V capability StorageBufferArrayNonUniformIndexingEXT", | ||
| 1709 | .dependencies = featureSet(&[_]Feature{ | ||
| 1710 | .v1_5, | ||
| 1711 | .ShaderNonUniform, | ||
| 1712 | }), | ||
| 1713 | }; | ||
| 1714 | result[@enumToInt(Feature.StorageImageArrayNonUniformIndexing)] = .{ | ||
| 1715 | .llvm_name = null, | ||
| 1716 | .description = "Enable SPIR-V capability StorageImageArrayNonUniformIndexing", | ||
| 1717 | .dependencies = featureSet(&[_]Feature{ | ||
| 1718 | .v1_5, | ||
| 1719 | .ShaderNonUniform, | ||
| 1720 | }), | ||
| 1721 | }; | ||
| 1722 | result[@enumToInt(Feature.StorageImageArrayNonUniformIndexingEXT)] = .{ | ||
| 1723 | .llvm_name = null, | ||
| 1724 | .description = "Enable SPIR-V capability StorageImageArrayNonUniformIndexingEXT", | ||
| 1725 | .dependencies = featureSet(&[_]Feature{ | ||
| 1726 | .v1_5, | ||
| 1727 | .ShaderNonUniform, | ||
| 1728 | }), | ||
| 1729 | }; | ||
| 1730 | result[@enumToInt(Feature.InputAttachmentArrayNonUniformIndexing)] = .{ | ||
| 1731 | .llvm_name = null, | ||
| 1732 | .description = "Enable SPIR-V capability InputAttachmentArrayNonUniformIndexing", | ||
| 1733 | .dependencies = featureSet(&[_]Feature{ | ||
| 1734 | .v1_5, | ||
| 1735 | .InputAttachment, | ||
| 1736 | .ShaderNonUniform, | ||
| 1737 | }), | ||
| 1738 | }; | ||
| 1739 | result[@enumToInt(Feature.InputAttachmentArrayNonUniformIndexingEXT)] = .{ | ||
| 1740 | .llvm_name = null, | ||
| 1741 | .description = "Enable SPIR-V capability InputAttachmentArrayNonUniformIndexingEXT", | ||
| 1742 | .dependencies = featureSet(&[_]Feature{ | ||
| 1743 | .v1_5, | ||
| 1744 | .InputAttachment, | ||
| 1745 | .ShaderNonUniform, | ||
| 1746 | }), | ||
| 1747 | }; | ||
| 1748 | result[@enumToInt(Feature.UniformTexelBufferArrayNonUniformIndexing)] = .{ | ||
| 1749 | .llvm_name = null, | ||
| 1750 | .description = "Enable SPIR-V capability UniformTexelBufferArrayNonUniformIndexing", | ||
| 1751 | .dependencies = featureSet(&[_]Feature{ | ||
| 1752 | .v1_5, | ||
| 1753 | .SampledBuffer, | ||
| 1754 | .ShaderNonUniform, | ||
| 1755 | }), | ||
| 1756 | }; | ||
| 1757 | result[@enumToInt(Feature.UniformTexelBufferArrayNonUniformIndexingEXT)] = .{ | ||
| 1758 | .llvm_name = null, | ||
| 1759 | .description = "Enable SPIR-V capability UniformTexelBufferArrayNonUniformIndexingEXT", | ||
| 1760 | .dependencies = featureSet(&[_]Feature{ | ||
| 1761 | .v1_5, | ||
| 1762 | .SampledBuffer, | ||
| 1763 | .ShaderNonUniform, | ||
| 1764 | }), | ||
| 1765 | }; | ||
| 1766 | result[@enumToInt(Feature.StorageTexelBufferArrayNonUniformIndexing)] = .{ | ||
| 1767 | .llvm_name = null, | ||
| 1768 | .description = "Enable SPIR-V capability StorageTexelBufferArrayNonUniformIndexing", | ||
| 1769 | .dependencies = featureSet(&[_]Feature{ | ||
| 1770 | .v1_5, | ||
| 1771 | .ImageBuffer, | ||
| 1772 | .ShaderNonUniform, | ||
| 1773 | }), | ||
| 1774 | }; | ||
| 1775 | result[@enumToInt(Feature.StorageTexelBufferArrayNonUniformIndexingEXT)] = .{ | ||
| 1776 | .llvm_name = null, | ||
| 1777 | .description = "Enable SPIR-V capability StorageTexelBufferArrayNonUniformIndexingEXT", | ||
| 1778 | .dependencies = featureSet(&[_]Feature{ | ||
| 1779 | .v1_5, | ||
| 1780 | .ImageBuffer, | ||
| 1781 | .ShaderNonUniform, | ||
| 1782 | }), | ||
| 1783 | }; | ||
| 1784 | result[@enumToInt(Feature.RayTracingNV)] = .{ | ||
| 1785 | .llvm_name = null, | ||
| 1786 | .description = "Enable SPIR-V capability RayTracingNV", | ||
| 1787 | .dependencies = featureSet(&[_]Feature{ | ||
| 1788 | .Shader, | ||
| 1789 | }), | ||
| 1790 | }; | ||
| 1791 | result[@enumToInt(Feature.VulkanMemoryModel)] = .{ | ||
| 1792 | .llvm_name = null, | ||
| 1793 | .description = "Enable SPIR-V capability VulkanMemoryModel", | ||
| 1794 | .dependencies = featureSet(&[_]Feature{ | ||
| 1795 | .v1_5, | ||
| 1796 | }), | ||
| 1797 | }; | ||
| 1798 | result[@enumToInt(Feature.VulkanMemoryModelKHR)] = .{ | ||
| 1799 | .llvm_name = null, | ||
| 1800 | .description = "Enable SPIR-V capability VulkanMemoryModelKHR", | ||
| 1801 | .dependencies = featureSet(&[_]Feature{ | ||
| 1802 | .v1_5, | ||
| 1803 | }), | ||
| 1804 | }; | ||
| 1805 | result[@enumToInt(Feature.VulkanMemoryModelDeviceScope)] = .{ | ||
| 1806 | .llvm_name = null, | ||
| 1807 | .description = "Enable SPIR-V capability VulkanMemoryModelDeviceScope", | ||
| 1808 | .dependencies = featureSet(&[_]Feature{ | ||
| 1809 | .v1_5, | ||
| 1810 | }), | ||
| 1811 | }; | ||
| 1812 | result[@enumToInt(Feature.VulkanMemoryModelDeviceScopeKHR)] = .{ | ||
| 1813 | .llvm_name = null, | ||
| 1814 | .description = "Enable SPIR-V capability VulkanMemoryModelDeviceScopeKHR", | ||
| 1815 | .dependencies = featureSet(&[_]Feature{ | ||
| 1816 | .v1_5, | ||
| 1817 | }), | ||
| 1818 | }; | ||
| 1819 | result[@enumToInt(Feature.PhysicalStorageBufferAddresses)] = .{ | ||
| 1820 | .llvm_name = null, | ||
| 1821 | .description = "Enable SPIR-V capability PhysicalStorageBufferAddresses", | ||
| 1822 | .dependencies = featureSet(&[_]Feature{ | ||
| 1823 | .v1_5, | ||
| 1824 | .Shader, | ||
| 1825 | }), | ||
| 1826 | }; | ||
| 1827 | result[@enumToInt(Feature.PhysicalStorageBufferAddressesEXT)] = .{ | ||
| 1828 | .llvm_name = null, | ||
| 1829 | .description = "Enable SPIR-V capability PhysicalStorageBufferAddressesEXT", | ||
| 1830 | .dependencies = featureSet(&[_]Feature{ | ||
| 1831 | .v1_5, | ||
| 1832 | .Shader, | ||
| 1833 | }), | ||
| 1834 | }; | ||
| 1835 | result[@enumToInt(Feature.ComputeDerivativeGroupLinearNV)] = .{ | ||
| 1836 | .llvm_name = null, | ||
| 1837 | .description = "Enable SPIR-V capability ComputeDerivativeGroupLinearNV", | ||
| 1838 | .dependencies = featureSet(&[_]Feature{ | ||
| 1839 | }), | ||
| 1840 | }; | ||
| 1841 | result[@enumToInt(Feature.RayTracingProvisionalKHR)] = .{ | ||
| 1842 | .llvm_name = null, | ||
| 1843 | .description = "Enable SPIR-V capability RayTracingProvisionalKHR", | ||
| 1844 | .dependencies = featureSet(&[_]Feature{ | ||
| 1845 | .Shader, | ||
| 1846 | }), | ||
| 1847 | }; | ||
| 1848 | result[@enumToInt(Feature.CooperativeMatrixNV)] = .{ | ||
| 1849 | .llvm_name = null, | ||
| 1850 | .description = "Enable SPIR-V capability CooperativeMatrixNV", | ||
| 1851 | .dependencies = featureSet(&[_]Feature{ | ||
| 1852 | .Shader, | ||
| 1853 | }), | ||
| 1854 | }; | ||
| 1855 | result[@enumToInt(Feature.FragmentShaderSampleInterlockEXT)] = .{ | ||
| 1856 | .llvm_name = null, | ||
| 1857 | .description = "Enable SPIR-V capability FragmentShaderSampleInterlockEXT", | ||
| 1858 | .dependencies = featureSet(&[_]Feature{ | ||
| 1859 | .Shader, | ||
| 1860 | }), | ||
| 1861 | }; | ||
| 1862 | result[@enumToInt(Feature.FragmentShaderShadingRateInterlockEXT)] = .{ | ||
| 1863 | .llvm_name = null, | ||
| 1864 | .description = "Enable SPIR-V capability FragmentShaderShadingRateInterlockEXT", | ||
| 1865 | .dependencies = featureSet(&[_]Feature{ | ||
| 1866 | .Shader, | ||
| 1867 | }), | ||
| 1868 | }; | ||
| 1869 | result[@enumToInt(Feature.ShaderSMBuiltinsNV)] = .{ | ||
| 1870 | .llvm_name = null, | ||
| 1871 | .description = "Enable SPIR-V capability ShaderSMBuiltinsNV", | ||
| 1872 | .dependencies = featureSet(&[_]Feature{ | ||
| 1873 | .Shader, | ||
| 1874 | }), | ||
| 1875 | }; | ||
| 1876 | result[@enumToInt(Feature.FragmentShaderPixelInterlockEXT)] = .{ | ||
| 1877 | .llvm_name = null, | ||
| 1878 | .description = "Enable SPIR-V capability FragmentShaderPixelInterlockEXT", | ||
| 1879 | .dependencies = featureSet(&[_]Feature{ | ||
| 1880 | .Shader, | ||
| 1881 | }), | ||
| 1882 | }; | ||
| 1883 | result[@enumToInt(Feature.DemoteToHelperInvocationEXT)] = .{ | ||
| 1884 | .llvm_name = null, | ||
| 1885 | .description = "Enable SPIR-V capability DemoteToHelperInvocationEXT", | ||
| 1886 | .dependencies = featureSet(&[_]Feature{ | ||
| 1887 | .Shader, | ||
| 1888 | }), | ||
| 1889 | }; | ||
| 1890 | result[@enumToInt(Feature.SubgroupShuffleINTEL)] = .{ | ||
| 1891 | .llvm_name = null, | ||
| 1892 | .description = "Enable SPIR-V capability SubgroupShuffleINTEL", | ||
| 1893 | .dependencies = featureSet(&[_]Feature{ | ||
| 1894 | }), | ||
| 1895 | }; | ||
| 1896 | result[@enumToInt(Feature.SubgroupBufferBlockIOINTEL)] = .{ | ||
| 1897 | .llvm_name = null, | ||
| 1898 | .description = "Enable SPIR-V capability SubgroupBufferBlockIOINTEL", | ||
| 1899 | .dependencies = featureSet(&[_]Feature{ | ||
| 1900 | }), | ||
| 1901 | }; | ||
| 1902 | result[@enumToInt(Feature.SubgroupImageBlockIOINTEL)] = .{ | ||
| 1903 | .llvm_name = null, | ||
| 1904 | .description = "Enable SPIR-V capability SubgroupImageBlockIOINTEL", | ||
| 1905 | .dependencies = featureSet(&[_]Feature{ | ||
| 1906 | }), | ||
| 1907 | }; | ||
| 1908 | result[@enumToInt(Feature.SubgroupImageMediaBlockIOINTEL)] = .{ | ||
| 1909 | .llvm_name = null, | ||
| 1910 | .description = "Enable SPIR-V capability SubgroupImageMediaBlockIOINTEL", | ||
| 1911 | .dependencies = featureSet(&[_]Feature{ | ||
| 1912 | }), | ||
| 1913 | }; | ||
| 1914 | result[@enumToInt(Feature.RoundToInfinityINTEL)] = .{ | ||
| 1915 | .llvm_name = null, | ||
| 1916 | .description = "Enable SPIR-V capability RoundToInfinityINTEL", | ||
| 1917 | .dependencies = featureSet(&[_]Feature{ | ||
| 1918 | }), | ||
| 1919 | }; | ||
| 1920 | result[@enumToInt(Feature.FloatingPointModeINTEL)] = .{ | ||
| 1921 | .llvm_name = null, | ||
| 1922 | .description = "Enable SPIR-V capability FloatingPointModeINTEL", | ||
| 1923 | .dependencies = featureSet(&[_]Feature{ | ||
| 1924 | }), | ||
| 1925 | }; | ||
| 1926 | result[@enumToInt(Feature.IntegerFunctions2INTEL)] = .{ | ||
| 1927 | .llvm_name = null, | ||
| 1928 | .description = "Enable SPIR-V capability IntegerFunctions2INTEL", | ||
| 1929 | .dependencies = featureSet(&[_]Feature{ | ||
| 1930 | .Shader, | ||
| 1931 | }), | ||
| 1932 | }; | ||
| 1933 | result[@enumToInt(Feature.FunctionPointersINTEL)] = .{ | ||
| 1934 | .llvm_name = null, | ||
| 1935 | .description = "Enable SPIR-V capability FunctionPointersINTEL", | ||
| 1936 | .dependencies = featureSet(&[_]Feature{ | ||
| 1937 | }), | ||
| 1938 | }; | ||
| 1939 | result[@enumToInt(Feature.IndirectReferencesINTEL)] = .{ | ||
| 1940 | .llvm_name = null, | ||
| 1941 | .description = "Enable SPIR-V capability IndirectReferencesINTEL", | ||
| 1942 | .dependencies = featureSet(&[_]Feature{ | ||
| 1943 | }), | ||
| 1944 | }; | ||
| 1945 | result[@enumToInt(Feature.AsmINTEL)] = .{ | ||
| 1946 | .llvm_name = null, | ||
| 1947 | .description = "Enable SPIR-V capability AsmINTEL", | ||
| 1948 | .dependencies = featureSet(&[_]Feature{ | ||
| 1949 | }), | ||
| 1950 | }; | ||
| 1951 | result[@enumToInt(Feature.AtomicFloat32MinMaxEXT)] = .{ | ||
| 1952 | .llvm_name = null, | ||
| 1953 | .description = "Enable SPIR-V capability AtomicFloat32MinMaxEXT", | ||
| 1954 | .dependencies = featureSet(&[_]Feature{ | ||
| 1955 | }), | ||
| 1956 | }; | ||
| 1957 | result[@enumToInt(Feature.AtomicFloat64MinMaxEXT)] = .{ | ||
| 1958 | .llvm_name = null, | ||
| 1959 | .description = "Enable SPIR-V capability AtomicFloat64MinMaxEXT", | ||
| 1960 | .dependencies = featureSet(&[_]Feature{ | ||
| 1961 | }), | ||
| 1962 | }; | ||
| 1963 | result[@enumToInt(Feature.AtomicFloat16MinMaxEXT)] = .{ | ||
| 1964 | .llvm_name = null, | ||
| 1965 | .description = "Enable SPIR-V capability AtomicFloat16MinMaxEXT", | ||
| 1966 | .dependencies = featureSet(&[_]Feature{ | ||
| 1967 | }), | ||
| 1968 | }; | ||
| 1969 | result[@enumToInt(Feature.VectorComputeINTEL)] = .{ | ||
| 1970 | .llvm_name = null, | ||
| 1971 | .description = "Enable SPIR-V capability VectorComputeINTEL", | ||
| 1972 | .dependencies = featureSet(&[_]Feature{ | ||
| 1973 | .VectorAnyINTEL, | ||
| 1974 | }), | ||
| 1975 | }; | ||
| 1976 | result[@enumToInt(Feature.VectorAnyINTEL)] = .{ | ||
| 1977 | .llvm_name = null, | ||
| 1978 | .description = "Enable SPIR-V capability VectorAnyINTEL", | ||
| 1979 | .dependencies = featureSet(&[_]Feature{ | ||
| 1980 | }), | ||
| 1981 | }; | ||
| 1982 | result[@enumToInt(Feature.ExpectAssumeKHR)] = .{ | ||
| 1983 | .llvm_name = null, | ||
| 1984 | .description = "Enable SPIR-V capability ExpectAssumeKHR", | ||
| 1985 | .dependencies = featureSet(&[_]Feature{ | ||
| 1986 | }), | ||
| 1987 | }; | ||
| 1988 | result[@enumToInt(Feature.SubgroupAvcMotionEstimationINTEL)] = .{ | ||
| 1989 | .llvm_name = null, | ||
| 1990 | .description = "Enable SPIR-V capability SubgroupAvcMotionEstimationINTEL", | ||
| 1991 | .dependencies = featureSet(&[_]Feature{ | ||
| 1992 | }), | ||
| 1993 | }; | ||
| 1994 | result[@enumToInt(Feature.SubgroupAvcMotionEstimationIntraINTEL)] = .{ | ||
| 1995 | .llvm_name = null, | ||
| 1996 | .description = "Enable SPIR-V capability SubgroupAvcMotionEstimationIntraINTEL", | ||
| 1997 | .dependencies = featureSet(&[_]Feature{ | ||
| 1998 | }), | ||
| 1999 | }; | ||
| 2000 | result[@enumToInt(Feature.SubgroupAvcMotionEstimationChromaINTEL)] = .{ | ||
| 2001 | .llvm_name = null, | ||
| 2002 | .description = "Enable SPIR-V capability SubgroupAvcMotionEstimationChromaINTEL", | ||
| 2003 | .dependencies = featureSet(&[_]Feature{ | ||
| 2004 | }), | ||
| 2005 | }; | ||
| 2006 | result[@enumToInt(Feature.VariableLengthArrayINTEL)] = .{ | ||
| 2007 | .llvm_name = null, | ||
| 2008 | .description = "Enable SPIR-V capability VariableLengthArrayINTEL", | ||
| 2009 | .dependencies = featureSet(&[_]Feature{ | ||
| 2010 | }), | ||
| 2011 | }; | ||
| 2012 | result[@enumToInt(Feature.FunctionFloatControlINTEL)] = .{ | ||
| 2013 | .llvm_name = null, | ||
| 2014 | .description = "Enable SPIR-V capability FunctionFloatControlINTEL", | ||
| 2015 | .dependencies = featureSet(&[_]Feature{ | ||
| 2016 | }), | ||
| 2017 | }; | ||
| 2018 | result[@enumToInt(Feature.FPGAMemoryAttributesINTEL)] = .{ | ||
| 2019 | .llvm_name = null, | ||
| 2020 | .description = "Enable SPIR-V capability FPGAMemoryAttributesINTEL", | ||
| 2021 | .dependencies = featureSet(&[_]Feature{ | ||
| 2022 | }), | ||
| 2023 | }; | ||
| 2024 | result[@enumToInt(Feature.FPFastMathModeINTEL)] = .{ | ||
| 2025 | .llvm_name = null, | ||
| 2026 | .description = "Enable SPIR-V capability FPFastMathModeINTEL", | ||
| 2027 | .dependencies = featureSet(&[_]Feature{ | ||
| 2028 | .Kernel, | ||
| 2029 | }), | ||
| 2030 | }; | ||
| 2031 | result[@enumToInt(Feature.ArbitraryPrecisionIntegersINTEL)] = .{ | ||
| 2032 | .llvm_name = null, | ||
| 2033 | .description = "Enable SPIR-V capability ArbitraryPrecisionIntegersINTEL", | ||
| 2034 | .dependencies = featureSet(&[_]Feature{ | ||
| 2035 | }), | ||
| 2036 | }; | ||
| 2037 | result[@enumToInt(Feature.UnstructuredLoopControlsINTEL)] = .{ | ||
| 2038 | .llvm_name = null, | ||
| 2039 | .description = "Enable SPIR-V capability UnstructuredLoopControlsINTEL", | ||
| 2040 | .dependencies = featureSet(&[_]Feature{ | ||
| 2041 | }), | ||
| 2042 | }; | ||
| 2043 | result[@enumToInt(Feature.FPGALoopControlsINTEL)] = .{ | ||
| 2044 | .llvm_name = null, | ||
| 2045 | .description = "Enable SPIR-V capability FPGALoopControlsINTEL", | ||
| 2046 | .dependencies = featureSet(&[_]Feature{ | ||
| 2047 | }), | ||
| 2048 | }; | ||
| 2049 | result[@enumToInt(Feature.KernelAttributesINTEL)] = .{ | ||
| 2050 | .llvm_name = null, | ||
| 2051 | .description = "Enable SPIR-V capability KernelAttributesINTEL", | ||
| 2052 | .dependencies = featureSet(&[_]Feature{ | ||
| 2053 | }), | ||
| 2054 | }; | ||
| 2055 | result[@enumToInt(Feature.FPGAKernelAttributesINTEL)] = .{ | ||
| 2056 | .llvm_name = null, | ||
| 2057 | .description = "Enable SPIR-V capability FPGAKernelAttributesINTEL", | ||
| 2058 | .dependencies = featureSet(&[_]Feature{ | ||
| 2059 | }), | ||
| 2060 | }; | ||
| 2061 | result[@enumToInt(Feature.FPGAMemoryAccessesINTEL)] = .{ | ||
| 2062 | .llvm_name = null, | ||
| 2063 | .description = "Enable SPIR-V capability FPGAMemoryAccessesINTEL", | ||
| 2064 | .dependencies = featureSet(&[_]Feature{ | ||
| 2065 | }), | ||
| 2066 | }; | ||
| 2067 | result[@enumToInt(Feature.FPGAClusterAttributesINTEL)] = .{ | ||
| 2068 | .llvm_name = null, | ||
| 2069 | .description = "Enable SPIR-V capability FPGAClusterAttributesINTEL", | ||
| 2070 | .dependencies = featureSet(&[_]Feature{ | ||
| 2071 | }), | ||
| 2072 | }; | ||
| 2073 | result[@enumToInt(Feature.LoopFuseINTEL)] = .{ | ||
| 2074 | .llvm_name = null, | ||
| 2075 | .description = "Enable SPIR-V capability LoopFuseINTEL", | ||
| 2076 | .dependencies = featureSet(&[_]Feature{ | ||
| 2077 | }), | ||
| 2078 | }; | ||
| 2079 | result[@enumToInt(Feature.FPGABufferLocationINTEL)] = .{ | ||
| 2080 | .llvm_name = null, | ||
| 2081 | .description = "Enable SPIR-V capability FPGABufferLocationINTEL", | ||
| 2082 | .dependencies = featureSet(&[_]Feature{ | ||
| 2083 | }), | ||
| 2084 | }; | ||
| 2085 | result[@enumToInt(Feature.USMStorageClassesINTEL)] = .{ | ||
| 2086 | .llvm_name = null, | ||
| 2087 | .description = "Enable SPIR-V capability USMStorageClassesINTEL", | ||
| 2088 | .dependencies = featureSet(&[_]Feature{ | ||
| 2089 | }), | ||
| 2090 | }; | ||
| 2091 | result[@enumToInt(Feature.IOPipesINTEL)] = .{ | ||
| 2092 | .llvm_name = null, | ||
| 2093 | .description = "Enable SPIR-V capability IOPipesINTEL", | ||
| 2094 | .dependencies = featureSet(&[_]Feature{ | ||
| 2095 | }), | ||
| 2096 | }; | ||
| 2097 | result[@enumToInt(Feature.BlockingPipesINTEL)] = .{ | ||
| 2098 | .llvm_name = null, | ||
| 2099 | .description = "Enable SPIR-V capability BlockingPipesINTEL", | ||
| 2100 | .dependencies = featureSet(&[_]Feature{ | ||
| 2101 | }), | ||
| 2102 | }; | ||
| 2103 | result[@enumToInt(Feature.FPGARegINTEL)] = .{ | ||
| 2104 | .llvm_name = null, | ||
| 2105 | .description = "Enable SPIR-V capability FPGARegINTEL", | ||
| 2106 | .dependencies = featureSet(&[_]Feature{ | ||
| 2107 | }), | ||
| 2108 | }; | ||
| 2109 | result[@enumToInt(Feature.AtomicFloat32AddEXT)] = .{ | ||
| 2110 | .llvm_name = null, | ||
| 2111 | .description = "Enable SPIR-V capability AtomicFloat32AddEXT", | ||
| 2112 | .dependencies = featureSet(&[_]Feature{ | ||
| 2113 | .Shader, | ||
| 2114 | }), | ||
| 2115 | }; | ||
| 2116 | result[@enumToInt(Feature.AtomicFloat64AddEXT)] = .{ | ||
| 2117 | .llvm_name = null, | ||
| 2118 | .description = "Enable SPIR-V capability AtomicFloat64AddEXT", | ||
| 2119 | .dependencies = featureSet(&[_]Feature{ | ||
| 2120 | .Shader, | ||
| 2121 | }), | ||
| 2122 | }; | ||
| 2123 | result[@enumToInt(Feature.LongConstantCompositeINTEL)] = .{ | ||
| 2124 | .llvm_name = null, | ||
| 2125 | .description = "Enable SPIR-V capability LongConstantCompositeINTEL", | ||
| 2126 | .dependencies = featureSet(&[_]Feature{ | ||
| 2127 | }), | ||
| 2128 | }; | ||
| 2129 | const ti = @typeInfo(Feature); | ||
| 2130 | for (result) |*elem, i| { | ||
| 2131 | elem.index = i; | ||
| 2132 | elem.name = ti.Enum.fields[i].name; | ||
| 2133 | } | ||
| 2134 | break :blk result; | ||
| 2135 | }; | ||
lib/std/testing.zig+16-16| ... | @@ -29,11 +29,11 @@ pub var zig_exe_path: []const u8 = undefined; | ... | @@ -29,11 +29,11 @@ pub var zig_exe_path: []const u8 = undefined; |
| 29 | /// and then aborts when actual_error_union is not expected_error. | 29 | /// and then aborts when actual_error_union is not expected_error. |
| 30 | pub fn expectError(expected_error: anyerror, actual_error_union: anytype) !void { | 30 | pub fn expectError(expected_error: anyerror, actual_error_union: anytype) !void { |
| 31 | if (actual_error_union) |actual_payload| { | 31 | if (actual_error_union) |actual_payload| { |
| 32 | std.debug.print("expected error.{s}, found {any}", .{ @errorName(expected_error), actual_payload }); | 32 | std.debug.print("expected error.{s}, found {any}\n", .{ @errorName(expected_error), actual_payload }); |
| 33 | return error.TestUnexpectedError; | 33 | return error.TestUnexpectedError; |
| 34 | } else |actual_error| { | 34 | } else |actual_error| { |
| 35 | if (expected_error != actual_error) { | 35 | if (expected_error != actual_error) { |
| 36 | std.debug.print("expected error.{s}, found error.{s}", .{ | 36 | std.debug.print("expected error.{s}, found error.{s}\n", .{ |
| 37 | @errorName(expected_error), | 37 | @errorName(expected_error), |
| 38 | @errorName(actual_error), | 38 | @errorName(actual_error), |
| 39 | }); | 39 | }); |
| ... | @@ -62,7 +62,7 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { | ... | @@ -62,7 +62,7 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { |
| 62 | 62 | ||
| 63 | .Type => { | 63 | .Type => { |
| 64 | if (actual != expected) { | 64 | if (actual != expected) { |
| 65 | std.debug.print("expected type {s}, found type {s}", .{ @typeName(expected), @typeName(actual) }); | 65 | std.debug.print("expected type {s}, found type {s}\n", .{ @typeName(expected), @typeName(actual) }); |
| 66 | return error.TestExpectedEqual; | 66 | return error.TestExpectedEqual; |
| 67 | } | 67 | } |
| 68 | }, | 68 | }, |
| ... | @@ -78,7 +78,7 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { | ... | @@ -78,7 +78,7 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { |
| 78 | .ErrorSet, | 78 | .ErrorSet, |
| 79 | => { | 79 | => { |
| 80 | if (actual != expected) { | 80 | if (actual != expected) { |
| 81 | std.debug.print("expected {}, found {}", .{ expected, actual }); | 81 | std.debug.print("expected {}, found {}\n", .{ expected, actual }); |
| 82 | return error.TestExpectedEqual; | 82 | return error.TestExpectedEqual; |
| 83 | } | 83 | } |
| 84 | }, | 84 | }, |
| ... | @@ -87,17 +87,17 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { | ... | @@ -87,17 +87,17 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { |
| 87 | switch (pointer.size) { | 87 | switch (pointer.size) { |
| 88 | .One, .Many, .C => { | 88 | .One, .Many, .C => { |
| 89 | if (actual != expected) { | 89 | if (actual != expected) { |
| 90 | std.debug.print("expected {*}, found {*}", .{ expected, actual }); | 90 | std.debug.print("expected {*}, found {*}\n", .{ expected, actual }); |
| 91 | return error.TestExpectedEqual; | 91 | return error.TestExpectedEqual; |
| 92 | } | 92 | } |
| 93 | }, | 93 | }, |
| 94 | .Slice => { | 94 | .Slice => { |
| 95 | if (actual.ptr != expected.ptr) { | 95 | if (actual.ptr != expected.ptr) { |
| 96 | std.debug.print("expected slice ptr {*}, found {*}", .{ expected.ptr, actual.ptr }); | 96 | std.debug.print("expected slice ptr {*}, found {*}\n", .{ expected.ptr, actual.ptr }); |
| 97 | return error.TestExpectedEqual; | 97 | return error.TestExpectedEqual; |
| 98 | } | 98 | } |
| 99 | if (actual.len != expected.len) { | 99 | if (actual.len != expected.len) { |
| 100 | std.debug.print("expected slice len {}, found {}", .{ expected.len, actual.len }); | 100 | std.debug.print("expected slice len {}, found {}\n", .{ expected.len, actual.len }); |
| 101 | return error.TestExpectedEqual; | 101 | return error.TestExpectedEqual; |
| 102 | } | 102 | } |
| 103 | }, | 103 | }, |
| ... | @@ -110,7 +110,7 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { | ... | @@ -110,7 +110,7 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { |
| 110 | var i: usize = 0; | 110 | var i: usize = 0; |
| 111 | while (i < vectorType.len) : (i += 1) { | 111 | while (i < vectorType.len) : (i += 1) { |
| 112 | if (!std.meta.eql(expected[i], actual[i])) { | 112 | if (!std.meta.eql(expected[i], actual[i])) { |
| 113 | std.debug.print("index {} incorrect. expected {}, found {}", .{ i, expected[i], actual[i] }); | 113 | std.debug.print("index {} incorrect. expected {}, found {}\n", .{ i, expected[i], actual[i] }); |
| 114 | return error.TestExpectedEqual; | 114 | return error.TestExpectedEqual; |
| 115 | } | 115 | } |
| 116 | } | 116 | } |
| ... | @@ -153,12 +153,12 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { | ... | @@ -153,12 +153,12 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { |
| 153 | if (actual) |actual_payload| { | 153 | if (actual) |actual_payload| { |
| 154 | try expectEqual(expected_payload, actual_payload); | 154 | try expectEqual(expected_payload, actual_payload); |
| 155 | } else { | 155 | } else { |
| 156 | std.debug.print("expected {any}, found null", .{expected_payload}); | 156 | std.debug.print("expected {any}, found null\n", .{expected_payload}); |
| 157 | return error.TestExpectedEqual; | 157 | return error.TestExpectedEqual; |
| 158 | } | 158 | } |
| 159 | } else { | 159 | } else { |
| 160 | if (actual) |actual_payload| { | 160 | if (actual) |actual_payload| { |
| 161 | std.debug.print("expected null, found {any}", .{actual_payload}); | 161 | std.debug.print("expected null, found {any}\n", .{actual_payload}); |
| 162 | return error.TestExpectedEqual; | 162 | return error.TestExpectedEqual; |
| 163 | } | 163 | } |
| 164 | } | 164 | } |
| ... | @@ -169,12 +169,12 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { | ... | @@ -169,12 +169,12 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { |
| 169 | if (actual) |actual_payload| { | 169 | if (actual) |actual_payload| { |
| 170 | try expectEqual(expected_payload, actual_payload); | 170 | try expectEqual(expected_payload, actual_payload); |
| 171 | } else |actual_err| { | 171 | } else |actual_err| { |
| 172 | std.debug.print("expected {any}, found {}", .{ expected_payload, actual_err }); | 172 | std.debug.print("expected {any}, found {}\n", .{ expected_payload, actual_err }); |
| 173 | return error.TestExpectedEqual; | 173 | return error.TestExpectedEqual; |
| 174 | } | 174 | } |
| 175 | } else |expected_err| { | 175 | } else |expected_err| { |
| 176 | if (actual) |actual_payload| { | 176 | if (actual) |actual_payload| { |
| 177 | std.debug.print("expected {}, found {any}", .{ expected_err, actual_payload }); | 177 | std.debug.print("expected {}, found {any}\n", .{ expected_err, actual_payload }); |
| 178 | return error.TestExpectedEqual; | 178 | return error.TestExpectedEqual; |
| 179 | } else |actual_err| { | 179 | } else |actual_err| { |
| 180 | try expectEqual(expected_err, actual_err); | 180 | try expectEqual(expected_err, actual_err); |
| ... | @@ -225,7 +225,7 @@ pub fn expectApproxEqAbs(expected: anytype, actual: @TypeOf(expected), tolerance | ... | @@ -225,7 +225,7 @@ pub fn expectApproxEqAbs(expected: anytype, actual: @TypeOf(expected), tolerance |
| 225 | 225 | ||
| 226 | switch (@typeInfo(T)) { | 226 | switch (@typeInfo(T)) { |
| 227 | .Float => if (!math.approxEqAbs(T, expected, actual, tolerance)) { | 227 | .Float => if (!math.approxEqAbs(T, expected, actual, tolerance)) { |
| 228 | std.debug.print("actual {}, not within absolute tolerance {} of expected {}", .{ actual, tolerance, expected }); | 228 | std.debug.print("actual {}, not within absolute tolerance {} of expected {}\n", .{ actual, tolerance, expected }); |
| 229 | return error.TestExpectedApproxEqAbs; | 229 | return error.TestExpectedApproxEqAbs; |
| 230 | }, | 230 | }, |
| 231 | 231 | ||
| ... | @@ -257,7 +257,7 @@ pub fn expectApproxEqRel(expected: anytype, actual: @TypeOf(expected), tolerance | ... | @@ -257,7 +257,7 @@ pub fn expectApproxEqRel(expected: anytype, actual: @TypeOf(expected), tolerance |
| 257 | 257 | ||
| 258 | switch (@typeInfo(T)) { | 258 | switch (@typeInfo(T)) { |
| 259 | .Float => if (!math.approxEqRel(T, expected, actual, tolerance)) { | 259 | .Float => if (!math.approxEqRel(T, expected, actual, tolerance)) { |
| 260 | std.debug.print("actual {}, not within relative tolerance {} of expected {}", .{ actual, tolerance, expected }); | 260 | std.debug.print("actual {}, not within relative tolerance {} of expected {}\n", .{ actual, tolerance, expected }); |
| 261 | return error.TestExpectedApproxEqRel; | 261 | return error.TestExpectedApproxEqRel; |
| 262 | }, | 262 | }, |
| 263 | 263 | ||
| ... | @@ -292,13 +292,13 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const | ... | @@ -292,13 +292,13 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const |
| 292 | // If the child type is u8 and no weird bytes, we could print it as strings | 292 | // If the child type is u8 and no weird bytes, we could print it as strings |
| 293 | // Even for the length difference, it would be useful to see the values of the slices probably. | 293 | // Even for the length difference, it would be useful to see the values of the slices probably. |
| 294 | if (expected.len != actual.len) { | 294 | if (expected.len != actual.len) { |
| 295 | std.debug.print("slice lengths differ. expected {d}, found {d}", .{ expected.len, actual.len }); | 295 | std.debug.print("slice lengths differ. expected {d}, found {d}\n", .{ expected.len, actual.len }); |
| 296 | return error.TestExpectedEqual; | 296 | return error.TestExpectedEqual; |
| 297 | } | 297 | } |
| 298 | var i: usize = 0; | 298 | var i: usize = 0; |
| 299 | while (i < expected.len) : (i += 1) { | 299 | while (i < expected.len) : (i += 1) { |
| 300 | if (!std.meta.eql(expected[i], actual[i])) { | 300 | if (!std.meta.eql(expected[i], actual[i])) { |
| 301 | std.debug.print("index {} incorrect. expected {any}, found {any}", .{ i, expected[i], actual[i] }); | 301 | std.debug.print("index {} incorrect. expected {any}, found {any}\n", .{ i, expected[i], actual[i] }); |
| 302 | return error.TestExpectedEqual; | 302 | return error.TestExpectedEqual; |
| 303 | } | 303 | } |
| 304 | } | 304 | } |
lib/std/zig/cross_target.zig+10| ... | @@ -606,6 +606,7 @@ pub const CrossTarget = struct { | ... | @@ -606,6 +606,7 @@ pub const CrossTarget = struct { |
| 606 | qemu: []const u8, | 606 | qemu: []const u8, |
| 607 | wine: []const u8, | 607 | wine: []const u8, |
| 608 | wasmtime: []const u8, | 608 | wasmtime: []const u8, |
| 609 | darling: []const u8, | ||
| 609 | unavailable, | 610 | unavailable, |
| 610 | }; | 611 | }; |
| 611 | 612 | ||
| ... | @@ -667,6 +668,15 @@ pub const CrossTarget = struct { | ... | @@ -667,6 +668,15 @@ pub const CrossTarget = struct { |
| 667 | 32 => return Executor{ .wasmtime = "wasmtime" }, | 668 | 32 => return Executor{ .wasmtime = "wasmtime" }, |
| 668 | else => return .unavailable, | 669 | else => return .unavailable, |
| 669 | }, | 670 | }, |
| 671 | .macos => { | ||
| 672 | // TODO loosen this check once upstream adds QEMU-based emulation | ||
| 673 | // layer for non-host architectures: | ||
| 674 | // https://github.com/darlinghq/darling/issues/863 | ||
| 675 | if (cpu_arch != Target.current.cpu.arch) { | ||
| 676 | return .unavailable; | ||
| 677 | } | ||
| 678 | return Executor{ .darling = "darling" }; | ||
| 679 | }, | ||
| 670 | else => return .unavailable, | 680 | else => return .unavailable, |
| 671 | } | 681 | } |
| 672 | } | 682 | } |
lib/std/zig/parse.zig+77-241| ... | @@ -1309,9 +1309,8 @@ const Parser = struct { | ... | @@ -1309,9 +1309,8 @@ const Parser = struct { |
| 1309 | return expr; | 1309 | return expr; |
| 1310 | } | 1310 | } |
| 1311 | 1311 | ||
| 1312 | /// Expr <- BoolOrExpr | ||
| 1313 | fn parseExpr(p: *Parser) Error!Node.Index { | 1312 | fn parseExpr(p: *Parser) Error!Node.Index { |
| 1314 | return p.parseBoolOrExpr(); | 1313 | return p.parseExprPrecedence(0); |
| 1315 | } | 1314 | } |
| 1316 | 1315 | ||
| 1317 | fn expectExpr(p: *Parser) Error!Node.Index { | 1316 | fn expectExpr(p: *Parser) Error!Node.Index { |
| ... | @@ -1323,263 +1322,100 @@ const Parser = struct { | ... | @@ -1323,263 +1322,100 @@ const Parser = struct { |
| 1323 | } | 1322 | } |
| 1324 | } | 1323 | } |
| 1325 | 1324 | ||
| 1326 | /// BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)* | 1325 | const Assoc = enum { |
| 1327 | fn parseBoolOrExpr(p: *Parser) Error!Node.Index { | 1326 | left, |
| 1328 | var res = try p.parseBoolAndExpr(); | 1327 | none, |
| 1329 | if (res == 0) return null_node; | 1328 | }; |
| 1330 | 1329 | ||
| 1331 | while (true) { | 1330 | const OperInfo = struct { |
| 1332 | switch (p.token_tags[p.tok_i]) { | 1331 | prec: i8, |
| 1333 | .keyword_or => { | 1332 | tag: Node.Tag, |
| 1334 | const or_token = p.nextToken(); | 1333 | assoc: Assoc = Assoc.left, |
| 1335 | const rhs = try p.parseBoolAndExpr(); | 1334 | }; |
| 1336 | if (rhs == 0) { | ||
| 1337 | return p.fail(.invalid_token); | ||
| 1338 | } | ||
| 1339 | res = try p.addNode(.{ | ||
| 1340 | .tag = .bool_or, | ||
| 1341 | .main_token = or_token, | ||
| 1342 | .data = .{ | ||
| 1343 | .lhs = res, | ||
| 1344 | .rhs = rhs, | ||
| 1345 | }, | ||
| 1346 | }); | ||
| 1347 | }, | ||
| 1348 | else => return res, | ||
| 1349 | } | ||
| 1350 | } | ||
| 1351 | } | ||
| 1352 | 1335 | ||
| 1353 | /// BoolAndExpr <- CompareExpr (KEYWORD_and CompareExpr)* | 1336 | // A table of binary operator information. Higher precedence numbers are |
| 1354 | fn parseBoolAndExpr(p: *Parser) !Node.Index { | 1337 | // stickier. All operators at the same precedence level should have the same |
| 1355 | var res = try p.parseCompareExpr(); | 1338 | // associativity. |
| 1356 | if (res == 0) return null_node; | 1339 | const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec = -1, .tag = Node.Tag.root }, 0, .{ |
| 1340 | .keyword_or = .{ .prec = 10, .tag = .bool_or }, | ||
| 1341 | |||
| 1342 | .keyword_and = .{ .prec = 20, .tag = .bool_and }, | ||
| 1343 | .invalid_ampersands = .{ .prec = 20, .tag = .bool_and }, | ||
| 1344 | |||
| 1345 | .equal_equal = .{ .prec = 30, .tag = .equal_equal, .assoc = Assoc.none }, | ||
| 1346 | .bang_equal = .{ .prec = 30, .tag = .bang_equal, .assoc = Assoc.none }, | ||
| 1347 | .angle_bracket_left = .{ .prec = 30, .tag = .less_than, .assoc = Assoc.none }, | ||
| 1348 | .angle_bracket_right = .{ .prec = 30, .tag = .greater_than, .assoc = Assoc.none }, | ||
| 1349 | .angle_bracket_left_equal = .{ .prec = 30, .tag = .less_or_equal, .assoc = Assoc.none }, | ||
| 1350 | .angle_bracket_right_equal = .{ .prec = 30, .tag = .greater_or_equal, .assoc = Assoc.none }, | ||
| 1351 | |||
| 1352 | .ampersand = .{ .prec = 40, .tag = .bit_and }, | ||
| 1353 | .caret = .{ .prec = 40, .tag = .bit_xor }, | ||
| 1354 | .pipe = .{ .prec = 40, .tag = .bit_or }, | ||
| 1355 | .keyword_orelse = .{ .prec = 40, .tag = .@"orelse" }, | ||
| 1356 | .keyword_catch = .{ .prec = 40, .tag = .@"catch" }, | ||
| 1357 | |||
| 1358 | .angle_bracket_angle_bracket_left = .{ .prec = 50, .tag = .bit_shift_left }, | ||
| 1359 | .angle_bracket_angle_bracket_right = .{ .prec = 50, .tag = .bit_shift_right }, | ||
| 1360 | |||
| 1361 | .plus = .{ .prec = 60, .tag = .add }, | ||
| 1362 | .minus = .{ .prec = 60, .tag = .sub }, | ||
| 1363 | .plus_plus = .{ .prec = 60, .tag = .array_cat }, | ||
| 1364 | .plus_percent = .{ .prec = 60, .tag = .add_wrap }, | ||
| 1365 | .minus_percent = .{ .prec = 60, .tag = .sub_wrap }, | ||
| 1366 | |||
| 1367 | .pipe_pipe = .{ .prec = 70, .tag = .merge_error_sets }, | ||
| 1368 | .asterisk = .{ .prec = 70, .tag = .mul }, | ||
| 1369 | .slash = .{ .prec = 70, .tag = .div }, | ||
| 1370 | .percent = .{ .prec = 70, .tag = .mod }, | ||
| 1371 | .asterisk_asterisk = .{ .prec = 70, .tag = .array_mult }, | ||
| 1372 | .asterisk_percent = .{ .prec = 70, .tag = .mul_wrap }, | ||
| 1373 | }); | ||
| 1357 | 1374 | ||
| 1358 | while (true) { | 1375 | fn parseExprPrecedence(p: *Parser, min_prec: i32) Error!Node.Index { |
| 1359 | switch (p.token_tags[p.tok_i]) { | 1376 | var node = try p.parsePrefixExpr(); |
| 1360 | .keyword_and => { | 1377 | if (node == 0) { |
| 1361 | const and_token = p.nextToken(); | 1378 | return null_node; |
| 1362 | const rhs = try p.parseCompareExpr(); | ||
| 1363 | if (rhs == 0) { | ||
| 1364 | return p.fail(.invalid_token); | ||
| 1365 | } | ||
| 1366 | res = try p.addNode(.{ | ||
| 1367 | .tag = .bool_and, | ||
| 1368 | .main_token = and_token, | ||
| 1369 | .data = .{ | ||
| 1370 | .lhs = res, | ||
| 1371 | .rhs = rhs, | ||
| 1372 | }, | ||
| 1373 | }); | ||
| 1374 | }, | ||
| 1375 | .invalid_ampersands => { | ||
| 1376 | try p.warn(.invalid_and); | ||
| 1377 | p.tok_i += 1; | ||
| 1378 | return p.parseCompareExpr(); | ||
| 1379 | }, | ||
| 1380 | else => return res, | ||
| 1381 | } | ||
| 1382 | } | 1379 | } |
| 1383 | } | ||
| 1384 | 1380 | ||
| 1385 | /// CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)? | 1381 | var banned_prec: i8 = -1; |
| 1386 | /// CompareOp | ||
| 1387 | /// <- EQUALEQUAL | ||
| 1388 | /// / EXCLAMATIONMARKEQUAL | ||
| 1389 | /// / LARROW | ||
| 1390 | /// / RARROW | ||
| 1391 | /// / LARROWEQUAL | ||
| 1392 | /// / RARROWEQUAL | ||
| 1393 | fn parseCompareExpr(p: *Parser) !Node.Index { | ||
| 1394 | const expr = try p.parseBitwiseExpr(); | ||
| 1395 | if (expr == 0) return null_node; | ||
| 1396 | |||
| 1397 | const tag: Node.Tag = switch (p.token_tags[p.tok_i]) { | ||
| 1398 | .equal_equal => .equal_equal, | ||
| 1399 | .bang_equal => .bang_equal, | ||
| 1400 | .angle_bracket_left => .less_than, | ||
| 1401 | .angle_bracket_right => .greater_than, | ||
| 1402 | .angle_bracket_left_equal => .less_or_equal, | ||
| 1403 | .angle_bracket_right_equal => .greater_or_equal, | ||
| 1404 | else => return expr, | ||
| 1405 | }; | ||
| 1406 | return p.addNode(.{ | ||
| 1407 | .tag = tag, | ||
| 1408 | .main_token = p.nextToken(), | ||
| 1409 | .data = .{ | ||
| 1410 | .lhs = expr, | ||
| 1411 | .rhs = try p.expectBitwiseExpr(), | ||
| 1412 | }, | ||
| 1413 | }); | ||
| 1414 | } | ||
| 1415 | |||
| 1416 | /// BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)* | ||
| 1417 | /// BitwiseOp | ||
| 1418 | /// <- AMPERSAND | ||
| 1419 | /// / CARET | ||
| 1420 | /// / PIPE | ||
| 1421 | /// / KEYWORD_orelse | ||
| 1422 | /// / KEYWORD_catch Payload? | ||
| 1423 | fn parseBitwiseExpr(p: *Parser) !Node.Index { | ||
| 1424 | var res = try p.parseBitShiftExpr(); | ||
| 1425 | if (res == 0) return null_node; | ||
| 1426 | 1382 | ||
| 1427 | while (true) { | 1383 | while (true) { |
| 1428 | const tag: Node.Tag = switch (p.token_tags[p.tok_i]) { | 1384 | const tok_tag = p.token_tags[p.tok_i]; |
| 1429 | .ampersand => .bit_and, | 1385 | const info = operTable[@intCast(usize, @enumToInt(tok_tag))]; |
| 1430 | .caret => .bit_xor, | 1386 | if (info.prec < min_prec or info.prec == banned_prec) { |
| 1431 | .pipe => .bit_or, | 1387 | break; |
| 1432 | .keyword_orelse => .@"orelse", | 1388 | } |
| 1389 | const oper_token = p.nextToken(); | ||
| 1390 | // Special-case handling for "catch" and "&&". | ||
| 1391 | switch (tok_tag) { | ||
| 1433 | .keyword_catch => { | 1392 | .keyword_catch => { |
| 1434 | const catch_token = p.nextToken(); | ||
| 1435 | _ = try p.parsePayload(); | 1393 | _ = try p.parsePayload(); |
| 1436 | const rhs = try p.parseBitShiftExpr(); | ||
| 1437 | if (rhs == 0) { | ||
| 1438 | return p.fail(.invalid_token); | ||
| 1439 | } | ||
| 1440 | res = try p.addNode(.{ | ||
| 1441 | .tag = .@"catch", | ||
| 1442 | .main_token = catch_token, | ||
| 1443 | .data = .{ | ||
| 1444 | .lhs = res, | ||
| 1445 | .rhs = rhs, | ||
| 1446 | }, | ||
| 1447 | }); | ||
| 1448 | continue; | ||
| 1449 | }, | ||
| 1450 | else => return res, | ||
| 1451 | }; | ||
| 1452 | res = try p.addNode(.{ | ||
| 1453 | .tag = tag, | ||
| 1454 | .main_token = p.nextToken(), | ||
| 1455 | .data = .{ | ||
| 1456 | .lhs = res, | ||
| 1457 | .rhs = try p.expectBitShiftExpr(), | ||
| 1458 | }, | 1394 | }, |
| 1459 | }); | 1395 | .invalid_ampersands => { |
| 1460 | } | 1396 | try p.warn(.invalid_and); |
| 1461 | } | ||
| 1462 | |||
| 1463 | fn expectBitwiseExpr(p: *Parser) Error!Node.Index { | ||
| 1464 | const node = try p.parseBitwiseExpr(); | ||
| 1465 | if (node == 0) { | ||
| 1466 | return p.fail(.invalid_token); | ||
| 1467 | } else { | ||
| 1468 | return node; | ||
| 1469 | } | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | /// BitShiftExpr <- AdditionExpr (BitShiftOp AdditionExpr)* | ||
| 1473 | /// BitShiftOp | ||
| 1474 | /// <- LARROW2 | ||
| 1475 | /// / RARROW2 | ||
| 1476 | fn parseBitShiftExpr(p: *Parser) Error!Node.Index { | ||
| 1477 | var res = try p.parseAdditionExpr(); | ||
| 1478 | if (res == 0) return null_node; | ||
| 1479 | |||
| 1480 | while (true) { | ||
| 1481 | const tag: Node.Tag = switch (p.token_tags[p.tok_i]) { | ||
| 1482 | .angle_bracket_angle_bracket_left => .bit_shift_left, | ||
| 1483 | .angle_bracket_angle_bracket_right => .bit_shift_right, | ||
| 1484 | else => return res, | ||
| 1485 | }; | ||
| 1486 | res = try p.addNode(.{ | ||
| 1487 | .tag = tag, | ||
| 1488 | .main_token = p.nextToken(), | ||
| 1489 | .data = .{ | ||
| 1490 | .lhs = res, | ||
| 1491 | .rhs = try p.expectAdditionExpr(), | ||
| 1492 | }, | 1397 | }, |
| 1493 | }); | 1398 | else => {}, |
| 1494 | } | 1399 | } |
| 1495 | } | 1400 | const rhs = try p.parseExprPrecedence(info.prec + 1); |
| 1496 | 1401 | if (rhs == 0) { | |
| 1497 | fn expectBitShiftExpr(p: *Parser) Error!Node.Index { | 1402 | return p.fail(.invalid_token); |
| 1498 | const node = try p.parseBitShiftExpr(); | 1403 | } |
| 1499 | if (node == 0) { | ||
| 1500 | return p.fail(.invalid_token); | ||
| 1501 | } else { | ||
| 1502 | return node; | ||
| 1503 | } | ||
| 1504 | } | ||
| 1505 | |||
| 1506 | /// AdditionExpr <- MultiplyExpr (AdditionOp MultiplyExpr)* | ||
| 1507 | /// AdditionOp | ||
| 1508 | /// <- PLUS | ||
| 1509 | /// / MINUS | ||
| 1510 | /// / PLUS2 | ||
| 1511 | /// / PLUSPERCENT | ||
| 1512 | /// / MINUSPERCENT | ||
| 1513 | fn parseAdditionExpr(p: *Parser) Error!Node.Index { | ||
| 1514 | var res = try p.parseMultiplyExpr(); | ||
| 1515 | if (res == 0) return null_node; | ||
| 1516 | 1404 | ||
| 1517 | while (true) { | 1405 | node = try p.addNode(.{ |
| 1518 | const tag: Node.Tag = switch (p.token_tags[p.tok_i]) { | 1406 | .tag = info.tag, |
| 1519 | .plus => .add, | 1407 | .main_token = oper_token, |
| 1520 | .minus => .sub, | ||
| 1521 | .plus_plus => .array_cat, | ||
| 1522 | .plus_percent => .add_wrap, | ||
| 1523 | .minus_percent => .sub_wrap, | ||
| 1524 | else => return res, | ||
| 1525 | }; | ||
| 1526 | res = try p.addNode(.{ | ||
| 1527 | .tag = tag, | ||
| 1528 | .main_token = p.nextToken(), | ||
| 1529 | .data = .{ | 1408 | .data = .{ |
| 1530 | .lhs = res, | 1409 | .lhs = node, |
| 1531 | .rhs = try p.expectMultiplyExpr(), | 1410 | .rhs = rhs, |
| 1532 | }, | 1411 | }, |
| 1533 | }); | 1412 | }); |
| 1534 | } | ||
| 1535 | } | ||
| 1536 | 1413 | ||
| 1537 | fn expectAdditionExpr(p: *Parser) Error!Node.Index { | 1414 | if (info.assoc == Assoc.none) { |
| 1538 | const node = try p.parseAdditionExpr(); | 1415 | banned_prec = info.prec; |
| 1539 | if (node == 0) { | 1416 | } |
| 1540 | return p.fail(.invalid_token); | ||
| 1541 | } | ||
| 1542 | return node; | ||
| 1543 | } | ||
| 1544 | |||
| 1545 | /// MultiplyExpr <- PrefixExpr (MultiplyOp PrefixExpr)* | ||
| 1546 | /// MultiplyOp | ||
| 1547 | /// <- PIPE2 | ||
| 1548 | /// / ASTERISK | ||
| 1549 | /// / SLASH | ||
| 1550 | /// / PERCENT | ||
| 1551 | /// / ASTERISK2 | ||
| 1552 | /// / ASTERISKPERCENT | ||
| 1553 | fn parseMultiplyExpr(p: *Parser) Error!Node.Index { | ||
| 1554 | var res = try p.parsePrefixExpr(); | ||
| 1555 | if (res == 0) return null_node; | ||
| 1556 | |||
| 1557 | while (true) { | ||
| 1558 | const tag: Node.Tag = switch (p.token_tags[p.tok_i]) { | ||
| 1559 | .pipe_pipe => .merge_error_sets, | ||
| 1560 | .asterisk => .mul, | ||
| 1561 | .slash => .div, | ||
| 1562 | .percent => .mod, | ||
| 1563 | .asterisk_asterisk => .array_mult, | ||
| 1564 | .asterisk_percent => .mul_wrap, | ||
| 1565 | else => return res, | ||
| 1566 | }; | ||
| 1567 | res = try p.addNode(.{ | ||
| 1568 | .tag = tag, | ||
| 1569 | .main_token = p.nextToken(), | ||
| 1570 | .data = .{ | ||
| 1571 | .lhs = res, | ||
| 1572 | .rhs = try p.expectPrefixExpr(), | ||
| 1573 | }, | ||
| 1574 | }); | ||
| 1575 | } | 1417 | } |
| 1576 | } | ||
| 1577 | 1418 | ||
| 1578 | fn expectMultiplyExpr(p: *Parser) Error!Node.Index { | ||
| 1579 | const node = try p.parseMultiplyExpr(); | ||
| 1580 | if (node == 0) { | ||
| 1581 | return p.fail(.invalid_token); | ||
| 1582 | } | ||
| 1583 | return node; | 1419 | return node; |
| 1584 | } | 1420 | } |
| 1585 | 1421 |
lib/std/zig/parser_test.zig+11| ... | @@ -2828,6 +2828,7 @@ test "zig fmt: precedence" { | ... | @@ -2828,6 +2828,7 @@ test "zig fmt: precedence" { |
| 2828 | \\ a or b and c; | 2828 | \\ a or b and c; |
| 2829 | \\ (a or b) and c; | 2829 | \\ (a or b) and c; |
| 2830 | \\ (a or b) and c; | 2830 | \\ (a or b) and c; |
| 2831 | \\ a == b and c == d; | ||
| 2831 | \\} | 2832 | \\} |
| 2832 | \\ | 2833 | \\ |
| 2833 | ); | 2834 | ); |
| ... | @@ -4892,6 +4893,16 @@ test "recovery: missing comma" { | ... | @@ -4892,6 +4893,16 @@ test "recovery: missing comma" { |
| 4892 | }); | 4893 | }); |
| 4893 | } | 4894 | } |
| 4894 | 4895 | ||
| 4896 | test "recovery: non-associative operators" { | ||
| 4897 | try testError( | ||
| 4898 | \\const x = a == b == c; | ||
| 4899 | \\const x = a == b != c; | ||
| 4900 | , &[_]Error{ | ||
| 4901 | .expected_token, | ||
| 4902 | .expected_token, | ||
| 4903 | }); | ||
| 4904 | } | ||
| 4905 | |||
| 4895 | test "recovery: extra qualifier" { | 4906 | test "recovery: extra qualifier" { |
| 4896 | try testError( | 4907 | try testError( |
| 4897 | \\const a: *const const u8; | 4908 | \\const a: *const const u8; |
src/Compilation.zig+16-8| ... | @@ -638,6 +638,7 @@ pub const InitOptions = struct { | ... | @@ -638,6 +638,7 @@ pub const InitOptions = struct { |
| 638 | system_libs: []const []const u8 = &[0][]const u8{}, | 638 | system_libs: []const []const u8 = &[0][]const u8{}, |
| 639 | link_libc: bool = false, | 639 | link_libc: bool = false, |
| 640 | link_libcpp: bool = false, | 640 | link_libcpp: bool = false, |
| 641 | link_libunwind: bool = false, | ||
| 641 | want_pic: ?bool = null, | 642 | want_pic: ?bool = null, |
| 642 | /// This means that if the output mode is an executable it will be a | 643 | /// This means that if the output mode is an executable it will be a |
| 643 | /// Position Independent Executable. If the output mode is not an | 644 | /// Position Independent Executable. If the output mode is not an |
| ... | @@ -885,8 +886,13 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -885,8 +886,13 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 885 | }; | 886 | }; |
| 886 | 887 | ||
| 887 | const tsan = options.want_tsan orelse false; | 888 | const tsan = options.want_tsan orelse false; |
| 889 | // TSAN is implemented in C++ so it requires linking libc++. | ||
| 890 | const link_libcpp = options.link_libcpp or tsan; | ||
| 891 | const link_libc = link_libcpp or options.link_libc or | ||
| 892 | target_util.osRequiresLibC(options.target); | ||
| 888 | 893 | ||
| 889 | const link_libc = options.link_libc or target_util.osRequiresLibC(options.target) or tsan; | 894 | const link_libunwind = options.link_libunwind or |
| 895 | (link_libcpp and target_util.libcNeedsLibUnwind(options.target)); | ||
| 890 | 896 | ||
| 891 | const must_dynamic_link = dl: { | 897 | const must_dynamic_link = dl: { |
| 892 | if (target_util.cannotDynamicLink(options.target)) | 898 | if (target_util.cannotDynamicLink(options.target)) |
| ... | @@ -972,9 +978,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -972,9 +978,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 972 | break :pic explicit; | 978 | break :pic explicit; |
| 973 | } else pie or must_pic; | 979 | } else pie or must_pic; |
| 974 | 980 | ||
| 975 | // TSAN is implemented in C++ so it requires linking libc++. | ||
| 976 | const link_libcpp = options.link_libcpp or tsan; | ||
| 977 | |||
| 978 | // Make a decision on whether to use Clang for translate-c and compiling C files. | 981 | // Make a decision on whether to use Clang for translate-c and compiling C files. |
| 979 | const use_clang = if (options.use_clang) |explicit| explicit else blk: { | 982 | const use_clang = if (options.use_clang) |explicit| explicit else blk: { |
| 980 | if (build_options.have_llvm) { | 983 | if (build_options.have_llvm) { |
| ... | @@ -1067,6 +1070,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -1067,6 +1070,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1067 | cache.hash.add(strip); | 1070 | cache.hash.add(strip); |
| 1068 | cache.hash.add(link_libc); | 1071 | cache.hash.add(link_libc); |
| 1069 | cache.hash.add(link_libcpp); | 1072 | cache.hash.add(link_libcpp); |
| 1073 | cache.hash.add(link_libunwind); | ||
| 1070 | cache.hash.add(options.output_mode); | 1074 | cache.hash.add(options.output_mode); |
| 1071 | cache.hash.add(options.machine_code_model); | 1075 | cache.hash.add(options.machine_code_model); |
| 1072 | cache.hash.addOptionalEmitLoc(options.emit_bin); | 1076 | cache.hash.addOptionalEmitLoc(options.emit_bin); |
| ... | @@ -1262,6 +1266,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -1262,6 +1266,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1262 | .system_linker_hack = darwin_options.system_linker_hack, | 1266 | .system_linker_hack = darwin_options.system_linker_hack, |
| 1263 | .link_libc = link_libc, | 1267 | .link_libc = link_libc, |
| 1264 | .link_libcpp = link_libcpp, | 1268 | .link_libcpp = link_libcpp, |
| 1269 | .link_libunwind = link_libunwind, | ||
| 1265 | .objects = options.link_objects, | 1270 | .objects = options.link_objects, |
| 1266 | .frameworks = options.frameworks, | 1271 | .frameworks = options.frameworks, |
| 1267 | .framework_dirs = options.framework_dirs, | 1272 | .framework_dirs = options.framework_dirs, |
| ... | @@ -2943,6 +2948,10 @@ pub fn addCCArgs( | ... | @@ -2943,6 +2948,10 @@ pub fn addCCArgs( |
| 2943 | try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p }); | 2948 | try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p }); |
| 2944 | } | 2949 | } |
| 2945 | 2950 | ||
| 2951 | if (target_util.clangMightShellOutForAssembly(target)) { | ||
| 2952 | try argv.append("-integrated-as"); | ||
| 2953 | } | ||
| 2954 | |||
| 2946 | if (target.os.tag == .freestanding) { | 2955 | if (target.os.tag == .freestanding) { |
| 2947 | try argv.append("-ffreestanding"); | 2956 | try argv.append("-ffreestanding"); |
| 2948 | } | 2957 | } |
| ... | @@ -3139,7 +3148,7 @@ fn detectLibCIncludeDirs( | ... | @@ -3139,7 +3148,7 @@ fn detectLibCIncludeDirs( |
| 3139 | 3148 | ||
| 3140 | if (is_native_abi) { | 3149 | if (is_native_abi) { |
| 3141 | const libc = try arena.create(LibCInstallation); | 3150 | const libc = try arena.create(LibCInstallation); |
| 3142 | libc.* = try LibCInstallation.findNative(.{ .allocator = arena }); | 3151 | libc.* = try LibCInstallation.findNative(.{ .allocator = arena, .verbose = true }); |
| 3143 | return detectLibCFromLibCInstallation(arena, target, libc); | 3152 | return detectLibCFromLibCInstallation(arena, target, libc); |
| 3144 | } | 3153 | } |
| 3145 | 3154 | ||
| ... | @@ -3276,9 +3285,8 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool { | ... | @@ -3276,9 +3285,8 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool { |
| 3276 | .Lib => comp.bin_file.options.link_mode == .Dynamic, | 3285 | .Lib => comp.bin_file.options.link_mode == .Dynamic, |
| 3277 | .Exe => true, | 3286 | .Exe => true, |
| 3278 | }; | 3287 | }; |
| 3279 | return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and | 3288 | return is_exe_or_dyn_lib and comp.bin_file.options.link_libunwind and |
| 3280 | comp.bin_file.options.object_format != .c and | 3289 | comp.bin_file.options.object_format != .c; |
| 3281 | target_util.libcNeedsLibUnwind(comp.getTarget()); | ||
| 3282 | } | 3290 | } |
| 3283 | 3291 | ||
| 3284 | fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) Allocator.Error!void { | 3292 | fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) Allocator.Error!void { |
src/clang.zig+5| ... | @@ -905,6 +905,11 @@ pub const TypedefNameDecl = opaque { | ... | @@ -905,6 +905,11 @@ pub const TypedefNameDecl = opaque { |
| 905 | extern fn ZigClangTypedefNameDecl_getLocation(*const TypedefNameDecl) SourceLocation; | 905 | extern fn ZigClangTypedefNameDecl_getLocation(*const TypedefNameDecl) SourceLocation; |
| 906 | }; | 906 | }; |
| 907 | 907 | ||
| 908 | pub const FileScopeAsmDecl = opaque { | ||
| 909 | pub const getAsmString = ZigClangFileScopeAsmDecl_getAsmString; | ||
| 910 | extern fn ZigClangFileScopeAsmDecl_getAsmString(*const FileScopeAsmDecl) *const StringLiteral; | ||
| 911 | }; | ||
| 912 | |||
| 908 | pub const TypedefType = opaque { | 913 | pub const TypedefType = opaque { |
| 909 | pub const getDecl = ZigClangTypedefType_getDecl; | 914 | pub const getDecl = ZigClangTypedefType_getDecl; |
| 910 | extern fn ZigClangTypedefType_getDecl(*const TypedefType) *const TypedefNameDecl; | 915 | extern fn ZigClangTypedefType_getDecl(*const TypedefType) *const TypedefNameDecl; |
src/codegen.zig+9-9| ... | @@ -960,7 +960,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -960,7 +960,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 960 | /// allocated. A second call to `copyToTmpRegister` may return the same register. | 960 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 961 | /// This can have a side effect of spilling instructions to the stack to free up a register. | 961 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 962 | fn copyToTmpRegister(self: *Self, src: LazySrcLoc, ty: Type, mcv: MCValue) !Register { | 962 | fn copyToTmpRegister(self: *Self, src: LazySrcLoc, ty: Type, mcv: MCValue) !Register { |
| 963 | const reg = try self.register_manager.allocRegWithoutTracking(&.{}); | 963 | const reg = try self.register_manager.allocReg(null, &.{}); |
| 964 | try self.genSetReg(src, ty, reg, mcv); | 964 | try self.genSetReg(src, ty, reg, mcv); |
| 965 | return reg; | 965 | return reg; |
| 966 | } | 966 | } |
| ... | @@ -2231,7 +2231,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2231,7 +2231,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2231 | switch (mc_arg) { | 2231 | switch (mc_arg) { |
| 2232 | .none => continue, | 2232 | .none => continue, |
| 2233 | .register => |reg| { | 2233 | .register => |reg| { |
| 2234 | try self.register_manager.getRegWithoutTracking(reg); | 2234 | try self.register_manager.getReg(reg, null); |
| 2235 | try self.genSetReg(arg.src, arg.ty, reg, arg_mcv); | 2235 | try self.genSetReg(arg.src, arg.ty, reg, arg_mcv); |
| 2236 | }, | 2236 | }, |
| 2237 | .stack_offset => { | 2237 | .stack_offset => { |
| ... | @@ -2327,7 +2327,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2327,7 +2327,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2327 | .compare_flags_signed => unreachable, | 2327 | .compare_flags_signed => unreachable, |
| 2328 | .compare_flags_unsigned => unreachable, | 2328 | .compare_flags_unsigned => unreachable, |
| 2329 | .register => |reg| { | 2329 | .register => |reg| { |
| 2330 | try self.register_manager.getRegWithoutTracking(reg); | 2330 | try self.register_manager.getReg(reg, null); |
| 2331 | try self.genSetReg(arg.src, arg.ty, reg, arg_mcv); | 2331 | try self.genSetReg(arg.src, arg.ty, reg, arg_mcv); |
| 2332 | }, | 2332 | }, |
| 2333 | .stack_offset => { | 2333 | .stack_offset => { |
| ... | @@ -2390,7 +2390,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2390,7 +2390,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2390 | .compare_flags_signed => unreachable, | 2390 | .compare_flags_signed => unreachable, |
| 2391 | .compare_flags_unsigned => unreachable, | 2391 | .compare_flags_unsigned => unreachable, |
| 2392 | .register => |reg| { | 2392 | .register => |reg| { |
| 2393 | try self.register_manager.getRegWithoutTracking(reg); | 2393 | try self.register_manager.getReg(reg, null); |
| 2394 | try self.genSetReg(arg.src, arg.ty, reg, arg_mcv); | 2394 | try self.genSetReg(arg.src, arg.ty, reg, arg_mcv); |
| 2395 | }, | 2395 | }, |
| 2396 | .stack_offset => { | 2396 | .stack_offset => { |
| ... | @@ -2443,7 +2443,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2443,7 +2443,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2443 | .register => |reg| { | 2443 | .register => |reg| { |
| 2444 | // TODO prevent this macho if block to be generated for all archs | 2444 | // TODO prevent this macho if block to be generated for all archs |
| 2445 | switch (arch) { | 2445 | switch (arch) { |
| 2446 | .x86_64, .aarch64 => try self.register_manager.getRegWithoutTracking(reg), | 2446 | .x86_64, .aarch64 => try self.register_manager.getReg(reg, null), |
| 2447 | else => unreachable, | 2447 | else => unreachable, |
| 2448 | } | 2448 | } |
| 2449 | try self.genSetReg(arg.src, arg.ty, reg, arg_mcv); | 2449 | try self.genSetReg(arg.src, arg.ty, reg, arg_mcv); |
| ... | @@ -3134,7 +3134,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -3134,7 +3134,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3134 | 3134 | ||
| 3135 | const arg = inst.args[i]; | 3135 | const arg = inst.args[i]; |
| 3136 | const arg_mcv = try self.resolveInst(arg); | 3136 | const arg_mcv = try self.resolveInst(arg); |
| 3137 | try self.register_manager.getRegWithoutTracking(reg); | 3137 | try self.register_manager.getReg(reg, null); |
| 3138 | try self.genSetReg(inst.base.src, arg.ty, reg, arg_mcv); | 3138 | try self.genSetReg(inst.base.src, arg.ty, reg, arg_mcv); |
| 3139 | } | 3139 | } |
| 3140 | 3140 | ||
| ... | @@ -3167,7 +3167,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -3167,7 +3167,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3167 | 3167 | ||
| 3168 | const arg = inst.args[i]; | 3168 | const arg = inst.args[i]; |
| 3169 | const arg_mcv = try self.resolveInst(arg); | 3169 | const arg_mcv = try self.resolveInst(arg); |
| 3170 | try self.register_manager.getRegWithoutTracking(reg); | 3170 | try self.register_manager.getReg(reg, null); |
| 3171 | try self.genSetReg(inst.base.src, arg.ty, reg, arg_mcv); | 3171 | try self.genSetReg(inst.base.src, arg.ty, reg, arg_mcv); |
| 3172 | } | 3172 | } |
| 3173 | 3173 | ||
| ... | @@ -3202,7 +3202,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -3202,7 +3202,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3202 | 3202 | ||
| 3203 | const arg = inst.args[i]; | 3203 | const arg = inst.args[i]; |
| 3204 | const arg_mcv = try self.resolveInst(arg); | 3204 | const arg_mcv = try self.resolveInst(arg); |
| 3205 | try self.register_manager.getRegWithoutTracking(reg); | 3205 | try self.register_manager.getReg(reg, null); |
| 3206 | try self.genSetReg(inst.base.src, arg.ty, reg, arg_mcv); | 3206 | try self.genSetReg(inst.base.src, arg.ty, reg, arg_mcv); |
| 3207 | } | 3207 | } |
| 3208 | 3208 | ||
| ... | @@ -3235,7 +3235,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -3235,7 +3235,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3235 | 3235 | ||
| 3236 | const arg = inst.args[i]; | 3236 | const arg = inst.args[i]; |
| 3237 | const arg_mcv = try self.resolveInst(arg); | 3237 | const arg_mcv = try self.resolveInst(arg); |
| 3238 | try self.register_manager.getRegWithoutTracking(reg); | 3238 | try self.register_manager.getReg(reg, null); |
| 3239 | try self.genSetReg(inst.base.src, arg.ty, reg, arg_mcv); | 3239 | try self.genSetReg(inst.base.src, arg.ty, reg, arg_mcv); |
| 3240 | } | 3240 | } |
| 3241 | 3241 |
src/codegen/spirv.zig+74-19| ... | @@ -1,9 +1,13 @@ | ... | @@ -1,9 +1,13 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const Allocator = std.mem.Allocator; | 2 | const Allocator = std.mem.Allocator; |
| 3 | const log = std.log.scoped(.codegen); | ||
| 3 | 4 | ||
| 4 | const spec = @import("spirv/spec.zig"); | 5 | const spec = @import("spirv/spec.zig"); |
| 5 | const Module = @import("../Module.zig"); | 6 | const Module = @import("../Module.zig"); |
| 6 | const Decl = Module.Decl; | 7 | const Decl = Module.Decl; |
| 8 | const Type = @import("../type.zig").Type; | ||
| 9 | |||
| 10 | pub const TypeMap = std.HashMap(Type, u32, Type.hash, Type.eql, std.hash_map.default_max_load_percentage); | ||
| 7 | 11 | ||
| 8 | pub fn writeInstruction(code: *std.ArrayList(u32), instr: spec.Opcode, args: []const u32) !void { | 12 | pub fn writeInstruction(code: *std.ArrayList(u32), instr: spec.Opcode, args: []const u32) !void { |
| 9 | const word_count = @intCast(u32, args.len + 1); | 13 | const word_count = @intCast(u32, args.len + 1); |
| ... | @@ -12,38 +16,89 @@ pub fn writeInstruction(code: *std.ArrayList(u32), instr: spec.Opcode, args: []c | ... | @@ -12,38 +16,89 @@ pub fn writeInstruction(code: *std.ArrayList(u32), instr: spec.Opcode, args: []c |
| 12 | } | 16 | } |
| 13 | 17 | ||
| 14 | pub const SPIRVModule = struct { | 18 | pub const SPIRVModule = struct { |
| 15 | next_id: u32 = 0, | 19 | next_result_id: u32 = 0, |
| 16 | free_id_list: std.ArrayList(u32), | 20 | |
| 21 | target: std.Target, | ||
| 22 | |||
| 23 | types: TypeMap, | ||
| 24 | |||
| 25 | types_and_globals: std.ArrayList(u32), | ||
| 26 | fn_decls: std.ArrayList(u32), | ||
| 17 | 27 | ||
| 18 | pub fn init(allocator: *Allocator) SPIRVModule { | 28 | pub fn init(target: std.Target, allocator: *Allocator) SPIRVModule { |
| 19 | return .{ | 29 | return .{ |
| 20 | .free_id_list = std.ArrayList(u32).init(allocator), | 30 | .target = target, |
| 31 | .types = TypeMap.init(allocator), | ||
| 32 | .types_and_globals = std.ArrayList(u32).init(allocator), | ||
| 33 | .fn_decls = std.ArrayList(u32).init(allocator), | ||
| 21 | }; | 34 | }; |
| 22 | } | 35 | } |
| 23 | 36 | ||
| 24 | pub fn deinit(self: *SPIRVModule) void { | 37 | pub fn deinit(self: *SPIRVModule) void { |
| 25 | self.free_id_list.deinit(); | 38 | self.fn_decls.deinit(); |
| 39 | self.types_and_globals.deinit(); | ||
| 40 | self.types.deinit(); | ||
| 41 | self.* = undefined; | ||
| 26 | } | 42 | } |
| 27 | 43 | ||
| 28 | pub fn allocId(self: *SPIRVModule) u32 { | 44 | pub fn allocResultId(self: *SPIRVModule) u32 { |
| 29 | if (self.free_id_list.popOrNull()) |id| return id; | 45 | defer self.next_result_id += 1; |
| 46 | return self.next_result_id; | ||
| 47 | } | ||
| 30 | 48 | ||
| 31 | defer self.next_id += 1; | 49 | pub fn resultIdBound(self: *SPIRVModule) u32 { |
| 32 | return self.next_id; | 50 | return self.next_result_id; |
| 33 | } | 51 | } |
| 34 | 52 | ||
| 35 | pub fn freeId(self: *SPIRVModule, id: u32) void { | 53 | pub fn getOrGenType(self: *SPIRVModule, t: Type) !u32 { |
| 36 | if (id + 1 == self.next_id) { | 54 | // We can't use getOrPut here so we can recursively generate types. |
| 37 | self.next_id -= 1; | 55 | if (self.types.get(t)) |already_generated| { |
| 38 | } else { | 56 | return already_generated; |
| 39 | // If no more memory to append the id to the free list, just ignore it. | ||
| 40 | self.free_id_list.append(id) catch {}; | ||
| 41 | } | 57 | } |
| 42 | } | ||
| 43 | 58 | ||
| 44 | pub fn idBound(self: *SPIRVModule) u32 { | 59 | const result = self.allocResultId(); |
| 45 | return self.next_id; | 60 | |
| 61 | switch (t.zigTypeTag()) { | ||
| 62 | .Void => try writeInstruction(&self.types_and_globals, .OpTypeVoid, &[_]u32{ result }), | ||
| 63 | .Bool => try writeInstruction(&self.types_and_globals, .OpTypeBool, &[_]u32{ result }), | ||
| 64 | .Int => { | ||
| 65 | const int_info = t.intInfo(self.target); | ||
| 66 | try writeInstruction(&self.types_and_globals, .OpTypeInt, &[_]u32{ | ||
| 67 | result, | ||
| 68 | int_info.bits, | ||
| 69 | switch (int_info.signedness) { | ||
| 70 | .unsigned => 0, | ||
| 71 | .signed => 1, | ||
| 72 | }, | ||
| 73 | }); | ||
| 74 | }, | ||
| 75 | // TODO: Verify that floatBits() will be correct. | ||
| 76 | .Float => try writeInstruction(&self.types_and_globals, .OpTypeFloat, &[_]u32{ result, t.floatBits(self.target) }), | ||
| 77 | .Null, | ||
| 78 | .Undefined, | ||
| 79 | .EnumLiteral, | ||
| 80 | .ComptimeFloat, | ||
| 81 | .ComptimeInt, | ||
| 82 | .Type, | ||
| 83 | => unreachable, // Must be const or comptime. | ||
| 84 | |||
| 85 | .BoundFn => unreachable, // this type will be deleted from the language. | ||
| 86 | |||
| 87 | else => return error.TODO, | ||
| 88 | } | ||
| 89 | |||
| 90 | try self.types.put(t, result); | ||
| 91 | return result; | ||
| 46 | } | 92 | } |
| 47 | 93 | ||
| 48 | pub fn genDecl(self: SPIRVModule, id: u32, code: *std.ArrayList(u32), decl: *Decl) !void {} | 94 | pub fn gen(self: *SPIRVModule, decl: *Decl) !void { |
| 95 | switch (decl.ty.zigTypeTag()) { | ||
| 96 | .Fn => { | ||
| 97 | log.debug("Generating code for function '{s}'", .{ std.mem.spanZ(decl.name) }); | ||
| 98 | |||
| 99 | _ = try self.getOrGenType(decl.ty.fnReturnType()); | ||
| 100 | }, | ||
| 101 | else => return error.TODO, | ||
| 102 | } | ||
| 103 | } | ||
| 49 | }; | 104 | }; |
src/codegen/spirv/spec.zig+89-31| ... | @@ -1,26 +1,5 @@ | ... | @@ -1,26 +1,5 @@ |
| 1 | // Copyright (c) 2014-2020 The Khronos Group Inc. | 1 | //! This file is auto-generated by tools/gen_spirv_spec.zig. |
| 2 | // | 2 | |
| 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 4 | // of this software and/or associated documentation files (the "Materials"), | ||
| 5 | // to deal in the Materials without restriction, including without limitation | ||
| 6 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 7 | // and/or sell copies of the Materials, and to permit persons to whom the | ||
| 8 | // Materials are furnished to do so, subject to the following conditions: | ||
| 9 | // | ||
| 10 | // The above copyright notice and this permission notice shall be included in | ||
| 11 | // all copies or substantial portions of the Materials. | ||
| 12 | // | ||
| 13 | // MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS | ||
| 14 | // STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND | ||
| 15 | // HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ | ||
| 16 | // | ||
| 17 | // THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
| 18 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 20 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 22 | // FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS | ||
| 23 | // IN THE MATERIALS. | ||
| 24 | const Version = @import("std").builtin.Version; | 3 | const Version = @import("std").builtin.Version; |
| 25 | pub const version = Version{ .major = 1, .minor = 5, .patch = 4 }; | 4 | pub const version = Version{ .major = 1, .minor = 5, .patch = 4 }; |
| 26 | pub const magic_number: u32 = 0x07230203; | 5 | pub const magic_number: u32 = 0x07230203; |
| ... | @@ -443,8 +422,15 @@ pub const Opcode = extern enum(u16) { | ... | @@ -443,8 +422,15 @@ pub const Opcode = extern enum(u16) { |
| 443 | OpUSubSatINTEL = 5596, | 422 | OpUSubSatINTEL = 5596, |
| 444 | OpIMul32x16INTEL = 5597, | 423 | OpIMul32x16INTEL = 5597, |
| 445 | OpUMul32x16INTEL = 5598, | 424 | OpUMul32x16INTEL = 5598, |
| 446 | OpFunctionPointerINTEL = 5600, | 425 | OpConstFunctionPointerINTEL = 5600, |
| 447 | OpFunctionPointerCallINTEL = 5601, | 426 | OpFunctionPointerCallINTEL = 5601, |
| 427 | OpAsmTargetINTEL = 5609, | ||
| 428 | OpAsmINTEL = 5610, | ||
| 429 | OpAsmCallINTEL = 5611, | ||
| 430 | OpAtomicFMinEXT = 5614, | ||
| 431 | OpAtomicFMaxEXT = 5615, | ||
| 432 | OpAssumeTrueKHR = 5630, | ||
| 433 | OpExpectKHR = 5631, | ||
| 448 | OpDecorateString = 5632, | 434 | OpDecorateString = 5632, |
| 449 | OpDecorateStringGOOGLE = 5632, | 435 | OpDecorateStringGOOGLE = 5632, |
| 450 | OpMemberDecorateString = 5633, | 436 | OpMemberDecorateString = 5633, |
| ... | @@ -567,7 +553,12 @@ pub const Opcode = extern enum(u16) { | ... | @@ -567,7 +553,12 @@ pub const Opcode = extern enum(u16) { |
| 567 | OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, | 553 | OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, |
| 568 | OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, | 554 | OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, |
| 569 | OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, | 555 | OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, |
| 556 | OpVariableLengthArrayINTEL = 5818, | ||
| 557 | OpSaveMemoryINTEL = 5819, | ||
| 558 | OpRestoreMemoryINTEL = 5820, | ||
| 570 | OpLoopControlINTEL = 5887, | 559 | OpLoopControlINTEL = 5887, |
| 560 | OpPtrCastToCrossWorkgroupINTEL = 5934, | ||
| 561 | OpCrossWorkgroupCastToPtrINTEL = 5938, | ||
| 571 | OpReadPipeBlockingINTEL = 5946, | 562 | OpReadPipeBlockingINTEL = 5946, |
| 572 | OpWritePipeBlockingINTEL = 5947, | 563 | OpWritePipeBlockingINTEL = 5947, |
| 573 | OpFPGARegINTEL = 5949, | 564 | OpFPGARegINTEL = 5949, |
| ... | @@ -589,6 +580,10 @@ pub const Opcode = extern enum(u16) { | ... | @@ -589,6 +580,10 @@ pub const Opcode = extern enum(u16) { |
| 589 | OpRayQueryGetIntersectionObjectToWorldKHR = 6031, | 580 | OpRayQueryGetIntersectionObjectToWorldKHR = 6031, |
| 590 | OpRayQueryGetIntersectionWorldToObjectKHR = 6032, | 581 | OpRayQueryGetIntersectionWorldToObjectKHR = 6032, |
| 591 | OpAtomicFAddEXT = 6035, | 582 | OpAtomicFAddEXT = 6035, |
| 583 | OpTypeBufferSurfaceINTEL = 6086, | ||
| 584 | OpTypeStructContinuedINTEL = 6090, | ||
| 585 | OpConstantCompositeContinuedINTEL = 6091, | ||
| 586 | OpSpecConstantCompositeContinuedINTEL = 6092, | ||
| 592 | _, | 587 | _, |
| 593 | }; | 588 | }; |
| 594 | pub const ImageOperands = packed struct { | 589 | pub const ImageOperands = packed struct { |
| ... | @@ -642,8 +637,8 @@ pub const FPFastMathMode = packed struct { | ... | @@ -642,8 +637,8 @@ pub const FPFastMathMode = packed struct { |
| 642 | _reserved_bit_13: bool = false, | 637 | _reserved_bit_13: bool = false, |
| 643 | _reserved_bit_14: bool = false, | 638 | _reserved_bit_14: bool = false, |
| 644 | _reserved_bit_15: bool = false, | 639 | _reserved_bit_15: bool = false, |
| 645 | _reserved_bit_16: bool = false, | 640 | AllowContractFastINTEL: bool = false, |
| 646 | _reserved_bit_17: bool = false, | 641 | AllowReassocINTEL: bool = false, |
| 647 | _reserved_bit_18: bool = false, | 642 | _reserved_bit_18: bool = false, |
| 648 | _reserved_bit_19: bool = false, | 643 | _reserved_bit_19: bool = false, |
| 649 | _reserved_bit_20: bool = false, | 644 | _reserved_bit_20: bool = false, |
| ... | @@ -717,7 +712,7 @@ pub const LoopControl = packed struct { | ... | @@ -717,7 +712,7 @@ pub const LoopControl = packed struct { |
| 717 | LoopCoalesceINTEL: bool = false, | 712 | LoopCoalesceINTEL: bool = false, |
| 718 | MaxInterleavingINTEL: bool = false, | 713 | MaxInterleavingINTEL: bool = false, |
| 719 | SpeculatedIterationsINTEL: bool = false, | 714 | SpeculatedIterationsINTEL: bool = false, |
| 720 | _reserved_bit_23: bool = false, | 715 | NoFusionINTEL: bool = false, |
| 721 | _reserved_bit_24: bool = false, | 716 | _reserved_bit_24: bool = false, |
| 722 | _reserved_bit_25: bool = false, | 717 | _reserved_bit_25: bool = false, |
| 723 | _reserved_bit_26: bool = false, | 718 | _reserved_bit_26: bool = false, |
| ... | @@ -1037,10 +1032,16 @@ pub const ExecutionMode = extern enum(u32) { | ... | @@ -1037,10 +1032,16 @@ pub const ExecutionMode = extern enum(u32) { |
| 1037 | SampleInterlockUnorderedEXT = 5369, | 1032 | SampleInterlockUnorderedEXT = 5369, |
| 1038 | ShadingRateInterlockOrderedEXT = 5370, | 1033 | ShadingRateInterlockOrderedEXT = 5370, |
| 1039 | ShadingRateInterlockUnorderedEXT = 5371, | 1034 | ShadingRateInterlockUnorderedEXT = 5371, |
| 1035 | SharedLocalMemorySizeINTEL = 5618, | ||
| 1036 | RoundingModeRTPINTEL = 5620, | ||
| 1037 | RoundingModeRTNINTEL = 5621, | ||
| 1038 | FloatingPointModeALTINTEL = 5622, | ||
| 1039 | FloatingPointModeIEEEINTEL = 5623, | ||
| 1040 | MaxWorkgroupSizeINTEL = 5893, | 1040 | MaxWorkgroupSizeINTEL = 5893, |
| 1041 | MaxWorkDimINTEL = 5894, | 1041 | MaxWorkDimINTEL = 5894, |
| 1042 | NoGlobalOffsetINTEL = 5895, | 1042 | NoGlobalOffsetINTEL = 5895, |
| 1043 | NumSIMDWorkitemsINTEL = 5896, | 1043 | NumSIMDWorkitemsINTEL = 5896, |
| 1044 | SchedulerTargetFmaxMhzINTEL = 5903, | ||
| 1044 | _, | 1045 | _, |
| 1045 | }; | 1046 | }; |
| 1046 | pub const StorageClass = extern enum(u32) { | 1047 | pub const StorageClass = extern enum(u32) { |
| ... | @@ -1072,6 +1073,8 @@ pub const StorageClass = extern enum(u32) { | ... | @@ -1072,6 +1073,8 @@ pub const StorageClass = extern enum(u32) { |
| 1072 | PhysicalStorageBuffer = 5349, | 1073 | PhysicalStorageBuffer = 5349, |
| 1073 | PhysicalStorageBufferEXT = 5349, | 1074 | PhysicalStorageBufferEXT = 5349, |
| 1074 | CodeSectionINTEL = 5605, | 1075 | CodeSectionINTEL = 5605, |
| 1076 | DeviceOnlyINTEL = 5936, | ||
| 1077 | HostOnlyINTEL = 5937, | ||
| 1075 | _, | 1078 | _, |
| 1076 | }; | 1079 | }; |
| 1077 | pub const Dim = extern enum(u32) { | 1080 | pub const Dim = extern enum(u32) { |
| ... | @@ -1192,9 +1195,20 @@ pub const FPRoundingMode = extern enum(u32) { | ... | @@ -1192,9 +1195,20 @@ pub const FPRoundingMode = extern enum(u32) { |
| 1192 | RTN = 3, | 1195 | RTN = 3, |
| 1193 | _, | 1196 | _, |
| 1194 | }; | 1197 | }; |
| 1198 | pub const FPDenormMode = extern enum(u32) { | ||
| 1199 | Preserve = 0, | ||
| 1200 | FlushToZero = 1, | ||
| 1201 | _, | ||
| 1202 | }; | ||
| 1203 | pub const FPOperationMode = extern enum(u32) { | ||
| 1204 | IEEE = 0, | ||
| 1205 | ALT = 1, | ||
| 1206 | _, | ||
| 1207 | }; | ||
| 1195 | pub const LinkageType = extern enum(u32) { | 1208 | pub const LinkageType = extern enum(u32) { |
| 1196 | Export = 0, | 1209 | Export = 0, |
| 1197 | Import = 1, | 1210 | Import = 1, |
| 1211 | LinkOnceODR = 2, | ||
| 1198 | _, | 1212 | _, |
| 1199 | }; | 1213 | }; |
| 1200 | pub const AccessQualifier = extern enum(u32) { | 1214 | pub const AccessQualifier = extern enum(u32) { |
| ... | @@ -1279,12 +1293,22 @@ pub const Decoration = extern enum(u32) { | ... | @@ -1279,12 +1293,22 @@ pub const Decoration = extern enum(u32) { |
| 1279 | RestrictPointerEXT = 5355, | 1293 | RestrictPointerEXT = 5355, |
| 1280 | AliasedPointer = 5356, | 1294 | AliasedPointer = 5356, |
| 1281 | AliasedPointerEXT = 5356, | 1295 | AliasedPointerEXT = 5356, |
| 1296 | SIMTCallINTEL = 5599, | ||
| 1282 | ReferencedIndirectlyINTEL = 5602, | 1297 | ReferencedIndirectlyINTEL = 5602, |
| 1298 | ClobberINTEL = 5607, | ||
| 1299 | SideEffectsINTEL = 5608, | ||
| 1300 | VectorComputeVariableINTEL = 5624, | ||
| 1301 | FuncParamIOKindINTEL = 5625, | ||
| 1302 | VectorComputeFunctionINTEL = 5626, | ||
| 1303 | StackCallINTEL = 5627, | ||
| 1304 | GlobalVariableOffsetINTEL = 5628, | ||
| 1283 | CounterBuffer = 5634, | 1305 | CounterBuffer = 5634, |
| 1284 | HlslCounterBufferGOOGLE = 5634, | 1306 | HlslCounterBufferGOOGLE = 5634, |
| 1285 | UserSemantic = 5635, | 1307 | UserSemantic = 5635, |
| 1286 | HlslSemanticGOOGLE = 5635, | 1308 | HlslSemanticGOOGLE = 5635, |
| 1287 | UserTypeGOOGLE = 5636, | 1309 | UserTypeGOOGLE = 5636, |
| 1310 | FunctionRoundingModeINTEL = 5822, | ||
| 1311 | FunctionDenormModeINTEL = 5823, | ||
| 1288 | RegisterINTEL = 5825, | 1312 | RegisterINTEL = 5825, |
| 1289 | MemoryINTEL = 5826, | 1313 | MemoryINTEL = 5826, |
| 1290 | NumbanksINTEL = 5827, | 1314 | NumbanksINTEL = 5827, |
| ... | @@ -1297,6 +1321,17 @@ pub const Decoration = extern enum(u32) { | ... | @@ -1297,6 +1321,17 @@ pub const Decoration = extern enum(u32) { |
| 1297 | MergeINTEL = 5834, | 1321 | MergeINTEL = 5834, |
| 1298 | BankBitsINTEL = 5835, | 1322 | BankBitsINTEL = 5835, |
| 1299 | ForcePow2DepthINTEL = 5836, | 1323 | ForcePow2DepthINTEL = 5836, |
| 1324 | BurstCoalesceINTEL = 5899, | ||
| 1325 | CacheSizeINTEL = 5900, | ||
| 1326 | DontStaticallyCoalesceINTEL = 5901, | ||
| 1327 | PrefetchINTEL = 5902, | ||
| 1328 | StallEnableINTEL = 5905, | ||
| 1329 | FuseLoopsInFunctionINTEL = 5907, | ||
| 1330 | BufferLocationINTEL = 5921, | ||
| 1331 | IOPipeStorageINTEL = 5944, | ||
| 1332 | FunctionFloatingPointModeINTEL = 6080, | ||
| 1333 | SingleElementVectorINTEL = 6085, | ||
| 1334 | VectorComputeCallableFunctionINTEL = 6087, | ||
| 1300 | _, | 1335 | _, |
| 1301 | }; | 1336 | }; |
| 1302 | pub const BuiltIn = extern enum(u32) { | 1337 | pub const BuiltIn = extern enum(u32) { |
| ... | @@ -1342,14 +1377,14 @@ pub const BuiltIn = extern enum(u32) { | ... | @@ -1342,14 +1377,14 @@ pub const BuiltIn = extern enum(u32) { |
| 1342 | VertexIndex = 42, | 1377 | VertexIndex = 42, |
| 1343 | InstanceIndex = 43, | 1378 | InstanceIndex = 43, |
| 1344 | SubgroupEqMask = 4416, | 1379 | SubgroupEqMask = 4416, |
| 1345 | SubgroupGeMask = 4417, | ||
| 1346 | SubgroupGtMask = 4418, | ||
| 1347 | SubgroupLeMask = 4419, | ||
| 1348 | SubgroupLtMask = 4420, | ||
| 1349 | SubgroupEqMaskKHR = 4416, | 1380 | SubgroupEqMaskKHR = 4416, |
| 1381 | SubgroupGeMask = 4417, | ||
| 1350 | SubgroupGeMaskKHR = 4417, | 1382 | SubgroupGeMaskKHR = 4417, |
| 1383 | SubgroupGtMask = 4418, | ||
| 1351 | SubgroupGtMaskKHR = 4418, | 1384 | SubgroupGtMaskKHR = 4418, |
| 1385 | SubgroupLeMask = 4419, | ||
| 1352 | SubgroupLeMaskKHR = 4419, | 1386 | SubgroupLeMaskKHR = 4419, |
| 1387 | SubgroupLtMask = 4420, | ||
| 1353 | SubgroupLtMaskKHR = 4420, | 1388 | SubgroupLtMaskKHR = 4420, |
| 1354 | BaseVertex = 4424, | 1389 | BaseVertex = 4424, |
| 1355 | BaseInstance = 4425, | 1390 | BaseInstance = 4425, |
| ... | @@ -1520,6 +1555,9 @@ pub const Capability = extern enum(u32) { | ... | @@ -1520,6 +1555,9 @@ pub const Capability = extern enum(u32) { |
| 1520 | FragmentShadingRateKHR = 4422, | 1555 | FragmentShadingRateKHR = 4422, |
| 1521 | SubgroupBallotKHR = 4423, | 1556 | SubgroupBallotKHR = 4423, |
| 1522 | DrawParameters = 4427, | 1557 | DrawParameters = 4427, |
| 1558 | WorkgroupMemoryExplicitLayoutKHR = 4428, | ||
| 1559 | WorkgroupMemoryExplicitLayout8BitAccessKHR = 4429, | ||
| 1560 | WorkgroupMemoryExplicitLayout16BitAccessKHR = 4430, | ||
| 1523 | SubgroupVoteKHR = 4431, | 1561 | SubgroupVoteKHR = 4431, |
| 1524 | StorageBuffer16BitAccess = 4433, | 1562 | StorageBuffer16BitAccess = 4433, |
| 1525 | StorageUniformBufferBlock16 = 4433, | 1563 | StorageUniformBufferBlock16 = 4433, |
| ... | @@ -1610,21 +1648,41 @@ pub const Capability = extern enum(u32) { | ... | @@ -1610,21 +1648,41 @@ pub const Capability = extern enum(u32) { |
| 1610 | SubgroupBufferBlockIOINTEL = 5569, | 1648 | SubgroupBufferBlockIOINTEL = 5569, |
| 1611 | SubgroupImageBlockIOINTEL = 5570, | 1649 | SubgroupImageBlockIOINTEL = 5570, |
| 1612 | SubgroupImageMediaBlockIOINTEL = 5579, | 1650 | SubgroupImageMediaBlockIOINTEL = 5579, |
| 1651 | RoundToInfinityINTEL = 5582, | ||
| 1652 | FloatingPointModeINTEL = 5583, | ||
| 1613 | IntegerFunctions2INTEL = 5584, | 1653 | IntegerFunctions2INTEL = 5584, |
| 1614 | FunctionPointersINTEL = 5603, | 1654 | FunctionPointersINTEL = 5603, |
| 1615 | IndirectReferencesINTEL = 5604, | 1655 | IndirectReferencesINTEL = 5604, |
| 1656 | AsmINTEL = 5606, | ||
| 1657 | AtomicFloat32MinMaxEXT = 5612, | ||
| 1658 | AtomicFloat64MinMaxEXT = 5613, | ||
| 1659 | AtomicFloat16MinMaxEXT = 5616, | ||
| 1660 | VectorComputeINTEL = 5617, | ||
| 1661 | VectorAnyINTEL = 5619, | ||
| 1662 | ExpectAssumeKHR = 5629, | ||
| 1616 | SubgroupAvcMotionEstimationINTEL = 5696, | 1663 | SubgroupAvcMotionEstimationINTEL = 5696, |
| 1617 | SubgroupAvcMotionEstimationIntraINTEL = 5697, | 1664 | SubgroupAvcMotionEstimationIntraINTEL = 5697, |
| 1618 | SubgroupAvcMotionEstimationChromaINTEL = 5698, | 1665 | SubgroupAvcMotionEstimationChromaINTEL = 5698, |
| 1666 | VariableLengthArrayINTEL = 5817, | ||
| 1667 | FunctionFloatControlINTEL = 5821, | ||
| 1619 | FPGAMemoryAttributesINTEL = 5824, | 1668 | FPGAMemoryAttributesINTEL = 5824, |
| 1669 | FPFastMathModeINTEL = 5837, | ||
| 1670 | ArbitraryPrecisionIntegersINTEL = 5844, | ||
| 1620 | UnstructuredLoopControlsINTEL = 5886, | 1671 | UnstructuredLoopControlsINTEL = 5886, |
| 1621 | FPGALoopControlsINTEL = 5888, | 1672 | FPGALoopControlsINTEL = 5888, |
| 1622 | KernelAttributesINTEL = 5892, | 1673 | KernelAttributesINTEL = 5892, |
| 1623 | FPGAKernelAttributesINTEL = 5897, | 1674 | FPGAKernelAttributesINTEL = 5897, |
| 1675 | FPGAMemoryAccessesINTEL = 5898, | ||
| 1676 | FPGAClusterAttributesINTEL = 5904, | ||
| 1677 | LoopFuseINTEL = 5906, | ||
| 1678 | FPGABufferLocationINTEL = 5920, | ||
| 1679 | USMStorageClassesINTEL = 5935, | ||
| 1680 | IOPipesINTEL = 5943, | ||
| 1624 | BlockingPipesINTEL = 5945, | 1681 | BlockingPipesINTEL = 5945, |
| 1625 | FPGARegINTEL = 5948, | 1682 | FPGARegINTEL = 5948, |
| 1626 | AtomicFloat32AddEXT = 6033, | 1683 | AtomicFloat32AddEXT = 6033, |
| 1627 | AtomicFloat64AddEXT = 6034, | 1684 | AtomicFloat64AddEXT = 6034, |
| 1685 | LongConstantCompositeINTEL = 6089, | ||
| 1628 | _, | 1686 | _, |
| 1629 | }; | 1687 | }; |
| 1630 | pub const RayQueryIntersection = extern enum(u32) { | 1688 | pub const RayQueryIntersection = extern enum(u32) { |
src/glibc.zig+7-3| ... | @@ -446,10 +446,14 @@ fn start_asm_path(comp: *Compilation, arena: *Allocator, basename: []const u8) ! | ... | @@ -446,10 +446,14 @@ fn start_asm_path(comp: *Compilation, arena: *Allocator, basename: []const u8) ! |
| 446 | try result.appendSlice(comp.zig_lib_directory.path.?); | 446 | try result.appendSlice(comp.zig_lib_directory.path.?); |
| 447 | try result.appendSlice(s ++ "libc" ++ s ++ "glibc" ++ s ++ "sysdeps" ++ s); | 447 | try result.appendSlice(s ++ "libc" ++ s ++ "glibc" ++ s ++ "sysdeps" ++ s); |
| 448 | if (is_sparc) { | 448 | if (is_sparc) { |
| 449 | if (is_64) { | 449 | if (mem.eql(u8, basename, "crti.S") or mem.eql(u8, basename, "crtn.S")) { |
| 450 | try result.appendSlice("sparc" ++ s ++ "sparc64"); | 450 | try result.appendSlice("sparc"); |
| 451 | } else { | 451 | } else { |
| 452 | try result.appendSlice("sparc" ++ s ++ "sparc32"); | 452 | if (is_64) { |
| 453 | try result.appendSlice("sparc" ++ s ++ "sparc64"); | ||
| 454 | } else { | ||
| 455 | try result.appendSlice("sparc" ++ s ++ "sparc32"); | ||
| 456 | } | ||
| 453 | } | 457 | } |
| 454 | } else if (arch.isARM()) { | 458 | } else if (arch.isARM()) { |
| 455 | try result.appendSlice("arm"); | 459 | try result.appendSlice("arm"); |
src/link.zig+1| ... | @@ -63,6 +63,7 @@ pub const Options = struct { | ... | @@ -63,6 +63,7 @@ pub const Options = struct { |
| 63 | system_linker_hack: bool, | 63 | system_linker_hack: bool, |
| 64 | link_libc: bool, | 64 | link_libc: bool, |
| 65 | link_libcpp: bool, | 65 | link_libcpp: bool, |
| 66 | link_libunwind: bool, | ||
| 66 | function_sections: bool, | 67 | function_sections: bool, |
| 67 | eh_frame_hdr: bool, | 68 | eh_frame_hdr: bool, |
| 68 | emit_relocs: bool, | 69 | emit_relocs: bool, |
src/link/Elf.zig+6-13| ... | @@ -1645,6 +1645,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1645,6 +1645,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1645 | try argv.append(comp.libcxx_static_lib.?.full_object_path); | 1645 | try argv.append(comp.libcxx_static_lib.?.full_object_path); |
| 1646 | } | 1646 | } |
| 1647 | 1647 | ||
| 1648 | // libunwind dep | ||
| 1649 | if (self.base.options.link_libunwind) { | ||
| 1650 | try argv.append(comp.libunwind_static_lib.?.full_object_path); | ||
| 1651 | } | ||
| 1652 | |||
| 1648 | // libc dep | 1653 | // libc dep |
| 1649 | if (self.base.options.link_libc) { | 1654 | if (self.base.options.link_libc) { |
| 1650 | if (self.base.options.libc_installation != null) { | 1655 | if (self.base.options.libc_installation != null) { |
| ... | @@ -1653,18 +1658,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1653,18 +1658,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1653 | } | 1658 | } |
| 1654 | const needs_grouping = self.base.options.link_mode == .Static; | 1659 | const needs_grouping = self.base.options.link_mode == .Static; |
| 1655 | if (needs_grouping) try argv.append("--start-group"); | 1660 | if (needs_grouping) try argv.append("--start-group"); |
| 1656 | // This matches the order of glibc.libs | 1661 | try argv.appendSlice(target_util.libcFullLinkFlags(target)); |
| 1657 | try argv.appendSlice(&[_][]const u8{ | ||
| 1658 | "-lm", | ||
| 1659 | "-lpthread", | ||
| 1660 | "-lc", | ||
| 1661 | "-ldl", | ||
| 1662 | "-lrt", | ||
| 1663 | "-lutil", | ||
| 1664 | }); | ||
| 1665 | if (needs_grouping) try argv.append("--end-group"); | 1662 | if (needs_grouping) try argv.append("--end-group"); |
| 1666 | } else if (target.isGnuLibC()) { | 1663 | } else if (target.isGnuLibC()) { |
| 1667 | try argv.append(comp.libunwind_static_lib.?.full_object_path); | ||
| 1668 | for (glibc.libs) |lib| { | 1664 | for (glibc.libs) |lib| { |
| 1669 | const lib_path = try std.fmt.allocPrint(arena, "{s}{c}lib{s}.so.{d}", .{ | 1665 | const lib_path = try std.fmt.allocPrint(arena, "{s}{c}lib{s}.so.{d}", .{ |
| 1670 | comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover, | 1666 | comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover, |
| ... | @@ -1673,13 +1669,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1673,13 +1669,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1673 | } | 1669 | } |
| 1674 | try argv.append(try comp.get_libc_crt_file(arena, "libc_nonshared.a")); | 1670 | try argv.append(try comp.get_libc_crt_file(arena, "libc_nonshared.a")); |
| 1675 | } else if (target.isMusl()) { | 1671 | } else if (target.isMusl()) { |
| 1676 | try argv.append(comp.libunwind_static_lib.?.full_object_path); | ||
| 1677 | try argv.append(try comp.get_libc_crt_file(arena, switch (self.base.options.link_mode) { | 1672 | try argv.append(try comp.get_libc_crt_file(arena, switch (self.base.options.link_mode) { |
| 1678 | .Static => "libc.a", | 1673 | .Static => "libc.a", |
| 1679 | .Dynamic => "libc.so", | 1674 | .Dynamic => "libc.so", |
| 1680 | })); | 1675 | })); |
| 1681 | } else if (self.base.options.link_libcpp) { | ||
| 1682 | try argv.append(comp.libunwind_static_lib.?.full_object_path); | ||
| 1683 | } else { | 1676 | } else { |
| 1684 | unreachable; // Compiler was supposed to emit an error for not being able to provide libc. | 1677 | unreachable; // Compiler was supposed to emit an error for not being able to provide libc. |
| 1685 | } | 1678 | } |
src/link/MachO.zig+56-21| ... | @@ -363,18 +363,30 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -363,18 +363,30 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 363 | self.base.file = file; | 363 | self.base.file = file; |
| 364 | 364 | ||
| 365 | // Create dSYM bundle. | 365 | // Create dSYM bundle. |
| 366 | const d_sym_path = try fmt.allocPrint(allocator, "{s}.dSYM/Contents/Resources/DWARF/", .{sub_path}); | 366 | if (!options.strip and options.module != null) { |
| 367 | defer allocator.free(d_sym_path); | 367 | const dir = options.module.?.zig_cache_artifact_directory; |
| 368 | var d_sym_bundle = try options.emit.?.directory.handle.makeOpenPath(d_sym_path, .{}); | 368 | log.debug("creating {s}.dSYM bundle in {s}", .{ sub_path, dir.path }); |
| 369 | defer d_sym_bundle.close(); | 369 | |
| 370 | const d_sym_file = try d_sym_bundle.createFile(sub_path, .{ | 370 | const d_sym_path = try fmt.allocPrint( |
| 371 | .truncate = false, | 371 | allocator, |
| 372 | .read = true, | 372 | "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF", |
| 373 | }); | 373 | .{sub_path}, |
| 374 | self.d_sym = .{ | 374 | ); |
| 375 | .base = self, | 375 | defer allocator.free(d_sym_path); |
| 376 | .file = d_sym_file, | 376 | |
| 377 | }; | 377 | var d_sym_bundle = try dir.handle.makeOpenPath(d_sym_path, .{}); |
| 378 | defer d_sym_bundle.close(); | ||
| 379 | |||
| 380 | const d_sym_file = try d_sym_bundle.createFile(sub_path, .{ | ||
| 381 | .truncate = false, | ||
| 382 | .read = true, | ||
| 383 | }); | ||
| 384 | |||
| 385 | self.d_sym = .{ | ||
| 386 | .base = self, | ||
| 387 | .file = d_sym_file, | ||
| 388 | }; | ||
| 389 | } | ||
| 378 | 390 | ||
| 379 | // Index 0 is always a null symbol. | 391 | // Index 0 is always a null symbol. |
| 380 | try self.locals.append(allocator, .{ | 392 | try self.locals.append(allocator, .{ |
| ... | @@ -1198,7 +1210,9 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { | ... | @@ -1198,7 +1210,9 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 1198 | const need_realloc = code.len > capacity or !mem.isAlignedGeneric(u64, symbol.n_value, required_alignment); | 1210 | const need_realloc = code.len > capacity or !mem.isAlignedGeneric(u64, symbol.n_value, required_alignment); |
| 1199 | if (need_realloc) { | 1211 | if (need_realloc) { |
| 1200 | const vaddr = try self.growTextBlock(&decl.link.macho, code.len, required_alignment); | 1212 | const vaddr = try self.growTextBlock(&decl.link.macho, code.len, required_alignment); |
| 1201 | log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl.name, symbol.n_value, vaddr }); | 1213 | |
| 1214 | log.debug("growing {s} and moving from 0x{x} to 0x{x}", .{ decl.name, symbol.n_value, vaddr }); | ||
| 1215 | |||
| 1202 | if (vaddr != symbol.n_value) { | 1216 | if (vaddr != symbol.n_value) { |
| 1203 | log.debug(" (writing new offset table entry)", .{}); | 1217 | log.debug(" (writing new offset table entry)", .{}); |
| 1204 | self.offset_table.items[decl.link.macho.offset_table_index] = .{ | 1218 | self.offset_table.items[decl.link.macho.offset_table_index] = .{ |
| ... | @@ -1208,6 +1222,8 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { | ... | @@ -1208,6 +1222,8 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 1208 | }; | 1222 | }; |
| 1209 | try self.writeOffsetTableEntry(decl.link.macho.offset_table_index); | 1223 | try self.writeOffsetTableEntry(decl.link.macho.offset_table_index); |
| 1210 | } | 1224 | } |
| 1225 | |||
| 1226 | symbol.n_value = vaddr; | ||
| 1211 | } else if (code.len < decl.link.macho.size) { | 1227 | } else if (code.len < decl.link.macho.size) { |
| 1212 | self.shrinkTextBlock(&decl.link.macho, code.len); | 1228 | self.shrinkTextBlock(&decl.link.macho, code.len); |
| 1213 | } | 1229 | } |
| ... | @@ -1224,7 +1240,9 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { | ... | @@ -1224,7 +1240,9 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 1224 | const decl_name = mem.spanZ(decl.name); | 1240 | const decl_name = mem.spanZ(decl.name); |
| 1225 | const name_str_index = try self.makeString(decl_name); | 1241 | const name_str_index = try self.makeString(decl_name); |
| 1226 | const addr = try self.allocateTextBlock(&decl.link.macho, code.len, required_alignment); | 1242 | const addr = try self.allocateTextBlock(&decl.link.macho, code.len, required_alignment); |
| 1243 | |||
| 1227 | log.debug("allocated text block for {s} at 0x{x}", .{ decl_name, addr }); | 1244 | log.debug("allocated text block for {s} at 0x{x}", .{ decl_name, addr }); |
| 1245 | |||
| 1228 | errdefer self.freeTextBlock(&decl.link.macho); | 1246 | errdefer self.freeTextBlock(&decl.link.macho); |
| 1229 | 1247 | ||
| 1230 | symbol.* = .{ | 1248 | symbol.* = .{ |
| ... | @@ -1368,15 +1386,32 @@ pub fn updateDeclExports( | ... | @@ -1368,15 +1386,32 @@ pub fn updateDeclExports( |
| 1368 | continue; | 1386 | continue; |
| 1369 | } | 1387 | } |
| 1370 | } | 1388 | } |
| 1371 | const n_desc = switch (exp.options.linkage) { | 1389 | |
| 1372 | .Internal => macho.REFERENCE_FLAG_PRIVATE_DEFINED, | 1390 | var n_type: u8 = macho.N_SECT | macho.N_EXT; |
| 1373 | .Strong => blk: { | 1391 | var n_desc: u16 = 0; |
| 1374 | if (mem.eql(u8, exp.options.name, "_start")) { | 1392 | |
| 1393 | switch (exp.options.linkage) { | ||
| 1394 | .Internal => { | ||
| 1395 | // Symbol should be hidden, or in MachO lingo, private extern. | ||
| 1396 | // We should also mark the symbol as Weak: n_desc == N_WEAK_DEF. | ||
| 1397 | // TODO work out when to add N_WEAK_REF. | ||
| 1398 | n_type |= macho.N_PEXT; | ||
| 1399 | n_desc |= macho.N_WEAK_DEF; | ||
| 1400 | }, | ||
| 1401 | .Strong => { | ||
| 1402 | // Check if the export is _main, and note if os. | ||
| 1403 | // Otherwise, don't do anything since we already have all the flags | ||
| 1404 | // set that we need for global (strong) linkage. | ||
| 1405 | // n_type == N_SECT | N_EXT | ||
| 1406 | if (mem.eql(u8, exp.options.name, "_main")) { | ||
| 1375 | self.entry_addr = decl_sym.n_value; | 1407 | self.entry_addr = decl_sym.n_value; |
| 1376 | } | 1408 | } |
| 1377 | break :blk macho.REFERENCE_FLAG_DEFINED; | ||
| 1378 | }, | 1409 | }, |
| 1379 | .Weak => macho.N_WEAK_REF, | 1410 | .Weak => { |
| 1411 | // Weak linkage is specified as part of n_desc field. | ||
| 1412 | // Symbol's n_type is like for a symbol with strong linkage. | ||
| 1413 | n_desc |= macho.N_WEAK_DEF; | ||
| 1414 | }, | ||
| 1380 | .LinkOnce => { | 1415 | .LinkOnce => { |
| 1381 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); | 1416 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); |
| 1382 | module.failed_exports.putAssumeCapacityNoClobber( | 1417 | module.failed_exports.putAssumeCapacityNoClobber( |
| ... | @@ -1385,8 +1420,8 @@ pub fn updateDeclExports( | ... | @@ -1385,8 +1420,8 @@ pub fn updateDeclExports( |
| 1385 | ); | 1420 | ); |
| 1386 | continue; | 1421 | continue; |
| 1387 | }, | 1422 | }, |
| 1388 | }; | 1423 | } |
| 1389 | const n_type = decl_sym.n_type | macho.N_EXT; | 1424 | |
| 1390 | if (exp.link.macho.sym_index) |i| { | 1425 | if (exp.link.macho.sym_index) |i| { |
| 1391 | const sym = &self.globals.items[i]; | 1426 | const sym = &self.globals.items[i]; |
| 1392 | sym.* = .{ | 1427 | sym.* = .{ |
src/link/SpirV.zig+49-52| ... | @@ -16,11 +16,16 @@ | ... | @@ -16,11 +16,16 @@ |
| 16 | //! All function declarations without a body (extern functions presumably). | 16 | //! All function declarations without a body (extern functions presumably). |
| 17 | //! All regular functions. | 17 | //! All regular functions. |
| 18 | 18 | ||
| 19 | // Because SPIR-V requires re-compilation anyway, and so hot swapping will not work | ||
| 20 | // anyway, we simply generate all the code in flushModule. This keeps | ||
| 21 | // things considerably simpler. | ||
| 22 | |||
| 19 | const SpirV = @This(); | 23 | const SpirV = @This(); |
| 20 | 24 | ||
| 21 | const std = @import("std"); | 25 | const std = @import("std"); |
| 22 | const Allocator = std.mem.Allocator; | 26 | const Allocator = std.mem.Allocator; |
| 23 | const assert = std.debug.assert; | 27 | const assert = std.debug.assert; |
| 28 | const log = std.log.scoped(.link); | ||
| 24 | 29 | ||
| 25 | const Module = @import("../Module.zig"); | 30 | const Module = @import("../Module.zig"); |
| 26 | const Compilation = @import("../Compilation.zig"); | 31 | const Compilation = @import("../Compilation.zig"); |
| ... | @@ -30,16 +35,15 @@ const trace = @import("../tracy.zig").trace; | ... | @@ -30,16 +35,15 @@ const trace = @import("../tracy.zig").trace; |
| 30 | const build_options = @import("build_options"); | 35 | const build_options = @import("build_options"); |
| 31 | const spec = @import("../codegen/spirv/spec.zig"); | 36 | const spec = @import("../codegen/spirv/spec.zig"); |
| 32 | 37 | ||
| 38 | // TODO: Should this struct be used at all rather than just a hashmap of aux data for every decl? | ||
| 33 | pub const FnData = struct { | 39 | pub const FnData = struct { |
| 34 | id: ?u32 = null, | 40 | // We're going to fill these in flushModule, and we're going to fill them unconditionally, |
| 35 | code: std.ArrayListUnmanaged(u32) = .{}, | 41 | // so just set it to undefined. |
| 42 | id: u32 = undefined | ||
| 36 | }; | 43 | }; |
| 37 | 44 | ||
| 38 | base: link.File, | 45 | base: link.File, |
| 39 | 46 | ||
| 40 | /// TODO: Does this file need to support multiple independent modules? | ||
| 41 | spirv_module: codegen.SPIRVModule, | ||
| 42 | |||
| 43 | /// This linker backend does not try to incrementally link output SPIR-V code. | 47 | /// This linker backend does not try to incrementally link output SPIR-V code. |
| 44 | /// Instead, it tracks all declarations in this table, and iterates over it | 48 | /// Instead, it tracks all declarations in this table, and iterates over it |
| 45 | /// in the flush function. | 49 | /// in the flush function. |
| ... | @@ -54,7 +58,6 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*SpirV { | ... | @@ -54,7 +58,6 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*SpirV { |
| 54 | .file = null, | 58 | .file = null, |
| 55 | .allocator = gpa, | 59 | .allocator = gpa, |
| 56 | }, | 60 | }, |
| 57 | .spirv_module = codegen.SPIRVModule.init(gpa), | ||
| 58 | }; | 61 | }; |
| 59 | 62 | ||
| 60 | // TODO: Figure out where to put all of these | 63 | // TODO: Figure out where to put all of these |
| ... | @@ -94,29 +97,11 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -94,29 +97,11 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 94 | 97 | ||
| 95 | pub fn deinit(self: *SpirV) void { | 98 | pub fn deinit(self: *SpirV) void { |
| 96 | self.decl_table.deinit(self.base.allocator); | 99 | self.decl_table.deinit(self.base.allocator); |
| 97 | self.spirv_module.deinit(); | ||
| 98 | } | 100 | } |
| 99 | 101 | ||
| 100 | pub fn updateDecl(self: *SpirV, module: *Module, decl: *Module.Decl) !void { | 102 | pub fn updateDecl(self: *SpirV, module: *Module, decl: *Module.Decl) !void { |
| 101 | const tracy = trace(@src()); | ||
| 102 | defer tracy.end(); | ||
| 103 | |||
| 104 | // Keep track of all decls so we can iterate over them on flush(). | 103 | // Keep track of all decls so we can iterate over them on flush(). |
| 105 | _ = try self.decl_table.getOrPut(self.base.allocator, decl); | 104 | _ = try self.decl_table.getOrPut(self.base.allocator, decl); |
| 106 | |||
| 107 | const fn_data = &decl.fn_link.spirv; | ||
| 108 | if (fn_data.id == null) { | ||
| 109 | fn_data.id = self.spirv_module.allocId(); | ||
| 110 | } | ||
| 111 | |||
| 112 | var managed_code = fn_data.code.toManaged(self.base.allocator); | ||
| 113 | managed_code.items.len = 0; | ||
| 114 | |||
| 115 | try self.spirv_module.genDecl(fn_data.id.?, &managed_code, decl); | ||
| 116 | fn_data.code = managed_code.toUnmanaged(); | ||
| 117 | |||
| 118 | // Free excess allocated memory for this Decl. | ||
| 119 | fn_data.code.shrinkAndFree(self.base.allocator, fn_data.code.items.len); | ||
| 120 | } | 105 | } |
| 121 | 106 | ||
| 122 | pub fn updateDeclExports( | 107 | pub fn updateDeclExports( |
| ... | @@ -128,10 +113,6 @@ pub fn updateDeclExports( | ... | @@ -128,10 +113,6 @@ pub fn updateDeclExports( |
| 128 | 113 | ||
| 129 | pub fn freeDecl(self: *SpirV, decl: *Module.Decl) void { | 114 | pub fn freeDecl(self: *SpirV, decl: *Module.Decl) void { |
| 130 | self.decl_table.removeAssertDiscard(decl); | 115 | self.decl_table.removeAssertDiscard(decl); |
| 131 | var fn_data = decl.fn_link.spirv; | ||
| 132 | fn_data.code.deinit(self.base.allocator); | ||
| 133 | if (fn_data.id) |id| self.spirv_module.freeId(id); | ||
| 134 | decl.fn_link.spirv = undefined; | ||
| 135 | } | 116 | } |
| 136 | 117 | ||
| 137 | pub fn flush(self: *SpirV, comp: *Compilation) !void { | 118 | pub fn flush(self: *SpirV, comp: *Compilation) !void { |
| ... | @@ -149,51 +130,67 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void { | ... | @@ -149,51 +130,67 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void { |
| 149 | const module = self.base.options.module.?; | 130 | const module = self.base.options.module.?; |
| 150 | const target = comp.getTarget(); | 131 | const target = comp.getTarget(); |
| 151 | 132 | ||
| 133 | var spirv_module = codegen.SPIRVModule.init(target, self.base.allocator); | ||
| 134 | defer spirv_module.deinit(); | ||
| 135 | |||
| 136 | // Allocate an ID for every declaration before generating code, | ||
| 137 | // so that we can access them before processing them. | ||
| 138 | // TODO: We're allocating an ID unconditionally now, are there | ||
| 139 | // declarations which don't generate a result? | ||
| 140 | // TODO: fn_link is used here, but thats probably not the right field. It will work anyway though. | ||
| 141 | { | ||
| 142 | for (self.decl_table.items()) |entry| { | ||
| 143 | const decl = entry.key; | ||
| 144 | if (!decl.has_tv) continue; | ||
| 145 | |||
| 146 | decl.fn_link.spirv.id = spirv_module.allocResultId(); | ||
| 147 | log.debug("Allocating id {} to '{s}'", .{ decl.fn_link.spirv.id, std.mem.spanZ(decl.name) }); | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | // Now, actually generate the code for all declarations. | ||
| 152 | { | ||
| 153 | for (self.decl_table.items()) |entry| { | ||
| 154 | const decl = entry.key; | ||
| 155 | if (!decl.has_tv) continue; | ||
| 156 | |||
| 157 | try spirv_module.gen(decl); | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 152 | var binary = std.ArrayList(u32).init(self.base.allocator); | 161 | var binary = std.ArrayList(u32).init(self.base.allocator); |
| 153 | defer binary.deinit(); | 162 | defer binary.deinit(); |
| 154 | 163 | ||
| 155 | // Note: The order of adding sections to the final binary | ||
| 156 | // follows the SPIR-V logical module format! | ||
| 157 | |||
| 158 | try binary.appendSlice(&[_]u32{ | 164 | try binary.appendSlice(&[_]u32{ |
| 159 | spec.magic_number, | 165 | spec.magic_number, |
| 160 | (spec.version.major << 16) | (spec.version.minor << 8), | 166 | (spec.version.major << 16) | (spec.version.minor << 8), |
| 161 | 0, // TODO: Register Zig compiler magic number. | 167 | 0, // TODO: Register Zig compiler magic number. |
| 162 | self.spirv_module.idBound(), | 168 | spirv_module.resultIdBound(), // ID bound. |
| 163 | 0, // Schema (currently reserved for future use in the SPIR-V spec). | 169 | 0, // Schema (currently reserved for future use in the SPIR-V spec). |
| 164 | }); | 170 | }); |
| 165 | 171 | ||
| 166 | try writeCapabilities(&binary, target); | 172 | try writeCapabilities(&binary, target); |
| 167 | try writeMemoryModel(&binary, target); | 173 | try writeMemoryModel(&binary, target); |
| 168 | 174 | ||
| 169 | // Collect list of buffers to write. | 175 | // Note: The order of adding sections to the final binary |
| 170 | // SPIR-V files support both little and big endian words. The actual format is | 176 | // follows the SPIR-V logical module format! |
| 171 | // disambiguated by the magic number, and so theoretically we don't need to worry | 177 | var all_buffers = [_]std.os.iovec_const{ |
| 172 | // about endian-ness when writing the final binary. | 178 | wordsToIovConst(binary.items), |
| 173 | var all_buffers = std.ArrayList(std.os.iovec_const).init(self.base.allocator); | 179 | wordsToIovConst(spirv_module.types_and_globals.items), |
| 174 | defer all_buffers.deinit(); | 180 | wordsToIovConst(spirv_module.fn_decls.items), |
| 175 | 181 | }; | |
| 176 | // Pre-allocate enough for the binary info + all functions | ||
| 177 | try all_buffers.ensureCapacity(self.decl_table.count() + 1); | ||
| 178 | |||
| 179 | all_buffers.appendAssumeCapacity(wordsToIovConst(binary.items)); | ||
| 180 | 182 | ||
| 181 | for (self.decl_table.items()) |entry| { | 183 | const file = self.base.file.?; |
| 182 | const decl = entry.key; | 184 | const bytes = std.mem.sliceAsBytes(binary.items); |
| 183 | if (!decl.has_tv) continue; | ||
| 184 | const fn_data = &decl.fn_link.spirv; | ||
| 185 | all_buffers.appendAssumeCapacity(wordsToIovConst(fn_data.code.items)); | ||
| 186 | } | ||
| 187 | 185 | ||
| 188 | var file_size: u64 = 0; | 186 | var file_size: u64 = 0; |
| 189 | for (all_buffers.items) |iov| { | 187 | for (all_buffers) |iov| { |
| 190 | file_size += iov.iov_len; | 188 | file_size += iov.iov_len; |
| 191 | } | 189 | } |
| 192 | 190 | ||
| 193 | const file = self.base.file.?; | ||
| 194 | try file.seekTo(0); | 191 | try file.seekTo(0); |
| 195 | try file.setEndPos(file_size); | 192 | try file.setEndPos(file_size); |
| 196 | try file.pwritevAll(all_buffers.items, 0); | 193 | try file.pwritevAll(&all_buffers, 0); |
| 197 | } | 194 | } |
| 198 | 195 | ||
| 199 | fn writeCapabilities(binary: *std.ArrayList(u32), target: std.Target) !void { | 196 | fn writeCapabilities(binary: *std.ArrayList(u32), target: std.Target) !void { |
src/main.zig+7| ... | @@ -544,6 +544,7 @@ fn buildOutputType( | ... | @@ -544,6 +544,7 @@ fn buildOutputType( |
| 544 | var ensure_libcpp_on_non_freestanding = false; | 544 | var ensure_libcpp_on_non_freestanding = false; |
| 545 | var link_libc = false; | 545 | var link_libc = false; |
| 546 | var link_libcpp = false; | 546 | var link_libcpp = false; |
| 547 | var link_libunwind = false; | ||
| 547 | var want_native_include_dirs = false; | 548 | var want_native_include_dirs = false; |
| 548 | var enable_cache: ?bool = null; | 549 | var enable_cache: ?bool = null; |
| 549 | var want_pic: ?bool = null; | 550 | var want_pic: ?bool = null; |
| ... | @@ -1556,6 +1557,11 @@ fn buildOutputType( | ... | @@ -1556,6 +1557,11 @@ fn buildOutputType( |
| 1556 | _ = system_libs.orderedRemove(i); | 1557 | _ = system_libs.orderedRemove(i); |
| 1557 | continue; | 1558 | continue; |
| 1558 | } | 1559 | } |
| 1560 | if (mem.eql(u8, lib_name, "unwind")) { | ||
| 1561 | link_libunwind = true; | ||
| 1562 | _ = system_libs.orderedRemove(i); | ||
| 1563 | continue; | ||
| 1564 | } | ||
| 1559 | if (std.fs.path.isAbsolute(lib_name)) { | 1565 | if (std.fs.path.isAbsolute(lib_name)) { |
| 1560 | fatal("cannot use absolute path as a system library: {s}", .{lib_name}); | 1566 | fatal("cannot use absolute path as a system library: {s}", .{lib_name}); |
| 1561 | } | 1567 | } |
| ... | @@ -1871,6 +1877,7 @@ fn buildOutputType( | ... | @@ -1871,6 +1877,7 @@ fn buildOutputType( |
| 1871 | .system_libs = system_libs.items, | 1877 | .system_libs = system_libs.items, |
| 1872 | .link_libc = link_libc, | 1878 | .link_libc = link_libc, |
| 1873 | .link_libcpp = link_libcpp, | 1879 | .link_libcpp = link_libcpp, |
| 1880 | .link_libunwind = link_libunwind, | ||
| 1874 | .want_pic = want_pic, | 1881 | .want_pic = want_pic, |
| 1875 | .want_pie = want_pie, | 1882 | .want_pie = want_pie, |
| 1876 | .want_lto = want_lto, | 1883 | .want_lto = want_lto, |
src/register_manager.zig+219-156| ... | @@ -7,6 +7,9 @@ const ir = @import("ir.zig"); | ... | @@ -7,6 +7,9 @@ const ir = @import("ir.zig"); |
| 7 | const Type = @import("type.zig").Type; | 7 | const Type = @import("type.zig").Type; |
| 8 | const Module = @import("Module.zig"); | 8 | const Module = @import("Module.zig"); |
| 9 | const LazySrcLoc = Module.LazySrcLoc; | 9 | const LazySrcLoc = Module.LazySrcLoc; |
| 10 | const expect = std.testing.expect; | ||
| 11 | const expectEqual = std.testing.expectEqual; | ||
| 12 | const expectEqualSlices = std.testing.expectEqualSlices; | ||
| 10 | 13 | ||
| 11 | const log = std.log.scoped(.register_manager); | 14 | const log = std.log.scoped(.register_manager); |
| 12 | 15 | ||
| ... | @@ -66,77 +69,14 @@ pub fn RegisterManager( | ... | @@ -66,77 +69,14 @@ pub fn RegisterManager( |
| 66 | return self.allocated_registers & @as(FreeRegInt, 1) << shift != 0; | 69 | return self.allocated_registers & @as(FreeRegInt, 1) << shift != 0; |
| 67 | } | 70 | } |
| 68 | 71 | ||
| 69 | /// Returns `null` if all registers are allocated. | 72 | /// Allocates a specified number of registers, optionally |
| 73 | /// tracking them. Returns `null` if not enough registers are | ||
| 74 | /// free. | ||
| 70 | pub fn tryAllocRegs( | 75 | pub fn tryAllocRegs( |
| 71 | self: *Self, | 76 | self: *Self, |
| 72 | comptime count: comptime_int, | 77 | comptime count: comptime_int, |
| 73 | insts: [count]*ir.Inst, | 78 | insts: [count]?*ir.Inst, |
| 74 | exceptions: []Register, | 79 | exceptions: []const Register, |
| 75 | ) ?[count]Register { | ||
| 76 | if (self.tryAllocRegsWithoutTracking(count, exceptions)) |regs| { | ||
| 77 | for (regs) |reg, i| { | ||
| 78 | const index = reg.allocIndex().?; // allocIndex() on a callee-preserved reg should never return null | ||
| 79 | self.registers[index] = insts[i]; | ||
| 80 | self.markRegUsed(reg); | ||
| 81 | } | ||
| 82 | |||
| 83 | return regs; | ||
| 84 | } else { | ||
| 85 | return null; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | /// Returns `null` if all registers are allocated. | ||
| 90 | pub fn tryAllocReg(self: *Self, inst: *ir.Inst, exceptions: []Register) ?Register { | ||
| 91 | return if (tryAllocRegs(self, 1, .{inst}, exceptions)) |regs| regs[0] else null; | ||
| 92 | } | ||
| 93 | |||
| 94 | pub fn allocRegs( | ||
| 95 | self: *Self, | ||
| 96 | comptime count: comptime_int, | ||
| 97 | insts: [count]*ir.Inst, | ||
| 98 | exceptions: []Register, | ||
| 99 | ) ![count]Register { | ||
| 100 | comptime assert(count > 0 and count <= callee_preserved_regs.len); | ||
| 101 | assert(count + exceptions.len <= callee_preserved_regs.len); | ||
| 102 | |||
| 103 | return self.tryAllocRegs(count, insts, exceptions) orelse blk: { | ||
| 104 | // We'll take over the first count registers. Spill | ||
| 105 | // the instructions that were previously there to a | ||
| 106 | // stack allocations. | ||
| 107 | var regs: [count]Register = undefined; | ||
| 108 | var i: usize = 0; | ||
| 109 | for (callee_preserved_regs) |reg| { | ||
| 110 | if (i >= count) break; | ||
| 111 | if (mem.indexOfScalar(Register, exceptions, reg) != null) continue; | ||
| 112 | regs[i] = reg; | ||
| 113 | |||
| 114 | const index = reg.allocIndex().?; // allocIndex() on a callee-preserved reg should never return null | ||
| 115 | if (self.isRegFree(reg)) { | ||
| 116 | self.markRegUsed(reg); | ||
| 117 | } else { | ||
| 118 | const spilled_inst = self.registers[index].?; | ||
| 119 | try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst); | ||
| 120 | } | ||
| 121 | self.registers[index] = insts[i]; | ||
| 122 | |||
| 123 | i += 1; | ||
| 124 | } | ||
| 125 | |||
| 126 | break :blk regs; | ||
| 127 | }; | ||
| 128 | } | ||
| 129 | |||
| 130 | pub fn allocReg(self: *Self, inst: *ir.Inst, exceptions: []Register) !Register { | ||
| 131 | return (try self.allocRegs(1, .{inst}, exceptions))[0]; | ||
| 132 | } | ||
| 133 | |||
| 134 | /// Does not track the registers. | ||
| 135 | /// Returns `null` if not enough registers are free. | ||
| 136 | pub fn tryAllocRegsWithoutTracking( | ||
| 137 | self: *Self, | ||
| 138 | comptime count: comptime_int, | ||
| 139 | exceptions: []Register, | ||
| 140 | ) ?[count]Register { | 80 | ) ?[count]Register { |
| 141 | comptime if (callee_preserved_regs.len == 0) return null; | 81 | comptime if (callee_preserved_regs.len == 0) return null; |
| 142 | comptime assert(count > 0 and count <= callee_preserved_regs.len); | 82 | comptime assert(count > 0 and count <= callee_preserved_regs.len); |
| ... | @@ -156,18 +96,40 @@ pub fn RegisterManager( | ... | @@ -156,18 +96,40 @@ pub fn RegisterManager( |
| 156 | } | 96 | } |
| 157 | } | 97 | } |
| 158 | 98 | ||
| 159 | return if (i < count) null else regs; | 99 | if (i == count) { |
| 100 | for (regs) |reg, j| { | ||
| 101 | if (insts[j]) |inst| { | ||
| 102 | // Track the register | ||
| 103 | const index = reg.allocIndex().?; // allocIndex() on a callee-preserved reg should never return null | ||
| 104 | self.registers[index] = inst; | ||
| 105 | self.markRegUsed(reg); | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | return regs; | ||
| 110 | } else return null; | ||
| 160 | } | 111 | } |
| 161 | 112 | ||
| 162 | /// Does not track the register. | 113 | /// Allocates a register and optionally tracks it with a |
| 163 | /// Returns `null` if all registers are allocated. | 114 | /// corresponding instruction. Returns `null` if all registers |
| 164 | pub fn tryAllocRegWithoutTracking(self: *Self, exceptions: []Register) ?Register { | 115 | /// are allocated. |
| 165 | return if (self.tryAllocRegsWithoutTracking(1, exceptions)) |regs| regs[0] else null; | 116 | pub fn tryAllocReg(self: *Self, inst: ?*ir.Inst, exceptions: []const Register) ?Register { |
| 117 | return if (tryAllocRegs(self, 1, .{inst}, exceptions)) |regs| regs[0] else null; | ||
| 166 | } | 118 | } |
| 167 | 119 | ||
| 168 | /// Does not track the registers | 120 | /// Allocates a specified number of registers, optionally |
| 169 | pub fn allocRegsWithoutTracking(self: *Self, comptime count: comptime_int, exceptions: []Register) ![count]Register { | 121 | /// tracking them. Asserts that count + exceptions.len is not |
| 170 | return self.tryAllocRegsWithoutTracking(count, exceptions) orelse blk: { | 122 | /// larger than the total number of registers available. |
| 123 | pub fn allocRegs( | ||
| 124 | self: *Self, | ||
| 125 | comptime count: comptime_int, | ||
| 126 | insts: [count]?*ir.Inst, | ||
| 127 | exceptions: []const Register, | ||
| 128 | ) ![count]Register { | ||
| 129 | comptime assert(count > 0 and count <= callee_preserved_regs.len); | ||
| 130 | assert(count + exceptions.len <= callee_preserved_regs.len); | ||
| 131 | |||
| 132 | return self.tryAllocRegs(count, insts, exceptions) orelse blk: { | ||
| 171 | // We'll take over the first count registers. Spill | 133 | // We'll take over the first count registers. Spill |
| 172 | // the instructions that were previously there to a | 134 | // the instructions that were previously there to a |
| 173 | // stack allocations. | 135 | // stack allocations. |
| ... | @@ -179,11 +141,22 @@ pub fn RegisterManager( | ... | @@ -179,11 +141,22 @@ pub fn RegisterManager( |
| 179 | regs[i] = reg; | 141 | regs[i] = reg; |
| 180 | 142 | ||
| 181 | const index = reg.allocIndex().?; // allocIndex() on a callee-preserved reg should never return null | 143 | const index = reg.allocIndex().?; // allocIndex() on a callee-preserved reg should never return null |
| 182 | if (!self.isRegFree(reg)) { | 144 | if (insts[i]) |inst| { |
| 183 | const spilled_inst = self.registers[index].?; | 145 | // Track the register |
| 184 | try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst); | 146 | if (self.isRegFree(reg)) { |
| 185 | self.registers[index] = null; | 147 | self.markRegUsed(reg); |
| 186 | self.markRegFree(reg); | 148 | } else { |
| 149 | const spilled_inst = self.registers[index].?; | ||
| 150 | try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst); | ||
| 151 | } | ||
| 152 | self.registers[index] = inst; | ||
| 153 | } else { | ||
| 154 | // Don't track the register | ||
| 155 | if (!self.isRegFree(reg)) { | ||
| 156 | const spilled_inst = self.registers[index].?; | ||
| 157 | try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst); | ||
| 158 | self.freeReg(reg); | ||
| 159 | } | ||
| 187 | } | 160 | } |
| 188 | 161 | ||
| 189 | i += 1; | 162 | i += 1; |
| ... | @@ -193,39 +166,36 @@ pub fn RegisterManager( | ... | @@ -193,39 +166,36 @@ pub fn RegisterManager( |
| 193 | }; | 166 | }; |
| 194 | } | 167 | } |
| 195 | 168 | ||
| 196 | /// Does not track the register. | 169 | /// Allocates a register and optionally tracks it with a |
| 197 | pub fn allocRegWithoutTracking(self: *Self, exceptions: []Register) !Register { | 170 | /// corresponding instruction. |
| 198 | return (try self.allocRegsWithoutTracking(1, exceptions))[0]; | 171 | pub fn allocReg(self: *Self, inst: ?*ir.Inst, exceptions: []const Register) !Register { |
| 199 | } | 172 | return (try self.allocRegs(1, .{inst}, exceptions))[0]; |
| 200 | |||
| 201 | /// Allocates the specified register with the specified | ||
| 202 | /// instruction. Spills the register if it is currently | ||
| 203 | /// allocated. | ||
| 204 | pub fn getReg(self: *Self, reg: Register, inst: *ir.Inst) !void { | ||
| 205 | const index = reg.allocIndex() orelse return; | ||
| 206 | |||
| 207 | if (!self.isRegFree(reg)) { | ||
| 208 | // Move the instruction that was previously there to a | ||
| 209 | // stack allocation. | ||
| 210 | const spilled_inst = self.registers[index].?; | ||
| 211 | self.registers[index] = inst; | ||
| 212 | try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst); | ||
| 213 | } else { | ||
| 214 | self.getRegAssumeFree(reg, inst); | ||
| 215 | } | ||
| 216 | } | 173 | } |
| 217 | 174 | ||
| 218 | /// Spills the register if it is currently allocated. | 175 | /// Spills the register if it is currently allocated. If a |
| 219 | /// Does not track the register. | 176 | /// corresponding instruction is passed, will also track this |
| 220 | pub fn getRegWithoutTracking(self: *Self, reg: Register) !void { | 177 | /// register. |
| 178 | pub fn getReg(self: *Self, reg: Register, inst: ?*ir.Inst) !void { | ||
| 221 | const index = reg.allocIndex() orelse return; | 179 | const index = reg.allocIndex() orelse return; |
| 222 | 180 | ||
| 223 | if (!self.isRegFree(reg)) { | 181 | if (inst) |tracked_inst| |
| 224 | // Move the instruction that was previously there to a | 182 | if (!self.isRegFree(reg)) { |
| 225 | // stack allocation. | 183 | // Move the instruction that was previously there to a |
| 226 | const spilled_inst = self.registers[index].?; | 184 | // stack allocation. |
| 227 | try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst); | 185 | const spilled_inst = self.registers[index].?; |
| 228 | self.markRegFree(reg); | 186 | self.registers[index] = tracked_inst; |
| 187 | try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst); | ||
| 188 | } else { | ||
| 189 | self.getRegAssumeFree(reg, tracked_inst); | ||
| 190 | } | ||
| 191 | else { | ||
| 192 | if (!self.isRegFree(reg)) { | ||
| 193 | // Move the instruction that was previously there to a | ||
| 194 | // stack allocation. | ||
| 195 | const spilled_inst = self.registers[index].?; | ||
| 196 | try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst); | ||
| 197 | self.freeReg(reg); | ||
| 198 | } | ||
| 229 | } | 199 | } |
| 230 | } | 200 | } |
| 231 | 201 | ||
| ... | @@ -250,42 +220,63 @@ pub fn RegisterManager( | ... | @@ -250,42 +220,63 @@ pub fn RegisterManager( |
| 250 | }; | 220 | }; |
| 251 | } | 221 | } |
| 252 | 222 | ||
| 253 | const MockRegister = enum(u2) { | 223 | const MockRegister1 = enum(u2) { |
| 254 | r0, | 224 | r0, |
| 255 | r1, | 225 | r1, |
| 256 | r2, | 226 | r2, |
| 257 | r3, | 227 | r3, |
| 258 | 228 | ||
| 259 | pub fn allocIndex(self: MockRegister) ?u2 { | 229 | pub fn allocIndex(self: MockRegister1) ?u2 { |
| 260 | inline for (mock_callee_preserved_regs) |cpreg, i| { | 230 | inline for (callee_preserved_regs) |cpreg, i| { |
| 261 | if (self == cpreg) return i; | 231 | if (self == cpreg) return i; |
| 262 | } | 232 | } |
| 263 | return null; | 233 | return null; |
| 264 | } | 234 | } |
| 265 | }; | ||
| 266 | |||
| 267 | const mock_callee_preserved_regs = [_]MockRegister{ .r2, .r3 }; | ||
| 268 | 235 | ||
| 269 | const MockFunction = struct { | 236 | const callee_preserved_regs = [_]MockRegister1{ .r2, .r3 }; |
| 270 | allocator: *Allocator, | 237 | }; |
| 271 | register_manager: RegisterManager(Self, MockRegister, &mock_callee_preserved_regs) = .{}, | ||
| 272 | spilled: std.ArrayListUnmanaged(MockRegister) = .{}, | ||
| 273 | 238 | ||
| 274 | const Self = @This(); | 239 | const MockRegister2 = enum(u2) { |
| 240 | r0, | ||
| 241 | r1, | ||
| 242 | r2, | ||
| 243 | r3, | ||
| 275 | 244 | ||
| 276 | pub fn deinit(self: *Self) void { | 245 | pub fn allocIndex(self: MockRegister2) ?u2 { |
| 277 | self.spilled.deinit(self.allocator); | 246 | inline for (callee_preserved_regs) |cpreg, i| { |
| 247 | if (self == cpreg) return i; | ||
| 248 | } | ||
| 249 | return null; | ||
| 278 | } | 250 | } |
| 279 | 251 | ||
| 280 | pub fn spillInstruction(self: *Self, src: LazySrcLoc, reg: MockRegister, inst: *ir.Inst) !void { | 252 | const callee_preserved_regs = [_]MockRegister2{ .r0, .r1, .r2, .r3 }; |
| 281 | try self.spilled.append(self.allocator, reg); | ||
| 282 | } | ||
| 283 | }; | 253 | }; |
| 284 | 254 | ||
| 285 | test "tryAllocReg: no spilling" { | 255 | fn MockFunction(comptime Register: type) type { |
| 256 | return struct { | ||
| 257 | allocator: *Allocator, | ||
| 258 | register_manager: RegisterManager(Self, Register, &Register.callee_preserved_regs) = .{}, | ||
| 259 | spilled: std.ArrayListUnmanaged(Register) = .{}, | ||
| 260 | |||
| 261 | const Self = @This(); | ||
| 262 | |||
| 263 | pub fn deinit(self: *Self) void { | ||
| 264 | self.spilled.deinit(self.allocator); | ||
| 265 | } | ||
| 266 | |||
| 267 | pub fn spillInstruction(self: *Self, src: LazySrcLoc, reg: Register, inst: *ir.Inst) !void { | ||
| 268 | try self.spilled.append(self.allocator, reg); | ||
| 269 | } | ||
| 270 | }; | ||
| 271 | } | ||
| 272 | |||
| 273 | const MockFunction1 = MockFunction(MockRegister1); | ||
| 274 | const MockFunction2 = MockFunction(MockRegister2); | ||
| 275 | |||
| 276 | test "default state" { | ||
| 286 | const allocator = std.testing.allocator; | 277 | const allocator = std.testing.allocator; |
| 287 | 278 | ||
| 288 | var function = MockFunction{ | 279 | var function = MockFunction1{ |
| 289 | .allocator = allocator, | 280 | .allocator = allocator, |
| 290 | }; | 281 | }; |
| 291 | defer function.deinit(); | 282 | defer function.deinit(); |
| ... | @@ -296,27 +287,48 @@ test "tryAllocReg: no spilling" { | ... | @@ -296,27 +287,48 @@ test "tryAllocReg: no spilling" { |
| 296 | .src = .unneeded, | 287 | .src = .unneeded, |
| 297 | }; | 288 | }; |
| 298 | 289 | ||
| 299 | try std.testing.expect(!function.register_manager.isRegAllocated(.r2)); | 290 | try expect(!function.register_manager.isRegAllocated(.r2)); |
| 300 | try std.testing.expect(!function.register_manager.isRegAllocated(.r3)); | 291 | try expect(!function.register_manager.isRegAllocated(.r3)); |
| 292 | try expect(function.register_manager.isRegFree(.r2)); | ||
| 293 | try expect(function.register_manager.isRegFree(.r3)); | ||
| 294 | } | ||
| 295 | |||
| 296 | test "tryAllocReg: no spilling" { | ||
| 297 | const allocator = std.testing.allocator; | ||
| 298 | |||
| 299 | var function = MockFunction1{ | ||
| 300 | .allocator = allocator, | ||
| 301 | }; | ||
| 302 | defer function.deinit(); | ||
| 303 | |||
| 304 | var mock_instruction = ir.Inst{ | ||
| 305 | .tag = .breakpoint, | ||
| 306 | .ty = Type.initTag(.void), | ||
| 307 | .src = .unneeded, | ||
| 308 | }; | ||
| 301 | 309 | ||
| 302 | try std.testing.expectEqual(@as(?MockRegister, .r2), function.register_manager.tryAllocReg(&mock_instruction, &.{})); | 310 | try expectEqual(@as(?MockRegister1, .r2), function.register_manager.tryAllocReg(&mock_instruction, &.{})); |
| 303 | try std.testing.expectEqual(@as(?MockRegister, .r3), function.register_manager.tryAllocReg(&mock_instruction, &.{})); | 311 | try expectEqual(@as(?MockRegister1, .r3), function.register_manager.tryAllocReg(&mock_instruction, &.{})); |
| 304 | try std.testing.expectEqual(@as(?MockRegister, null), function.register_manager.tryAllocReg(&mock_instruction, &.{})); | 312 | try expectEqual(@as(?MockRegister1, null), function.register_manager.tryAllocReg(&mock_instruction, &.{})); |
| 305 | 313 | ||
| 306 | try std.testing.expect(function.register_manager.isRegAllocated(.r2)); | 314 | try expect(function.register_manager.isRegAllocated(.r2)); |
| 307 | try std.testing.expect(function.register_manager.isRegAllocated(.r3)); | 315 | try expect(function.register_manager.isRegAllocated(.r3)); |
| 316 | try expect(!function.register_manager.isRegFree(.r2)); | ||
| 317 | try expect(!function.register_manager.isRegFree(.r3)); | ||
| 308 | 318 | ||
| 309 | function.register_manager.freeReg(.r2); | 319 | function.register_manager.freeReg(.r2); |
| 310 | function.register_manager.freeReg(.r3); | 320 | function.register_manager.freeReg(.r3); |
| 311 | 321 | ||
| 312 | try std.testing.expect(function.register_manager.isRegAllocated(.r2)); | 322 | try expect(function.register_manager.isRegAllocated(.r2)); |
| 313 | try std.testing.expect(function.register_manager.isRegAllocated(.r3)); | 323 | try expect(function.register_manager.isRegAllocated(.r3)); |
| 324 | try expect(function.register_manager.isRegFree(.r2)); | ||
| 325 | try expect(function.register_manager.isRegFree(.r3)); | ||
| 314 | } | 326 | } |
| 315 | 327 | ||
| 316 | test "allocReg: spilling" { | 328 | test "allocReg: spilling" { |
| 317 | const allocator = std.testing.allocator; | 329 | const allocator = std.testing.allocator; |
| 318 | 330 | ||
| 319 | var function = MockFunction{ | 331 | var function = MockFunction1{ |
| 320 | .allocator = allocator, | 332 | .allocator = allocator, |
| 321 | }; | 333 | }; |
| 322 | defer function.deinit(); | 334 | defer function.deinit(); |
| ... | @@ -327,26 +339,28 @@ test "allocReg: spilling" { | ... | @@ -327,26 +339,28 @@ test "allocReg: spilling" { |
| 327 | .src = .unneeded, | 339 | .src = .unneeded, |
| 328 | }; | 340 | }; |
| 329 | 341 | ||
| 330 | try std.testing.expect(!function.register_manager.isRegAllocated(.r2)); | 342 | try expectEqual(@as(?MockRegister1, .r2), try function.register_manager.allocReg(&mock_instruction, &.{})); |
| 331 | try std.testing.expect(!function.register_manager.isRegAllocated(.r3)); | 343 | try expectEqual(@as(?MockRegister1, .r3), try function.register_manager.allocReg(&mock_instruction, &.{})); |
| 332 | |||
| 333 | try std.testing.expectEqual(@as(?MockRegister, .r2), try function.register_manager.allocReg(&mock_instruction, &.{})); | ||
| 334 | try std.testing.expectEqual(@as(?MockRegister, .r3), try function.register_manager.allocReg(&mock_instruction, &.{})); | ||
| 335 | 344 | ||
| 336 | // Spill a register | 345 | // Spill a register |
| 337 | try std.testing.expectEqual(@as(?MockRegister, .r2), try function.register_manager.allocReg(&mock_instruction, &.{})); | 346 | try expectEqual(@as(?MockRegister1, .r2), try function.register_manager.allocReg(&mock_instruction, &.{})); |
| 338 | try std.testing.expectEqualSlices(MockRegister, &[_]MockRegister{.r2}, function.spilled.items); | 347 | try expectEqualSlices(MockRegister1, &[_]MockRegister1{.r2}, function.spilled.items); |
| 339 | 348 | ||
| 340 | // No spilling necessary | 349 | // No spilling necessary |
| 341 | function.register_manager.freeReg(.r3); | 350 | function.register_manager.freeReg(.r3); |
| 342 | try std.testing.expectEqual(@as(?MockRegister, .r3), try function.register_manager.allocReg(&mock_instruction, &.{})); | 351 | try expectEqual(@as(?MockRegister1, .r3), try function.register_manager.allocReg(&mock_instruction, &.{})); |
| 343 | try std.testing.expectEqualSlices(MockRegister, &[_]MockRegister{.r2}, function.spilled.items); | 352 | try expectEqualSlices(MockRegister1, &[_]MockRegister1{.r2}, function.spilled.items); |
| 353 | |||
| 354 | // Exceptions | ||
| 355 | function.register_manager.freeReg(.r2); | ||
| 356 | function.register_manager.freeReg(.r3); | ||
| 357 | try expectEqual(@as(?MockRegister1, .r3), try function.register_manager.allocReg(&mock_instruction, &.{.r2})); | ||
| 344 | } | 358 | } |
| 345 | 359 | ||
| 346 | test "getReg" { | 360 | test "tryAllocRegs" { |
| 347 | const allocator = std.testing.allocator; | 361 | const allocator = std.testing.allocator; |
| 348 | 362 | ||
| 349 | var function = MockFunction{ | 363 | var function = MockFunction2{ |
| 350 | .allocator = allocator, | 364 | .allocator = allocator, |
| 351 | }; | 365 | }; |
| 352 | defer function.deinit(); | 366 | defer function.deinit(); |
| ... | @@ -357,18 +371,67 @@ test "getReg" { | ... | @@ -357,18 +371,67 @@ test "getReg" { |
| 357 | .src = .unneeded, | 371 | .src = .unneeded, |
| 358 | }; | 372 | }; |
| 359 | 373 | ||
| 360 | try std.testing.expect(!function.register_manager.isRegAllocated(.r2)); | 374 | try expectEqual([_]MockRegister2{ .r0, .r1, .r2 }, function.register_manager.tryAllocRegs(3, .{ null, null, null }, &.{}).?); |
| 361 | try std.testing.expect(!function.register_manager.isRegAllocated(.r3)); | 375 | |
| 376 | // Exceptions | ||
| 377 | function.register_manager.freeReg(.r0); | ||
| 378 | function.register_manager.freeReg(.r1); | ||
| 379 | function.register_manager.freeReg(.r2); | ||
| 380 | try expectEqual([_]MockRegister2{ .r0, .r2, .r3 }, function.register_manager.tryAllocRegs(3, .{ null, null, null }, &.{.r1}).?); | ||
| 381 | } | ||
| 382 | |||
| 383 | test "allocRegs" { | ||
| 384 | const allocator = std.testing.allocator; | ||
| 385 | |||
| 386 | var function = MockFunction2{ | ||
| 387 | .allocator = allocator, | ||
| 388 | }; | ||
| 389 | defer function.deinit(); | ||
| 390 | |||
| 391 | var mock_instruction = ir.Inst{ | ||
| 392 | .tag = .breakpoint, | ||
| 393 | .ty = Type.initTag(.void), | ||
| 394 | .src = .unneeded, | ||
| 395 | }; | ||
| 396 | |||
| 397 | try expectEqual([_]MockRegister2{ .r0, .r1, .r2 }, try function.register_manager.allocRegs(3, .{ | ||
| 398 | &mock_instruction, | ||
| 399 | &mock_instruction, | ||
| 400 | &mock_instruction, | ||
| 401 | }, &.{})); | ||
| 402 | |||
| 403 | // Exceptions | ||
| 404 | try expectEqual([_]MockRegister2{ .r0, .r2, .r3 }, try function.register_manager.allocRegs(3, .{ null, null, null }, &.{.r1})); | ||
| 405 | try expectEqualSlices(MockRegister2, &[_]MockRegister2{ .r0, .r2 }, function.spilled.items); | ||
| 406 | } | ||
| 407 | |||
| 408 | test "getReg" { | ||
| 409 | const allocator = std.testing.allocator; | ||
| 410 | |||
| 411 | var function = MockFunction1{ | ||
| 412 | .allocator = allocator, | ||
| 413 | }; | ||
| 414 | defer function.deinit(); | ||
| 415 | |||
| 416 | var mock_instruction = ir.Inst{ | ||
| 417 | .tag = .breakpoint, | ||
| 418 | .ty = Type.initTag(.void), | ||
| 419 | .src = .unneeded, | ||
| 420 | }; | ||
| 362 | 421 | ||
| 363 | try function.register_manager.getReg(.r3, &mock_instruction); | 422 | try function.register_manager.getReg(.r3, &mock_instruction); |
| 364 | 423 | ||
| 365 | try std.testing.expect(!function.register_manager.isRegAllocated(.r2)); | 424 | try expect(!function.register_manager.isRegAllocated(.r2)); |
| 366 | try std.testing.expect(function.register_manager.isRegAllocated(.r3)); | 425 | try expect(function.register_manager.isRegAllocated(.r3)); |
| 426 | try expect(function.register_manager.isRegFree(.r2)); | ||
| 427 | try expect(!function.register_manager.isRegFree(.r3)); | ||
| 367 | 428 | ||
| 368 | // Spill r3 | 429 | // Spill r3 |
| 369 | try function.register_manager.getReg(.r3, &mock_instruction); | 430 | try function.register_manager.getReg(.r3, &mock_instruction); |
| 370 | 431 | ||
| 371 | try std.testing.expect(!function.register_manager.isRegAllocated(.r2)); | 432 | try expect(!function.register_manager.isRegAllocated(.r2)); |
| 372 | try std.testing.expect(function.register_manager.isRegAllocated(.r3)); | 433 | try expect(function.register_manager.isRegAllocated(.r3)); |
| 373 | try std.testing.expectEqualSlices(MockRegister, &[_]MockRegister{.r3}, function.spilled.items); | 434 | try expect(function.register_manager.isRegFree(.r2)); |
| 435 | try expect(!function.register_manager.isRegFree(.r3)); | ||
| 436 | try expectEqualSlices(MockRegister1, &[_]MockRegister1{.r3}, function.spilled.items); | ||
| 374 | } | 437 | } |
src/stage1/codegen.cpp+3-3| ... | @@ -5485,8 +5485,8 @@ static enum ZigLLVM_AtomicRMWBinOp to_ZigLLVMAtomicRMWBinOp(AtomicRmwOp op, bool | ... | @@ -5485,8 +5485,8 @@ static enum ZigLLVM_AtomicRMWBinOp to_ZigLLVMAtomicRMWBinOp(AtomicRmwOp op, bool |
| 5485 | } | 5485 | } |
| 5486 | 5486 | ||
| 5487 | static LLVMTypeRef get_atomic_abi_type(CodeGen *g, IrInstGen *instruction) { | 5487 | static LLVMTypeRef get_atomic_abi_type(CodeGen *g, IrInstGen *instruction) { |
| 5488 | // If the operand type of an atomic operation is not a power of two sized | 5488 | // If the operand type of an atomic operation is not byte sized we need to |
| 5489 | // we need to widen it before using it and then truncate the result. | 5489 | // widen it before using it and then truncate the result. |
| 5490 | 5490 | ||
| 5491 | ir_assert(instruction->value->type->id == ZigTypeIdPointer, instruction); | 5491 | ir_assert(instruction->value->type->id == ZigTypeIdPointer, instruction); |
| 5492 | ZigType *operand_type = instruction->value->type->data.pointer.child_type; | 5492 | ZigType *operand_type = instruction->value->type->data.pointer.child_type; |
| ... | @@ -5498,7 +5498,7 @@ static LLVMTypeRef get_atomic_abi_type(CodeGen *g, IrInstGen *instruction) { | ... | @@ -5498,7 +5498,7 @@ static LLVMTypeRef get_atomic_abi_type(CodeGen *g, IrInstGen *instruction) { |
| 5498 | bool is_signed = operand_type->data.integral.is_signed; | 5498 | bool is_signed = operand_type->data.integral.is_signed; |
| 5499 | 5499 | ||
| 5500 | ir_assert(bit_count != 0, instruction); | 5500 | ir_assert(bit_count != 0, instruction); |
| 5501 | if (bit_count == 1 || !is_power_of_2(bit_count)) { | 5501 | if (!is_power_of_2(bit_count) || bit_count % 8) { |
| 5502 | return get_llvm_type(g, get_int_type(g, is_signed, operand_type->abi_size * 8)); | 5502 | return get_llvm_type(g, get_int_type(g, is_signed, operand_type->abi_size * 8)); |
| 5503 | } else { | 5503 | } else { |
| 5504 | return nullptr; | 5504 | return nullptr; |
src/target.zig+27| ... | @@ -374,3 +374,30 @@ pub fn hasRedZone(target: std.Target) bool { | ... | @@ -374,3 +374,30 @@ pub fn hasRedZone(target: std.Target) bool { |
| 374 | else => false, | 374 | else => false, |
| 375 | }; | 375 | }; |
| 376 | } | 376 | } |
| 377 | |||
| 378 | pub fn libcFullLinkFlags(target: std.Target) []const []const u8 { | ||
| 379 | // The linking order of these is significant and should match the order other | ||
| 380 | // c compilers such as gcc or clang use. | ||
| 381 | return switch (target.os.tag) { | ||
| 382 | .netbsd, .openbsd => &[_][]const u8{ | ||
| 383 | "-lm", | ||
| 384 | "-lpthread", | ||
| 385 | "-lc", | ||
| 386 | "-lutil", | ||
| 387 | }, | ||
| 388 | else => &[_][]const u8{ | ||
| 389 | "-lm", | ||
| 390 | "-lpthread", | ||
| 391 | "-lc", | ||
| 392 | "-ldl", | ||
| 393 | "-lrt", | ||
| 394 | "-lutil", | ||
| 395 | }, | ||
| 396 | }; | ||
| 397 | } | ||
| 398 | |||
| 399 | pub fn clangMightShellOutForAssembly(target: std.Target) bool { | ||
| 400 | // Clang defaults to using the system assembler over the internal one | ||
| 401 | // when targeting a non-BSD OS. | ||
| 402 | return target.cpu.arch.isSPARC(); | ||
| 403 | } |
src/test.zig+11| ... | @@ -8,6 +8,7 @@ const build_options = @import("build_options"); | ... | @@ -8,6 +8,7 @@ const build_options = @import("build_options"); |
| 8 | const enable_qemu: bool = build_options.enable_qemu; | 8 | const enable_qemu: bool = build_options.enable_qemu; |
| 9 | const enable_wine: bool = build_options.enable_wine; | 9 | const enable_wine: bool = build_options.enable_wine; |
| 10 | const enable_wasmtime: bool = build_options.enable_wasmtime; | 10 | const enable_wasmtime: bool = build_options.enable_wasmtime; |
| 11 | const enable_darling: bool = build_options.enable_darling; | ||
| 11 | const glibc_multi_install_dir: ?[]const u8 = build_options.glibc_multi_install_dir; | 12 | const glibc_multi_install_dir: ?[]const u8 = build_options.glibc_multi_install_dir; |
| 12 | const ThreadPool = @import("ThreadPool.zig"); | 13 | const ThreadPool = @import("ThreadPool.zig"); |
| 13 | const CrossTarget = std.zig.CrossTarget; | 14 | const CrossTarget = std.zig.CrossTarget; |
| ... | @@ -901,6 +902,16 @@ pub const TestContext = struct { | ... | @@ -901,6 +902,16 @@ pub const TestContext = struct { |
| 901 | } else { | 902 | } else { |
| 902 | return; // wasmtime not available; pass test. | 903 | return; // wasmtime not available; pass test. |
| 903 | }, | 904 | }, |
| 905 | |||
| 906 | .darling => |darling_bin_name| if (enable_darling) { | ||
| 907 | try argv.append(darling_bin_name); | ||
| 908 | // Since we use relative to cwd here, we invoke darling with | ||
| 909 | // "shell" subcommand. | ||
| 910 | try argv.append("shell"); | ||
| 911 | try argv.append(exe_path); | ||
| 912 | } else { | ||
| 913 | return; // Darling not available; pass test. | ||
| 914 | }, | ||
| 904 | } | 915 | } |
| 905 | 916 | ||
| 906 | try comp.makeBinFileExecutable(); | 917 | try comp.makeBinFileExecutable(); |
src/translate_c.zig+18| ... | @@ -480,6 +480,9 @@ fn declVisitor(c: *Context, decl: *const clang.Decl) Error!void { | ... | @@ -480,6 +480,9 @@ fn declVisitor(c: *Context, decl: *const clang.Decl) Error!void { |
| 480 | .Empty => { | 480 | .Empty => { |
| 481 | // Do nothing | 481 | // Do nothing |
| 482 | }, | 482 | }, |
| 483 | .FileScopeAsm => { | ||
| 484 | try transFileScopeAsm(c, &c.global_scope.base, @ptrCast(*const clang.FileScopeAsmDecl, decl)); | ||
| 485 | }, | ||
| 483 | else => { | 486 | else => { |
| 484 | const decl_name = try c.str(decl.getDeclKindName()); | 487 | const decl_name = try c.str(decl.getDeclKindName()); |
| 485 | try warn(c, &c.global_scope.base, decl.getLocation(), "ignoring {s} declaration", .{decl_name}); | 488 | try warn(c, &c.global_scope.base, decl.getLocation(), "ignoring {s} declaration", .{decl_name}); |
| ... | @@ -487,6 +490,21 @@ fn declVisitor(c: *Context, decl: *const clang.Decl) Error!void { | ... | @@ -487,6 +490,21 @@ fn declVisitor(c: *Context, decl: *const clang.Decl) Error!void { |
| 487 | } | 490 | } |
| 488 | } | 491 | } |
| 489 | 492 | ||
| 493 | fn transFileScopeAsm(c: *Context, scope: *Scope, file_scope_asm: *const clang.FileScopeAsmDecl) Error!void { | ||
| 494 | const asm_string = file_scope_asm.getAsmString(); | ||
| 495 | var len: usize = undefined; | ||
| 496 | const bytes_ptr = asm_string.getString_bytes_begin_size(&len); | ||
| 497 | |||
| 498 | const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(bytes_ptr[0..len])}); | ||
| 499 | const str_node = try Tag.string_literal.create(c.arena, str); | ||
| 500 | |||
| 501 | const asm_node = try Tag.asm_simple.create(c.arena, str_node); | ||
| 502 | const block = try Tag.block_single.create(c.arena, asm_node); | ||
| 503 | const comptime_node = try Tag.@"comptime".create(c.arena, block); | ||
| 504 | |||
| 505 | try scope.appendNode(comptime_node); | ||
| 506 | } | ||
| 507 | |||
| 490 | fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void { | 508 | fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void { |
| 491 | const fn_name = try c.str(@ptrCast(*const clang.NamedDecl, fn_decl).getName_bytes_begin()); | 509 | const fn_name = try c.str(@ptrCast(*const clang.NamedDecl, fn_decl).getName_bytes_begin()); |
| 492 | if (c.global_scope.sym_table.contains(fn_name)) | 510 | if (c.global_scope.sym_table.contains(fn_name)) |
src/translate_c/ast.zig+17| ... | @@ -161,6 +161,8 @@ pub const Node = extern union { | ... | @@ -161,6 +161,8 @@ pub const Node = extern union { |
| 161 | /// @shuffle(type, a, b, mask) | 161 | /// @shuffle(type, a, b, mask) |
| 162 | shuffle, | 162 | shuffle, |
| 163 | 163 | ||
| 164 | asm_simple, | ||
| 165 | |||
| 164 | negate, | 166 | negate, |
| 165 | negate_wrap, | 167 | negate_wrap, |
| 166 | bit_not, | 168 | bit_not, |
| ... | @@ -245,6 +247,7 @@ pub const Node = extern union { | ... | @@ -245,6 +247,7 @@ pub const Node = extern union { |
| 245 | .std_mem_zeroes, | 247 | .std_mem_zeroes, |
| 246 | .@"return", | 248 | .@"return", |
| 247 | .@"comptime", | 249 | .@"comptime", |
| 250 | .asm_simple, | ||
| 248 | .discard, | 251 | .discard, |
| 249 | .std_math_Log2Int, | 252 | .std_math_Log2Int, |
| 250 | .negate, | 253 | .negate, |
| ... | @@ -1017,6 +1020,19 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { | ... | @@ -1017,6 +1020,19 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1017 | }, | 1020 | }, |
| 1018 | }); | 1021 | }); |
| 1019 | }, | 1022 | }, |
| 1023 | .asm_simple => { | ||
| 1024 | const payload = node.castTag(.asm_simple).?.data; | ||
| 1025 | const asm_token = try c.addToken(.keyword_asm, "asm"); | ||
| 1026 | _ = try c.addToken(.l_paren, "("); | ||
| 1027 | return c.addNode(.{ | ||
| 1028 | .tag = .asm_simple, | ||
| 1029 | .main_token = asm_token, | ||
| 1030 | .data = .{ | ||
| 1031 | .lhs = try renderNode(c, payload), | ||
| 1032 | .rhs = try c.addToken(.r_paren, ")"), | ||
| 1033 | }, | ||
| 1034 | }); | ||
| 1035 | }, | ||
| 1020 | .type => { | 1036 | .type => { |
| 1021 | const payload = node.castTag(.type).?.data; | 1037 | const payload = node.castTag(.type).?.data; |
| 1022 | return c.addNode(.{ | 1038 | return c.addNode(.{ |
| ... | @@ -2257,6 +2273,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { | ... | @@ -2257,6 +2273,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { |
| 2257 | .@"continue", | 2273 | .@"continue", |
| 2258 | .@"return", | 2274 | .@"return", |
| 2259 | .@"comptime", | 2275 | .@"comptime", |
| 2276 | .asm_simple, | ||
| 2260 | .usingnamespace_builtins, | 2277 | .usingnamespace_builtins, |
| 2261 | .while_true, | 2278 | .while_true, |
| 2262 | .if_not_break, | 2279 | .if_not_break, |
src/zig_clang.cpp+5| ... | @@ -1820,6 +1820,11 @@ const ZigClangEnumDecl *ZigClangEnumDecl_getDefinition(const ZigClangEnumDecl *z | ... | @@ -1820,6 +1820,11 @@ const ZigClangEnumDecl *ZigClangEnumDecl_getDefinition(const ZigClangEnumDecl *z |
| 1820 | return reinterpret_cast<const ZigClangEnumDecl *>(definition); | 1820 | return reinterpret_cast<const ZigClangEnumDecl *>(definition); |
| 1821 | } | 1821 | } |
| 1822 | 1822 | ||
| 1823 | const ZigClangStringLiteral *ZigClangFileScopeAsmDecl_getAsmString(const ZigClangFileScopeAsmDecl *self) { | ||
| 1824 | const clang::StringLiteral *result = reinterpret_cast<const clang::FileScopeAsmDecl*>(self)->getAsmString(); | ||
| 1825 | return reinterpret_cast<const ZigClangStringLiteral *>(result); | ||
| 1826 | } | ||
| 1827 | |||
| 1823 | bool ZigClangRecordDecl_isUnion(const ZigClangRecordDecl *record_decl) { | 1828 | bool ZigClangRecordDecl_isUnion(const ZigClangRecordDecl *record_decl) { |
| 1824 | return reinterpret_cast<const clang::RecordDecl*>(record_decl)->isUnion(); | 1829 | return reinterpret_cast<const clang::RecordDecl*>(record_decl)->isUnion(); |
| 1825 | } | 1830 | } |
src/zig_clang.h+3| ... | @@ -124,6 +124,7 @@ struct ZigClangEnumType; | ... | @@ -124,6 +124,7 @@ struct ZigClangEnumType; |
| 124 | struct ZigClangExpr; | 124 | struct ZigClangExpr; |
| 125 | struct ZigClangFieldDecl; | 125 | struct ZigClangFieldDecl; |
| 126 | struct ZigClangFileID; | 126 | struct ZigClangFileID; |
| 127 | struct ZigClangFileScopeAsmDecl; | ||
| 127 | struct ZigClangFloatingLiteral; | 128 | struct ZigClangFloatingLiteral; |
| 128 | struct ZigClangForStmt; | 129 | struct ZigClangForStmt; |
| 129 | struct ZigClangFullSourceLoc; | 130 | struct ZigClangFullSourceLoc; |
| ... | @@ -1000,6 +1001,8 @@ ZIG_EXTERN_C unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangV | ... | @@ -1000,6 +1001,8 @@ ZIG_EXTERN_C unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangV |
| 1000 | ZIG_EXTERN_C unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx); | 1001 | ZIG_EXTERN_C unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx); |
| 1001 | ZIG_EXTERN_C unsigned ZigClangFieldDecl_getAlignedAttribute(const struct ZigClangFieldDecl *self, const ZigClangASTContext* ctx); | 1002 | ZIG_EXTERN_C unsigned ZigClangFieldDecl_getAlignedAttribute(const struct ZigClangFieldDecl *self, const ZigClangASTContext* ctx); |
| 1002 | 1003 | ||
| 1004 | ZIG_EXTERN_C const struct ZigClangStringLiteral *ZigClangFileScopeAsmDecl_getAsmString(const struct ZigClangFileScopeAsmDecl *self); | ||
| 1005 | |||
| 1003 | ZIG_EXTERN_C struct ZigClangQualType ZigClangParmVarDecl_getOriginalType(const struct ZigClangParmVarDecl *self); | 1006 | ZIG_EXTERN_C struct ZigClangQualType ZigClangParmVarDecl_getOriginalType(const struct ZigClangParmVarDecl *self); |
| 1004 | 1007 | ||
| 1005 | ZIG_EXTERN_C bool ZigClangRecordDecl_getPackedAttribute(const struct ZigClangRecordDecl *); | 1008 | ZIG_EXTERN_C bool ZigClangRecordDecl_getPackedAttribute(const struct ZigClangRecordDecl *); |
test/behavior/atomics.zig+1-1| ... | @@ -199,7 +199,7 @@ fn testAtomicRmwInt() !void { | ... | @@ -199,7 +199,7 @@ fn testAtomicRmwInt() !void { |
| 199 | 199 | ||
| 200 | test "atomics with different types" { | 200 | test "atomics with different types" { |
| 201 | try testAtomicsWithType(bool, true, false); | 201 | try testAtomicsWithType(bool, true, false); |
| 202 | inline for (.{ u1, i5, u15 }) |T| { | 202 | inline for (.{ u1, i4, u5, i15, u24 }) |T| { |
| 203 | var x: T = 0; | 203 | var x: T = 0; |
| 204 | try testAtomicsWithType(T, 0, 1); | 204 | try testAtomicsWithType(T, 0, 1); |
| 205 | } | 205 | } |
test/stage2/darwin.zig+34-7| ... | @@ -19,7 +19,7 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -19,7 +19,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 19 | 19 | ||
| 20 | // Incorrect return type | 20 | // Incorrect return type |
| 21 | case.addError( | 21 | case.addError( |
| 22 | \\pub export fn _start() noreturn { | 22 | \\pub export fn main() noreturn { |
| 23 | \\} | 23 | \\} |
| 24 | , &[_][]const u8{ | 24 | , &[_][]const u8{ |
| 25 | ":2:1: error: expected noreturn, found void", | 25 | ":2:1: error: expected noreturn, found void", |
| ... | @@ -30,7 +30,7 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -30,7 +30,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 30 | \\extern "c" fn write(usize, usize, usize) usize; | 30 | \\extern "c" fn write(usize, usize, usize) usize; |
| 31 | \\extern "c" fn exit(usize) noreturn; | 31 | \\extern "c" fn exit(usize) noreturn; |
| 32 | \\ | 32 | \\ |
| 33 | \\pub export fn _start() noreturn { | 33 | \\pub export fn main() noreturn { |
| 34 | \\ print(); | 34 | \\ print(); |
| 35 | \\ | 35 | \\ |
| 36 | \\ exit(0); | 36 | \\ exit(0); |
| ... | @@ -45,12 +45,39 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -45,12 +45,39 @@ pub fn addCases(ctx: *TestContext) !void { |
| 45 | "Hello, World!\n", | 45 | "Hello, World!\n", |
| 46 | ); | 46 | ); |
| 47 | 47 | ||
| 48 | // Now change the message only | 48 | // Print it 4 times and force growth and realloc. |
| 49 | case.addCompareOutput( | 49 | case.addCompareOutput( |
| 50 | \\extern "c" fn write(usize, usize, usize) usize; | 50 | \\extern "c" fn write(usize, usize, usize) usize; |
| 51 | \\extern "c" fn exit(usize) noreturn; | 51 | \\extern "c" fn exit(usize) noreturn; |
| 52 | \\ | 52 | \\ |
| 53 | \\pub export fn _start() noreturn { | 53 | \\pub export fn main() noreturn { |
| 54 | \\ print(); | ||
| 55 | \\ print(); | ||
| 56 | \\ print(); | ||
| 57 | \\ print(); | ||
| 58 | \\ | ||
| 59 | \\ exit(0); | ||
| 60 | \\} | ||
| 61 | \\ | ||
| 62 | \\fn print() void { | ||
| 63 | \\ const msg = @ptrToInt("Hello, World!\n"); | ||
| 64 | \\ const len = 14; | ||
| 65 | \\ _ = write(1, msg, len); | ||
| 66 | \\} | ||
| 67 | , | ||
| 68 | \\Hello, World! | ||
| 69 | \\Hello, World! | ||
| 70 | \\Hello, World! | ||
| 71 | \\Hello, World! | ||
| 72 | \\ | ||
| 73 | ); | ||
| 74 | |||
| 75 | // Print it once, and change the message. | ||
| 76 | case.addCompareOutput( | ||
| 77 | \\extern "c" fn write(usize, usize, usize) usize; | ||
| 78 | \\extern "c" fn exit(usize) noreturn; | ||
| 79 | \\ | ||
| 80 | \\export fn _main() noreturn { | ||
| 54 | \\ print(); | 81 | \\ print(); |
| 55 | \\ | 82 | \\ |
| 56 | \\ exit(0); | 83 | \\ exit(0); |
| ... | @@ -70,7 +97,7 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -70,7 +97,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 70 | \\extern "c" fn write(usize, usize, usize) usize; | 97 | \\extern "c" fn write(usize, usize, usize) usize; |
| 71 | \\extern "c" fn exit(usize) noreturn; | 98 | \\extern "c" fn exit(usize) noreturn; |
| 72 | \\ | 99 | \\ |
| 73 | \\pub export fn _start() noreturn { | 100 | \\pub export fn main() noreturn { |
| 74 | \\ print(); | 101 | \\ print(); |
| 75 | \\ print(); | 102 | \\ print(); |
| 76 | \\ | 103 | \\ |
| ... | @@ -96,7 +123,7 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -96,7 +123,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 96 | case.addCompareOutput( | 123 | case.addCompareOutput( |
| 97 | \\extern "c" fn exit(usize) noreturn; | 124 | \\extern "c" fn exit(usize) noreturn; |
| 98 | \\ | 125 | \\ |
| 99 | \\pub export fn _start() noreturn { | 126 | \\pub export fn main() noreturn { |
| 100 | \\ exit(0); | 127 | \\ exit(0); |
| 101 | \\} | 128 | \\} |
| 102 | , | 129 | , |
| ... | @@ -107,7 +134,7 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -107,7 +134,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 107 | \\extern "c" fn exit(usize) noreturn; | 134 | \\extern "c" fn exit(usize) noreturn; |
| 108 | \\extern "c" fn write(usize, usize, usize) usize; | 135 | \\extern "c" fn write(usize, usize, usize) usize; |
| 109 | \\ | 136 | \\ |
| 110 | \\pub export fn _start() noreturn { | 137 | \\pub export fn main() noreturn { |
| 111 | \\ _ = write(1, @ptrToInt("Hey!\n"), 5); | 138 | \\ _ = write(1, @ptrToInt("Hey!\n"), 5); |
| 112 | \\ exit(0); | 139 | \\ exit(0); |
| 113 | \\} | 140 | \\} |
test/tests.zig+2| ... | @@ -503,6 +503,7 @@ pub fn addPkgTests( | ... | @@ -503,6 +503,7 @@ pub fn addPkgTests( |
| 503 | is_wine_enabled: bool, | 503 | is_wine_enabled: bool, |
| 504 | is_qemu_enabled: bool, | 504 | is_qemu_enabled: bool, |
| 505 | is_wasmtime_enabled: bool, | 505 | is_wasmtime_enabled: bool, |
| 506 | is_darling_enabled: bool, | ||
| 506 | glibc_dir: ?[]const u8, | 507 | glibc_dir: ?[]const u8, |
| 507 | ) *build.Step { | 508 | ) *build.Step { |
| 508 | const step = b.step(b.fmt("test-{s}", .{name}), desc); | 509 | const step = b.step(b.fmt("test-{s}", .{name}), desc); |
| ... | @@ -564,6 +565,7 @@ pub fn addPkgTests( | ... | @@ -564,6 +565,7 @@ pub fn addPkgTests( |
| 564 | these_tests.enable_wine = is_wine_enabled; | 565 | these_tests.enable_wine = is_wine_enabled; |
| 565 | these_tests.enable_qemu = is_qemu_enabled; | 566 | these_tests.enable_qemu = is_qemu_enabled; |
| 566 | these_tests.enable_wasmtime = is_wasmtime_enabled; | 567 | these_tests.enable_wasmtime = is_wasmtime_enabled; |
| 568 | these_tests.enable_darling = is_darling_enabled; | ||
| 567 | these_tests.glibc_multi_install_dir = glibc_dir; | 569 | these_tests.glibc_multi_install_dir = glibc_dir; |
| 568 | these_tests.addIncludeDir("test"); | 570 | these_tests.addIncludeDir("test"); |
| 569 | 571 |
test/translate_c.zig+14| ... | @@ -3499,4 +3499,18 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -3499,4 +3499,18 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3499 | \\ '\u{1f4af}', | 3499 | \\ '\u{1f4af}', |
| 3500 | \\}; | 3500 | \\}; |
| 3501 | }); | 3501 | }); |
| 3502 | |||
| 3503 | cases.add("global assembly", | ||
| 3504 | \\__asm__(".globl func\n\t" | ||
| 3505 | \\ ".type func, @function\n\t" | ||
| 3506 | \\ "func:\n\t" | ||
| 3507 | \\ ".cfi_startproc\n\t" | ||
| 3508 | \\ "movl $42, %eax\n\t" | ||
| 3509 | \\ "ret\n\t" | ||
| 3510 | \\ ".cfi_endproc"); | ||
| 3511 | , &[_][]const u8{ | ||
| 3512 | \\comptime { | ||
| 3513 | \\ asm (".globl func\n\t.type func, @function\n\tfunc:\n\t.cfi_startproc\n\tmovl $42, %eax\n\tret\n\t.cfi_endproc"); | ||
| 3514 | \\} | ||
| 3515 | }); | ||
| 3502 | } | 3516 | } |
tools/gen_spirv_spec.zig+25-122| ... | @@ -1,96 +1,5 @@ | ... | @@ -1,96 +1,5 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const Writer = std.ArrayList(u8).Writer; | 2 | const g = @import("spirv/grammar.zig"); |
| 3 | |||
| 4 | //! See https://www.khronos.org/registry/spir-v/specs/unified1/MachineReadableGrammar.html | ||
| 5 | //! and the files in https://github.com/KhronosGroup/SPIRV-Headers/blob/master/include/spirv/unified1/ | ||
| 6 | //! Note: Non-canonical casing in these structs used to match SPIR-V spec json. | ||
| 7 | const Registry = union(enum) { | ||
| 8 | core: CoreRegistry, | ||
| 9 | extension: ExtensionRegistry, | ||
| 10 | }; | ||
| 11 | |||
| 12 | const CoreRegistry = struct { | ||
| 13 | copyright: [][]const u8, | ||
| 14 | /// Hexadecimal representation of the magic number | ||
| 15 | magic_number: []const u8, | ||
| 16 | major_version: u32, | ||
| 17 | minor_version: u32, | ||
| 18 | revision: u32, | ||
| 19 | instruction_printing_class: []InstructionPrintingClass, | ||
| 20 | instructions: []Instruction, | ||
| 21 | operand_kinds: []OperandKind, | ||
| 22 | }; | ||
| 23 | |||
| 24 | const ExtensionRegistry = struct { | ||
| 25 | copyright: [][]const u8, | ||
| 26 | version: u32, | ||
| 27 | revision: u32, | ||
| 28 | instructions: []Instruction, | ||
| 29 | operand_kinds: []OperandKind = &[_]OperandKind{}, | ||
| 30 | }; | ||
| 31 | |||
| 32 | const InstructionPrintingClass = struct { | ||
| 33 | tag: []const u8, | ||
| 34 | heading: ?[]const u8 = null, | ||
| 35 | }; | ||
| 36 | |||
| 37 | const Instruction = struct { | ||
| 38 | opname: []const u8, | ||
| 39 | class: ?[]const u8 = null, // Note: Only available in the core registry. | ||
| 40 | opcode: u32, | ||
| 41 | operands: []Operand = &[_]Operand{}, | ||
| 42 | capabilities: [][]const u8 = &[_][]const u8{}, | ||
| 43 | extensions: [][]const u8 = &[_][]const u8{}, | ||
| 44 | version: ?[]const u8 = null, | ||
| 45 | |||
| 46 | lastVersion: ?[]const u8 = null, | ||
| 47 | }; | ||
| 48 | |||
| 49 | const Operand = struct { | ||
| 50 | kind: []const u8, | ||
| 51 | /// If this field is 'null', the operand is only expected once. | ||
| 52 | quantifier: ?Quantifier = null, | ||
| 53 | name: []const u8 = "", | ||
| 54 | }; | ||
| 55 | |||
| 56 | const Quantifier = enum { | ||
| 57 | /// zero or once | ||
| 58 | @"?", | ||
| 59 | /// zero or more | ||
| 60 | @"*", | ||
| 61 | }; | ||
| 62 | |||
| 63 | const OperandCategory = enum { | ||
| 64 | BitEnum, | ||
| 65 | ValueEnum, | ||
| 66 | Id, | ||
| 67 | Literal, | ||
| 68 | Composite, | ||
| 69 | }; | ||
| 70 | |||
| 71 | const OperandKind = struct { | ||
| 72 | category: OperandCategory, | ||
| 73 | /// The name | ||
| 74 | kind: []const u8, | ||
| 75 | doc: ?[]const u8 = null, | ||
| 76 | enumerants: ?[]Enumerant = null, | ||
| 77 | bases: ?[]const []const u8 = null, | ||
| 78 | }; | ||
| 79 | |||
| 80 | const Enumerant = struct { | ||
| 81 | enumerant: []const u8, | ||
| 82 | value: union(enum) { | ||
| 83 | bitflag: []const u8, // Hexadecimal representation of the value | ||
| 84 | int: u31, | ||
| 85 | }, | ||
| 86 | capabilities: [][]const u8 = &[_][]const u8{}, | ||
| 87 | /// Valid for .ValueEnum and .BitEnum | ||
| 88 | extensions: [][]const u8 = &[_][]const u8{}, | ||
| 89 | /// `quantifier` will always be `null`. | ||
| 90 | parameters: []Operand = &[_]Operand{}, | ||
| 91 | version: ?[]const u8 = null, | ||
| 92 | lastVersion: ?[]const u8 = null, | ||
| 93 | }; | ||
| 94 | 3 | ||
| 95 | pub fn main() !void { | 4 | pub fn main() !void { |
| 96 | var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); | 5 | var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); |
| ... | @@ -106,24 +15,25 @@ pub fn main() !void { | ... | @@ -106,24 +15,25 @@ pub fn main() !void { |
| 106 | const spec = try std.fs.cwd().readFileAlloc(allocator, spec_path, std.math.maxInt(usize)); | 15 | const spec = try std.fs.cwd().readFileAlloc(allocator, spec_path, std.math.maxInt(usize)); |
| 107 | 16 | ||
| 108 | var tokens = std.json.TokenStream.init(spec); | 17 | var tokens = std.json.TokenStream.init(spec); |
| 109 | var registry = try std.json.parse(Registry, &tokens, .{.allocator = allocator}); | 18 | var registry = try std.json.parse(g.Registry, &tokens, .{.allocator = allocator}); |
| 110 | 19 | ||
| 111 | var buf = std.ArrayList(u8).init(allocator); | 20 | var bw = std.io.bufferedWriter(std.io.getStdOut().writer()); |
| 112 | defer buf.deinit(); | 21 | try render(bw.writer(), registry); |
| 113 | 22 | try bw.flush(); | |
| 114 | try render(buf.writer(), registry); | ||
| 115 | |||
| 116 | const tree = try std.zig.parse(allocator, buf.items); | ||
| 117 | _ = try std.zig.render(allocator, std.io.getStdOut().writer(), tree); | ||
| 118 | } | 23 | } |
| 119 | 24 | ||
| 120 | fn render(writer: Writer, registry: Registry) !void { | 25 | fn render(writer: anytype, registry: g.Registry) !void { |
| 26 | try writer.writeAll( | ||
| 27 | \\//! This file is auto-generated by tools/gen_spirv_spec.zig. | ||
| 28 | \\ | ||
| 29 | \\const Version = @import("std").builtin.Version; | ||
| 30 | \\ | ||
| 31 | ); | ||
| 32 | |||
| 121 | switch (registry) { | 33 | switch (registry) { |
| 122 | .core => |core_reg| { | 34 | .core => |core_reg| { |
| 123 | try renderCopyRight(writer, core_reg.copyright); | ||
| 124 | try writer.print( | 35 | try writer.print( |
| 125 | \\const Version = @import("builtin").Version; | 36 | \\pub const version = Version{{ .major = {}, .minor = {}, .patch = {} }}; |
| 126 | \\pub const version = Version{{.major = {}, .minor = {}, .patch = {}}}; | ||
| 127 | \\pub const magic_number: u32 = {s}; | 37 | \\pub const magic_number: u32 = {s}; |
| 128 | \\ | 38 | \\ |
| 129 | , .{ core_reg.major_version, core_reg.minor_version, core_reg.revision, core_reg.magic_number }, | 39 | , .{ core_reg.major_version, core_reg.minor_version, core_reg.revision, core_reg.magic_number }, |
| ... | @@ -132,10 +42,8 @@ fn render(writer: Writer, registry: Registry) !void { | ... | @@ -132,10 +42,8 @@ fn render(writer: Writer, registry: Registry) !void { |
| 132 | try renderOperandKinds(writer, core_reg.operand_kinds); | 42 | try renderOperandKinds(writer, core_reg.operand_kinds); |
| 133 | }, | 43 | }, |
| 134 | .extension => |ext_reg| { | 44 | .extension => |ext_reg| { |
| 135 | try renderCopyRight(writer, ext_reg.copyright); | ||
| 136 | try writer.print( | 45 | try writer.print( |
| 137 | \\const Version = @import("builtin").Version; | 46 | \\pub const version = Version{{ .major = {}, .minor = 0, .patch = {} }}; |
| 138 | \\pub const version = Version{{.major = {}, .minor = 0, .patch = {}}}; | ||
| 139 | \\ | 47 | \\ |
| 140 | , .{ ext_reg.version, ext_reg.revision }, | 48 | , .{ ext_reg.version, ext_reg.revision }, |
| 141 | ); | 49 | ); |
| ... | @@ -145,21 +53,15 @@ fn render(writer: Writer, registry: Registry) !void { | ... | @@ -145,21 +53,15 @@ fn render(writer: Writer, registry: Registry) !void { |
| 145 | } | 53 | } |
| 146 | } | 54 | } |
| 147 | 55 | ||
| 148 | fn renderCopyRight(writer: Writer, copyright: []const []const u8) !void { | 56 | fn renderOpcodes(writer: anytype, instructions: []const g.Instruction) !void { |
| 149 | for (copyright) |line| { | ||
| 150 | try writer.print("// {s}\n", .{ line }); | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | fn renderOpcodes(writer: Writer, instructions: []const Instruction) !void { | ||
| 155 | try writer.writeAll("pub const Opcode = extern enum(u16) {\n"); | 57 | try writer.writeAll("pub const Opcode = extern enum(u16) {\n"); |
| 156 | for (instructions) |instr| { | 58 | for (instructions) |instr| { |
| 157 | try writer.print("{} = {},\n", .{ std.zig.fmtId(instr.opname), instr.opcode }); | 59 | try writer.print(" {} = {},\n", .{ std.zig.fmtId(instr.opname), instr.opcode }); |
| 158 | } | 60 | } |
| 159 | try writer.writeAll("_,\n};\n"); | 61 | try writer.writeAll(" _,\n};\n"); |
| 160 | } | 62 | } |
| 161 | 63 | ||
| 162 | fn renderOperandKinds(writer: Writer, kinds: []const OperandKind) !void { | 64 | fn renderOperandKinds(writer: anytype, kinds: []const g.OperandKind) !void { |
| 163 | for (kinds) |kind| { | 65 | for (kinds) |kind| { |
| 164 | switch (kind.category) { | 66 | switch (kind.category) { |
| 165 | .ValueEnum => try renderValueEnum(writer, kind), | 67 | .ValueEnum => try renderValueEnum(writer, kind), |
| ... | @@ -169,20 +71,20 @@ fn renderOperandKinds(writer: Writer, kinds: []const OperandKind) !void { | ... | @@ -169,20 +71,20 @@ fn renderOperandKinds(writer: Writer, kinds: []const OperandKind) !void { |
| 169 | } | 71 | } |
| 170 | } | 72 | } |
| 171 | 73 | ||
| 172 | fn renderValueEnum(writer: Writer, enumeration: OperandKind) !void { | 74 | fn renderValueEnum(writer: anytype, enumeration: g.OperandKind) !void { |
| 173 | try writer.print("pub const {s} = extern enum(u32) {{\n", .{ enumeration.kind }); | 75 | try writer.print("pub const {s} = extern enum(u32) {{\n", .{ enumeration.kind }); |
| 174 | 76 | ||
| 175 | const enumerants = enumeration.enumerants orelse return error.InvalidRegistry; | 77 | const enumerants = enumeration.enumerants orelse return error.InvalidRegistry; |
| 176 | for (enumerants) |enumerant| { | 78 | for (enumerants) |enumerant| { |
| 177 | if (enumerant.value != .int) return error.InvalidRegistry; | 79 | if (enumerant.value != .int) return error.InvalidRegistry; |
| 178 | 80 | ||
| 179 | try writer.print("{} = {},\n", .{ std.zig.fmtId(enumerant.enumerant), enumerant.value.int }); | 81 | try writer.print(" {} = {},\n", .{ std.zig.fmtId(enumerant.enumerant), enumerant.value.int }); |
| 180 | } | 82 | } |
| 181 | 83 | ||
| 182 | try writer.writeAll("_,\n};\n"); | 84 | try writer.writeAll(" _,\n};\n"); |
| 183 | } | 85 | } |
| 184 | 86 | ||
| 185 | fn renderBitEnum(writer: Writer, enumeration: OperandKind) !void { | 87 | fn renderBitEnum(writer: anytype, enumeration: g.OperandKind) !void { |
| 186 | try writer.print("pub const {s} = packed struct {{\n", .{ enumeration.kind }); | 88 | try writer.print("pub const {s} = packed struct {{\n", .{ enumeration.kind }); |
| 187 | 89 | ||
| 188 | var flags_by_bitpos = [_]?[]const u8{null} ** 32; | 90 | var flags_by_bitpos = [_]?[]const u8{null} ** 32; |
| ... | @@ -205,6 +107,7 @@ fn renderBitEnum(writer: Writer, enumeration: OperandKind) !void { | ... | @@ -205,6 +107,7 @@ fn renderBitEnum(writer: Writer, enumeration: OperandKind) !void { |
| 205 | } | 107 | } |
| 206 | 108 | ||
| 207 | for (flags_by_bitpos) |maybe_flag_name, bitpos| { | 109 | for (flags_by_bitpos) |maybe_flag_name, bitpos| { |
| 110 | try writer.writeAll(" "); | ||
| 208 | if (maybe_flag_name) |flag_name| { | 111 | if (maybe_flag_name) |flag_name| { |
| 209 | try writer.writeAll(flag_name); | 112 | try writer.writeAll(flag_name); |
| 210 | } else { | 113 | } else { |
| ... | @@ -215,7 +118,7 @@ fn renderBitEnum(writer: Writer, enumeration: OperandKind) !void { | ... | @@ -215,7 +118,7 @@ fn renderBitEnum(writer: Writer, enumeration: OperandKind) !void { |
| 215 | if (bitpos == 0) { // Force alignment to integer boundaries | 118 | if (bitpos == 0) { // Force alignment to integer boundaries |
| 216 | try writer.writeAll("align(@alignOf(u32)) "); | 119 | try writer.writeAll("align(@alignOf(u32)) "); |
| 217 | } | 120 | } |
| 218 | try writer.writeAll("= false, "); | 121 | try writer.writeAll("= false,\n"); |
| 219 | } | 122 | } |
| 220 | 123 | ||
| 221 | try writer.writeAll("};\n"); | 124 | try writer.writeAll("};\n"); |
tools/spirv/grammar.zig created+90| ... | @@ -0,0 +1,90 @@ | ||
| 1 | //! See https://www.khronos.org/registry/spir-v/specs/unified1/MachineReadableGrammar.html | ||
| 2 | //! and the files in https://github.com/KhronosGroup/SPIRV-Headers/blob/master/include/spirv/unified1/ | ||
| 3 | //! Note: Non-canonical casing in these structs used to match SPIR-V spec json. | ||
| 4 | pub const Registry = union(enum) { | ||
| 5 | core: CoreRegistry, | ||
| 6 | extension: ExtensionRegistry, | ||
| 7 | }; | ||
| 8 | |||
| 9 | pub const CoreRegistry = struct { | ||
| 10 | copyright: [][]const u8, | ||
| 11 | /// Hexadecimal representation of the magic number | ||
| 12 | magic_number: []const u8, | ||
| 13 | major_version: u32, | ||
| 14 | minor_version: u32, | ||
| 15 | revision: u32, | ||
| 16 | instruction_printing_class: []InstructionPrintingClass, | ||
| 17 | instructions: []Instruction, | ||
| 18 | operand_kinds: []OperandKind, | ||
| 19 | }; | ||
| 20 | |||
| 21 | pub const ExtensionRegistry = struct { | ||
| 22 | copyright: [][]const u8, | ||
| 23 | version: u32, | ||
| 24 | revision: u32, | ||
| 25 | instructions: []Instruction, | ||
| 26 | operand_kinds: []OperandKind = &[_]OperandKind{}, | ||
| 27 | }; | ||
| 28 | |||
| 29 | pub const InstructionPrintingClass = struct { | ||
| 30 | tag: []const u8, | ||
| 31 | heading: ?[]const u8 = null, | ||
| 32 | }; | ||
| 33 | |||
| 34 | pub const Instruction = struct { | ||
| 35 | opname: []const u8, | ||
| 36 | class: ?[]const u8 = null, // Note: Only available in the core registry. | ||
| 37 | opcode: u32, | ||
| 38 | operands: []Operand = &[_]Operand{}, | ||
| 39 | capabilities: [][]const u8 = &[_][]const u8{}, | ||
| 40 | extensions: [][]const u8 = &[_][]const u8{}, | ||
| 41 | version: ?[]const u8 = null, | ||
| 42 | |||
| 43 | lastVersion: ?[]const u8 = null, | ||
| 44 | }; | ||
| 45 | |||
| 46 | pub const Operand = struct { | ||
| 47 | kind: []const u8, | ||
| 48 | /// If this field is 'null', the operand is only expected once. | ||
| 49 | quantifier: ?Quantifier = null, | ||
| 50 | name: []const u8 = "", | ||
| 51 | }; | ||
| 52 | |||
| 53 | pub const Quantifier = enum { | ||
| 54 | /// zero or once | ||
| 55 | @"?", | ||
| 56 | /// zero or more | ||
| 57 | @"*", | ||
| 58 | }; | ||
| 59 | |||
| 60 | pub const OperandCategory = enum { | ||
| 61 | BitEnum, | ||
| 62 | ValueEnum, | ||
| 63 | Id, | ||
| 64 | Literal, | ||
| 65 | Composite, | ||
| 66 | }; | ||
| 67 | |||
| 68 | pub const OperandKind = struct { | ||
| 69 | category: OperandCategory, | ||
| 70 | /// The name | ||
| 71 | kind: []const u8, | ||
| 72 | doc: ?[]const u8 = null, | ||
| 73 | enumerants: ?[]Enumerant = null, | ||
| 74 | bases: ?[]const []const u8 = null, | ||
| 75 | }; | ||
| 76 | |||
| 77 | pub const Enumerant = struct { | ||
| 78 | enumerant: []const u8, | ||
| 79 | value: union(enum) { | ||
| 80 | bitflag: []const u8, // Hexadecimal representation of the value | ||
| 81 | int: u31, | ||
| 82 | }, | ||
| 83 | capabilities: [][]const u8 = &[_][]const u8{}, | ||
| 84 | /// Valid for .ValueEnum and .BitEnum | ||
| 85 | extensions: [][]const u8 = &[_][]const u8{}, | ||
| 86 | /// `quantifier` will always be `null`. | ||
| 87 | parameters: []Operand = &[_]Operand{}, | ||
| 88 | version: ?[]const u8 = null, | ||
| 89 | lastVersion: ?[]const u8 = null, | ||
| 90 | }; | ||
tools/update_spirv_features.zig created+321| ... | @@ -0,0 +1,321 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const fs = std.fs; | ||
| 3 | const Allocator = std.mem.Allocator; | ||
| 4 | const g = @import("spirv/grammar.zig"); | ||
| 5 | |||
| 6 | //! This tool generates SPIR-V features from the grammar files in the SPIRV-Headers | ||
| 7 | //! (https://github.com/KhronosGroup/SPIRV-Headers/) and SPIRV-Registry (https://github.com/KhronosGroup/SPIRV-Registry/) | ||
| 8 | //! repositories. Currently it only generates a basic feature set definition consisting of versions, extensions and capabilities. | ||
| 9 | //! There is a lot left to be desired, as currently dependencies of extensions and dependencies on extensions aren't generated. | ||
| 10 | //! This is because there are some peculiarities in the SPIR-V registries: | ||
| 11 | //! - Capabilities may depend on multiple extensions, which cannot be modelled yet by std.Target. | ||
| 12 | //! - Extension dependencies are not documented in a machine-readable manner. | ||
| 13 | //! - Note that the grammar spec also contains definitions from extensions which aren't actually official. Most of these seem to be | ||
| 14 | //! from an intel project (https://github.com/intel/llvm/, https://github.com/intel/llvm/tree/sycl/sycl/doc/extensions/SPIRV), | ||
| 15 | //! and so ONLY extensions in the SPIRV-Registry should be included. | ||
| 16 | |||
| 17 | const Version = struct { | ||
| 18 | major: u32, | ||
| 19 | minor: u32, | ||
| 20 | |||
| 21 | fn parse(str: []const u8) !Version { | ||
| 22 | var it = std.mem.split(str, "."); | ||
| 23 | |||
| 24 | const major = it.next() orelse return error.InvalidVersion; | ||
| 25 | const minor = it.next() orelse return error.InvalidVersion; | ||
| 26 | |||
| 27 | if (it.next() != null) return error.InvalidVersion; | ||
| 28 | |||
| 29 | return Version{ | ||
| 30 | .major = std.fmt.parseInt(u32, major, 10) catch return error.InvalidVersion, | ||
| 31 | .minor = std.fmt.parseInt(u32, minor, 10) catch return error.InvalidVersion, | ||
| 32 | }; | ||
| 33 | } | ||
| 34 | |||
| 35 | fn eql(a: Version, b: Version) bool { | ||
| 36 | return a.major == b.major and a.minor == b.minor; | ||
| 37 | } | ||
| 38 | |||
| 39 | fn lessThan(ctx: void, a: Version, b: Version) bool { | ||
| 40 | return if (a.major == b.major) | ||
| 41 | a.minor < b.minor | ||
| 42 | else | ||
| 43 | a.major < b.major; | ||
| 44 | } | ||
| 45 | }; | ||
| 46 | |||
| 47 | pub fn main() !void { | ||
| 48 | var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); | ||
| 49 | defer arena.deinit(); | ||
| 50 | const allocator = &arena.allocator; | ||
| 51 | |||
| 52 | const args = try std.process.argsAlloc(allocator); | ||
| 53 | |||
| 54 | if (args.len <= 1) { | ||
| 55 | usageAndExit(std.io.getStdErr(), args[0], 1); | ||
| 56 | } | ||
| 57 | if (std.mem.eql(u8, args[1], "--help")) { | ||
| 58 | usageAndExit(std.io.getStdErr(), args[0], 0); | ||
| 59 | } | ||
| 60 | if (args.len != 3) { | ||
| 61 | usageAndExit(std.io.getStdErr(), args[0], 1); | ||
| 62 | } | ||
| 63 | |||
| 64 | const spirv_headers_root = args[1]; | ||
| 65 | const spirv_registry_root = args[2]; | ||
| 66 | |||
| 67 | if (std.mem.startsWith(u8, spirv_headers_root, "-") or std.mem.startsWith(u8, spirv_registry_root, "-")) { | ||
| 68 | usageAndExit(std.io.getStdErr(), args[0], 1); | ||
| 69 | } | ||
| 70 | |||
| 71 | const registry_path = try fs.path.join(allocator, &.{ spirv_headers_root, "include", "spirv", "unified1", "spirv.core.grammar.json" }); | ||
| 72 | const registry_json = try std.fs.cwd().readFileAlloc(allocator, registry_path, std.math.maxInt(usize)); | ||
| 73 | var tokens = std.json.TokenStream.init(registry_json); | ||
| 74 | const registry = try std.json.parse(g.CoreRegistry, &tokens, .{ .allocator = allocator }); | ||
| 75 | |||
| 76 | const capabilities = for (registry.operand_kinds) |opkind| { | ||
| 77 | if (std.mem.eql(u8, opkind.kind, "Capability")) | ||
| 78 | break opkind.enumerants orelse return error.InvalidRegistry; | ||
| 79 | } else return error.InvalidRegistry; | ||
| 80 | |||
| 81 | const extensions = try gather_extensions(allocator, spirv_registry_root); | ||
| 82 | const versions = try gatherVersions(allocator, registry); | ||
| 83 | |||
| 84 | var bw = std.io.bufferedWriter(std.io.getStdOut().writer()); | ||
| 85 | const w = bw.writer(); | ||
| 86 | |||
| 87 | try w.writeAll( | ||
| 88 | \\//! This file is auto-generated by tools/update_spirv_features.zig. | ||
| 89 | \\//! TODO: Dependencies of capabilities on extensions. | ||
| 90 | \\//! TODO: Dependencies of extensions on extensions. | ||
| 91 | \\//! TODO: Dependencies of extensions on versions. | ||
| 92 | \\ | ||
| 93 | \\const std = @import("../std.zig"); | ||
| 94 | \\const CpuFeature = std.Target.Cpu.Feature; | ||
| 95 | \\const CpuModel = std.Target.Cpu.Model; | ||
| 96 | \\ | ||
| 97 | \\pub const Feature = enum { | ||
| 98 | \\ | ||
| 99 | ); | ||
| 100 | |||
| 101 | for (versions) |ver| { | ||
| 102 | try w.print(" v{}_{},\n", .{ ver.major, ver.minor }); | ||
| 103 | } | ||
| 104 | |||
| 105 | for (extensions) |ext| { | ||
| 106 | try w.print(" {},\n", .{ std.zig.fmtId(ext) }); | ||
| 107 | } | ||
| 108 | |||
| 109 | for (capabilities) |cap| { | ||
| 110 | try w.print(" {},\n", .{ std.zig.fmtId(cap.enumerant) }); | ||
| 111 | } | ||
| 112 | |||
| 113 | try w.writeAll( | ||
| 114 | \\}; | ||
| 115 | \\ | ||
| 116 | \\pub usingnamespace CpuFeature.feature_set_fns(Feature); | ||
| 117 | \\ | ||
| 118 | \\pub const all_features = blk: { | ||
| 119 | \\ @setEvalBranchQuota(2000); | ||
| 120 | \\ const len = @typeInfo(Feature).Enum.fields.len; | ||
| 121 | \\ std.debug.assert(len <= CpuFeature.Set.needed_bit_count); | ||
| 122 | \\ var result: [len]CpuFeature = undefined; | ||
| 123 | \\ | ||
| 124 | ); | ||
| 125 | |||
| 126 | for (versions) |ver, i| { | ||
| 127 | try w.print( | ||
| 128 | \\ result[@enumToInt(Feature.v{0}_{1})] = .{{ | ||
| 129 | \\ .llvm_name = null, | ||
| 130 | \\ .description = "SPIR-V version {0}.{1}", | ||
| 131 | \\ | ||
| 132 | , .{ ver.major, ver.minor } | ||
| 133 | ); | ||
| 134 | |||
| 135 | if (i == 0) { | ||
| 136 | try w.writeAll( | ||
| 137 | \\ .dependencies = featureSet(&[_]Feature{}), | ||
| 138 | \\ }; | ||
| 139 | \\ | ||
| 140 | ); | ||
| 141 | } else { | ||
| 142 | try w.print( | ||
| 143 | \\ .dependencies = featureSet(&[_]Feature{{ | ||
| 144 | \\ .v{}_{}, | ||
| 145 | \\ }}), | ||
| 146 | \\ }}; | ||
| 147 | \\ | ||
| 148 | , .{ versions[i - 1].major, versions[i - 1].minor } | ||
| 149 | ); | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 153 | // TODO: Extension dependencies. | ||
| 154 | for (extensions) |ext| { | ||
| 155 | try w.print( | ||
| 156 | \\ result[@enumToInt(Feature.{s})] = .{{ | ||
| 157 | \\ .llvm_name = null, | ||
| 158 | \\ .description = "SPIR-V extension {s}", | ||
| 159 | \\ .dependencies = featureSet(&[_]Feature{{}}), | ||
| 160 | \\ }}; | ||
| 161 | \\ | ||
| 162 | , .{ | ||
| 163 | std.zig.fmtId(ext), | ||
| 164 | ext, | ||
| 165 | } | ||
| 166 | ); | ||
| 167 | } | ||
| 168 | |||
| 169 | // TODO: Capability extension dependencies. | ||
| 170 | for (capabilities) |cap| { | ||
| 171 | try w.print( | ||
| 172 | \\ result[@enumToInt(Feature.{s})] = .{{ | ||
| 173 | \\ .llvm_name = null, | ||
| 174 | \\ .description = "Enable SPIR-V capability {s}", | ||
| 175 | \\ .dependencies = featureSet(&[_]Feature{{ | ||
| 176 | \\ | ||
| 177 | , .{ | ||
| 178 | std.zig.fmtId(cap.enumerant), | ||
| 179 | cap.enumerant, | ||
| 180 | } | ||
| 181 | ); | ||
| 182 | |||
| 183 | if (cap.version) |ver_str| { | ||
| 184 | if (!std.mem.eql(u8, ver_str, "None")) { | ||
| 185 | const ver = try Version.parse(ver_str); | ||
| 186 | try w.print(" .v{}_{},\n", .{ ver.major, ver.minor }); | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 190 | for (cap.capabilities) |cap_dep| { | ||
| 191 | try w.print(" .{},\n", .{ std.zig.fmtId(cap_dep) }); | ||
| 192 | } | ||
| 193 | |||
| 194 | try w.writeAll( | ||
| 195 | \\ }), | ||
| 196 | \\ }; | ||
| 197 | \\ | ||
| 198 | ); | ||
| 199 | } | ||
| 200 | |||
| 201 | try w.writeAll( | ||
| 202 | \\ const ti = @typeInfo(Feature); | ||
| 203 | \\ for (result) |*elem, i| { | ||
| 204 | \\ elem.index = i; | ||
| 205 | \\ elem.name = ti.Enum.fields[i].name; | ||
| 206 | \\ } | ||
| 207 | \\ break :blk result; | ||
| 208 | \\}; | ||
| 209 | \\ | ||
| 210 | ); | ||
| 211 | |||
| 212 | try bw.flush(); | ||
| 213 | } | ||
| 214 | |||
| 215 | /// SPIRV-Registry should hold all extensions currently registered for SPIR-V. | ||
| 216 | /// The *.grammar.json in SPIRV-Headers should have most of these as well, but with this we're sure to get only the actually | ||
| 217 | /// registered ones. | ||
| 218 | /// TODO: Unfortunately, neither repository contains a machine-readable list of extension dependencies. | ||
| 219 | fn gather_extensions(allocator: *Allocator, spirv_registry_root: []const u8) ![]const []const u8 { | ||
| 220 | const extensions_path = try fs.path.join(allocator, &.{spirv_registry_root, "extensions"}); | ||
| 221 | var extensions_dir = try fs.cwd().openDir(extensions_path, .{ .iterate = true }); | ||
| 222 | defer extensions_dir.close(); | ||
| 223 | |||
| 224 | var extensions = std.ArrayList([]const u8).init(allocator); | ||
| 225 | |||
| 226 | var vendor_it = extensions_dir.iterate(); | ||
| 227 | while (try vendor_it.next()) |vendor_entry| { | ||
| 228 | std.debug.assert(vendor_entry.kind == .Directory); // If this fails, the structure of SPIRV-Registry has changed. | ||
| 229 | |||
| 230 | const vendor_dir = try extensions_dir.openDir(vendor_entry.name, .{ .iterate = true }); | ||
| 231 | var ext_it = vendor_dir.iterate(); | ||
| 232 | while (try ext_it.next()) |ext_entry| { | ||
| 233 | // There is both a HTML and asciidoc version of every spec (as well as some other directories), | ||
| 234 | // we need just the name, but to avoid duplicates here we will just skip anything thats not asciidoc. | ||
| 235 | if (!std.mem.endsWith(u8, ext_entry.name, ".asciidoc")) | ||
| 236 | continue; | ||
| 237 | |||
| 238 | // Unfortunately, some extension filenames are incorrect, so we need to look for the string in tne 'Name Strings' section. | ||
| 239 | // This has the following format: | ||
| 240 | // ``` | ||
| 241 | // Name Strings | ||
| 242 | // ------------ | ||
| 243 | // | ||
| 244 | // SPV_EXT_name | ||
| 245 | // ``` | ||
| 246 | // OR | ||
| 247 | // ``` | ||
| 248 | // == Name Strings | ||
| 249 | // | ||
| 250 | // SPV_EXT_name | ||
| 251 | // ``` | ||
| 252 | |||
| 253 | const ext_spec = try vendor_dir.readFileAlloc(allocator, ext_entry.name, std.math.maxInt(usize)); | ||
| 254 | const name_strings = "Name Strings"; | ||
| 255 | |||
| 256 | const name_strings_offset = std.mem.indexOf(u8, ext_spec, name_strings) orelse return error.InvalidRegistry; | ||
| 257 | |||
| 258 | // As the specs are inconsistent on this next part, just skip any newlines/minuses | ||
| 259 | var ext_start = name_strings_offset + name_strings.len + 1; | ||
| 260 | while (ext_spec[ext_start] == '\n' or ext_spec[ext_start] == '-') { | ||
| 261 | ext_start += 1; | ||
| 262 | } | ||
| 263 | |||
| 264 | const ext_end = std.mem.indexOfScalarPos(u8, ext_spec, ext_start, '\n') orelse return error.InvalidRegistry; | ||
| 265 | const ext = ext_spec[ext_start .. ext_end]; | ||
| 266 | |||
| 267 | std.debug.assert(std.mem.startsWith(u8, ext, "SPV_")); // Sanity check, all extensions should have a name like SPV_VENDOR_extension. | ||
| 268 | |||
| 269 | try extensions.append(try allocator.dupe(u8, ext)); | ||
| 270 | } | ||
| 271 | } | ||
| 272 | |||
| 273 | return extensions.items; | ||
| 274 | } | ||
| 275 | |||
| 276 | fn insertVersion(versions: *std.ArrayList(Version), version: ?[]const u8) !void { | ||
| 277 | const ver_str = version orelse return; | ||
| 278 | if (std.mem.eql(u8, ver_str, "None")) | ||
| 279 | return; | ||
| 280 | |||
| 281 | const ver = try Version.parse(ver_str); | ||
| 282 | for (versions.items) |existing_ver| { | ||
| 283 | if (ver.eql(existing_ver)) return; | ||
| 284 | } | ||
| 285 | |||
| 286 | try versions.append(ver); | ||
| 287 | } | ||
| 288 | |||
| 289 | fn gatherVersions(allocator: *Allocator, registry: g.CoreRegistry) ![]const Version { | ||
| 290 | // Expected number of versions is small | ||
| 291 | var versions = std.ArrayList(Version).init(allocator); | ||
| 292 | |||
| 293 | for (registry.instructions) |inst| { | ||
| 294 | try insertVersion(&versions, inst.version); | ||
| 295 | } | ||
| 296 | |||
| 297 | for (registry.operand_kinds) |opkind| { | ||
| 298 | const enumerants = opkind.enumerants orelse continue; | ||
| 299 | for (enumerants) |enumerant| { | ||
| 300 | try insertVersion(&versions, enumerant.version); | ||
| 301 | } | ||
| 302 | } | ||
| 303 | |||
| 304 | std.sort.sort(Version, versions.items, {}, Version.lessThan); | ||
| 305 | |||
| 306 | return versions.items; | ||
| 307 | } | ||
| 308 | |||
| 309 | fn usageAndExit(file: fs.File, arg0: []const u8, code: u8) noreturn { | ||
| 310 | file.writer().print( | ||
| 311 | \\Usage: {s} /path/git/SPIRV-Headers /path/git/SPIRV-Registry | ||
| 312 | \\ | ||
| 313 | \\Prints to stdout Zig code which can be used to replace the file lib/std/target/spirv.zig. | ||
| 314 | \\ | ||
| 315 | \\SPIRV-Headers can be cloned from https://github.com/KhronosGroup/SPIRV-Headers, | ||
| 316 | \\SPIRV-Registry can be cloned from https://github.com/KhronosGroup/SPIRV-Registry. | ||
| 317 | \\ | ||
| 318 | , .{arg0} | ||
| 319 | ) catch std.process.exit(1); | ||
| 320 | std.process.exit(code); | ||
| 321 | } | ||