aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig23
1 files changed, 21 insertions, 2 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 5159d6f5d3..0cf449991d 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -18678,8 +18678,6 @@ fn structFieldPtrByIndex(
const target = sema.mod.getTarget();
- // TODO handle when the struct pointer is overaligned, we should return a potentially
- // over-aligned field pointer too.
if (struct_obj.layout == .Packed) {
comptime assert(Type.packed_struct_layout_version == 2);
@@ -18700,6 +18698,27 @@ fn structFieldPtrByIndex(
ptr_ty_data.host_size = struct_ptr_ty_info.host_size;
ptr_ty_data.bit_offset += struct_ptr_ty_info.bit_offset;
}
+
+ const parent_align = if (struct_ptr_ty_info.@"align" != 0)
+ struct_ptr_ty_info.@"align"
+ else
+ struct_ptr_ty_info.pointee_type.abiAlignment(target);
+ ptr_ty_data.@"align" = parent_align;
+
+ // If the field happens to be byte-aligned, simplify the pointer type.
+ // The pointee type bit size must match its ABI byte size so that loads and stores
+ // do not interfere with the surrounding packed bits.
+ if (parent_align != 0 and ptr_ty_data.bit_offset % 8 == 0) {
+ const byte_offset = ptr_ty_data.bit_offset / 8;
+ const elem_size_bytes = ptr_ty_data.pointee_type.abiSize(target);
+ const elem_size_bits = ptr_ty_data.pointee_type.bitSize(target);
+ if (elem_size_bytes * 8 == elem_size_bits) {
+ const new_align = @as(u32, 1) << @intCast(u5, @ctz(u64, byte_offset | parent_align));
+ ptr_ty_data.bit_offset = 0;
+ ptr_ty_data.host_size = 0;
+ ptr_ty_data.@"align" = new_align;
+ }
+ }
} else {
ptr_ty_data.@"align" = field.abi_align;
}