Skip to content

Commit cee82c7

Browse files
committed
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
1 parent b975f7a commit cee82c7

File tree

4 files changed

+69
-32
lines changed

4 files changed

+69
-32
lines changed

lib/std/target.zig

+6-3
Original file line numberDiff line numberDiff line change
@@ -1808,20 +1808,23 @@ pub const Target = struct {
18081808
// 1. Different machine code instruction when loading into SIMD register.
18091809
// 2. The C ABI wants 16 for extern structs.
18101810
// 3. 16-byte cmpxchg needs 16-byte alignment.
1811-
// Same logic for riscv64, powerpc64, mips64, sparc64.
1811+
// Same logic for powerpc64, mips64, sparc64.
18121812
.x86_64,
1813-
.riscv64,
18141813
.powerpc64,
18151814
.powerpc64le,
18161815
.mips64,
18171816
.mips64el,
18181817
.sparc64,
1819-
=> 8,
1818+
=> return switch (target.ofmt) {
1819+
.c => 16,
1820+
else => 8,
1821+
},
18201822

18211823
// Even LLVMABIAlignmentOfType(i128) agrees on these targets.
18221824
.aarch64,
18231825
.aarch64_be,
18241826
.aarch64_32,
1827+
.riscv64,
18251828
.bpfel,
18261829
.bpfeb,
18271830
.nvptx,

src/Module.zig

+19-11
Original file line numberDiff line numberDiff line change
@@ -948,20 +948,28 @@ pub const Struct = struct {
948948

949949
switch (layout) {
950950
.Packed => return 0,
951-
.Auto => return field.ty.abiAlignment(target),
952-
.Extern => {
953-
// This logic is duplicated in Type.abiAlignmentAdvanced.
954-
const ty_abi_align = field.ty.abiAlignment(target);
955-
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);
951+
.Auto => {
952+
if (target.ofmt == .c) {
953+
return alignmentExtern(field, target);
954+
} else {
955+
return field.ty.abiAlignment(target);
960956
}
961-
962-
return ty_abi_align;
963957
},
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);
964970
}
971+
972+
return ty_abi_align;
965973
}
966974
};
967975

src/type.zig

+14-2
Original file line numberDiff line numberDiff line change
@@ -3019,7 +3019,7 @@ pub const Type = extern union {
30193019
big_align = @maximum(big_align, field_align);
30203020

30213021
// 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) {
30233023
if (field.ty.isAbiInt() and field.ty.intInfo(target).bits >= 128) {
30243024
// The C ABI requires 128 bit integer fields of structs
30253025
// to be 16-bytes aligned.
@@ -3348,7 +3348,13 @@ pub const Type = extern union {
33483348
.f128 => return AbiSizeAdvanced{ .scalar = 16 },
33493349

33503350
.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+
},
33523358
.x86_64 => return AbiSizeAdvanced{ .scalar = 16 },
33533359
else => {
33543360
var payload: Payload.Bits = .{
@@ -4559,6 +4565,12 @@ pub const Type = extern union {
45594565

45604566
.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+
45624574
else => unreachable,
45634575
};
45644576
}

test/behavior/align.zig

+30-16
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ test "alignment and size of structs with 128-bit fields" {
100100
.a_align = 8,
101101
.a_size = 16,
102102

103-
.b_align = 8,
104-
.b_size = 24,
103+
.b_align = 16,
104+
.b_size = 32,
105105

106106
.u128_align = 8,
107107
.u128_size = 16,
@@ -114,8 +114,8 @@ test "alignment and size of structs with 128-bit fields" {
114114
.a_align = 8,
115115
.a_size = 16,
116116

117-
.b_align = 8,
118-
.b_size = 24,
117+
.b_align = 16,
118+
.b_size = 32,
119119

120120
.u128_align = 8,
121121
.u128_size = 16,
@@ -126,8 +126,8 @@ test "alignment and size of structs with 128-bit fields" {
126126
.a_align = 4,
127127
.a_size = 16,
128128

129-
.b_align = 4,
130-
.b_size = 20,
129+
.b_align = 16,
130+
.b_size = 32,
131131

132132
.u128_align = 4,
133133
.u128_size = 16,
@@ -140,25 +140,39 @@ test "alignment and size of structs with 128-bit fields" {
140140
.mips64el,
141141
.powerpc64,
142142
.powerpc64le,
143-
.riscv64,
144143
.sparc64,
145144
.x86_64,
146-
=> .{
147-
.a_align = 8,
148-
.a_size = 16,
145+
=> switch (builtin.object_format) {
146+
.c => .{
147+
.a_align = 16,
148+
.a_size = 16,
149149

150-
.b_align = 16,
151-
.b_size = 32,
150+
.b_align = 16,
151+
.b_size = 32,
152152

153-
.u128_align = 8,
154-
.u128_size = 16,
155-
.u129_align = 8,
156-
.u129_size = 24,
153+
.u128_align = 16,
154+
.u128_size = 16,
155+
.u129_align = 16,
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+
},
157170
},
158171

159172
.aarch64,
160173
.aarch64_be,
161174
.aarch64_32,
175+
.riscv64,
162176
.bpfel,
163177
.bpfeb,
164178
.nvptx,

0 commit comments

Comments
 (0)