stage2: Implement explicit backing integers for packed structs

Now the backing integer of a packed struct type may be explicitly
specified with e.g. `packed struct(u32) { ... }`.
This commit is contained in:
Isaac Freund
2022-08-08 18:39:14 +02:00
parent bb1c3e8b7e
commit 0d32b73078
20 changed files with 493 additions and 73 deletions

View File

@@ -895,6 +895,11 @@ pub const Struct = struct {
zir_index: Zir.Inst.Index,
layout: std.builtin.Type.ContainerLayout,
/// If the layout is not packed, this is the noreturn type.
/// If the layout is packed, this is the backing integer type of the packed struct.
/// Whether zig chooses this type or the user specifies it, it is stored here.
/// This will be set to the noreturn type until status is `have_layout`.
backing_int_ty: Type = Type.initTag(.noreturn),
status: enum {
none,
field_types_wip,
@@ -1025,7 +1030,7 @@ pub const Struct = struct {
pub fn packedFieldBitOffset(s: Struct, target: Target, index: usize) u16 {
assert(s.layout == .Packed);
assert(s.haveFieldTypes());
assert(s.haveLayout());
var bit_sum: u64 = 0;
for (s.fields.values()) |field, i| {
if (i == index) {
@@ -1033,19 +1038,7 @@ pub const Struct = struct {
}
bit_sum += field.ty.bitSize(target);
}
return @intCast(u16, bit_sum);
}
pub fn packedIntegerBits(s: Struct, target: Target) u16 {
return s.packedFieldBitOffset(target, s.fields.count());
}
pub fn packedIntegerType(s: Struct, target: Target, buf: *Type.Payload.Bits) Type {
buf.* = .{
.base = .{ .tag = .int_unsigned },
.data = s.packedIntegerBits(target),
};
return Type.initPayload(&buf.base);
unreachable; // index out of bounds
}
};