aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2023-06-16 23:08:33 +0100
committerJacob Young <jacobly0@users.noreply.github.com>2023-06-30 23:23:03 -0400
commit730f2e040770b9f537922c18d95d8bef0b2603d7 (patch)
tree2a069f4444915c7b6335966230b1d62ae6f9a309 /src
parent5b594139d93bb94642a94928adf00506f30da746 (diff)
downloadzig-730f2e040770b9f537922c18d95d8bef0b2603d7.tar.gz
zig-730f2e040770b9f537922c18d95d8bef0b2603d7.zip
Sema: copy pointer alignment to struct field pointers
Diffstat (limited to 'src')
-rw-r--r--src/Module.zig1
-rw-r--r--src/Sema.zig34
2 files changed, 32 insertions, 3 deletions
diff --git a/src/Module.zig b/src/Module.zig
index 6d04b8f894..16f1c4f641 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -991,6 +991,7 @@ pub const Struct = struct {
is_comptime: bool,
/// Returns the field alignment. If the struct is packed, returns 0.
+ /// Keep implementation in sync with `Sema.structFieldAlignment`.
pub fn alignment(
field: Field,
mod: *Module,
diff --git a/src/Sema.zig b/src/Sema.zig
index 4403df671a..16b3b5c710 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -25842,6 +25842,9 @@ fn structFieldPtrByIndex(
const target = mod.getTarget();
+ const parent_align = struct_ptr_ty_info.flags.alignment.toByteUnitsOptional() orelse
+ try sema.typeAbiAlignment(struct_ptr_ty_info.child.toType());
+
if (struct_obj.layout == .Packed) {
comptime assert(Type.packed_struct_layout_version == 2);
@@ -25863,8 +25866,6 @@ fn structFieldPtrByIndex(
ptr_ty_data.packed_offset.bit_offset += struct_ptr_ty_info.packed_offset.bit_offset;
}
- const parent_align = struct_ptr_ty_info.flags.alignment.toByteUnitsOptional() orelse
- struct_ptr_ty_info.child.toType().abiAlignment(mod);
ptr_ty_data.flags.alignment = Alignment.fromByteUnits(parent_align);
// If the field happens to be byte-aligned, simplify the pointer type.
@@ -25888,8 +25889,13 @@ fn structFieldPtrByIndex(
ptr_ty_data.packed_offset = .{ .host_size = 0, .bit_offset = 0 };
}
}
+ } else if (struct_obj.layout == .Extern and field_index == 0) {
+ // This is the first field in memory, so can inherit the struct alignment
+ ptr_ty_data.flags.alignment = Alignment.fromByteUnits(parent_align);
} else {
- ptr_ty_data.flags.alignment = field.abi_align;
+ // Our alignment is capped at the field alignment
+ const field_align = try sema.structFieldAlignment(field, struct_obj.layout);
+ ptr_ty_data.flags.alignment = Alignment.fromByteUnits(@min(field_align, parent_align));
}
const ptr_field_ty = try mod.ptrType(ptr_ty_data);
@@ -35952,6 +35958,28 @@ fn unionFieldAlignment(sema: *Sema, field: Module.Union.Field) !u32 {
field.abi_align.toByteUnitsOptional() orelse try sema.typeAbiAlignment(field.ty)));
}
+/// Keep implementation in sync with `Module.Struct.Field.alignment`.
+fn structFieldAlignment(sema: *Sema, field: Module.Struct.Field, layout: std.builtin.Type.ContainerLayout) !u32 {
+ const mod = sema.mod;
+ if (field.abi_align.toByteUnitsOptional()) |a| {
+ assert(layout != .Packed);
+ return @as(u32, @intCast(a));
+ }
+ switch (layout) {
+ .Packed => return 0,
+ .Auto => if (mod.getTarget().ofmt != .c) {
+ return sema.typeAbiAlignment(field.ty);
+ },
+ .Extern => {},
+ }
+ // extern
+ const ty_abi_align = try sema.typeAbiAlignment(field.ty);
+ if (field.ty.isAbiInt(mod) and field.ty.intInfo(mod).bits >= 128) {
+ return @max(ty_abi_align, 16);
+ }
+ return ty_abi_align;
+}
+
/// Synchronize logic with `Type.isFnOrHasRuntimeBits`.
pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {
const mod = sema.mod;