| ... | ... | @@ -748,7 +748,8 @@ fn lowerTuple(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 748 | 748 | |
| 749 | 749 | fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index { |
| 750 | 750 | const pt = self.sema.pt; |
| 751 | | const comp = pt.zcu.comp; |
| 751 | const zcu = pt.zcu; |
| 752 | const comp = zcu.comp; |
| 752 | 753 | const gpa = comp.gpa; |
| 753 | 754 | const io = comp.io; |
| 754 | 755 | const ip = &pt.zcu.intern_pool; |
| ... | ... | @@ -807,7 +808,28 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool |
| 807 | 808 | if (value.* == .none) return self.fail(node, "missing field '{f}'", .{name.fmt(ip)}); |
| 808 | 809 | } |
| 809 | 810 | |
| 810 | | return (try self.sema.pt.aggregateValue(res_ty, field_values)).toIntern(); |
| 811 | const result: Value = switch (struct_info.layout) { |
| 812 | .auto, .@"extern" => try pt.aggregateValue(res_ty, field_values), |
| 813 | .@"packed" => result: { |
| 814 | const arena = self.sema.arena; |
| 815 | const buf = try arena.alloc(u8, @intCast((res_ty.bitSize(zcu) + 7) / 8)); |
| 816 | var bit_offset: u16 = 0; |
| 817 | for (field_values) |field_ip| { |
| 818 | const field_val: Value = .fromInterned(field_ip); |
| 819 | field_val.writeToPackedMemory(zcu, buf, bit_offset) catch |err| switch (err) { |
| 820 | error.ReinterpretDeclRef => unreachable, // bitpack fields cannot be pointers |
| 821 | error.OutOfMemory => |e| return e, |
| 822 | }; |
| 823 | bit_offset += @intCast(field_val.typeOf(zcu).bitSize(zcu)); |
| 824 | } |
| 825 | assert(bit_offset == res_ty.bitSize(zcu)); |
| 826 | break :result Value.readFromPackedMemory(res_ty, pt, buf, 0, arena) catch |err| switch (err) { |
| 827 | error.IllDefinedMemoryLayout => unreachable, // bitpacks have well-defined layout |
| 828 | error.OutOfMemory => |e| return e, |
| 829 | }; |
| 830 | }, |
| 831 | }; |
| 832 | return result.toIntern(); |
| 811 | 833 | } |
| 812 | 834 | |
| 813 | 835 | fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index { |
| ... | ... | @@ -944,22 +966,24 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 944 | 966 | }; |
| 945 | 967 | const tag = try self.sema.pt.enumValueFieldIndex(.fromInterned(union_info.enum_tag_type), name_index); |
| 946 | 968 | const field_type: Type = .fromInterned(union_info.field_types.get(ip)[name_index]); |
| 947 | | const val = if (maybe_field_node) |field_node| b: { |
| 969 | const val: Value = if (maybe_field_node) |field_node| b: { |
| 948 | 970 | if (field_type.toIntern() == .void_type) { |
| 949 | 971 | return self.fail(field_node, "expected type 'void'", .{}); |
| 950 | 972 | } |
| 951 | | break :b try self.lowerExprKnownResTy(field_node, field_type); |
| 973 | break :b .fromInterned(try self.lowerExprKnownResTy(field_node, field_type)); |
| 952 | 974 | } else b: { |
| 953 | 975 | if (field_type.toIntern() != .void_type) { |
| 954 | 976 | return error.WrongType; |
| 955 | 977 | } |
| 956 | | break :b .void_value; |
| 978 | break :b .void; |
| 957 | 979 | }; |
| 958 | | return ip.getUnion(gpa, io, self.sema.pt.tid, .{ |
| 959 | | .ty = res_ty.toIntern(), |
| 960 | | .tag = tag.toIntern(), |
| 961 | | .val = val, |
| 962 | | }); |
| 980 | const result: Value = switch (union_info.layout) { |
| 981 | .auto, .@"extern" => try pt.unionValue(res_ty, tag, val), |
| 982 | .@"packed" => try self.sema.bitCastVal(val, res_ty, 0, 0, 0) orelse { |
| 983 | unreachable; // `null` is only possible if the input value contains a pointer, which a packed union cannot. |
| 984 | }, |
| 985 | }; |
| 986 | return result.toIntern(); |
| 963 | 987 | } |
| 964 | 988 | |
| 965 | 989 | fn lowerVector(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index { |