| ... | ... | @@ -763,6 +763,47 @@ pub const DeclGen = struct { |
| 763 | 763 | |
| 764 | 764 | try self.addUndef(layout.padding); |
| 765 | 765 | }, |
| 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 | }, |
| 766 | 807 | else => |tag| return dg.todo("indirect constant of type {s}", .{@tagName(tag)}), |
| 767 | 808 | } |
| 768 | 809 | } |
| ... | ... | @@ -1209,6 +1250,35 @@ pub const DeclGen = struct { |
| 1209 | 1250 | }); |
| 1210 | 1251 | }, |
| 1211 | 1252 | .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 | }, |
| 1212 | 1282 | |
| 1213 | 1283 | .Null, |
| 1214 | 1284 | .Undefined, |