diff --git a/lib/std/target.zig b/lib/std/target.zig index 00553bb52079..64f9f9780961 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1808,20 +1808,23 @@ pub const Target = struct { // 1. Different machine code instruction when loading into SIMD register. // 2. The C ABI wants 16 for extern structs. // 3. 16-byte cmpxchg needs 16-byte alignment. - // Same logic for riscv64, powerpc64, mips64, sparc64. + // Same logic for powerpc64, mips64, sparc64. .x86_64, - .riscv64, .powerpc64, .powerpc64le, .mips64, .mips64el, .sparc64, - => 8, + => return switch (target.ofmt) { + .c => 16, + else => 8, + }, // Even LLVMABIAlignmentOfType(i128) agrees on these targets. .aarch64, .aarch64_be, .aarch64_32, + .riscv64, .bpfel, .bpfeb, .nvptx, diff --git a/src/Module.zig b/src/Module.zig index 6d2180e8e747..3ae61c264fea 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -948,20 +948,28 @@ pub const Struct = struct { switch (layout) { .Packed => return 0, - .Auto => return field.ty.abiAlignment(target), - .Extern => { - // This logic is duplicated in Type.abiAlignmentAdvanced. - const ty_abi_align = field.ty.abiAlignment(target); - - if (field.ty.isAbiInt() and field.ty.intInfo(target).bits >= 128) { - // The C ABI requires 128 bit integer fields of structs - // to be 16-bytes aligned. - return @maximum(ty_abi_align, 16); + .Auto => { + if (target.ofmt == .c) { + return alignmentExtern(field, target); + } else { + return field.ty.abiAlignment(target); } - - return ty_abi_align; }, + .Extern => return alignmentExtern(field, target), + } + } + + pub fn alignmentExtern(field: Field, target: Target) u32 { + // This logic is duplicated in Type.abiAlignmentAdvanced. + const ty_abi_align = field.ty.abiAlignment(target); + + if (field.ty.isAbiInt() and field.ty.intInfo(target).bits >= 128) { + // The C ABI requires 128 bit integer fields of structs + // to be 16-bytes aligned. + return @maximum(ty_abi_align, 16); } + + return ty_abi_align; } }; diff --git a/src/type.zig b/src/type.zig index fb2ca1e3fcb8..6a66fb9d700c 100644 --- a/src/type.zig +++ b/src/type.zig @@ -3019,7 +3019,7 @@ pub const Type = extern union { big_align = @maximum(big_align, field_align); // This logic is duplicated in Module.Struct.Field.alignment. - if (struct_obj.layout == .Extern) { + if (struct_obj.layout == .Extern or target.ofmt == .c) { if (field.ty.isAbiInt() and field.ty.intInfo(target).bits >= 128) { // The C ABI requires 128 bit integer fields of structs // to be 16-bytes aligned. @@ -3348,7 +3348,13 @@ pub const Type = extern union { .f128 => return AbiSizeAdvanced{ .scalar = 16 }, .f80 => switch (target.cpu.arch) { - .i386 => return AbiSizeAdvanced{ .scalar = 12 }, + .i386 => switch (target.os.tag) { + .windows => switch (target.abi) { + .msvc => return AbiSizeAdvanced{ .scalar = 16 }, + else => return AbiSizeAdvanced{ .scalar = 12 }, + }, + else => return AbiSizeAdvanced{ .scalar = 12 }, + }, .x86_64 => return AbiSizeAdvanced{ .scalar = 16 }, else => { var payload: Payload.Bits = .{ @@ -4559,6 +4565,12 @@ pub const Type = extern union { .vector => ty = ty.castTag(.vector).?.data.elem_type, + .@"struct" => { + const struct_obj = ty.castTag(.@"struct").?.data; + assert(struct_obj.layout == .Packed); + ty = struct_obj.backing_int_ty; + }, + else => unreachable, }; } diff --git a/test/behavior/align.zig b/test/behavior/align.zig index 4a824bc9cf48..ad857fb9c2e7 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -100,8 +100,8 @@ test "alignment and size of structs with 128-bit fields" { .a_align = 8, .a_size = 16, - .b_align = 8, - .b_size = 24, + .b_align = 16, + .b_size = 32, .u128_align = 8, .u128_size = 16, @@ -114,8 +114,8 @@ test "alignment and size of structs with 128-bit fields" { .a_align = 8, .a_size = 16, - .b_align = 8, - .b_size = 24, + .b_align = 16, + .b_size = 32, .u128_align = 8, .u128_size = 16, @@ -126,8 +126,8 @@ test "alignment and size of structs with 128-bit fields" { .a_align = 4, .a_size = 16, - .b_align = 4, - .b_size = 20, + .b_align = 16, + .b_size = 32, .u128_align = 4, .u128_size = 16, @@ -140,25 +140,39 @@ test "alignment and size of structs with 128-bit fields" { .mips64el, .powerpc64, .powerpc64le, - .riscv64, .sparc64, .x86_64, - => .{ - .a_align = 8, - .a_size = 16, + => switch (builtin.object_format) { + .c => .{ + .a_align = 16, + .a_size = 16, - .b_align = 16, - .b_size = 32, + .b_align = 16, + .b_size = 32, - .u128_align = 8, - .u128_size = 16, - .u129_align = 8, - .u129_size = 24, + .u128_align = 16, + .u128_size = 16, + .u129_align = 16, + .u129_size = 32, + }, + else => .{ + .a_align = 8, + .a_size = 16, + + .b_align = 16, + .b_size = 32, + + .u128_align = 8, + .u128_size = 16, + .u129_align = 8, + .u129_size = 24, + }, }, .aarch64, .aarch64_be, .aarch64_32, + .riscv64, .bpfel, .bpfeb, .nvptx,