authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-18 20:34:36-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-18 20:34:36-07:00
logcee82c7ce4fb8beb39042f9dba16a1a391803fa4
treeea2a12b10b3742acc3f343a36bf14a8c34246776
parentb975f7a56fec9e0e7aca9832282bc772c743d731

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

4 files changed, 69 insertions(+), 32 deletions(-)

lib/std/target.zig+6-3
...@@ -1808,20 +1808,23 @@ pub const Target = struct {...@@ -1808,20 +1808,23 @@ pub const Target = struct {
1808 // 1. Different machine code instruction when loading into SIMD register.1808 // 1. Different machine code instruction when loading into SIMD register.
1809 // 2. The C ABI wants 16 for extern structs.1809 // 2. The C ABI wants 16 for extern structs.
1810 // 3. 16-byte cmpxchg needs 16-byte alignment.1810 // 3. 16-byte cmpxchg needs 16-byte alignment.
1811 // Same logic for riscv64, powerpc64, mips64, sparc64.1811 // Same logic for powerpc64, mips64, sparc64.
1812 .x86_64,1812 .x86_64,
1813 .riscv64,
1814 .powerpc64,1813 .powerpc64,
1815 .powerpc64le,1814 .powerpc64le,
1816 .mips64,1815 .mips64,
1817 .mips64el,1816 .mips64el,
1818 .sparc64,1817 .sparc64,
1819 => 8,1818 => return switch (target.ofmt) {
1819 .c => 16,
1820 else => 8,
1821 },
18201822
1821 // Even LLVMABIAlignmentOfType(i128) agrees on these targets.1823 // Even LLVMABIAlignmentOfType(i128) agrees on these targets.
1822 .aarch64,1824 .aarch64,
1823 .aarch64_be,1825 .aarch64_be,
1824 .aarch64_32,1826 .aarch64_32,
1827 .riscv64,
1825 .bpfel,1828 .bpfel,
1826 .bpfeb,1829 .bpfeb,
1827 .nvptx,1830 .nvptx,
src/Module.zig+19-11
...@@ -948,20 +948,28 @@ pub const Struct = struct {...@@ -948,20 +948,28 @@ pub const Struct = struct {
948948
949 switch (layout) {949 switch (layout) {
950 .Packed => return 0,950 .Packed => return 0,
951 .Auto => return field.ty.abiAlignment(target),951 .Auto => {
952 .Extern => {952 if (target.ofmt == .c) {
953 // This logic is duplicated in Type.abiAlignmentAdvanced.953 return alignmentExtern(field, target);
954 const ty_abi_align = field.ty.abiAlignment(target);954 } else {
955955 return field.ty.abiAlignment(target);
956 if (field.ty.isAbiInt() and field.ty.intInfo(target).bits >= 128) {
957 // The C ABI requires 128 bit integer fields of structs
958 // to be 16-bytes aligned.
959 return @maximum(ty_abi_align, 16);
960 }956 }
961
962 return ty_abi_align;
963 },957 },
958 .Extern => return alignmentExtern(field, target),
959 }
960 }
961
962 pub fn alignmentExtern(field: Field, target: Target) u32 {
963 // This logic is duplicated in Type.abiAlignmentAdvanced.
964 const ty_abi_align = field.ty.abiAlignment(target);
965
966 if (field.ty.isAbiInt() and field.ty.intInfo(target).bits >= 128) {
967 // The C ABI requires 128 bit integer fields of structs
968 // to be 16-bytes aligned.
969 return @maximum(ty_abi_align, 16);
964 }970 }
971
972 return ty_abi_align;
965 }973 }
966 };974 };
967975
src/type.zig+14-2
...@@ -3019,7 +3019,7 @@ pub const Type = extern union {...@@ -3019,7 +3019,7 @@ pub const Type = extern union {
3019 big_align = @maximum(big_align, field_align);3019 big_align = @maximum(big_align, field_align);
30203020
3021 // This logic is duplicated in Module.Struct.Field.alignment.3021 // This logic is duplicated in Module.Struct.Field.alignment.
3022 if (struct_obj.layout == .Extern) {3022 if (struct_obj.layout == .Extern or target.ofmt == .c) {
3023 if (field.ty.isAbiInt() and field.ty.intInfo(target).bits >= 128) {3023 if (field.ty.isAbiInt() and field.ty.intInfo(target).bits >= 128) {
3024 // The C ABI requires 128 bit integer fields of structs3024 // The C ABI requires 128 bit integer fields of structs
3025 // to be 16-bytes aligned.3025 // to be 16-bytes aligned.
...@@ -3348,7 +3348,13 @@ pub const Type = extern union {...@@ -3348,7 +3348,13 @@ pub const Type = extern union {
3348 .f128 => return AbiSizeAdvanced{ .scalar = 16 },3348 .f128 => return AbiSizeAdvanced{ .scalar = 16 },
33493349
3350 .f80 => switch (target.cpu.arch) {3350 .f80 => switch (target.cpu.arch) {
3351 .i386 => return AbiSizeAdvanced{ .scalar = 12 },3351 .i386 => switch (target.os.tag) {
3352 .windows => switch (target.abi) {
3353 .msvc => return AbiSizeAdvanced{ .scalar = 16 },
3354 else => return AbiSizeAdvanced{ .scalar = 12 },
3355 },
3356 else => return AbiSizeAdvanced{ .scalar = 12 },
3357 },
3352 .x86_64 => return AbiSizeAdvanced{ .scalar = 16 },3358 .x86_64 => return AbiSizeAdvanced{ .scalar = 16 },
3353 else => {3359 else => {
3354 var payload: Payload.Bits = .{3360 var payload: Payload.Bits = .{
...@@ -4559,6 +4565,12 @@ pub const Type = extern union {...@@ -4559,6 +4565,12 @@ pub const Type = extern union {
45594565
4560 .vector => ty = ty.castTag(.vector).?.data.elem_type,4566 .vector => ty = ty.castTag(.vector).?.data.elem_type,
45614567
4568 .@"struct" => {
4569 const struct_obj = ty.castTag(.@"struct").?.data;
4570 assert(struct_obj.layout == .Packed);
4571 ty = struct_obj.backing_int_ty;
4572 },
4573
4562 else => unreachable,4574 else => unreachable,
4563 };4575 };
4564 }4576 }
test/behavior/align.zig+30-16
...@@ -100,8 +100,8 @@ test "alignment and size of structs with 128-bit fields" {...@@ -100,8 +100,8 @@ test "alignment and size of structs with 128-bit fields" {
100 .a_align = 8,100 .a_align = 8,
101 .a_size = 16,101 .a_size = 16,
102102
103 .b_align = 8,103 .b_align = 16,
104 .b_size = 24,104 .b_size = 32,
105105
106 .u128_align = 8,106 .u128_align = 8,
107 .u128_size = 16,107 .u128_size = 16,
...@@ -114,8 +114,8 @@ test "alignment and size of structs with 128-bit fields" {...@@ -114,8 +114,8 @@ test "alignment and size of structs with 128-bit fields" {
114 .a_align = 8,114 .a_align = 8,
115 .a_size = 16,115 .a_size = 16,
116116
117 .b_align = 8,117 .b_align = 16,
118 .b_size = 24,118 .b_size = 32,
119119
120 .u128_align = 8,120 .u128_align = 8,
121 .u128_size = 16,121 .u128_size = 16,
...@@ -126,8 +126,8 @@ test "alignment and size of structs with 128-bit fields" {...@@ -126,8 +126,8 @@ test "alignment and size of structs with 128-bit fields" {
126 .a_align = 4,126 .a_align = 4,
127 .a_size = 16,127 .a_size = 16,
128128
129 .b_align = 4,129 .b_align = 16,
130 .b_size = 20,130 .b_size = 32,
131131
132 .u128_align = 4,132 .u128_align = 4,
133 .u128_size = 16,133 .u128_size = 16,
...@@ -140,25 +140,39 @@ test "alignment and size of structs with 128-bit fields" {...@@ -140,25 +140,39 @@ test "alignment and size of structs with 128-bit fields" {
140 .mips64el,140 .mips64el,
141 .powerpc64,141 .powerpc64,
142 .powerpc64le,142 .powerpc64le,
143 .riscv64,
144 .sparc64,143 .sparc64,
145 .x86_64,144 .x86_64,
146 => .{145 => switch (builtin.object_format) {
147 .a_align = 8,146 .c => .{
148 .a_size = 16,147 .a_align = 16,
148 .a_size = 16,
149149
150 .b_align = 16,150 .b_align = 16,
151 .b_size = 32,151 .b_size = 32,
152152
153 .u128_align = 8,153 .u128_align = 16,
154 .u128_size = 16,154 .u128_size = 16,
155 .u129_align = 8,155 .u129_align = 16,
156 .u129_size = 24,156 .u129_size = 32,
157 },
158 else => .{
159 .a_align = 8,
160 .a_size = 16,
161
162 .b_align = 16,
163 .b_size = 32,
164
165 .u128_align = 8,
166 .u128_size = 16,
167 .u129_align = 8,
168 .u129_size = 24,
169 },
157 },170 },
158171
159 .aarch64,172 .aarch64,
160 .aarch64_be,173 .aarch64_be,
161 .aarch64_32,174 .aarch64_32,
175 .riscv64,
162 .bpfel,176 .bpfel,
163 .bpfeb,177 .bpfeb,
164 .nvptx,178 .nvptx,