improved ABI alignment/size for >= 128-bit integers

* riscv64: adjust alignment and size of 128-bit integers.
 * take ofmt=c into account for ABI alignment of 128-bit integers and
   structs.
 * Type: make packed struct support intInfo
 * fix f80 alignment for i386-windows-msvc
This commit is contained in:
Andrew Kelley 2022-08-18 20:34:36 -07:00
parent b975f7a56f
commit cee82c7ce4
4 changed files with 69 additions and 32 deletions

View File

@ -1808,20 +1808,23 @@ pub const Target = struct {
// 1. Different machine code instruction when loading into SIMD register. // 1. Different machine code instruction when loading into SIMD register.
// 2. The C ABI wants 16 for extern structs. // 2. The C ABI wants 16 for extern structs.
// 3. 16-byte cmpxchg needs 16-byte alignment. // 3. 16-byte cmpxchg needs 16-byte alignment.
// Same logic for riscv64, powerpc64, mips64, sparc64. // Same logic for powerpc64, mips64, sparc64.
.x86_64, .x86_64,
.riscv64,
.powerpc64, .powerpc64,
.powerpc64le, .powerpc64le,
.mips64, .mips64,
.mips64el, .mips64el,
.sparc64, .sparc64,
=> 8, => return switch (target.ofmt) {
.c => 16,
else => 8,
},
// Even LLVMABIAlignmentOfType(i128) agrees on these targets. // Even LLVMABIAlignmentOfType(i128) agrees on these targets.
.aarch64, .aarch64,
.aarch64_be, .aarch64_be,
.aarch64_32, .aarch64_32,
.riscv64,
.bpfel, .bpfel,
.bpfeb, .bpfeb,
.nvptx, .nvptx,

View File

@ -948,8 +948,18 @@ pub const Struct = struct {
switch (layout) { switch (layout) {
.Packed => return 0, .Packed => return 0,
.Auto => return field.ty.abiAlignment(target), .Auto => {
.Extern => { if (target.ofmt == .c) {
return alignmentExtern(field, target);
} else {
return field.ty.abiAlignment(target);
}
},
.Extern => return alignmentExtern(field, target),
}
}
pub fn alignmentExtern(field: Field, target: Target) u32 {
// This logic is duplicated in Type.abiAlignmentAdvanced. // This logic is duplicated in Type.abiAlignmentAdvanced.
const ty_abi_align = field.ty.abiAlignment(target); const ty_abi_align = field.ty.abiAlignment(target);
@ -960,8 +970,6 @@ pub const Struct = struct {
} }
return ty_abi_align; return ty_abi_align;
},
}
} }
}; };

View File

@ -3019,7 +3019,7 @@ pub const Type = extern union {
big_align = @maximum(big_align, field_align); big_align = @maximum(big_align, field_align);
// This logic is duplicated in Module.Struct.Field.alignment. // 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) { if (field.ty.isAbiInt() and field.ty.intInfo(target).bits >= 128) {
// The C ABI requires 128 bit integer fields of structs // The C ABI requires 128 bit integer fields of structs
// to be 16-bytes aligned. // to be 16-bytes aligned.
@ -3348,7 +3348,13 @@ pub const Type = extern union {
.f128 => return AbiSizeAdvanced{ .scalar = 16 }, .f128 => return AbiSizeAdvanced{ .scalar = 16 },
.f80 => switch (target.cpu.arch) { .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 }, .x86_64 => return AbiSizeAdvanced{ .scalar = 16 },
else => { else => {
var payload: Payload.Bits = .{ var payload: Payload.Bits = .{
@ -4559,6 +4565,12 @@ pub const Type = extern union {
.vector => ty = ty.castTag(.vector).?.data.elem_type, .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, else => unreachable,
}; };
} }

View File

@ -100,8 +100,8 @@ test "alignment and size of structs with 128-bit fields" {
.a_align = 8, .a_align = 8,
.a_size = 16, .a_size = 16,
.b_align = 8, .b_align = 16,
.b_size = 24, .b_size = 32,
.u128_align = 8, .u128_align = 8,
.u128_size = 16, .u128_size = 16,
@ -114,8 +114,8 @@ test "alignment and size of structs with 128-bit fields" {
.a_align = 8, .a_align = 8,
.a_size = 16, .a_size = 16,
.b_align = 8, .b_align = 16,
.b_size = 24, .b_size = 32,
.u128_align = 8, .u128_align = 8,
.u128_size = 16, .u128_size = 16,
@ -126,8 +126,8 @@ test "alignment and size of structs with 128-bit fields" {
.a_align = 4, .a_align = 4,
.a_size = 16, .a_size = 16,
.b_align = 4, .b_align = 16,
.b_size = 20, .b_size = 32,
.u128_align = 4, .u128_align = 4,
.u128_size = 16, .u128_size = 16,
@ -140,10 +140,22 @@ test "alignment and size of structs with 128-bit fields" {
.mips64el, .mips64el,
.powerpc64, .powerpc64,
.powerpc64le, .powerpc64le,
.riscv64,
.sparc64, .sparc64,
.x86_64, .x86_64,
=> .{ => switch (builtin.object_format) {
.c => .{
.a_align = 16,
.a_size = 16,
.b_align = 16,
.b_size = 32,
.u128_align = 16,
.u128_size = 16,
.u129_align = 16,
.u129_size = 32,
},
else => .{
.a_align = 8, .a_align = 8,
.a_size = 16, .a_size = 16,
@ -155,10 +167,12 @@ test "alignment and size of structs with 128-bit fields" {
.u129_align = 8, .u129_align = 8,
.u129_size = 24, .u129_size = 24,
}, },
},
.aarch64, .aarch64,
.aarch64_be, .aarch64_be,
.aarch64_32, .aarch64_32,
.riscv64,
.bpfel, .bpfel,
.bpfeb, .bpfeb,
.nvptx, .nvptx,