aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-08-18 20:34:36 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-08-18 20:34:36 -0700
commitcee82c7ce4fb8beb39042f9dba16a1a391803fa4 (patch)
treeea2a12b10b3742acc3f343a36bf14a8c34246776
parentb975f7a56fec9e0e7aca9832282bc772c743d731 (diff)
downloadzig-cee82c7ce4fb8beb39042f9dba16a1a391803fa4.tar.gz
zig-cee82c7ce4fb8beb39042f9dba16a1a391803fa4.zip
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
-rw-r--r--lib/std/target.zig9
-rw-r--r--src/Module.zig30
-rw-r--r--src/type.zig16
-rw-r--r--test/behavior/align.zig46
4 files changed, 69 insertions, 32 deletions
diff --git a/lib/std/target.zig b/lib/std/target.zig
index 00553bb520..64f9f97809 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 6d2180e8e7..3ae61c264f 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 fb2ca1e3fc..6a66fb9d70 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 4a824bc9cf..ad857fb9c2 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,