| 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 | 228 | const is_wine_enabled = b.option(bool, "enable-wine", "Use Wine to run cross compiled Windows tests") orelse false; |
| 229 | 229 | const is_qemu_enabled = b.option(bool, "enable-qemu", "Use QEMU to run cross compiled foreign architecture tests") orelse false; |
| 230 | 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 | 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 | 234 | test_stage2.addBuildOption(bool, "skip_non_native", skip_non_native); |
| ... | ... | @@ -238,6 +239,7 @@ pub fn build(b: *Builder) !void { |
| 238 | 239 | test_stage2.addBuildOption(bool, "enable_wine", is_wine_enabled); |
| 239 | 240 | test_stage2.addBuildOption(bool, "enable_wasmtime", is_wasmtime_enabled); |
| 240 | 241 | test_stage2.addBuildOption(u32, "mem_leak_frames", mem_leak_frames * 2); |
| 242 | test_stage2.addBuildOption(bool, "enable_darling", is_darling_enabled); | |
| 241 | 243 | test_stage2.addBuildOption(?[]const u8, "glibc_multi_install_dir", glibc_multi_dir); |
| 242 | 244 | test_stage2.addBuildOption([]const u8, "version", version); |
| 243 | 245 | |
| ... | ... | @@ -272,11 +274,56 @@ pub fn build(b: *Builder) !void { |
| 272 | 274 | const fmt_step = b.step("test-fmt", "Run zig fmt against build.zig to make sure it works"); |
| 273 | 275 | fmt_step.dependOn(&fmt_build_zig.step); |
| 274 | 276 | |
| 275 | // TODO for the moment, skip wasm32-wasi until bugs are sorted out. | |
| 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)); | |
| 277 | ||
| 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)); | |
| 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)); | |
| 277 | toolchain_step.dependOn(tests.addPkgTests( | |
| 278 | b, | |
| 279 | test_filter, | |
| 280 | "test/behavior.zig", | |
| 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 | 328 | toolchain_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes)); |
| 282 | 329 | toolchain_step.dependOn(tests.addStandaloneTests(b, test_filter, modes)); |
| ... | ... | @@ -294,7 +341,22 @@ pub fn build(b: *Builder) !void { |
| 294 | 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 | 361 | const test_step = b.step("test", "Run all the tests"); |
| 300 | 362 | test_step.dependOn(toolchain_step); |
| ... | ... | @@ -346,8 +408,7 @@ fn addCmakeCfgOptionsToExe( |
| 346 | 408 | }, |
| 347 | 409 | else => |e| return e, |
| 348 | 410 | }; |
| 349 | ||
| 350 | exe.linkSystemLibrary("pthread"); | |
| 411 | exe.linkSystemLibrary("unwind"); | |
| 351 | 412 | } else if (exe.target.isFreeBSD()) { |
| 352 | 413 | try addCxxKnownPath(b, cfg, exe, "libc++.a", null, need_cpp_includes); |
| 353 | 414 | exe.linkSystemLibrary("pthread"); |
| ... | ... | @@ -355,20 +416,7 @@ fn addCmakeCfgOptionsToExe( |
| 355 | 416 | try addCxxKnownPath(b, cfg, exe, "libc++.a", null, need_cpp_includes); |
| 356 | 417 | try addCxxKnownPath(b, cfg, exe, "libc++abi.a", null, need_cpp_includes); |
| 357 | 418 | } else if (exe.target.isDarwin()) { |
| 358 | if (addCxxKnownPath(b, cfg, exe, "libgcc_eh.a", "", need_cpp_includes)) { | |
| 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 | } | |
| 419 | exe.linkSystemLibrary("c++"); | |
| 372 | 420 | } |
| 373 | 421 | |
| 374 | 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 | 1398 | /// Uses system Wasmtime installation to run cross compiled wasm/wasi build artifacts. |
| 1399 | 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 | 1404 | /// After following the steps in https://github.com/ziglang/zig/wiki/Updating-libc#glibc, |
| 1402 | 1405 | /// this will be the directory $glibc-build-dir/install/glibcs |
| 1403 | 1406 | /// Given the example of the aarch64 target, this is the directory |
| ... | ... | @@ -2514,6 +2517,11 @@ pub const LibExeObjStep = struct { |
| 2514 | 2517 | try zig_args.append("--dir=."); |
| 2515 | 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 | 2527 | for (self.packages.items) |pkg| { |
lib/std/debug.zig+4-2| ... | ... | @@ -309,6 +309,7 @@ const RED = "\x1b[31;1m"; |
| 309 | 309 | const GREEN = "\x1b[32;1m"; |
| 310 | 310 | const CYAN = "\x1b[36;1m"; |
| 311 | 311 | const WHITE = "\x1b[37;1m"; |
| 312 | const BOLD = "\x1b[1m"; | |
| 312 | 313 | const DIM = "\x1b[2m"; |
| 313 | 314 | const RESET = "\x1b[0m"; |
| 314 | 315 | |
| ... | ... | @@ -479,8 +480,9 @@ pub const TTY = struct { |
| 479 | 480 | .Red => out_stream.writeAll(RED) catch return, |
| 480 | 481 | .Green => out_stream.writeAll(GREEN) catch return, |
| 481 | 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 | 484 | .Dim => out_stream.writeAll(DIM) catch return, |
| 485 | .Bold => out_stream.writeAll(BOLD) catch return, | |
| 484 | 486 | .Reset => out_stream.writeAll(RESET) catch return, |
| 485 | 487 | }, |
| 486 | 488 | .windows_api => if (native_os == .windows) { |
| ... | ... | @@ -632,7 +634,7 @@ fn printLineInfo( |
| 632 | 634 | comptime printLineFromFile: anytype, |
| 633 | 635 | ) !void { |
| 634 | 636 | nosuspend { |
| 635 | tty_config.setColor(out_stream, .White); | |
| 637 | tty_config.setColor(out_stream, .Bold); | |
| 636 | 638 | |
| 637 | 639 | if (line_info) |*li| { |
| 638 | 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 | 501 | }, |
| 502 | 502 | .linux => struct { |
| 503 | 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 | 507 | index: usize, |
| 506 | 508 | end_index: usize, |
| 507 | 509 |
lib/std/hash_map.zig+13-12| ... | ... | @@ -303,29 +303,32 @@ pub fn HashMapUnmanaged( |
| 303 | 303 | /// Metadata for a slot. It can be in three states: empty, used or |
| 304 | 304 | /// tombstone. Tombstones indicate that an entry was previously used, |
| 305 | 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 | 307 | /// used as a fast way to disambiguate between entries without |
| 308 | 308 | /// having to use the equality function. If two fingerprints are |
| 309 | 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 | 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 | |
| 313 | /// when multiple elements with different hashes end up wanting to be in / the same slot. | |
| 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. | |
| 314 | 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 | 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 | 324 | used: u1 = 0, |
| 320 | tombstone: u1 = 0, | |
| 321 | fingerprint: FingerPrint = 0, | |
| 322 | 325 | |
| 323 | 326 | pub fn isUsed(self: Metadata) bool { |
| 324 | 327 | return self.used == 1; |
| 325 | 328 | } |
| 326 | 329 | |
| 327 | 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 | 334 | pub fn takeFingerprint(hash: Hash) FingerPrint { |
| ... | ... | @@ -336,14 +339,12 @@ pub fn HashMapUnmanaged( |
| 336 | 339 | |
| 337 | 340 | pub fn fill(self: *Metadata, fp: FingerPrint) void { |
| 338 | 341 | self.used = 1; |
| 339 | self.tombstone = 0; | |
| 340 | 342 | self.fingerprint = fp; |
| 341 | 343 | } |
| 342 | 344 | |
| 343 | 345 | pub fn remove(self: *Metadata) void { |
| 344 | 346 | self.used = 0; |
| 345 | self.tombstone = 1; | |
| 346 | self.fingerprint = 0; | |
| 347 | self.fingerprint = tombstone; | |
| 347 | 348 | } |
| 348 | 349 | }; |
| 349 | 350 |
lib/std/json.zig+45-10| ... | ... | @@ -623,7 +623,7 @@ pub const StreamingParser = struct { |
| 623 | 623 | |
| 624 | 624 | .ObjectSeparator => switch (c) { |
| 625 | 625 | ':' => { |
| 626 | p.state = .ValueBegin; | |
| 626 | p.state = .ValueBeginNoClosing; | |
| 627 | 627 | p.after_string_state = .ValueEnd; |
| 628 | 628 | }, |
| 629 | 629 | 0x09, 0x0A, 0x0D, 0x20 => { |
| ... | ... | @@ -1205,6 +1205,13 @@ test "json.token mismatched close" { |
| 1205 | 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 | 1215 | /// Validate a JSON string. This does not limit number precision so a decoder may not necessarily |
| 1209 | 1216 | /// be able to decode the string even if this returns true. |
| 1210 | 1217 | pub fn validate(s: []const u8) bool { |
| ... | ... | @@ -1566,11 +1573,16 @@ fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options: |
| 1566 | 1573 | // .UseLast => {}, |
| 1567 | 1574 | // } |
| 1568 | 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 | 1579 | break; |
| 1570 | 1580 | } else if (options.duplicate_field_behavior == .Error) { |
| 1571 | 1581 | return error.DuplicateJSONField; |
| 1572 | 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 | 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 | 1736 | }, |
| 1725 | 1737 | .Struct => |structInfo| { |
| 1726 | 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 | 1744 | .Array => |arrayInfo| { |
| ... | ... | @@ -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 | 1924 | \\ "kind": "float", |
| 1907 | 1925 | \\ "b": 1.0 |
| 1908 | 1926 | \\} |
| 1909 | ), .{ | |
| 1910 | .allocator = std.testing.allocator, | |
| 1911 | }); | |
| 1927 | ), options); | |
| 1928 | ||
| 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 | 2014 | const ballast = try testing.allocator.alloc(u64, 1); |
| 1996 | 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 | 2023 | .allocator = testing.allocator, |
| 2000 | 2024 | .duplicate_field_behavior = .UseLast, |
| 2001 | 2025 | }; |
| 2026 | ||
| 2002 | 2027 | const str = "{ \"a\": 1, \"a\": 0.25 }"; |
| 2003 | 2028 | |
| 2004 | 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 | 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 | 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 | 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 | 87 | test "y_array_arraysWithSpaces" { |
lib/std/math/isnormal.zig+9-2| ... | ... | @@ -14,16 +14,20 @@ pub fn isNormal(x: anytype) bool { |
| 14 | 14 | switch (T) { |
| 15 | 15 | f16 => { |
| 16 | 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 | 19 | f32 => { |
| 20 | 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 | 23 | f64 => { |
| 24 | 24 | const bits = @bitCast(u64, x); |
| 25 | 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 | 31 | else => { |
| 28 | 32 | @compileError("isNormal not implemented for " ++ @typeName(T)); |
| 29 | 33 | }, |
| ... | ... | @@ -34,10 +38,13 @@ test "math.isNormal" { |
| 34 | 38 | try expect(!isNormal(math.nan(f16))); |
| 35 | 39 | try expect(!isNormal(math.nan(f32))); |
| 36 | 40 | try expect(!isNormal(math.nan(f64))); |
| 41 | try expect(!isNormal(math.nan(f128))); | |
| 37 | 42 | try expect(!isNormal(@as(f16, 0))); |
| 38 | 43 | try expect(!isNormal(@as(f32, 0))); |
| 39 | 44 | try expect(!isNormal(@as(f64, 0))); |
| 45 | try expect(!isNormal(@as(f128, 0))); | |
| 40 | 46 | try expect(isNormal(@as(f16, 1.0))); |
| 41 | 47 | try expect(isNormal(@as(f32, 1.0))); |
| 42 | 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 | 9 | // https://git.musl-libc.org/cgit/musl/tree/src/math/scalbnf.c |
| 10 | 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 | 13 | const math = std.math; |
| 14 | const assert = std.debug.assert; | |
| 14 | 15 | const expect = std.testing.expect; |
| 15 | 16 | |
| 16 | 17 | /// Returns x * 2^n. |
| 17 | 18 | pub fn scalbn(x: anytype, n: i32) @TypeOf(x) { |
| 18 | const T = @TypeOf(x); | |
| 19 | return switch (T) { | |
| 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_; | |
| 19 | var base = x; | |
| 20 | var shift = n; | |
| 29 | 21 | |
| 30 | if (n > 127) { | |
| 31 | y *= 0x1.0p127; | |
| 32 | n -= 127; | |
| 33 | if (n > 1023) { | |
| 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 | } | |
| 22 | const T = @TypeOf(base); | |
| 23 | const IntT = std.meta.Int(.unsigned, @bitSizeOf(T)); | |
| 24 | if (@typeInfo(T) != .Float) { | |
| 25 | @compileError("scalbn not implemented for " ++ @typeName(T)); | |
| 50 | 26 | } |
| 51 | 27 | |
| 52 | const u = @intCast(u32, n +% 0x7F) << 23; | |
| 53 | return y * @bitCast(f32, u); | |
| 54 | } | |
| 28 | const mantissa_bits = math.floatMantissaBits(T); | |
| 29 | const exponent_bits = math.floatExponentBits(T); | |
| 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 { | |
| 57 | var y = x; | |
| 58 | var n = n_; | |
| 34 | // fix double rounding errors in subnormal ranges | |
| 35 | // https://git.musl-libc.org/cgit/musl/commit/src/math/scalbn.c?id=8c44a060243f04283ca68dad199aab90336141db | |
| 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) { | |
| 61 | y *= 0x1.0p1023; | |
| 62 | n -= 1023; | |
| 63 | if (n > 1023) { | |
| 64 | y *= 0x1.0p1023; | |
| 65 | n -= 1023; | |
| 66 | if (n > 1023) { | |
| 67 | n = 1023; | |
| 68 | } | |
| 40 | // scale `shift` within floating point limits, if possible | |
| 41 | // second pass is possible due to subnormal range | |
| 42 | // third pass always results in +/-0.0 or +/-inf | |
| 43 | if (shift > exponent_max) { | |
| 44 | base *= scale_max; | |
| 45 | shift -= exponent_max; | |
| 46 | if (shift > exponent_max) { | |
| 47 | base *= scale_max; | |
| 48 | shift -= exponent_max; | |
| 49 | if (shift > exponent_max) shift = exponent_max; | |
| 69 | 50 | } |
| 70 | } else if (n < -1022) { | |
| 71 | y *= 0x1.0p-1022 * 0x1.0p53; | |
| 72 | n += 1022 - 53; | |
| 73 | if (n < -1022) { | |
| 74 | y *= 0x1.0p-1022 * 0x1.0p53; | |
| 75 | n += 1022 - 53; | |
| 76 | if (n < -1022) { | |
| 77 | n = -1022; | |
| 78 | } | |
| 51 | } else if (shift < exponent_min) { | |
| 52 | base *= scale_min; | |
| 53 | shift -= scale_min_expo; | |
| 54 | if (shift < exponent_min) { | |
| 55 | base *= scale_min; | |
| 56 | shift -= scale_min_expo; | |
| 57 | if (shift < exponent_min) shift = exponent_min; | |
| 79 | 58 | } |
| 80 | 59 | } |
| 81 | 60 | |
| 82 | const u = @intCast(u64, n +% 0x3FF) << 52; | |
| 83 | return y * @bitCast(f64, u); | |
| 61 | return base * @bitCast(T, @intCast(IntT, shift + exponent_bias) << mantissa_bits); | |
| 84 | 62 | } |
| 85 | 63 | |
| 86 | 64 | test "math.scalbn" { |
| 87 | try expect(scalbn(@as(f32, 1.5), 4) == scalbn32(1.5, 4)); | |
| 88 | try expect(scalbn(@as(f64, 1.5), 4) == scalbn64(1.5, 4)); | |
| 89 | } | |
| 65 | // basic usage | |
| 66 | try expect(scalbn(@as(f16, 1.5), 4) == 24.0); | |
| 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" { | |
| 92 | try expect(scalbn32(1.5, 4) == 24.0); | |
| 93 | } | |
| 71 | // subnormals | |
| 72 | try expect(math.isNormal(scalbn(@as(f16, 1.0), -14))); | |
| 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" { | |
| 96 | try expect(scalbn64(1.5, 4) == 24.0); | |
| 86 | // float limits | |
| 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 | 52 | pub const EPROTONOSUPPORT = 43; |
| 53 | 53 | pub const ESOCKTNOSUPPORT = 44; |
| 54 | 54 | pub const EOPNOTSUPP = 45; |
| 55 | pub const ENOTSUP = EOPNOTSUPP; | |
| 55 | 56 | pub const EPFNOSUPPORT = 46; |
| 56 | 57 | pub const EAFNOSUPPORT = 47; |
| 57 | 58 | pub const EADDRINUSE = 48; |
lib/std/special/compiler_rt.zig+10| ... | ... | @@ -297,7 +297,17 @@ comptime { |
| 297 | 297 | @export(@import("compiler_rt/sparc.zig")._Qp_fgt, .{ .name = "_Qp_fgt", .linkage = linkage }); |
| 298 | 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 | 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 | 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 | 98 | // one or both of a or b is denormal, the other (if applicable) is a |
| 99 | 99 | // normal number. Renormalize one or both of a and b, and set scale to |
| 100 | 100 | // include the necessary exponent adjustment. |
| 101 | if (aAbs < implicitBit) scale +%= normalize(T, &aSignificand); | |
| 102 | if (bAbs < implicitBit) scale +%= normalize(T, &bSignificand); | |
| 101 | if (aAbs < implicitBit) scale += normalize(T, &aSignificand); | |
| 102 | if (bAbs < implicitBit) scale += normalize(T, &bSignificand); | |
| 103 | 103 | } |
| 104 | 104 | |
| 105 | 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 | 277 | |
| 278 | 278 | const shift = @clz(Z, significand.*) - @clz(Z, implicitBit); |
| 279 | 279 | significand.* <<= @intCast(std.math.Log2Int(Z), shift); |
| 280 | return 1 - shift; | |
| 280 | return @as(i32, 1) - shift; | |
| 281 | 281 | } |
| 282 | 282 | |
| 283 | 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 | 285 | const typeWidth = @typeInfo(Z).Int.bits; |
| 286 | 286 | const S = std.math.Log2Int(Z); |
| 287 | 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 | 289 | lo.* = (hi.* << @intCast(S, typeWidth -% count)) | (lo.* >> @intCast(S, count)) | sticky; |
| 290 | 290 | hi.* = hi.* >> @intCast(S, count); |
| 291 | 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 | 293 | lo.* = hi.* >> @intCast(S, count -% typeWidth) | sticky; |
| 294 | 294 | hi.* = 0; |
| 295 | 295 | } else { |
| 296 | const sticky = @truncate(u8, hi.* | lo.*); | |
| 296 | const sticky = @boolToInt((hi.* | lo.*) != 0); | |
| 297 | 297 | lo.* = sticky; |
| 298 | 298 | hi.* = 0; |
| 299 | 299 | } |
lib/std/special/compiler_rt/mulXf3_test.zig+14| ... | ... | @@ -88,4 +88,18 @@ test "multf3" { |
| 88 | 88 | ); |
| 89 | 89 | |
| 90 | 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 | 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 | 93 | pub fn _Qp_dtoq(c: *f128, a: f64) callconv(.C) void { |
| 74 | 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 | 117 | pub fn _Qp_qtod(a: *f128) callconv(.C) f64 { |
| 78 | 118 | return @import("truncXfYf2.zig").__trunctfdf2(a.*); |
| 79 | 119 | } |
lib/std/start.zig+1-1| ... | ... | @@ -46,7 +46,7 @@ comptime { |
| 46 | 46 | } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) { |
| 47 | 47 | if (builtin.link_libc and @hasDecl(root, "main")) { |
| 48 | 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 | 51 | } else if (native_os == .windows) { |
| 52 | 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 | 431 | pub const powerpc = @import("target/powerpc.zig"); |
| 432 | 432 | pub const riscv = @import("target/riscv.zig"); |
| 433 | 433 | pub const sparc = @import("target/sparc.zig"); |
| 434 | pub const spirv = @import("target/spirv.zig"); | |
| 434 | 435 | pub const systemz = @import("target/systemz.zig"); |
| 435 | 436 | pub const ve = @import("target/ve.zig"); |
| 436 | 437 | pub const wasm = @import("target/wasm.zig"); |
| ... | ... | @@ -594,7 +595,7 @@ pub const Target = struct { |
| 594 | 595 | pub const Set = struct { |
| 595 | 596 | ints: [usize_count]usize, |
| 596 | 597 | |
| 597 | pub const needed_bit_count = 172; | |
| 598 | pub const needed_bit_count = 288; | |
| 598 | 599 | pub const byte_count = (needed_bit_count + 7) / 8; |
| 599 | 600 | pub const usize_count = (byte_count + (@sizeOf(usize) - 1)) / @sizeOf(usize); |
| 600 | 601 | pub const Index = std.math.Log2Int(std.meta.Int(.unsigned, usize_count * @bitSizeOf(usize))); |
| ... | ... | @@ -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 | 833 | pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model { |
| 826 | 834 | for (arch.allCpuModels()) |cpu| { |
| 827 | 835 | if (mem.eql(u8, cpu_name, cpu.name)) { |
| ... | ... | @@ -1116,6 +1124,7 @@ pub const Target = struct { |
| 1116 | 1124 | .amdgcn => &amdgpu.all_features, |
| 1117 | 1125 | .riscv32, .riscv64 => &riscv.all_features, |
| 1118 | 1126 | .sparc, .sparcv9, .sparcel => &sparc.all_features, |
| 1127 | .spirv32, .spirv64 => &spirv.all_features, | |
| 1119 | 1128 | .s390x => &systemz.all_features, |
| 1120 | 1129 | .i386, .x86_64 => &x86.all_features, |
| 1121 | 1130 | .nvptx, .nvptx64 => &nvptx.all_features, |
| ... | ... | @@ -1320,6 +1329,9 @@ pub const Target = struct { |
| 1320 | 1329 | if (cpu_arch.isWasm()) { |
| 1321 | 1330 | return .wasm; |
| 1322 | 1331 | } |
| 1332 | if (cpu_arch.isSPIRV()) { | |
| 1333 | return .spirv; | |
| 1334 | } | |
| 1323 | 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 | 29 | /// and then aborts when actual_error_union is not expected_error. |
| 30 | 30 | pub fn expectError(expected_error: anyerror, actual_error_union: anytype) !void { |
| 31 | 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 | 33 | return error.TestUnexpectedError; |
| 34 | 34 | } else |actual_error| { |
| 35 | 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 | 37 | @errorName(expected_error), |
| 38 | 38 | @errorName(actual_error), |
| 39 | 39 | }); |
| ... | ... | @@ -62,7 +62,7 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { |
| 62 | 62 | |
| 63 | 63 | .Type => { |
| 64 | 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 | 66 | return error.TestExpectedEqual; |
| 67 | 67 | } |
| 68 | 68 | }, |
| ... | ... | @@ -78,7 +78,7 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { |
| 78 | 78 | .ErrorSet, |
| 79 | 79 | => { |
| 80 | 80 | if (actual != expected) { |
| 81 | std.debug.print("expected {}, found {}", .{ expected, actual }); | |
| 81 | std.debug.print("expected {}, found {}\n", .{ expected, actual }); | |
| 82 | 82 | return error.TestExpectedEqual; |
| 83 | 83 | } |
| 84 | 84 | }, |
| ... | ... | @@ -87,17 +87,17 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { |
| 87 | 87 | switch (pointer.size) { |
| 88 | 88 | .One, .Many, .C => { |
| 89 | 89 | if (actual != expected) { |
| 90 | std.debug.print("expected {*}, found {*}", .{ expected, actual }); | |
| 90 | std.debug.print("expected {*}, found {*}\n", .{ expected, actual }); | |
| 91 | 91 | return error.TestExpectedEqual; |
| 92 | 92 | } |
| 93 | 93 | }, |
| 94 | 94 | .Slice => { |
| 95 | 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 | 97 | return error.TestExpectedEqual; |
| 98 | 98 | } |
| 99 | 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 | 101 | return error.TestExpectedEqual; |
| 102 | 102 | } |
| 103 | 103 | }, |
| ... | ... | @@ -110,7 +110,7 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { |
| 110 | 110 | var i: usize = 0; |
| 111 | 111 | while (i < vectorType.len) : (i += 1) { |
| 112 | 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 | 114 | return error.TestExpectedEqual; |
| 115 | 115 | } |
| 116 | 116 | } |
| ... | ... | @@ -153,12 +153,12 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { |
| 153 | 153 | if (actual) |actual_payload| { |
| 154 | 154 | try expectEqual(expected_payload, actual_payload); |
| 155 | 155 | } else { |
| 156 | std.debug.print("expected {any}, found null", .{expected_payload}); | |
| 156 | std.debug.print("expected {any}, found null\n", .{expected_payload}); | |
| 157 | 157 | return error.TestExpectedEqual; |
| 158 | 158 | } |
| 159 | 159 | } else { |
| 160 | 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 | 162 | return error.TestExpectedEqual; |
| 163 | 163 | } |
| 164 | 164 | } |
| ... | ... | @@ -169,12 +169,12 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { |
| 169 | 169 | if (actual) |actual_payload| { |
| 170 | 170 | try expectEqual(expected_payload, actual_payload); |
| 171 | 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 | 173 | return error.TestExpectedEqual; |
| 174 | 174 | } |
| 175 | 175 | } else |expected_err| { |
| 176 | 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 | 178 | return error.TestExpectedEqual; |
| 179 | 179 | } else |actual_err| { |
| 180 | 180 | try expectEqual(expected_err, actual_err); |
| ... | ... | @@ -225,7 +225,7 @@ pub fn expectApproxEqAbs(expected: anytype, actual: @TypeOf(expected), tolerance |
| 225 | 225 | |
| 226 | 226 | switch (@typeInfo(T)) { |
| 227 | 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 | 229 | return error.TestExpectedApproxEqAbs; |
| 230 | 230 | }, |
| 231 | 231 | |
| ... | ... | @@ -257,7 +257,7 @@ pub fn expectApproxEqRel(expected: anytype, actual: @TypeOf(expected), tolerance |
| 257 | 257 | |
| 258 | 258 | switch (@typeInfo(T)) { |
| 259 | 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 | 261 | return error.TestExpectedApproxEqRel; |
| 262 | 262 | }, |
| 263 | 263 | |
| ... | ... | @@ -292,13 +292,13 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const |
| 292 | 292 | // If the child type is u8 and no weird bytes, we could print it as strings |
| 293 | 293 | // Even for the length difference, it would be useful to see the values of the slices probably. |
| 294 | 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 | 296 | return error.TestExpectedEqual; |
| 297 | 297 | } |
| 298 | 298 | var i: usize = 0; |
| 299 | 299 | while (i < expected.len) : (i += 1) { |
| 300 | 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 | 302 | return error.TestExpectedEqual; |
| 303 | 303 | } |
| 304 | 304 | } |
lib/std/zig/cross_target.zig+10| ... | ... | @@ -606,6 +606,7 @@ pub const CrossTarget = struct { |
| 606 | 606 | qemu: []const u8, |
| 607 | 607 | wine: []const u8, |
| 608 | 608 | wasmtime: []const u8, |
| 609 | darling: []const u8, | |
| 609 | 610 | unavailable, |
| 610 | 611 | }; |
| 611 | 612 | |
| ... | ... | @@ -667,6 +668,15 @@ pub const CrossTarget = struct { |
| 667 | 668 | 32 => return Executor{ .wasmtime = "wasmtime" }, |
| 668 | 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 | 680 | else => return .unavailable, |
| 671 | 681 | } |
| 672 | 682 | } |
lib/std/zig/parse.zig+77-241| ... | ... | @@ -1309,9 +1309,8 @@ const Parser = struct { |
| 1309 | 1309 | return expr; |
| 1310 | 1310 | } |
| 1311 | 1311 | |
| 1312 | /// Expr <- BoolOrExpr | |
| 1313 | 1312 | fn parseExpr(p: *Parser) Error!Node.Index { |
| 1314 | return p.parseBoolOrExpr(); | |
| 1313 | return p.parseExprPrecedence(0); | |
| 1315 | 1314 | } |
| 1316 | 1315 | |
| 1317 | 1316 | fn expectExpr(p: *Parser) Error!Node.Index { |
| ... | ... | @@ -1323,263 +1322,100 @@ const Parser = struct { |
| 1323 | 1322 | } |
| 1324 | 1323 | } |
| 1325 | 1324 | |
| 1326 | /// BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)* | |
| 1327 | fn parseBoolOrExpr(p: *Parser) Error!Node.Index { | |
| 1328 | var res = try p.parseBoolAndExpr(); | |
| 1329 | if (res == 0) return null_node; | |
| 1325 | const Assoc = enum { | |
| 1326 | left, | |
| 1327 | none, | |
| 1328 | }; | |
| 1330 | 1329 | |
| 1331 | while (true) { | |
| 1332 | switch (p.token_tags[p.tok_i]) { | |
| 1333 | .keyword_or => { | |
| 1334 | const or_token = p.nextToken(); | |
| 1335 | const rhs = try p.parseBoolAndExpr(); | |
| 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 | } | |
| 1330 | const OperInfo = struct { | |
| 1331 | prec: i8, | |
| 1332 | tag: Node.Tag, | |
| 1333 | assoc: Assoc = Assoc.left, | |
| 1334 | }; | |
| 1352 | 1335 | |
| 1353 | /// BoolAndExpr <- CompareExpr (KEYWORD_and CompareExpr)* | |
| 1354 | fn parseBoolAndExpr(p: *Parser) !Node.Index { | |
| 1355 | var res = try p.parseCompareExpr(); | |
| 1356 | if (res == 0) return null_node; | |
| 1336 | // A table of binary operator information. Higher precedence numbers are | |
| 1337 | // stickier. All operators at the same precedence level should have the same | |
| 1338 | // associativity. | |
| 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) { | |
| 1359 | switch (p.token_tags[p.tok_i]) { | |
| 1360 | .keyword_and => { | |
| 1361 | const and_token = p.nextToken(); | |
| 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 | } | |
| 1375 | fn parseExprPrecedence(p: *Parser, min_prec: i32) Error!Node.Index { | |
| 1376 | var node = try p.parsePrefixExpr(); | |
| 1377 | if (node == 0) { | |
| 1378 | return null_node; | |
| 1382 | 1379 | } |
| 1383 | } | |
| 1384 | 1380 | |
| 1385 | /// CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)? | |
| 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; | |
| 1381 | var banned_prec: i8 = -1; | |
| 1426 | 1382 | |
| 1427 | 1383 | while (true) { |
| 1428 | const tag: Node.Tag = switch (p.token_tags[p.tok_i]) { | |
| 1429 | .ampersand => .bit_and, | |
| 1430 | .caret => .bit_xor, | |
| 1431 | .pipe => .bit_or, | |
| 1432 | .keyword_orelse => .@"orelse", | |
| 1384 | const tok_tag = p.token_tags[p.tok_i]; | |
| 1385 | const info = operTable[@intCast(usize, @enumToInt(tok_tag))]; | |
| 1386 | if (info.prec < min_prec or info.prec == banned_prec) { | |
| 1387 | break; | |
| 1388 | } | |
| 1389 | const oper_token = p.nextToken(); | |
| 1390 | // Special-case handling for "catch" and "&&". | |
| 1391 | switch (tok_tag) { | |
| 1433 | 1392 | .keyword_catch => { |
| 1434 | const catch_token = p.nextToken(); | |
| 1435 | 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 | }); | |
| 1460 | } | |
| 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(), | |
| 1395 | .invalid_ampersands => { | |
| 1396 | try p.warn(.invalid_and); | |
| 1492 | 1397 | }, |
| 1493 | }); | |
| 1494 | } | |
| 1495 | } | |
| 1496 | ||
| 1497 | fn expectBitShiftExpr(p: *Parser) Error!Node.Index { | |
| 1498 | const node = try p.parseBitShiftExpr(); | |
| 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; | |
| 1398 | else => {}, | |
| 1399 | } | |
| 1400 | const rhs = try p.parseExprPrecedence(info.prec + 1); | |
| 1401 | if (rhs == 0) { | |
| 1402 | return p.fail(.invalid_token); | |
| 1403 | } | |
| 1516 | 1404 | |
| 1517 | while (true) { | |
| 1518 | const tag: Node.Tag = switch (p.token_tags[p.tok_i]) { | |
| 1519 | .plus => .add, | |
| 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(), | |
| 1405 | node = try p.addNode(.{ | |
| 1406 | .tag = info.tag, | |
| 1407 | .main_token = oper_token, | |
| 1529 | 1408 | .data = .{ |
| 1530 | .lhs = res, | |
| 1531 | .rhs = try p.expectMultiplyExpr(), | |
| 1409 | .lhs = node, | |
| 1410 | .rhs = rhs, | |
| 1532 | 1411 | }, |
| 1533 | 1412 | }); |
| 1534 | } | |
| 1535 | } | |
| 1536 | 1413 | |
| 1537 | fn expectAdditionExpr(p: *Parser) Error!Node.Index { | |
| 1538 | const node = try p.parseAdditionExpr(); | |
| 1539 | if (node == 0) { | |
| 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 | }); | |
| 1414 | if (info.assoc == Assoc.none) { | |
| 1415 | banned_prec = info.prec; | |
| 1416 | } | |
| 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 | 1419 | return node; |
| 1584 | 1420 | } |
| 1585 | 1421 |
lib/std/zig/parser_test.zig+11| ... | ... | @@ -2828,6 +2828,7 @@ test "zig fmt: precedence" { |
| 2828 | 2828 | \\ a or b and c; |
| 2829 | 2829 | \\ (a or b) and c; |
| 2830 | 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 | 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 | 4906 | test "recovery: extra qualifier" { |
| 4896 | 4907 | try testError( |
| 4897 | 4908 | \\const a: *const const u8; |
src/Compilation.zig+16-8| ... | ... | @@ -638,6 +638,7 @@ pub const InitOptions = struct { |
| 638 | 638 | system_libs: []const []const u8 = &[0][]const u8{}, |
| 639 | 639 | link_libc: bool = false, |
| 640 | 640 | link_libcpp: bool = false, |
| 641 | link_libunwind: bool = false, | |
| 641 | 642 | want_pic: ?bool = null, |
| 642 | 643 | /// This means that if the output mode is an executable it will be a |
| 643 | 644 | /// Position Independent Executable. If the output mode is not an |
| ... | ... | @@ -885,8 +886,13 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 885 | 886 | }; |
| 886 | 887 | |
| 887 | 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 | 897 | const must_dynamic_link = dl: { |
| 892 | 898 | if (target_util.cannotDynamicLink(options.target)) |
| ... | ... | @@ -972,9 +978,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 972 | 978 | break :pic explicit; |
| 973 | 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 | 981 | // Make a decision on whether to use Clang for translate-c and compiling C files. |
| 979 | 982 | const use_clang = if (options.use_clang) |explicit| explicit else blk: { |
| 980 | 983 | if (build_options.have_llvm) { |
| ... | ... | @@ -1067,6 +1070,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1067 | 1070 | cache.hash.add(strip); |
| 1068 | 1071 | cache.hash.add(link_libc); |
| 1069 | 1072 | cache.hash.add(link_libcpp); |
| 1073 | cache.hash.add(link_libunwind); | |
| 1070 | 1074 | cache.hash.add(options.output_mode); |
| 1071 | 1075 | cache.hash.add(options.machine_code_model); |
| 1072 | 1076 | cache.hash.addOptionalEmitLoc(options.emit_bin); |
| ... | ... | @@ -1262,6 +1266,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1262 | 1266 | .system_linker_hack = darwin_options.system_linker_hack, |
| 1263 | 1267 | .link_libc = link_libc, |
| 1264 | 1268 | .link_libcpp = link_libcpp, |
| 1269 | .link_libunwind = link_libunwind, | |
| 1265 | 1270 | .objects = options.link_objects, |
| 1266 | 1271 | .frameworks = options.frameworks, |
| 1267 | 1272 | .framework_dirs = options.framework_dirs, |
| ... | ... | @@ -2943,6 +2948,10 @@ pub fn addCCArgs( |
| 2943 | 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 | 2955 | if (target.os.tag == .freestanding) { |
| 2947 | 2956 | try argv.append("-ffreestanding"); |
| 2948 | 2957 | } |
| ... | ... | @@ -3139,7 +3148,7 @@ fn detectLibCIncludeDirs( |
| 3139 | 3148 | |
| 3140 | 3149 | if (is_native_abi) { |
| 3141 | 3150 | const libc = try arena.create(LibCInstallation); |
| 3142 | libc.* = try LibCInstallation.findNative(.{ .allocator = arena }); | |
| 3151 | libc.* = try LibCInstallation.findNative(.{ .allocator = arena, .verbose = true }); | |
| 3143 | 3152 | return detectLibCFromLibCInstallation(arena, target, libc); |
| 3144 | 3153 | } |
| 3145 | 3154 | |
| ... | ... | @@ -3276,9 +3285,8 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool { |
| 3276 | 3285 | .Lib => comp.bin_file.options.link_mode == .Dynamic, |
| 3277 | 3286 | .Exe => true, |
| 3278 | 3287 | }; |
| 3279 | return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and | |
| 3280 | comp.bin_file.options.object_format != .c and | |
| 3281 | target_util.libcNeedsLibUnwind(comp.getTarget()); | |
| 3288 | return is_exe_or_dyn_lib and comp.bin_file.options.link_libunwind and | |
| 3289 | comp.bin_file.options.object_format != .c; | |
| 3282 | 3290 | } |
| 3283 | 3291 | |
| 3284 | 3292 | fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) Allocator.Error!void { |
src/clang.zig+5| ... | ... | @@ -905,6 +905,11 @@ pub const TypedefNameDecl = opaque { |
| 905 | 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 | 913 | pub const TypedefType = opaque { |
| 909 | 914 | pub const getDecl = ZigClangTypedefType_getDecl; |
| 910 | 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 | 960 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 961 | 961 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 962 | 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 | 964 | try self.genSetReg(src, ty, reg, mcv); |
| 965 | 965 | return reg; |
| 966 | 966 | } |
| ... | ... | @@ -2231,7 +2231,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2231 | 2231 | switch (mc_arg) { |
| 2232 | 2232 | .none => continue, |
| 2233 | 2233 | .register => |reg| { |
| 2234 | try self.register_manager.getRegWithoutTracking(reg); | |
| 2234 | try self.register_manager.getReg(reg, null); | |
| 2235 | 2235 | try self.genSetReg(arg.src, arg.ty, reg, arg_mcv); |
| 2236 | 2236 | }, |
| 2237 | 2237 | .stack_offset => { |
| ... | ... | @@ -2327,7 +2327,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2327 | 2327 | .compare_flags_signed => unreachable, |
| 2328 | 2328 | .compare_flags_unsigned => unreachable, |
| 2329 | 2329 | .register => |reg| { |
| 2330 | try self.register_manager.getRegWithoutTracking(reg); | |
| 2330 | try self.register_manager.getReg(reg, null); | |
| 2331 | 2331 | try self.genSetReg(arg.src, arg.ty, reg, arg_mcv); |
| 2332 | 2332 | }, |
| 2333 | 2333 | .stack_offset => { |
| ... | ... | @@ -2390,7 +2390,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2390 | 2390 | .compare_flags_signed => unreachable, |
| 2391 | 2391 | .compare_flags_unsigned => unreachable, |
| 2392 | 2392 | .register => |reg| { |
| 2393 | try self.register_manager.getRegWithoutTracking(reg); | |
| 2393 | try self.register_manager.getReg(reg, null); | |
| 2394 | 2394 | try self.genSetReg(arg.src, arg.ty, reg, arg_mcv); |
| 2395 | 2395 | }, |
| 2396 | 2396 | .stack_offset => { |
| ... | ... | @@ -2443,7 +2443,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2443 | 2443 | .register => |reg| { |
| 2444 | 2444 | // TODO prevent this macho if block to be generated for all archs |
| 2445 | 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 | 2447 | else => unreachable, |
| 2448 | 2448 | } |
| 2449 | 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 | 3134 | |
| 3135 | 3135 | const arg = inst.args[i]; |
| 3136 | 3136 | const arg_mcv = try self.resolveInst(arg); |
| 3137 | try self.register_manager.getRegWithoutTracking(reg); | |
| 3137 | try self.register_manager.getReg(reg, null); | |
| 3138 | 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 | 3167 | |
| 3168 | 3168 | const arg = inst.args[i]; |
| 3169 | 3169 | const arg_mcv = try self.resolveInst(arg); |
| 3170 | try self.register_manager.getRegWithoutTracking(reg); | |
| 3170 | try self.register_manager.getReg(reg, null); | |
| 3171 | 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 | 3202 | |
| 3203 | 3203 | const arg = inst.args[i]; |
| 3204 | 3204 | const arg_mcv = try self.resolveInst(arg); |
| 3205 | try self.register_manager.getRegWithoutTracking(reg); | |
| 3205 | try self.register_manager.getReg(reg, null); | |
| 3206 | 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 | 3235 | |
| 3236 | 3236 | const arg = inst.args[i]; |
| 3237 | 3237 | const arg_mcv = try self.resolveInst(arg); |
| 3238 | try self.register_manager.getRegWithoutTracking(reg); | |
| 3238 | try self.register_manager.getReg(reg, null); | |
| 3239 | 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 | 1 | const std = @import("std"); |
| 2 | 2 | const Allocator = std.mem.Allocator; |
| 3 | const log = std.log.scoped(.codegen); | |
| 3 | 4 | |
| 4 | 5 | const spec = @import("spirv/spec.zig"); |
| 5 | 6 | const Module = @import("../Module.zig"); |
| 6 | 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 | 12 | pub fn writeInstruction(code: *std.ArrayList(u32), instr: spec.Opcode, args: []const u32) !void { |
| 9 | 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 | 16 | } |
| 13 | 17 | |
| 14 | 18 | pub const SPIRVModule = struct { |
| 15 | next_id: u32 = 0, | |
| 16 | free_id_list: std.ArrayList(u32), | |
| 19 | next_result_id: u32 = 0, | |
| 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 | 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 | 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 { | |
| 29 | if (self.free_id_list.popOrNull()) |id| return id; | |
| 44 | pub fn allocResultId(self: *SPIRVModule) u32 { | |
| 45 | defer self.next_result_id += 1; | |
| 46 | return self.next_result_id; | |
| 47 | } | |
| 30 | 48 | |
| 31 | defer self.next_id += 1; | |
| 32 | return self.next_id; | |
| 49 | pub fn resultIdBound(self: *SPIRVModule) u32 { | |
| 50 | return self.next_result_id; | |
| 33 | 51 | } |
| 34 | 52 | |
| 35 | pub fn freeId(self: *SPIRVModule, id: u32) void { | |
| 36 | if (id + 1 == self.next_id) { | |
| 37 | self.next_id -= 1; | |
| 38 | } else { | |
| 39 | // If no more memory to append the id to the free list, just ignore it. | |
| 40 | self.free_id_list.append(id) catch {}; | |
| 53 | pub fn getOrGenType(self: *SPIRVModule, t: Type) !u32 { | |
| 54 | // We can't use getOrPut here so we can recursively generate types. | |
| 55 | if (self.types.get(t)) |already_generated| { | |
| 56 | return already_generated; | |
| 41 | 57 | } |
| 42 | } | |
| 43 | 58 | |
| 44 | pub fn idBound(self: *SPIRVModule) u32 { | |
| 45 | return self.next_id; | |
| 59 | const result = self.allocResultId(); | |
| 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 | // Copyright (c) 2014-2020 The Khronos Group Inc. | |
| 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. | |
| 1 | //! This file is auto-generated by tools/gen_spirv_spec.zig. | |
| 2 | ||
| 24 | 3 | const Version = @import("std").builtin.Version; |
| 25 | 4 | pub const version = Version{ .major = 1, .minor = 5, .patch = 4 }; |
| 26 | 5 | pub const magic_number: u32 = 0x07230203; |
| ... | ... | @@ -443,8 +422,15 @@ pub const Opcode = extern enum(u16) { |
| 443 | 422 | OpUSubSatINTEL = 5596, |
| 444 | 423 | OpIMul32x16INTEL = 5597, |
| 445 | 424 | OpUMul32x16INTEL = 5598, |
| 446 | OpFunctionPointerINTEL = 5600, | |
| 425 | OpConstFunctionPointerINTEL = 5600, | |
| 447 | 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 | 434 | OpDecorateString = 5632, |
| 449 | 435 | OpDecorateStringGOOGLE = 5632, |
| 450 | 436 | OpMemberDecorateString = 5633, |
| ... | ... | @@ -567,7 +553,12 @@ pub const Opcode = extern enum(u16) { |
| 567 | 553 | OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, |
| 568 | 554 | OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, |
| 569 | 555 | OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, |
| 556 | OpVariableLengthArrayINTEL = 5818, | |
| 557 | OpSaveMemoryINTEL = 5819, | |
| 558 | OpRestoreMemoryINTEL = 5820, | |
| 570 | 559 | OpLoopControlINTEL = 5887, |
| 560 | OpPtrCastToCrossWorkgroupINTEL = 5934, | |
| 561 | OpCrossWorkgroupCastToPtrINTEL = 5938, | |
| 571 | 562 | OpReadPipeBlockingINTEL = 5946, |
| 572 | 563 | OpWritePipeBlockingINTEL = 5947, |
| 573 | 564 | OpFPGARegINTEL = 5949, |
| ... | ... | @@ -589,6 +580,10 @@ pub const Opcode = extern enum(u16) { |
| 589 | 580 | OpRayQueryGetIntersectionObjectToWorldKHR = 6031, |
| 590 | 581 | OpRayQueryGetIntersectionWorldToObjectKHR = 6032, |
| 591 | 582 | OpAtomicFAddEXT = 6035, |
| 583 | OpTypeBufferSurfaceINTEL = 6086, | |
| 584 | OpTypeStructContinuedINTEL = 6090, | |
| 585 | OpConstantCompositeContinuedINTEL = 6091, | |
| 586 | OpSpecConstantCompositeContinuedINTEL = 6092, | |
| 592 | 587 | _, |
| 593 | 588 | }; |
| 594 | 589 | pub const ImageOperands = packed struct { |
| ... | ... | @@ -642,8 +637,8 @@ pub const FPFastMathMode = packed struct { |
| 642 | 637 | _reserved_bit_13: bool = false, |
| 643 | 638 | _reserved_bit_14: bool = false, |
| 644 | 639 | _reserved_bit_15: bool = false, |
| 645 | _reserved_bit_16: bool = false, | |
| 646 | _reserved_bit_17: bool = false, | |
| 640 | AllowContractFastINTEL: bool = false, | |
| 641 | AllowReassocINTEL: bool = false, | |
| 647 | 642 | _reserved_bit_18: bool = false, |
| 648 | 643 | _reserved_bit_19: bool = false, |
| 649 | 644 | _reserved_bit_20: bool = false, |
| ... | ... | @@ -717,7 +712,7 @@ pub const LoopControl = packed struct { |
| 717 | 712 | LoopCoalesceINTEL: bool = false, |
| 718 | 713 | MaxInterleavingINTEL: bool = false, |
| 719 | 714 | SpeculatedIterationsINTEL: bool = false, |
| 720 | _reserved_bit_23: bool = false, | |
| 715 | NoFusionINTEL: bool = false, | |
| 721 | 716 | _reserved_bit_24: bool = false, |
| 722 | 717 | _reserved_bit_25: bool = false, |
| 723 | 718 | _reserved_bit_26: bool = false, |
| ... | ... | @@ -1037,10 +1032,16 @@ pub const ExecutionMode = extern enum(u32) { |
| 1037 | 1032 | SampleInterlockUnorderedEXT = 5369, |
| 1038 | 1033 | ShadingRateInterlockOrderedEXT = 5370, |
| 1039 | 1034 | ShadingRateInterlockUnorderedEXT = 5371, |
| 1035 | SharedLocalMemorySizeINTEL = 5618, | |
| 1036 | RoundingModeRTPINTEL = 5620, | |
| 1037 | RoundingModeRTNINTEL = 5621, | |
| 1038 | FloatingPointModeALTINTEL = 5622, | |
| 1039 | FloatingPointModeIEEEINTEL = 5623, | |
| 1040 | 1040 | MaxWorkgroupSizeINTEL = 5893, |
| 1041 | 1041 | MaxWorkDimINTEL = 5894, |
| 1042 | 1042 | NoGlobalOffsetINTEL = 5895, |
| 1043 | 1043 | NumSIMDWorkitemsINTEL = 5896, |
| 1044 | SchedulerTargetFmaxMhzINTEL = 5903, | |
| 1044 | 1045 | _, |
| 1045 | 1046 | }; |
| 1046 | 1047 | pub const StorageClass = extern enum(u32) { |
| ... | ... | @@ -1072,6 +1073,8 @@ pub const StorageClass = extern enum(u32) { |
| 1072 | 1073 | PhysicalStorageBuffer = 5349, |
| 1073 | 1074 | PhysicalStorageBufferEXT = 5349, |
| 1074 | 1075 | CodeSectionINTEL = 5605, |
| 1076 | DeviceOnlyINTEL = 5936, | |
| 1077 | HostOnlyINTEL = 5937, | |
| 1075 | 1078 | _, |
| 1076 | 1079 | }; |
| 1077 | 1080 | pub const Dim = extern enum(u32) { |
| ... | ... | @@ -1192,9 +1195,20 @@ pub const FPRoundingMode = extern enum(u32) { |
| 1192 | 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 | 1208 | pub const LinkageType = extern enum(u32) { |
| 1196 | 1209 | Export = 0, |
| 1197 | 1210 | Import = 1, |
| 1211 | LinkOnceODR = 2, | |
| 1198 | 1212 | _, |
| 1199 | 1213 | }; |
| 1200 | 1214 | pub const AccessQualifier = extern enum(u32) { |
| ... | ... | @@ -1279,12 +1293,22 @@ pub const Decoration = extern enum(u32) { |
| 1279 | 1293 | RestrictPointerEXT = 5355, |
| 1280 | 1294 | AliasedPointer = 5356, |
| 1281 | 1295 | AliasedPointerEXT = 5356, |
| 1296 | SIMTCallINTEL = 5599, | |
| 1282 | 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 | 1305 | CounterBuffer = 5634, |
| 1284 | 1306 | HlslCounterBufferGOOGLE = 5634, |
| 1285 | 1307 | UserSemantic = 5635, |
| 1286 | 1308 | HlslSemanticGOOGLE = 5635, |
| 1287 | 1309 | UserTypeGOOGLE = 5636, |
| 1310 | FunctionRoundingModeINTEL = 5822, | |
| 1311 | FunctionDenormModeINTEL = 5823, | |
| 1288 | 1312 | RegisterINTEL = 5825, |
| 1289 | 1313 | MemoryINTEL = 5826, |
| 1290 | 1314 | NumbanksINTEL = 5827, |
| ... | ... | @@ -1297,6 +1321,17 @@ pub const Decoration = extern enum(u32) { |
| 1297 | 1321 | MergeINTEL = 5834, |
| 1298 | 1322 | BankBitsINTEL = 5835, |
| 1299 | 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 | 1337 | pub const BuiltIn = extern enum(u32) { |
| ... | ... | @@ -1342,14 +1377,14 @@ pub const BuiltIn = extern enum(u32) { |
| 1342 | 1377 | VertexIndex = 42, |
| 1343 | 1378 | InstanceIndex = 43, |
| 1344 | 1379 | SubgroupEqMask = 4416, |
| 1345 | SubgroupGeMask = 4417, | |
| 1346 | SubgroupGtMask = 4418, | |
| 1347 | SubgroupLeMask = 4419, | |
| 1348 | SubgroupLtMask = 4420, | |
| 1349 | 1380 | SubgroupEqMaskKHR = 4416, |
| 1381 | SubgroupGeMask = 4417, | |
| 1350 | 1382 | SubgroupGeMaskKHR = 4417, |
| 1383 | SubgroupGtMask = 4418, | |
| 1351 | 1384 | SubgroupGtMaskKHR = 4418, |
| 1385 | SubgroupLeMask = 4419, | |
| 1352 | 1386 | SubgroupLeMaskKHR = 4419, |
| 1387 | SubgroupLtMask = 4420, | |
| 1353 | 1388 | SubgroupLtMaskKHR = 4420, |
| 1354 | 1389 | BaseVertex = 4424, |
| 1355 | 1390 | BaseInstance = 4425, |
| ... | ... | @@ -1520,6 +1555,9 @@ pub const Capability = extern enum(u32) { |
| 1520 | 1555 | FragmentShadingRateKHR = 4422, |
| 1521 | 1556 | SubgroupBallotKHR = 4423, |
| 1522 | 1557 | DrawParameters = 4427, |
| 1558 | WorkgroupMemoryExplicitLayoutKHR = 4428, | |
| 1559 | WorkgroupMemoryExplicitLayout8BitAccessKHR = 4429, | |
| 1560 | WorkgroupMemoryExplicitLayout16BitAccessKHR = 4430, | |
| 1523 | 1561 | SubgroupVoteKHR = 4431, |
| 1524 | 1562 | StorageBuffer16BitAccess = 4433, |
| 1525 | 1563 | StorageUniformBufferBlock16 = 4433, |
| ... | ... | @@ -1610,21 +1648,41 @@ pub const Capability = extern enum(u32) { |
| 1610 | 1648 | SubgroupBufferBlockIOINTEL = 5569, |
| 1611 | 1649 | SubgroupImageBlockIOINTEL = 5570, |
| 1612 | 1650 | SubgroupImageMediaBlockIOINTEL = 5579, |
| 1651 | RoundToInfinityINTEL = 5582, | |
| 1652 | FloatingPointModeINTEL = 5583, | |
| 1613 | 1653 | IntegerFunctions2INTEL = 5584, |
| 1614 | 1654 | FunctionPointersINTEL = 5603, |
| 1615 | 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 | 1663 | SubgroupAvcMotionEstimationINTEL = 5696, |
| 1617 | 1664 | SubgroupAvcMotionEstimationIntraINTEL = 5697, |
| 1618 | 1665 | SubgroupAvcMotionEstimationChromaINTEL = 5698, |
| 1666 | VariableLengthArrayINTEL = 5817, | |
| 1667 | FunctionFloatControlINTEL = 5821, | |
| 1619 | 1668 | FPGAMemoryAttributesINTEL = 5824, |
| 1669 | FPFastMathModeINTEL = 5837, | |
| 1670 | ArbitraryPrecisionIntegersINTEL = 5844, | |
| 1620 | 1671 | UnstructuredLoopControlsINTEL = 5886, |
| 1621 | 1672 | FPGALoopControlsINTEL = 5888, |
| 1622 | 1673 | KernelAttributesINTEL = 5892, |
| 1623 | 1674 | FPGAKernelAttributesINTEL = 5897, |
| 1675 | FPGAMemoryAccessesINTEL = 5898, | |
| 1676 | FPGAClusterAttributesINTEL = 5904, | |
| 1677 | LoopFuseINTEL = 5906, | |
| 1678 | FPGABufferLocationINTEL = 5920, | |
| 1679 | USMStorageClassesINTEL = 5935, | |
| 1680 | IOPipesINTEL = 5943, | |
| 1624 | 1681 | BlockingPipesINTEL = 5945, |
| 1625 | 1682 | FPGARegINTEL = 5948, |
| 1626 | 1683 | AtomicFloat32AddEXT = 6033, |
| 1627 | 1684 | AtomicFloat64AddEXT = 6034, |
| 1685 | LongConstantCompositeINTEL = 6089, | |
| 1628 | 1686 | _, |
| 1629 | 1687 | }; |
| 1630 | 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 | 446 | try result.appendSlice(comp.zig_lib_directory.path.?); |
| 447 | 447 | try result.appendSlice(s ++ "libc" ++ s ++ "glibc" ++ s ++ "sysdeps" ++ s); |
| 448 | 448 | if (is_sparc) { |
| 449 | if (is_64) { | |
| 450 | try result.appendSlice("sparc" ++ s ++ "sparc64"); | |
| 449 | if (mem.eql(u8, basename, "crti.S") or mem.eql(u8, basename, "crtn.S")) { | |
| 450 | try result.appendSlice("sparc"); | |
| 451 | 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 | 458 | } else if (arch.isARM()) { |
| 455 | 459 | try result.appendSlice("arm"); |
src/link.zig+1| ... | ... | @@ -63,6 +63,7 @@ pub const Options = struct { |
| 63 | 63 | system_linker_hack: bool, |
| 64 | 64 | link_libc: bool, |
| 65 | 65 | link_libcpp: bool, |
| 66 | link_libunwind: bool, | |
| 66 | 67 | function_sections: bool, |
| 67 | 68 | eh_frame_hdr: bool, |
| 68 | 69 | emit_relocs: bool, |
src/link/Elf.zig+6-13| ... | ... | @@ -1645,6 +1645,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1645 | 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 | 1653 | // libc dep |
| 1649 | 1654 | if (self.base.options.link_libc) { |
| 1650 | 1655 | if (self.base.options.libc_installation != null) { |
| ... | ... | @@ -1653,18 +1658,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1653 | 1658 | } |
| 1654 | 1659 | const needs_grouping = self.base.options.link_mode == .Static; |
| 1655 | 1660 | if (needs_grouping) try argv.append("--start-group"); |
| 1656 | // This matches the order of glibc.libs | |
| 1657 | try argv.appendSlice(&[_][]const u8{ | |
| 1658 | "-lm", | |
| 1659 | "-lpthread", | |
| 1660 | "-lc", | |
| 1661 | "-ldl", | |
| 1662 | "-lrt", | |
| 1663 | "-lutil", | |
| 1664 | }); | |
| 1661 | try argv.appendSlice(target_util.libcFullLinkFlags(target)); | |
| 1665 | 1662 | if (needs_grouping) try argv.append("--end-group"); |
| 1666 | 1663 | } else if (target.isGnuLibC()) { |
| 1667 | try argv.append(comp.libunwind_static_lib.?.full_object_path); | |
| 1668 | 1664 | for (glibc.libs) |lib| { |
| 1669 | 1665 | const lib_path = try std.fmt.allocPrint(arena, "{s}{c}lib{s}.so.{d}", .{ |
| 1670 | 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 | 1669 | } |
| 1674 | 1670 | try argv.append(try comp.get_libc_crt_file(arena, "libc_nonshared.a")); |
| 1675 | 1671 | } else if (target.isMusl()) { |
| 1676 | try argv.append(comp.libunwind_static_lib.?.full_object_path); | |
| 1677 | 1672 | try argv.append(try comp.get_libc_crt_file(arena, switch (self.base.options.link_mode) { |
| 1678 | 1673 | .Static => "libc.a", |
| 1679 | 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 | 1676 | } else { |
| 1684 | 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 | 363 | self.base.file = file; |
| 364 | 364 | |
| 365 | 365 | // Create dSYM bundle. |
| 366 | const d_sym_path = try fmt.allocPrint(allocator, "{s}.dSYM/Contents/Resources/DWARF/", .{sub_path}); | |
| 367 | defer allocator.free(d_sym_path); | |
| 368 | var d_sym_bundle = try options.emit.?.directory.handle.makeOpenPath(d_sym_path, .{}); | |
| 369 | defer d_sym_bundle.close(); | |
| 370 | const d_sym_file = try d_sym_bundle.createFile(sub_path, .{ | |
| 371 | .truncate = false, | |
| 372 | .read = true, | |
| 373 | }); | |
| 374 | self.d_sym = .{ | |
| 375 | .base = self, | |
| 376 | .file = d_sym_file, | |
| 377 | }; | |
| 366 | if (!options.strip and options.module != null) { | |
| 367 | const dir = options.module.?.zig_cache_artifact_directory; | |
| 368 | log.debug("creating {s}.dSYM bundle in {s}", .{ sub_path, dir.path }); | |
| 369 | ||
| 370 | const d_sym_path = try fmt.allocPrint( | |
| 371 | allocator, | |
| 372 | "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF", | |
| 373 | .{sub_path}, | |
| 374 | ); | |
| 375 | defer allocator.free(d_sym_path); | |
| 376 | ||
| 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 | 391 | // Index 0 is always a null symbol. |
| 380 | 392 | try self.locals.append(allocator, .{ |
| ... | ... | @@ -1198,7 +1210,9 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 1198 | 1210 | const need_realloc = code.len > capacity or !mem.isAlignedGeneric(u64, symbol.n_value, required_alignment); |
| 1199 | 1211 | if (need_realloc) { |
| 1200 | 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 | 1216 | if (vaddr != symbol.n_value) { |
| 1203 | 1217 | log.debug(" (writing new offset table entry)", .{}); |
| 1204 | 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 | 1222 | }; |
| 1209 | 1223 | try self.writeOffsetTableEntry(decl.link.macho.offset_table_index); |
| 1210 | 1224 | } |
| 1225 | ||
| 1226 | symbol.n_value = vaddr; | |
| 1211 | 1227 | } else if (code.len < decl.link.macho.size) { |
| 1212 | 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 | 1240 | const decl_name = mem.spanZ(decl.name); |
| 1225 | 1241 | const name_str_index = try self.makeString(decl_name); |
| 1226 | 1242 | const addr = try self.allocateTextBlock(&decl.link.macho, code.len, required_alignment); |
| 1243 | ||
| 1227 | 1244 | log.debug("allocated text block for {s} at 0x{x}", .{ decl_name, addr }); |
| 1245 | ||
| 1228 | 1246 | errdefer self.freeTextBlock(&decl.link.macho); |
| 1229 | 1247 | |
| 1230 | 1248 | symbol.* = .{ |
| ... | ... | @@ -1368,15 +1386,32 @@ pub fn updateDeclExports( |
| 1368 | 1386 | continue; |
| 1369 | 1387 | } |
| 1370 | 1388 | } |
| 1371 | const n_desc = switch (exp.options.linkage) { | |
| 1372 | .Internal => macho.REFERENCE_FLAG_PRIVATE_DEFINED, | |
| 1373 | .Strong => blk: { | |
| 1374 | if (mem.eql(u8, exp.options.name, "_start")) { | |
| 1389 | ||
| 1390 | var n_type: u8 = macho.N_SECT | macho.N_EXT; | |
| 1391 | var n_desc: u16 = 0; | |
| 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 | 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 | 1415 | .LinkOnce => { |
| 1381 | 1416 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); |
| 1382 | 1417 | module.failed_exports.putAssumeCapacityNoClobber( |
| ... | ... | @@ -1385,8 +1420,8 @@ pub fn updateDeclExports( |
| 1385 | 1420 | ); |
| 1386 | 1421 | continue; |
| 1387 | 1422 | }, |
| 1388 | }; | |
| 1389 | const n_type = decl_sym.n_type | macho.N_EXT; | |
| 1423 | } | |
| 1424 | ||
| 1390 | 1425 | if (exp.link.macho.sym_index) |i| { |
| 1391 | 1426 | const sym = &self.globals.items[i]; |
| 1392 | 1427 | sym.* = .{ |
src/link/SpirV.zig+49-52| ... | ... | @@ -16,11 +16,16 @@ |
| 16 | 16 | //! All function declarations without a body (extern functions presumably). |
| 17 | 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 | 23 | const SpirV = @This(); |
| 20 | 24 | |
| 21 | 25 | const std = @import("std"); |
| 22 | 26 | const Allocator = std.mem.Allocator; |
| 23 | 27 | const assert = std.debug.assert; |
| 28 | const log = std.log.scoped(.link); | |
| 24 | 29 | |
| 25 | 30 | const Module = @import("../Module.zig"); |
| 26 | 31 | const Compilation = @import("../Compilation.zig"); |
| ... | ... | @@ -30,16 +35,15 @@ const trace = @import("../tracy.zig").trace; |
| 30 | 35 | const build_options = @import("build_options"); |
| 31 | 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 | 39 | pub const FnData = struct { |
| 34 | id: ?u32 = null, | |
| 35 | code: std.ArrayListUnmanaged(u32) = .{}, | |
| 40 | // We're going to fill these in flushModule, and we're going to fill them unconditionally, | |
| 41 | // so just set it to undefined. | |
| 42 | id: u32 = undefined | |
| 36 | 43 | }; |
| 37 | 44 | |
| 38 | 45 | base: link.File, |
| 39 | 46 | |
| 40 | /// TODO: Does this file need to support multiple independent modules? | |
| 41 | spirv_module: codegen.SPIRVModule, | |
| 42 | ||
| 43 | 47 | /// This linker backend does not try to incrementally link output SPIR-V code. |
| 44 | 48 | /// Instead, it tracks all declarations in this table, and iterates over it |
| 45 | 49 | /// in the flush function. |
| ... | ... | @@ -54,7 +58,6 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*SpirV { |
| 54 | 58 | .file = null, |
| 55 | 59 | .allocator = gpa, |
| 56 | 60 | }, |
| 57 | .spirv_module = codegen.SPIRVModule.init(gpa), | |
| 58 | 61 | }; |
| 59 | 62 | |
| 60 | 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 | 97 | |
| 95 | 98 | pub fn deinit(self: *SpirV) void { |
| 96 | 99 | self.decl_table.deinit(self.base.allocator); |
| 97 | self.spirv_module.deinit(); | |
| 98 | 100 | } |
| 99 | 101 | |
| 100 | 102 | pub fn updateDecl(self: *SpirV, module: *Module, decl: *Module.Decl) !void { |
| 101 | const tracy = trace(@src()); | |
| 102 | defer tracy.end(); | |
| 103 | ||
| 104 | 103 | // Keep track of all decls so we can iterate over them on flush(). |
| 105 | 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 | 107 | pub fn updateDeclExports( |
| ... | ... | @@ -128,10 +113,6 @@ pub fn updateDeclExports( |
| 128 | 113 | |
| 129 | 114 | pub fn freeDecl(self: *SpirV, decl: *Module.Decl) void { |
| 130 | 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 | 118 | pub fn flush(self: *SpirV, comp: *Compilation) !void { |
| ... | ... | @@ -149,51 +130,67 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void { |
| 149 | 130 | const module = self.base.options.module.?; |
| 150 | 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 | 161 | var binary = std.ArrayList(u32).init(self.base.allocator); |
| 153 | 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 | 164 | try binary.appendSlice(&[_]u32{ |
| 159 | 165 | spec.magic_number, |
| 160 | 166 | (spec.version.major << 16) | (spec.version.minor << 8), |
| 161 | 167 | 0, // TODO: Register Zig compiler magic number. |
| 162 | self.spirv_module.idBound(), | |
| 168 | spirv_module.resultIdBound(), // ID bound. | |
| 163 | 169 | 0, // Schema (currently reserved for future use in the SPIR-V spec). |
| 164 | 170 | }); |
| 165 | 171 | |
| 166 | 172 | try writeCapabilities(&binary, target); |
| 167 | 173 | try writeMemoryModel(&binary, target); |
| 168 | 174 | |
| 169 | // Collect list of buffers to write. | |
| 170 | // SPIR-V files support both little and big endian words. The actual format is | |
| 171 | // disambiguated by the magic number, and so theoretically we don't need to worry | |
| 172 | // about endian-ness when writing the final binary. | |
| 173 | var all_buffers = std.ArrayList(std.os.iovec_const).init(self.base.allocator); | |
| 174 | defer all_buffers.deinit(); | |
| 175 | ||
| 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)); | |
| 175 | // Note: The order of adding sections to the final binary | |
| 176 | // follows the SPIR-V logical module format! | |
| 177 | var all_buffers = [_]std.os.iovec_const{ | |
| 178 | wordsToIovConst(binary.items), | |
| 179 | wordsToIovConst(spirv_module.types_and_globals.items), | |
| 180 | wordsToIovConst(spirv_module.fn_decls.items), | |
| 181 | }; | |
| 180 | 182 | |
| 181 | for (self.decl_table.items()) |entry| { | |
| 182 | const decl = entry.key; | |
| 183 | if (!decl.has_tv) continue; | |
| 184 | const fn_data = &decl.fn_link.spirv; | |
| 185 | all_buffers.appendAssumeCapacity(wordsToIovConst(fn_data.code.items)); | |
| 186 | } | |
| 183 | const file = self.base.file.?; | |
| 184 | const bytes = std.mem.sliceAsBytes(binary.items); | |
| 187 | 185 | |
| 188 | 186 | var file_size: u64 = 0; |
| 189 | for (all_buffers.items) |iov| { | |
| 187 | for (all_buffers) |iov| { | |
| 190 | 188 | file_size += iov.iov_len; |
| 191 | 189 | } |
| 192 | 190 | |
| 193 | const file = self.base.file.?; | |
| 194 | 191 | try file.seekTo(0); |
| 195 | 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 | 196 | fn writeCapabilities(binary: *std.ArrayList(u32), target: std.Target) !void { |
src/main.zig+7| ... | ... | @@ -544,6 +544,7 @@ fn buildOutputType( |
| 544 | 544 | var ensure_libcpp_on_non_freestanding = false; |
| 545 | 545 | var link_libc = false; |
| 546 | 546 | var link_libcpp = false; |
| 547 | var link_libunwind = false; | |
| 547 | 548 | var want_native_include_dirs = false; |
| 548 | 549 | var enable_cache: ?bool = null; |
| 549 | 550 | var want_pic: ?bool = null; |
| ... | ... | @@ -1556,6 +1557,11 @@ fn buildOutputType( |
| 1556 | 1557 | _ = system_libs.orderedRemove(i); |
| 1557 | 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 | 1565 | if (std.fs.path.isAbsolute(lib_name)) { |
| 1560 | 1566 | fatal("cannot use absolute path as a system library: {s}", .{lib_name}); |
| 1561 | 1567 | } |
| ... | ... | @@ -1871,6 +1877,7 @@ fn buildOutputType( |
| 1871 | 1877 | .system_libs = system_libs.items, |
| 1872 | 1878 | .link_libc = link_libc, |
| 1873 | 1879 | .link_libcpp = link_libcpp, |
| 1880 | .link_libunwind = link_libunwind, | |
| 1874 | 1881 | .want_pic = want_pic, |
| 1875 | 1882 | .want_pie = want_pie, |
| 1876 | 1883 | .want_lto = want_lto, |
src/register_manager.zig+219-156| ... | ... | @@ -7,6 +7,9 @@ const ir = @import("ir.zig"); |
| 7 | 7 | const Type = @import("type.zig").Type; |
| 8 | 8 | const Module = @import("Module.zig"); |
| 9 | 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 | 14 | const log = std.log.scoped(.register_manager); |
| 12 | 15 | |
| ... | ... | @@ -66,77 +69,14 @@ pub fn RegisterManager( |
| 66 | 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 | 75 | pub fn tryAllocRegs( |
| 71 | 76 | self: *Self, |
| 72 | 77 | comptime count: comptime_int, |
| 73 | insts: [count]*ir.Inst, | |
| 74 | exceptions: []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, | |
| 78 | insts: [count]?*ir.Inst, | |
| 79 | exceptions: []const Register, | |
| 140 | 80 | ) ?[count]Register { |
| 141 | 81 | comptime if (callee_preserved_regs.len == 0) return null; |
| 142 | 82 | comptime assert(count > 0 and count <= callee_preserved_regs.len); |
| ... | ... | @@ -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. | |
| 163 | /// Returns `null` if all registers are allocated. | |
| 164 | pub fn tryAllocRegWithoutTracking(self: *Self, exceptions: []Register) ?Register { | |
| 165 | return if (self.tryAllocRegsWithoutTracking(1, exceptions)) |regs| regs[0] else null; | |
| 113 | /// Allocates a register and optionally tracks it with a | |
| 114 | /// corresponding instruction. Returns `null` if all registers | |
| 115 | /// are allocated. | |
| 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 | |
| 169 | pub fn allocRegsWithoutTracking(self: *Self, comptime count: comptime_int, exceptions: []Register) ![count]Register { | |
| 170 | return self.tryAllocRegsWithoutTracking(count, exceptions) orelse blk: { | |
| 120 | /// Allocates a specified number of registers, optionally | |
| 121 | /// tracking them. Asserts that count + exceptions.len is not | |
| 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 | 133 | // We'll take over the first count registers. Spill |
| 172 | 134 | // the instructions that were previously there to a |
| 173 | 135 | // stack allocations. |
| ... | ... | @@ -179,11 +141,22 @@ pub fn RegisterManager( |
| 179 | 141 | regs[i] = reg; |
| 180 | 142 | |
| 181 | 143 | const index = reg.allocIndex().?; // allocIndex() on a callee-preserved reg should never return null |
| 182 | if (!self.isRegFree(reg)) { | |
| 183 | const spilled_inst = self.registers[index].?; | |
| 184 | try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst); | |
| 185 | self.registers[index] = null; | |
| 186 | self.markRegFree(reg); | |
| 144 | if (insts[i]) |inst| { | |
| 145 | // Track the register | |
| 146 | if (self.isRegFree(reg)) { | |
| 147 | self.markRegUsed(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 | 162 | i += 1; |
| ... | ... | @@ -193,39 +166,36 @@ pub fn RegisterManager( |
| 193 | 166 | }; |
| 194 | 167 | } |
| 195 | 168 | |
| 196 | /// Does not track the register. | |
| 197 | pub fn allocRegWithoutTracking(self: *Self, exceptions: []Register) !Register { | |
| 198 | return (try self.allocRegsWithoutTracking(1, exceptions))[0]; | |
| 199 | } | |
| 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 | } | |
| 169 | /// Allocates a register and optionally tracks it with a | |
| 170 | /// corresponding instruction. | |
| 171 | pub fn allocReg(self: *Self, inst: ?*ir.Inst, exceptions: []const Register) !Register { | |
| 172 | return (try self.allocRegs(1, .{inst}, exceptions))[0]; | |
| 216 | 173 | } |
| 217 | 174 | |
| 218 | /// Spills the register if it is currently allocated. | |
| 219 | /// Does not track the register. | |
| 220 | pub fn getRegWithoutTracking(self: *Self, reg: Register) !void { | |
| 175 | /// Spills the register if it is currently allocated. If a | |
| 176 | /// corresponding instruction is passed, will also track this | |
| 177 | /// register. | |
| 178 | pub fn getReg(self: *Self, reg: Register, inst: ?*ir.Inst) !void { | |
| 221 | 179 | const index = reg.allocIndex() orelse return; |
| 222 | 180 | |
| 223 | if (!self.isRegFree(reg)) { | |
| 224 | // Move the instruction that was previously there to a | |
| 225 | // stack allocation. | |
| 226 | const spilled_inst = self.registers[index].?; | |
| 227 | try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst); | |
| 228 | self.markRegFree(reg); | |
| 181 | if (inst) |tracked_inst| | |
| 182 | if (!self.isRegFree(reg)) { | |
| 183 | // Move the instruction that was previously there to a | |
| 184 | // stack allocation. | |
| 185 | const spilled_inst = self.registers[index].?; | |
| 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 | 220 | }; |
| 251 | 221 | } |
| 252 | 222 | |
| 253 | const MockRegister = enum(u2) { | |
| 223 | const MockRegister1 = enum(u2) { | |
| 254 | 224 | r0, |
| 255 | 225 | r1, |
| 256 | 226 | r2, |
| 257 | 227 | r3, |
| 258 | 228 | |
| 259 | pub fn allocIndex(self: MockRegister) ?u2 { | |
| 260 | inline for (mock_callee_preserved_regs) |cpreg, i| { | |
| 229 | pub fn allocIndex(self: MockRegister1) ?u2 { | |
| 230 | inline for (callee_preserved_regs) |cpreg, i| { | |
| 261 | 231 | if (self == cpreg) return i; |
| 262 | 232 | } |
| 263 | 233 | return null; |
| 264 | 234 | } |
| 265 | }; | |
| 266 | ||
| 267 | const mock_callee_preserved_regs = [_]MockRegister{ .r2, .r3 }; | |
| 268 | 235 | |
| 269 | const MockFunction = struct { | |
| 270 | allocator: *Allocator, | |
| 271 | register_manager: RegisterManager(Self, MockRegister, &mock_callee_preserved_regs) = .{}, | |
| 272 | spilled: std.ArrayListUnmanaged(MockRegister) = .{}, | |
| 236 | const callee_preserved_regs = [_]MockRegister1{ .r2, .r3 }; | |
| 237 | }; | |
| 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 { | |
| 277 | self.spilled.deinit(self.allocator); | |
| 245 | pub fn allocIndex(self: MockRegister2) ?u2 { | |
| 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 { | |
| 281 | try self.spilled.append(self.allocator, reg); | |
| 282 | } | |
| 252 | const callee_preserved_regs = [_]MockRegister2{ .r0, .r1, .r2, .r3 }; | |
| 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 | 277 | const allocator = std.testing.allocator; |
| 287 | 278 | |
| 288 | var function = MockFunction{ | |
| 279 | var function = MockFunction1{ | |
| 289 | 280 | .allocator = allocator, |
| 290 | 281 | }; |
| 291 | 282 | defer function.deinit(); |
| ... | ... | @@ -296,27 +287,48 @@ test "tryAllocReg: no spilling" { |
| 296 | 287 | .src = .unneeded, |
| 297 | 288 | }; |
| 298 | 289 | |
| 299 | try std.testing.expect(!function.register_manager.isRegAllocated(.r2)); | |
| 300 | try std.testing.expect(!function.register_manager.isRegAllocated(.r3)); | |
| 290 | try expect(!function.register_manager.isRegAllocated(.r2)); | |
| 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, &.{})); | |
| 303 | try std.testing.expectEqual(@as(?MockRegister, .r3), function.register_manager.tryAllocReg(&mock_instruction, &.{})); | |
| 304 | try std.testing.expectEqual(@as(?MockRegister, null), function.register_manager.tryAllocReg(&mock_instruction, &.{})); | |
| 310 | try expectEqual(@as(?MockRegister1, .r2), function.register_manager.tryAllocReg(&mock_instruction, &.{})); | |
| 311 | try expectEqual(@as(?MockRegister1, .r3), 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)); | |
| 307 | try std.testing.expect(function.register_manager.isRegAllocated(.r3)); | |
| 314 | try expect(function.register_manager.isRegAllocated(.r2)); | |
| 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 | 319 | function.register_manager.freeReg(.r2); |
| 310 | 320 | function.register_manager.freeReg(.r3); |
| 311 | 321 | |
| 312 | try std.testing.expect(function.register_manager.isRegAllocated(.r2)); | |
| 313 | try std.testing.expect(function.register_manager.isRegAllocated(.r3)); | |
| 322 | try expect(function.register_manager.isRegAllocated(.r2)); | |
| 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 | 328 | test "allocReg: spilling" { |
| 317 | 329 | const allocator = std.testing.allocator; |
| 318 | 330 | |
| 319 | var function = MockFunction{ | |
| 331 | var function = MockFunction1{ | |
| 320 | 332 | .allocator = allocator, |
| 321 | 333 | }; |
| 322 | 334 | defer function.deinit(); |
| ... | ... | @@ -327,26 +339,28 @@ test "allocReg: spilling" { |
| 327 | 339 | .src = .unneeded, |
| 328 | 340 | }; |
| 329 | 341 | |
| 330 | try std.testing.expect(!function.register_manager.isRegAllocated(.r2)); | |
| 331 | try std.testing.expect(!function.register_manager.isRegAllocated(.r3)); | |
| 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, &.{})); | |
| 342 | try expectEqual(@as(?MockRegister1, .r2), try function.register_manager.allocReg(&mock_instruction, &.{})); | |
| 343 | try expectEqual(@as(?MockRegister1, .r3), try function.register_manager.allocReg(&mock_instruction, &.{})); | |
| 335 | 344 | |
| 336 | 345 | // Spill a register |
| 337 | try std.testing.expectEqual(@as(?MockRegister, .r2), try function.register_manager.allocReg(&mock_instruction, &.{})); | |
| 338 | try std.testing.expectEqualSlices(MockRegister, &[_]MockRegister{.r2}, function.spilled.items); | |
| 346 | try expectEqual(@as(?MockRegister1, .r2), try function.register_manager.allocReg(&mock_instruction, &.{})); | |
| 347 | try expectEqualSlices(MockRegister1, &[_]MockRegister1{.r2}, function.spilled.items); | |
| 339 | 348 | |
| 340 | 349 | // No spilling necessary |
| 341 | 350 | function.register_manager.freeReg(.r3); |
| 342 | try std.testing.expectEqual(@as(?MockRegister, .r3), try function.register_manager.allocReg(&mock_instruction, &.{})); | |
| 343 | try std.testing.expectEqualSlices(MockRegister, &[_]MockRegister{.r2}, function.spilled.items); | |
| 351 | try expectEqual(@as(?MockRegister1, .r3), try function.register_manager.allocReg(&mock_instruction, &.{})); | |
| 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 | 361 | const allocator = std.testing.allocator; |
| 348 | 362 | |
| 349 | var function = MockFunction{ | |
| 363 | var function = MockFunction2{ | |
| 350 | 364 | .allocator = allocator, |
| 351 | 365 | }; |
| 352 | 366 | defer function.deinit(); |
| ... | ... | @@ -357,18 +371,67 @@ test "getReg" { |
| 357 | 371 | .src = .unneeded, |
| 358 | 372 | }; |
| 359 | 373 | |
| 360 | try std.testing.expect(!function.register_manager.isRegAllocated(.r2)); | |
| 361 | try std.testing.expect(!function.register_manager.isRegAllocated(.r3)); | |
| 374 | try expectEqual([_]MockRegister2{ .r0, .r1, .r2 }, function.register_manager.tryAllocRegs(3, .{ null, null, null }, &.{}).?); | |
| 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 | 422 | try function.register_manager.getReg(.r3, &mock_instruction); |
| 364 | 423 | |
| 365 | try std.testing.expect(!function.register_manager.isRegAllocated(.r2)); | |
| 366 | try std.testing.expect(function.register_manager.isRegAllocated(.r3)); | |
| 424 | try expect(!function.register_manager.isRegAllocated(.r2)); | |
| 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 | 429 | // Spill r3 |
| 369 | 430 | try function.register_manager.getReg(.r3, &mock_instruction); |
| 370 | 431 | |
| 371 | try std.testing.expect(!function.register_manager.isRegAllocated(.r2)); | |
| 372 | try std.testing.expect(function.register_manager.isRegAllocated(.r3)); | |
| 373 | try std.testing.expectEqualSlices(MockRegister, &[_]MockRegister{.r3}, function.spilled.items); | |
| 432 | try expect(!function.register_manager.isRegAllocated(.r2)); | |
| 433 | try expect(function.register_manager.isRegAllocated(.r3)); | |
| 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 | 5485 | } |
| 5486 | 5486 | |
| 5487 | 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 | |
| 5489 | // we need to widen it before using it and then truncate the result. | |
| 5488 | // If the operand type of an atomic operation is not byte sized we need to | |
| 5489 | // widen it before using it and then truncate the result. | |
| 5490 | 5490 | |
| 5491 | 5491 | ir_assert(instruction->value->type->id == ZigTypeIdPointer, instruction); |
| 5492 | 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 | 5498 | bool is_signed = operand_type->data.integral.is_signed; |
| 5499 | 5499 | |
| 5500 | 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 | 5502 | return get_llvm_type(g, get_int_type(g, is_signed, operand_type->abi_size * 8)); |
| 5503 | 5503 | } else { |
| 5504 | 5504 | return nullptr; |
src/target.zig+27| ... | ... | @@ -374,3 +374,30 @@ pub fn hasRedZone(target: std.Target) bool { |
| 374 | 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 | 8 | const enable_qemu: bool = build_options.enable_qemu; |
| 9 | 9 | const enable_wine: bool = build_options.enable_wine; |
| 10 | 10 | const enable_wasmtime: bool = build_options.enable_wasmtime; |
| 11 | const enable_darling: bool = build_options.enable_darling; | |
| 11 | 12 | const glibc_multi_install_dir: ?[]const u8 = build_options.glibc_multi_install_dir; |
| 12 | 13 | const ThreadPool = @import("ThreadPool.zig"); |
| 13 | 14 | const CrossTarget = std.zig.CrossTarget; |
| ... | ... | @@ -901,6 +902,16 @@ pub const TestContext = struct { |
| 901 | 902 | } else { |
| 902 | 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 | 917 | try comp.makeBinFileExecutable(); |
src/translate_c.zig+18| ... | ... | @@ -480,6 +480,9 @@ fn declVisitor(c: *Context, decl: *const clang.Decl) Error!void { |
| 480 | 480 | .Empty => { |
| 481 | 481 | // Do nothing |
| 482 | 482 | }, |
| 483 | .FileScopeAsm => { | |
| 484 | try transFileScopeAsm(c, &c.global_scope.base, @ptrCast(*const clang.FileScopeAsmDecl, decl)); | |
| 485 | }, | |
| 483 | 486 | else => { |
| 484 | 487 | const decl_name = try c.str(decl.getDeclKindName()); |
| 485 | 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 | 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 | 508 | fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void { |
| 491 | 509 | const fn_name = try c.str(@ptrCast(*const clang.NamedDecl, fn_decl).getName_bytes_begin()); |
| 492 | 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 | 161 | /// @shuffle(type, a, b, mask) |
| 162 | 162 | shuffle, |
| 163 | 163 | |
| 164 | asm_simple, | |
| 165 | ||
| 164 | 166 | negate, |
| 165 | 167 | negate_wrap, |
| 166 | 168 | bit_not, |
| ... | ... | @@ -245,6 +247,7 @@ pub const Node = extern union { |
| 245 | 247 | .std_mem_zeroes, |
| 246 | 248 | .@"return", |
| 247 | 249 | .@"comptime", |
| 250 | .asm_simple, | |
| 248 | 251 | .discard, |
| 249 | 252 | .std_math_Log2Int, |
| 250 | 253 | .negate, |
| ... | ... | @@ -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 | 1036 | .type => { |
| 1021 | 1037 | const payload = node.castTag(.type).?.data; |
| 1022 | 1038 | return c.addNode(.{ |
| ... | ... | @@ -2257,6 +2273,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { |
| 2257 | 2273 | .@"continue", |
| 2258 | 2274 | .@"return", |
| 2259 | 2275 | .@"comptime", |
| 2276 | .asm_simple, | |
| 2260 | 2277 | .usingnamespace_builtins, |
| 2261 | 2278 | .while_true, |
| 2262 | 2279 | .if_not_break, |
src/zig_clang.cpp+5| ... | ... | @@ -1820,6 +1820,11 @@ const ZigClangEnumDecl *ZigClangEnumDecl_getDefinition(const ZigClangEnumDecl *z |
| 1820 | 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 | 1828 | bool ZigClangRecordDecl_isUnion(const ZigClangRecordDecl *record_decl) { |
| 1824 | 1829 | return reinterpret_cast<const clang::RecordDecl*>(record_decl)->isUnion(); |
| 1825 | 1830 | } |
src/zig_clang.h+3| ... | ... | @@ -124,6 +124,7 @@ struct ZigClangEnumType; |
| 124 | 124 | struct ZigClangExpr; |
| 125 | 125 | struct ZigClangFieldDecl; |
| 126 | 126 | struct ZigClangFileID; |
| 127 | struct ZigClangFileScopeAsmDecl; | |
| 127 | 128 | struct ZigClangFloatingLiteral; |
| 128 | 129 | struct ZigClangForStmt; |
| 129 | 130 | struct ZigClangFullSourceLoc; |
| ... | ... | @@ -1000,6 +1001,8 @@ ZIG_EXTERN_C unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangV |
| 1000 | 1001 | ZIG_EXTERN_C unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx); |
| 1001 | 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 | 1006 | ZIG_EXTERN_C struct ZigClangQualType ZigClangParmVarDecl_getOriginalType(const struct ZigClangParmVarDecl *self); |
| 1004 | 1007 | |
| 1005 | 1008 | ZIG_EXTERN_C bool ZigClangRecordDecl_getPackedAttribute(const struct ZigClangRecordDecl *); |
test/behavior/atomics.zig+1-1| ... | ... | @@ -199,7 +199,7 @@ fn testAtomicRmwInt() !void { |
| 199 | 199 | |
| 200 | 200 | test "atomics with different types" { |
| 201 | 201 | try testAtomicsWithType(bool, true, false); |
| 202 | inline for (.{ u1, i5, u15 }) |T| { | |
| 202 | inline for (.{ u1, i4, u5, i15, u24 }) |T| { | |
| 203 | 203 | var x: T = 0; |
| 204 | 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 | 19 | |
| 20 | 20 | // Incorrect return type |
| 21 | 21 | case.addError( |
| 22 | \\pub export fn _start() noreturn { | |
| 22 | \\pub export fn main() noreturn { | |
| 23 | 23 | \\} |
| 24 | 24 | , &[_][]const u8{ |
| 25 | 25 | ":2:1: error: expected noreturn, found void", |
| ... | ... | @@ -30,7 +30,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 30 | 30 | \\extern "c" fn write(usize, usize, usize) usize; |
| 31 | 31 | \\extern "c" fn exit(usize) noreturn; |
| 32 | 32 | \\ |
| 33 | \\pub export fn _start() noreturn { | |
| 33 | \\pub export fn main() noreturn { | |
| 34 | 34 | \\ print(); |
| 35 | 35 | \\ |
| 36 | 36 | \\ exit(0); |
| ... | ... | @@ -45,12 +45,39 @@ pub fn addCases(ctx: *TestContext) !void { |
| 45 | 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 | 49 | case.addCompareOutput( |
| 50 | 50 | \\extern "c" fn write(usize, usize, usize) usize; |
| 51 | 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 | 81 | \\ print(); |
| 55 | 82 | \\ |
| 56 | 83 | \\ exit(0); |
| ... | ... | @@ -70,7 +97,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 70 | 97 | \\extern "c" fn write(usize, usize, usize) usize; |
| 71 | 98 | \\extern "c" fn exit(usize) noreturn; |
| 72 | 99 | \\ |
| 73 | \\pub export fn _start() noreturn { | |
| 100 | \\pub export fn main() noreturn { | |
| 74 | 101 | \\ print(); |
| 75 | 102 | \\ print(); |
| 76 | 103 | \\ |
| ... | ... | @@ -96,7 +123,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 96 | 123 | case.addCompareOutput( |
| 97 | 124 | \\extern "c" fn exit(usize) noreturn; |
| 98 | 125 | \\ |
| 99 | \\pub export fn _start() noreturn { | |
| 126 | \\pub export fn main() noreturn { | |
| 100 | 127 | \\ exit(0); |
| 101 | 128 | \\} |
| 102 | 129 | , |
| ... | ... | @@ -107,7 +134,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 107 | 134 | \\extern "c" fn exit(usize) noreturn; |
| 108 | 135 | \\extern "c" fn write(usize, usize, usize) usize; |
| 109 | 136 | \\ |
| 110 | \\pub export fn _start() noreturn { | |
| 137 | \\pub export fn main() noreturn { | |
| 111 | 138 | \\ _ = write(1, @ptrToInt("Hey!\n"), 5); |
| 112 | 139 | \\ exit(0); |
| 113 | 140 | \\} |
test/tests.zig+2| ... | ... | @@ -503,6 +503,7 @@ pub fn addPkgTests( |
| 503 | 503 | is_wine_enabled: bool, |
| 504 | 504 | is_qemu_enabled: bool, |
| 505 | 505 | is_wasmtime_enabled: bool, |
| 506 | is_darling_enabled: bool, | |
| 506 | 507 | glibc_dir: ?[]const u8, |
| 507 | 508 | ) *build.Step { |
| 508 | 509 | const step = b.step(b.fmt("test-{s}", .{name}), desc); |
| ... | ... | @@ -564,6 +565,7 @@ pub fn addPkgTests( |
| 564 | 565 | these_tests.enable_wine = is_wine_enabled; |
| 565 | 566 | these_tests.enable_qemu = is_qemu_enabled; |
| 566 | 567 | these_tests.enable_wasmtime = is_wasmtime_enabled; |
| 568 | these_tests.enable_darling = is_darling_enabled; | |
| 567 | 569 | these_tests.glibc_multi_install_dir = glibc_dir; |
| 568 | 570 | these_tests.addIncludeDir("test"); |
| 569 | 571 |
test/translate_c.zig+14| ... | ... | @@ -3499,4 +3499,18 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3499 | 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 | 1 | const std = @import("std"); |
| 2 | const Writer = std.ArrayList(u8).Writer; | |
| 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 | }; | |
| 2 | const g = @import("spirv/grammar.zig"); | |
| 94 | 3 | |
| 95 | 4 | pub fn main() !void { |
| 96 | 5 | var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); |
| ... | ... | @@ -106,24 +15,25 @@ pub fn main() !void { |
| 106 | 15 | const spec = try std.fs.cwd().readFileAlloc(allocator, spec_path, std.math.maxInt(usize)); |
| 107 | 16 | |
| 108 | 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); | |
| 112 | defer buf.deinit(); | |
| 113 | ||
| 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); | |
| 20 | var bw = std.io.bufferedWriter(std.io.getStdOut().writer()); | |
| 21 | try render(bw.writer(), registry); | |
| 22 | try bw.flush(); | |
| 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 | 33 | switch (registry) { |
| 122 | 34 | .core => |core_reg| { |
| 123 | try renderCopyRight(writer, core_reg.copyright); | |
| 124 | 35 | try writer.print( |
| 125 | \\const Version = @import("builtin").Version; | |
| 126 | \\pub const version = Version{{.major = {}, .minor = {}, .patch = {}}}; | |
| 36 | \\pub const version = Version{{ .major = {}, .minor = {}, .patch = {} }}; | |
| 127 | 37 | \\pub const magic_number: u32 = {s}; |
| 128 | 38 | \\ |
| 129 | 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 | 42 | try renderOperandKinds(writer, core_reg.operand_kinds); |
| 133 | 43 | }, |
| 134 | 44 | .extension => |ext_reg| { |
| 135 | try renderCopyRight(writer, ext_reg.copyright); | |
| 136 | 45 | try writer.print( |
| 137 | \\const Version = @import("builtin").Version; | |
| 138 | \\pub const version = Version{{.major = {}, .minor = 0, .patch = {}}}; | |
| 46 | \\pub const version = Version{{ .major = {}, .minor = 0, .patch = {} }}; | |
| 139 | 47 | \\ |
| 140 | 48 | , .{ ext_reg.version, ext_reg.revision }, |
| 141 | 49 | ); |
| ... | ... | @@ -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 { | |
| 149 | for (copyright) |line| { | |
| 150 | try writer.print("// {s}\n", .{ line }); | |
| 151 | } | |
| 152 | } | |
| 153 | ||
| 154 | fn renderOpcodes(writer: Writer, instructions: []const Instruction) !void { | |
| 56 | fn renderOpcodes(writer: anytype, instructions: []const g.Instruction) !void { | |
| 155 | 57 | try writer.writeAll("pub const Opcode = extern enum(u16) {\n"); |
| 156 | 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 | 65 | for (kinds) |kind| { |
| 164 | 66 | switch (kind.category) { |
| 165 | 67 | .ValueEnum => try renderValueEnum(writer, kind), |
| ... | ... | @@ -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 | 75 | try writer.print("pub const {s} = extern enum(u32) {{\n", .{ enumeration.kind }); |
| 174 | 76 | |
| 175 | 77 | const enumerants = enumeration.enumerants orelse return error.InvalidRegistry; |
| 176 | 78 | for (enumerants) |enumerant| { |
| 177 | 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 | 88 | try writer.print("pub const {s} = packed struct {{\n", .{ enumeration.kind }); |
| 187 | 89 | |
| 188 | 90 | var flags_by_bitpos = [_]?[]const u8{null} ** 32; |
| ... | ... | @@ -205,6 +107,7 @@ fn renderBitEnum(writer: Writer, enumeration: OperandKind) !void { |
| 205 | 107 | } |
| 206 | 108 | |
| 207 | 109 | for (flags_by_bitpos) |maybe_flag_name, bitpos| { |
| 110 | try writer.writeAll(" "); | |
| 208 | 111 | if (maybe_flag_name) |flag_name| { |
| 209 | 112 | try writer.writeAll(flag_name); |
| 210 | 113 | } else { |
| ... | ... | @@ -215,7 +118,7 @@ fn renderBitEnum(writer: Writer, enumeration: OperandKind) !void { |
| 215 | 118 | if (bitpos == 0) { // Force alignment to integer boundaries |
| 216 | 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 | 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 | } |