diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2023-06-16 23:08:33 +0100 |
|---|---|---|
| committer | Jacob Young <jacobly0@users.noreply.github.com> | 2023-06-30 23:23:03 -0400 |
| commit | 730f2e040770b9f537922c18d95d8bef0b2603d7 (patch) | |
| tree | 2a069f4444915c7b6335966230b1d62ae6f9a309 /src | |
| parent | 5b594139d93bb94642a94928adf00506f30da746 (diff) | |
| download | zig-730f2e040770b9f537922c18d95d8bef0b2603d7.tar.gz zig-730f2e040770b9f537922c18d95d8bef0b2603d7.zip | |
Sema: copy pointer alignment to struct field pointers
Diffstat (limited to 'src')
| -rw-r--r-- | src/Module.zig | 1 | ||||
| -rw-r--r-- | src/Sema.zig | 34 |
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; |
