Commit 8895025688
src/codegen/spirv.zig
@@ -1734,6 +1734,7 @@ pub const DeclGen = struct {
.unwrap_errunion_err => try self.airErrUnionErr(inst),
.unwrap_errunion_payload => try self.airErrUnionPayload(inst),
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
+ .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
.is_null => try self.airIsNull(inst, .is_null),
.is_non_null => try self.airIsNull(inst, .is_non_null),
@@ -3216,20 +3217,35 @@ pub const DeclGen = struct {
}
const payload_ty_ref = try self.resolveType(payload_ty, .indirect);
- var members = std.BoundedArray(IdRef, 2){};
- const payload_id = try self.spv.constUndef(payload_ty_ref);
- if (eu_layout.error_first) {
- members.appendAssumeCapacity(operand_id);
- members.appendAssumeCapacity(payload_id);
- // TODO: ABI padding?
- } else {
- members.appendAssumeCapacity(payload_id);
- members.appendAssumeCapacity(operand_id);
- // TODO: ABI padding?
+
+ var members: [2]IdRef = undefined;
+ members[eu_layout.errorFieldIndex()] = operand_id;
+ members[eu_layout.payloadFieldIndex()] = try self.spv.constUndef(payload_ty_ref);
+
+ const err_union_ty_ref = try self.resolveType(err_union_ty, .direct);
+ return try self.constructStruct(err_union_ty_ref, &members);
+ }
+
+ fn airWrapErrUnionPayload(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
+ if (self.liveness.isUnused(inst)) return null;
+
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ const err_union_ty = self.typeOfIndex(inst);
+ const operand_id = try self.resolve(ty_op.operand);
+ const payload_ty = self.typeOf(ty_op.operand);
+ const err_ty_ref = try self.resolveType(Type.anyerror, .direct);
+ const eu_layout = self.errorUnionLayout(payload_ty);
+
+ if (!eu_layout.payload_has_bits) {
+ return try self.constInt(err_ty_ref, 0);
}
+ var members: [2]IdRef = undefined;
+ members[eu_layout.errorFieldIndex()] = try self.constInt(err_ty_ref, 0);
+ members[eu_layout.payloadFieldIndex()] = try self.convertToIndirect(payload_ty, operand_id);
+
const err_union_ty_ref = try self.resolveType(err_union_ty, .direct);
- return try self.constructStruct(err_union_ty_ref, members.slice());
+ return try self.constructStruct(err_union_ty_ref, &members);
}
fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_null, is_non_null }) !?IdRef {
test/behavior/error.zig
@@ -30,7 +30,6 @@ fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
test "error binary operator" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const a = errBinaryOperatorG(true) catch 3;
const b = errBinaryOperatorG(false) catch 3;
@@ -62,14 +61,12 @@ pub fn baz() anyerror!i32 {
test "error wrapping" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
try expect((baz() catch unreachable) == 15);
}
test "unwrap simple value from error" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const i = unwrapSimpleValueFromErrorDo() catch unreachable;
try expect(i == 13);
@@ -80,7 +77,6 @@ fn unwrapSimpleValueFromErrorDo() anyerror!isize {
test "error return in assignment" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
doErrReturnInAssignment() catch unreachable;
}
@@ -103,7 +99,6 @@ test "syntax: optional operator in front of error union operator" {
test "widen cast integer payload of error union function call" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
fn errorable() !u64 {
@@ -150,7 +145,6 @@ test "implicit cast to optional to error union to return result loc" {
}
test "fn returning empty error set can be passed as fn returning any error" {
- if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
entry();
comptime entry();
}
@@ -243,7 +237,6 @@ fn testExplicitErrorSetCast(set1: Set1) !void {
test "comptime test error for empty error set" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
try testComptimeTestErrorEmptySet(1234);
try comptime testComptimeTestErrorEmptySet(1234);
@@ -279,7 +272,6 @@ test "inferred empty error set comptime catch" {
}
test "error inference with an empty set" {
- if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
const Struct = struct {
pub fn func() (error{})!usize {
@@ -334,7 +326,6 @@ fn quux_1() !i32 {
test "error: Zero sized error set returned with value payload crash" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
_ = try foo3(0);
_ = try comptime foo3(0);
@@ -434,7 +425,6 @@ test "nested error union function call in optional unwrap" {
test "return function call to error set from error union function" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
fn errorable() anyerror!i32 {
@@ -670,7 +660,6 @@ test "peer type resolution of two different error unions" {
}
test "coerce error set to the current inferred error set" {
- if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
fn foo() !void {
var a = false;
@@ -862,8 +851,6 @@ fn non_errorable() void {
}
test "catch within a function that calls no errorable functions" {
- if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
-
non_errorable();
}
@@ -895,7 +882,6 @@ test "field access of anyerror results in smaller error set" {
test "optional error union return type" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
fn foo() ?anyerror!u32 {