authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-15 21:44:38-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-15 21:44:38-07:00
log597082adf45cebbf2c6a81c3f732b6d2ce4a1435
tree9309977e204cceaac2c18efbea2153a69f86d1f4
parent07606d12daabe8c201dba3d5b27e702ce58d0ffb
parentd98e39fa6864f287bc50f265f98b7195849afa68

Merge remote-tracking branch 'origin/master' into stage2-whole-file-astgen

Conflicts: * build.zig * src/Compilation.zig * src/codegen/spirv/spec.zig * src/link/SpirV.zig * test/stage2/darwin.zig - this one might be problematic; start.zig looks for `main` in the root source file, not `_main`. Not sure why there is an underscore there in master branch.

48 files changed, 3668 insertions(+), 907 deletions(-)

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