Commit Graph
75 Commits
Author SHA1 Message Date
Brian Ferri 25cafe0b34 spirv: fix vector casts, packed field pointers and debug names of comptime-known values (#37040)
I'm writing a small numeric library whose kernels run on the CPU, on CUDA and on Vulkan through the self-hosted SPIR-V backend, and I was making them generic over the float type. `f64` needs its own `exp` and `log` on the GPU, so I wrote them as polynomial series, and the `f64` Vulkan module stopped validating. This fixes the three backend bugs underneath that, and a crash I ran into after merging master.

The series take floats apart with `@bitCast` on vectors. Between vectors of the same length this reaches the Vulkan/OpenGL fallback in `bitCast`, which stores the source into a function variable of the destination type:

```zig
export fn main() callconv(.{ .spirv_kernel = .{ .x = 1, .y = 1, .z = 1 } }) void {
    var x: @Vector(2, f32) = .{ 1, 2 };
    _ = &x;
    const bits: @Vector(2, i32) = @bitCast(x);
    _ = bits;
}
```

```
$ zig build-exe -fno-llvm -target spirv64-vulkan -mcpu vulkan_v1_2 bitcast.zig -femit-bin=bitcast.spv
$ spirv-val --target-env vulkan1.2 bitcast.spv
error: line 45: OpStore Pointer <id> '36[%36]'s type does not match Object <id> '29[%29]'s type.
```

An elementwise vector bitcast is now a scalar `bitCast` per lane, the way `buildConvert` and friends already unroll vectors. Going through the scalar path also normalizes lanes of strange integers: a single `OpBitcast` on the whole vector validates for `@Vector(n, u3)` to `@Vector(n, i3)`, but leaves lanes that don't compare equal to the negative values they should hold.

The series also convert between integer and float lanes. A vector of one lane, or of more than four without `vector16`, is an array in SPIR-V, and `airFloatFromInt` and `airIntFromFloat` emitted a single `OpConvert*` with that array as its result type:

```zig
export fn main() callconv(.{ .spirv_kernel = .{ .x = 1, .y = 1, .z = 1 } }) void {
    var x: @Vector(1, i32) = .{1};
    _ = &x;
    const y: @Vector(1, f32) = @floatFromInt(x);
    _ = y;
}
```

```
$ spirv-val --target-env vulkan1.2 convert.spv
error: line 40: Expected float scalar or vector type as Result Type: ConvertSToF
  %y = OpConvertSToF %_arr_f32_u32_1 %26
```

`@floatCast` and `@intCast` already go through `buildConvert`, which unrolls the vector; these two now do as well, with `buildConvert` picking the int/float conversion opcodes.

The coefficients sit in a comptime array that the series take as a comptime slice, and that alone fails to compile, although nothing reads the slice at runtime:

```zig
const weights = [_]f32{ 1, 2, 3 };

inline fn first(comptime w: []const f32) f32 {
    return w[0];
}

export fn main() callconv(.{ .spirv_kernel = .{ .x = 1, .y = 1, .z = 1 } }) void {
    var x: f32 = first(&weights);
    _ = &x;
}
```

```
$ zig build-exe -fno-llvm -target spirv64-vulkan -mcpu vulkan_v1_2 dbgvar.zig -femit-bin=dbgvar.spv
dbgvar.zig:7:8: error: TODO (SPIR-V): pointer to constant 'dbgvar.weights'
```

It appears `airDbgVar` lowers the operand only to attach an `OpName` to it, and a pointer to a non-extern constant is still a TODO. A comptime-known value has no runtime variable of its own to name, so `airDbgVar` now leaves interned operands alone. The same thing held back 58 of the behavior tests skipped on SPIR-V, and the test commit un-skips them.

After merging master, four of those tests crashed the compiler in `structFieldPtr`, which has `unreachable` for packed containers since ebb8683ef1 ([#36996](https://codeberg.org/ziglang/zig/pulls/36996)):

```zig
const Flags = packed struct { a: bool, b: bool };

export fn main() callconv(.{ .spirv_kernel = .{ .x = 1, .y = 1, .z = 1 } }) void {
    var flags: Flags = .{ .a = true, .b = false };
    const b = &flags.b;
    b.* = true;
}
```

```
thread 3961624 panic: reached unreachable code
src/codegen/spirv/CodeGen.zig:6906:27: 0x4767157 in structFieldPtr (main.zig)
            .@"packed" => unreachable,
```

My reading is that the `unreachable` holds for the pointer derivations it was written for, since `constantPtr` now turns packed pointers into pointers to their host integer first, but `airStructFieldPtr` and `airStructFieldPtrIndex` still pass packed structs through. A pointer to a packed field is a bit-pointer into the struct's own host integer, so it is the struct pointer: that is what the old code computed, and what the C backend now does with `.begin`. Packed unions get back the TODO error they had before. I may be missing a plan for packed field pointers here, and I'm happy to change it if so. The commit also un-skips three packed tests that crash on master the same way. I suppose nothing caught this because those tests are skipped on SPIR-V and the `spirv64-vulkan` behavior target is commented out in `test/tests.zig`.

I ran the behavior tests through `tools/unskip_spirv_tests.zig` and [zig-spirv-test-executor](https://github.com/Snektron/zig-spirv-test-executor) on a Radeon 680M, and the new and un-skipped tests on an RTX 4060 as well. Every fix has tests that fail on master and pass with it; the vector ones compare lane by lane, since `expectEqual` on vectors doesn't compile for SPIR-V yet. Running each behavior file whole, nothing that passes on master fails. Five more skips already pass on master without these changes, so I left them out, but I can add them. The new vector tests copy the aarch64, arm, sparc64 and riscv64 skips of the tests around them, which I couldn't check.

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/37040
Reviewed-by: Ali Cheraghi <alichraghi@noreply.codeberg.org>
2026-10-04 11:50:49 +02:00
Ali Cheraghi d95c7db6ec test: skip failing behavior tests for spirv 2026-08-26 08:13:06 +03:30
David Rubin c150a66bfe Sema: fix inline for loop breaks 2026-06-26 23:29:08 +02:00
Ali Cheraghi 9115f88386 test: skip failing/crashing behavior tests for spirv backend
tested with `-target spirv64-vulkan` and `-mcpu vulkan_v1_2+float16+variable_pointers+float64+int64`
2026-06-14 09:11:59 +02:00
Matthew Lugg fdac89d6cd remove uses of array multiplication
In preparation for its removal as accepted in
https://github.com/ziglang/zig/issues/24738.
2026-04-30 08:57:51 +01:00
Matthew Lugg 01546e68cd compiler: handle switch rewrite review feedback 2026-01-11 14:37:28 +00:00
Justus Klausecker bce7e7a52b AstGen: Re-allow labeled break from loop else block targeting its label
This fixes a regression from a couple of commits ago; breaking from the
`else` block of a loop to the loop's tag should be allowed when explicitly
targeting the label by name.
2026-01-11 11:37:17 +00:00
Jacob Young 5060ab99c9 aarch64: add new from scratch self-hosted backend 2025-07-22 19:43:47 -07:00
Ali Cheraghi 872f68c9cb rename spirv backend name
`stage2_spirv64` -> `stage2_spirv`
2025-06-16 13:22:19 +03:30
David Rubin 22013f1b39 test: add a behavior test for 0-length loop fix 2025-03-24 06:58:01 -07:00
Ali Cheraghi aec0f9b3e7 test: skip failing tests with spirv-vulkan 2025-02-24 19:39:42 +01:00
David Rubin 8da212c11b riscv: update tests and fix reuse bug 2024-07-26 04:19:58 -07:00
David Rubin a1f6a8ef90 riscv: airAsm rewrite
with this rewrite we can call functions inside of
inline assembly, enabling us to use the default start.zig logic

all that's left is to implement lr/sc loops for atomically manipulating
1 and 2 byte values, after which we can use the segfault handler logic.
2024-07-26 04:19:55 -07:00
David Rubin 8d30fc45c4 riscv: implement more operators
we can run `std.debug.print` now, with both run-time strings and integers!
2024-07-26 04:05:39 -07:00
David Rubin 4fd8900337 riscv: rewrite "binOp"
Reorganize how the binOp and genBinOp functions work.

I've spent quite a while here reading exactly through the spec and so many
tests are enabled because of several critical issues the old design had.

There are some regressions that will take a long time to figure out individually
so I will ignore them for now, and pray they get fixed by themselves. When
we're closer to 100% passing is when I will start diving into them one-by-one.
2024-06-13 02:24:39 -07:00
David Rubin b67995689d riscv: add airAggregateInit for arrays 2024-06-13 02:22:04 -07:00
David Rubin 05de6c279b riscv: std.fmt.format running
- implements `airSlice`, `airBitAnd`, `airBitOr`, `airShr`.

- got a basic design going for the `airErrorName` but for some reason it simply returns
empty bytes. will investigate further.

- only generating `.got.zig` entries when not compiling an object or shared library

- reduced the total amount of ops a mnemonic can have to 3, simplifying the logic
2024-06-13 02:20:47 -07:00
David Rubin c457f35da5 riscv: arbitrary sized arrays 2024-06-13 02:19:40 -07:00
David Rubin a30af172e8 riscv: math progress 2024-05-11 02:17:24 -07:00
David Rubin d9e0cafe64 riscv: add stage2_riscv to test matrix and bypass failing tests 2024-05-11 02:17:24 -07:00
Ali Chraghi 436f53f55d spirv: implement @mulWithOverflow 2024-04-06 09:01:46 +03:30
Robin Voetter 9fbba0e01a spirv: update tests 2024-02-04 19:09:33 +01:00
Veikka Tuominen 804cee3b93 categorize behavior/bugs/<issueno>.zig tests 2024-01-06 16:49:41 -08:00
David Rubin 1e42a3de89 Remove all usages of std.mem.copy and remove std.mem.set (#18143) 2023-11-29 16:03:02 -05:00
mlugg 9c16b2370d test: update behavior to silence 'var is never mutated' errors 2023-11-19 09:57:03 +00:00
Robin Voetter faad97edff spirv: update failing / passing tests
Some tests are now failing due to debug info changes, some tests
now pass due to improved compiler functionality.
2023-10-15 20:08:18 +02:00
Robin Voetter 15cf1315bb spirv: fix incorrect repr of some optional operations 2023-10-15 14:00:01 +02:00
Robin Voetter 0a3e566f57 spirv: make bitcasts between the same spirv type a no-op 2023-10-15 14:00:01 +02:00
Robin Voetter 075584a4d7 spirv: enable passing tests 2023-09-23 12:36:56 -07:00
Jacob Young 7201e69454 AstGen: fix missing deferred ref
Closes #16524
2023-07-26 22:19:30 -07:00
mlugg f26dda2117 all: migrate code to new cast builtin syntax
Most of this migration was performed automatically with `zig fmt`. There
were a few exceptions which I had to manually fix:

* `@alignCast` and `@addrSpaceCast` cannot be automatically rewritten
* `@truncate`'s fixup is incorrect for vectors
* Test cases are not formatted, and their error locations change
2023-06-24 16:56:39 -07:00
mlugg ce88c43a4e Sema: allow indexing tuple and vector pointers
Resolves: #13852
Resolves: #14705
2023-06-14 22:07:25 -07:00
Eric Joldasov d884d7050e all: replace comptime try with try comptime
Signed-off-by: Eric Joldasov <bratishkaerik@getgoogleoff.me>
2023-06-13 23:46:58 +06:00
Robin Voetter 65157d30ab spirv: ptr_elem_val
Implements the ptr_elem_val air tag. Implementation is unified
with ptr_elem_ptr.
2023-05-20 17:30:23 +02:00
Robin Voetter 37aa343079 spirv: more passing tests 2023-05-20 17:30:22 +02:00
Ali Chraghi ccc490ef68 setup spirv backend in behavior tests 2023-05-11 20:31:52 +02:00
Jacob Young 3f5592c114 x86_64: implement slice elem ptr for more MCValue tags 2023-05-03 04:25:14 -04:00
Jacob Young 488d804a1c x86_64: rewrite inst tracking 2023-04-20 20:49:34 +01:00
mlugg 1059b57898 Liveness: defer deaths of externally-scoped instructions in loop bodies 2023-04-07 01:29:20 +01:00
Jacob Young dbe1b4a7e5 x86_64: fix value tracking bugs 2023-03-24 17:57:58 -04:00
Jacob Young c51930b060 behavior: enable passing behavior tests on stage2_x86_64 2023-03-15 01:04:21 -04:00
Andrew Kelley 40c4c25e2b Sema: add missing coercion when checking for loop len 2023-02-18 19:20:19 -07:00
Andrew Kelley 8b05205bb7 implement error for unbounded for loops 2023-02-18 19:20:19 -07:00
Andrew Kelley 74db8c2e83 omit safety checks for element access in for loops
One of the main points of for loops is that you can safety check the
length once, before entering the loop, and then safely assume that every
element inside the loop is in bounds.

In master branch, the safety checks are incorrectly intact even inside
for loops. This commit fixes it. It's especially nice with multi-object
loops because the number of elided checks is N * M where N is how many
iterations and M is how many objects.
2023-02-18 19:20:19 -07:00
Andrew Kelley bcb72401d3 AstGen: add error for discard of unbounded counter 2023-02-18 19:17:21 -07:00
Andrew Kelley b13745ac03 disable failing x86_64 backend tests 2023-02-18 19:17:21 -07:00
Andrew Kelley b6a5e52dec add passing for loop test: two counters 2023-02-18 19:17:21 -07:00
Andrew Kelley f2a6a1756b Sema: fix for loops with comptime-known int ranges 2023-02-18 19:17:21 -07:00
Andrew Kelley f0530385b5 update existing behavior tests and std lib to new for loop semantics 2023-02-18 19:17:21 -07:00
Veikka Tuominen 9a0c593a54 add tests for fixed stage1 bugs
Closes #1957
Closes #1994
Closes #2140
Closes #2746
Closes #2802
Closes #2855
Closes #2895
Closes #2981
Closes #3054
Closes #3158
Closes #3234
Closes #3259
Closes #3371
Closes #3376
Closes #3387
Closes #3529
Closes #3653
Closes #3750
Closes #3778
Closes #3882
Closes #3915
Closes #3929
Closes #3961
Closes #3988
Closes #4123
Closes #7448
2022-12-29 12:42:44 +02:00