From fedc9a19e7909694fac107c3da245e08616fd6e4 Mon Sep 17 00:00:00 2001 From: Ali Chraghi Date: Wed, 17 May 2023 11:24:09 +0330 Subject: [PATCH 1/2] spirv: lower get_union_tag --- src/codegen/spirv.zig | 17 +++++++++++++++++ test/behavior/enum.zig | 1 - test/behavior/pub_enum.zig | 2 -- test/behavior/union.zig | 9 --------- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index d1def8a02ef51974f11665180fb8c5ed12783a94..1793e9fe18d9caece7f4420733052205f3096aae 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -1735,6 +1735,7 @@ pub const DeclGen = struct { .slice_elem_val => try self.airSliceElemVal(inst), .ptr_elem_ptr => try self.airPtrElemPtr(inst), + .get_union_tag => try self.airGetUnionTag(inst), .struct_field_val => try self.airStructFieldVal(inst), .struct_field_ptr_index_0 => try self.airStructFieldPtrIndex(inst, 0), @@ -2320,6 +2321,22 @@ pub const DeclGen = struct { return result_id; } + fn airGetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const un_ty = self.air.typeOf(ty_op.operand); + + const target = self.module.getTarget(); + const layout = un_ty.unionGetLayout(target); + if (layout.tag_size == 0) return null; + + const union_handle = try self.resolve(ty_op.operand); + if (layout.payload_size == 0) return union_handle; + + const tag_ty = un_ty.unionTagTypeSafety().?; + const tag_index = @boolToInt(layout.tag_align < layout.payload_align); + return try self.extractField(tag_ty, union_handle, tag_index); + } + fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { if (self.liveness.isUnused(inst)) return null; diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig index 097caaad19e820787ad239b7c6cdee513520fa15..61ad010ed75aedba47f38c94232072847aa52809 100644 --- a/test/behavior/enum.zig +++ b/test/behavior/enum.zig @@ -910,7 +910,6 @@ test "enum literal casting to tagged union" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const Arch = union(enum) { x86_64, diff --git a/test/behavior/pub_enum.zig b/test/behavior/pub_enum.zig index 672d097250c00580bdcc43dcea7cd383198422d6..e17546157db49e1eea6e586f0e098b4f5fda1c88 100644 --- a/test/behavior/pub_enum.zig +++ b/test/behavior/pub_enum.zig @@ -3,8 +3,6 @@ const other = @import("pub_enum/other.zig"); const expect = @import("std").testing.expect; test "pub enum" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - try pubEnumTest(other.APubEnum.Two); } fn pubEnumTest(foo: other.APubEnum) !void { diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 26232159b650cd54c75cc3d48f225adc6abd52c3..2520241aff84e7ee72d7be24022b61b00a6ea99d 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -272,7 +272,6 @@ test "comparison between union and enum literal" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testComparison(); comptime try testComparison(); @@ -288,7 +287,6 @@ test "cast union to tag type of union" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; try testCastUnionToTag(); comptime try testCastUnionToTag(); @@ -309,7 +307,6 @@ test "cast tag type of union to union" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var x: Value2 = Letter2.B; try expect(@as(Letter2, x) == Letter2.B); @@ -325,7 +322,6 @@ test "implicit cast union to its tag type" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var x: Value2 = Letter2.B; try expect(x == Letter2.B); @@ -422,7 +418,6 @@ test "tagged union with no payloads" { test "union with only 1 field casted to its enum type" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const Literal = union(enum) { Number: f64, @@ -736,7 +731,6 @@ test "@enumToInt works on unions" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 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 Bar = union(enum) { A: bool, @@ -959,7 +953,6 @@ test "function call result coerces from tagged union to the tag" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 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 { const Arch = union(enum) { @@ -1467,8 +1460,6 @@ test "packed union in packed struct" { } test "Namespace-like union" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - const DepType = enum { git, http, -- 2.54.0 From d7ddaf64a2978d80814ac7f57e3db2d1c6a45c2e Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 20 May 2023 17:25:17 +0200 Subject: [PATCH 2/2] spirv: don't generate union tag type if it doesnt exist Previously the tag type was generated even if it was nonexistant, triggering an assertion that an integer type should never have zero bits. Now its only generated when the tag type is actually emitted. --- src/codegen/spirv.zig | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 1793e9fe18d9caece7f4420733052205f3096aae..644bb95cca1184894b372ad5e6ae3e7ef5b10e75 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -1116,21 +1116,20 @@ pub const DeclGen = struct { return self.todo("packed union types", .{}); } - const tag_ty_ref = try self.resolveType(union_ty.tag_ty, .indirect); if (layout.payload_size == 0) { // No payload, so represent this as just the tag type. - return tag_ty_ref; + return try self.resolveType(union_ty.tag_ty, .indirect); } var members = std.BoundedArray(SpvType.Payload.Struct.Member, 4){}; const has_tag = layout.tag_size != 0; const tag_first = layout.tag_align >= layout.payload_align; - const tag_member = .{ .name = "tag", .ty = tag_ty_ref }; const u8_ty_ref = try self.intType(.unsigned, 8); // TODO: What if Int8Type is not enabled? if (has_tag and tag_first) { - members.appendAssumeCapacity(tag_member); + const tag_ty_ref = try self.resolveType(union_ty.tag_ty, .indirect); + members.appendAssumeCapacity(.{ .name = "tag", .ty = tag_ty_ref }); } const active_field = maybe_active_field orelse layout.most_aligned_field; @@ -1149,7 +1148,8 @@ pub const DeclGen = struct { } if (has_tag and !tag_first) { - members.appendAssumeCapacity(tag_member); + const tag_ty_ref = try self.resolveType(union_ty.tag_ty, .indirect); + members.appendAssumeCapacity(.{ .name = "tag", .ty = tag_ty_ref }); } if (layout.padding != 0) { -- 2.54.0