authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-04-09 01:30:06+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-04-09 01:51:53+02:00
log719d47d823a7e27ba0902b2878835297a6001fd0
tree4cbe958c228ac520423879deb94d98643616acdb
parent8bbfbfc956af163434c734e196d5c2a77e77ff07
signaturelock-open Commit is signed but in an unrecognized format.

spirv: implement error set and error unions

Implements lowering types and constants for error sets and error unions.

1 files changed, 70 insertions(+), 0 deletions(-)

src/codegen/spirv.zig+70
......@@ -763,6 +763,47 @@ pub const DeclGen = struct {
763763
764764 try self.addUndef(layout.padding);
765765 },
766 .ErrorSet => switch (val.tag()) {
767 .@"error" => {
768 const err_name = val.castTag(.@"error").?.data.name;
769 const kv = try dg.module.getErrorValue(err_name);
770 try self.addConstInt(u16, @intCast(u16, kv.value));
771 },
772 .zero => {
773 // Unactivated error set.
774 try self.addConstInt(u16, 0);
775 },
776 else => unreachable,
777 },
778 .ErrorUnion => {
779 const payload_ty = ty.errorUnionPayload();
780 const is_pl = val.errorUnionIsPayload();
781 const error_val = if (!is_pl) val else Value.initTag(.zero);
782
783 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
784 return try self.lower(Type.anyerror, error_val);
785 }
786
787 const payload_align = payload_ty.abiAlignment(target);
788 const error_align = Type.anyerror.abiAlignment(target);
789
790 const payload_size = payload_ty.abiSize(target);
791 const error_size = Type.anyerror.abiAlignment(target);
792 const ty_size = ty.abiSize(target);
793 const padding = ty_size - payload_size - error_size;
794
795 const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef);
796
797 if (error_align > payload_align) {
798 try self.lower(Type.anyerror, error_val);
799 try self.lower(payload_ty, payload_val);
800 } else {
801 try self.lower(payload_ty, payload_val);
802 try self.lower(Type.anyerror, error_val);
803 }
804
805 try self.addUndef(padding);
806 },
766807 else => |tag| return dg.todo("indirect constant of type {s}", .{@tagName(tag)}),
767808 }
768809 }
......@@ -1209,6 +1250,35 @@ pub const DeclGen = struct {
12091250 });
12101251 },
12111252 .Union => return try self.resolveUnionType(ty, null),
1253 .ErrorSet => return try self.intType(.unsigned, 16),
1254 .ErrorUnion => {
1255 const payload_ty = ty.errorUnionPayload();
1256 const error_ty_ref = try self.resolveType(Type.anyerror, .indirect);
1257 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1258 return error_ty_ref;
1259 }
1260
1261 const payload_ty_ref = try self.resolveType(payload_ty, .indirect);
1262
1263 const payload_align = payload_ty.abiAlignment(target);
1264 const error_align = Type.anyerror.abiAlignment(target);
1265
1266 var members = std.BoundedArray(SpvType.Payload.Struct.Member, 2){};
1267 // Similar to unions, we're going to put the most aligned member first.
1268 if (error_align > payload_align) {
1269 // Put the error first
1270 members.appendAssumeCapacity(.{ .ty = error_ty_ref, .name = "error" });
1271 members.appendAssumeCapacity(.{ .ty = payload_ty_ref, .name = "payload" });
1272 // TODO: ABI padding?
1273 } else {
1274 // Put the payload first.
1275 members.appendAssumeCapacity(.{ .ty = payload_ty_ref, .name = "payload" });
1276 members.appendAssumeCapacity(.{ .ty = error_ty_ref, .name = "error" });
1277 // TODO: ABI padding?
1278 }
1279
1280 return try self.spv.simpleStructType(members.slice());
1281 },
12121282
12131283 .Null,
12141284 .Undefined,