| ... | @@ -748,7 +748,8 @@ fn lowerTuple(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. | ... | @@ -748,7 +748,8 @@ fn lowerTuple(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 748 | | 748 | |
| 749 | fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index { | 749 | fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index { |
| 750 | const pt = self.sema.pt; | 750 | const pt = self.sema.pt; |
| 751 | const comp = pt.zcu.comp; | 751 | const zcu = pt.zcu; |
| | 752 | const comp = zcu.comp; |
| 752 | const gpa = comp.gpa; | 753 | const gpa = comp.gpa; |
| 753 | const io = comp.io; | 754 | const io = comp.io; |
| 754 | const ip = &pt.zcu.intern_pool; | 755 | const ip = &pt.zcu.intern_pool; |
| ... | @@ -807,7 +808,28 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool | ... | @@ -807,7 +808,28 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool |
| 807 | if (value.* == .none) return self.fail(node, "missing field '{f}'", .{name.fmt(ip)}); | 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 | fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index { | 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,22 +966,24 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 944 | }; | 966 | }; |
| 945 | const tag = try self.sema.pt.enumValueFieldIndex(.fromInterned(union_info.enum_tag_type), name_index); | 967 | const tag = try self.sema.pt.enumValueFieldIndex(.fromInterned(union_info.enum_tag_type), name_index); |
| 946 | const field_type: Type = .fromInterned(union_info.field_types.get(ip)[name_index]); | 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 | if (field_type.toIntern() == .void_type) { | 970 | if (field_type.toIntern() == .void_type) { |
| 949 | return self.fail(field_node, "expected type 'void'", .{}); | 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 | } else b: { | 974 | } else b: { |
| 953 | if (field_type.toIntern() != .void_type) { | 975 | if (field_type.toIntern() != .void_type) { |
| 954 | return error.WrongType; | 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, .{ | 980 | const result: Value = switch (union_info.layout) { |
| 959 | .ty = res_ty.toIntern(), | 981 | .auto, .@"extern" => try pt.unionValue(res_ty, tag, val), |
| 960 | .tag = tag.toIntern(), | 982 | .@"packed" => try self.sema.bitCastVal(val, res_ty, 0, 0, 0) orelse { |
| 961 | .val = val, | 983 | unreachable; // `null` is only possible if the input value contains a pointer, which a packed union cannot. |
| 962 | }); | 984 | }, |
| | 985 | }; |
| | 986 | return result.toIntern(); |
| 963 | } | 987 | } |
| 964 | | 988 | |
| 965 | fn lowerVector(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index { | 989 | fn lowerVector(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index { |