Skip to content

Commit 6e4491f

Browse files
committed
[ARM, AArch64] Fix passing of structures with aligned base classes
RecordLayout::UnadjustedAlignment was documented as "Maximum of the alignments of the record members in characters", but RecordLayout::getUnadjustedAlignment(), which just returns UnadjustedAlignment, was documented as getting "the record alignment in characters, before alignment adjustement." These are not the same thing: the former excludes alignment of base classes, the latter takes it into account. ItaniumRecordLayoutBuilder::LayoutBase was setting it according to the former, but the AAPCS calling convention handling, currently the only user, relies on it being set according to the latter. Alignment tests in aapcs64-align.cpp are moved to AArch64/args.cpp so that we can test that this change is not applied to Apple. Fixes #135551.
1 parent e4f2191 commit 6e4491f

File tree

5 files changed

+115
-101
lines changed

5 files changed

+115
-101
lines changed

clang/include/clang/AST/RecordLayout.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,9 @@ class ASTRecordLayout {
7575
// performance or backwards compatibility preserving (e.g. AIX-ABI).
7676
CharUnits PreferredAlignment;
7777

78-
// UnadjustedAlignment - Maximum of the alignments of the record members in
79-
// characters.
78+
// UnadjustedAlignment - Alignment of record in characters before alignment
79+
// adjustments. Maximum of the alignments of the record members and base
80+
// classes in characters.
8081
CharUnits UnadjustedAlignment;
8182

8283
/// RequiredAlignment - The required alignment of the object. In the MS-ABI
@@ -186,7 +187,7 @@ class ASTRecordLayout {
186187
CharUnits getPreferredAlignment() const { return PreferredAlignment; }
187188

188189
/// getUnadjustedAlignment - Get the record alignment in characters, before
189-
/// alignment adjustement.
190+
/// alignment adjustment.
190191
CharUnits getUnadjustedAlignment() const { return UnadjustedAlignment; }
191192

192193
/// getSize - Get the record size in characters.

clang/lib/AST/RecordLayoutBuilder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,6 +1302,7 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
13021302
setSize(std::max(getSize(), Offset + Layout.getSize()));
13031303

13041304
// Remember max struct/class alignment.
1305+
UnadjustedAlignment = std::max(UnadjustedAlignment, BaseAlign);
13051306
UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
13061307

13071308
return Offset;

clang/test/CodeGen/AArch64/args.cpp

Lines changed: 109 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %clang_cc1 -triple arm64-apple-ios7.0 -target-abi darwinpcs -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,DARWIN
2-
// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - -x c %s | FileCheck %s --check-prefixes=CHECK,C
3-
// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,CXX
2+
// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - -x c %s | FileCheck %s --check-prefixes=CHECK,C,AAPCS
3+
// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,CXX,AAPCS
44

55
// Empty structs are ignored for PCS purposes on Darwin and in C mode elsewhere.
66
// In C++ mode on ELF they consume a register slot though. Functions are
@@ -110,3 +110,110 @@ EXTERNC struct SortOfEmpty sort_of_empty_arg_variadic(int a, ...) {
110110
return b;
111111
}
112112

113+
// Base case, nothing interesting.
114+
struct S {
115+
long x, y;
116+
};
117+
118+
// CHECK-LABEL: @g_S(
119+
// CHECK: call void @f_S(i64 noundef 1, [2 x i64] {{.*}})
120+
// CHECK: call void @fm_S(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 noundef 4, i64 noundef 5, [2 x i64] {{.*}})
121+
EXTERNC void f_S(long, struct S);
122+
EXTERNC void fm_S(long, long, long, long, long, struct S);
123+
EXTERNC void g_S() {
124+
struct S s = {6, 7};
125+
f_S(1, s);
126+
fm_S(1, 2, 3, 4, 5, s);
127+
}
128+
129+
// Aligned struct passed according to its natural alignment.
130+
struct __attribute__((aligned(16))) S16 {
131+
long x, y;
132+
};
133+
134+
// CHECK-LABEL: @g_S16(
135+
// DARWIN: call void @f_S16(i64 noundef 1, i128 {{.*}})
136+
// AAPCS: call void @f_S16(i64 noundef 1, [2 x i64] {{.*}})
137+
// DARWIN: call void @fm_S16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 noundef 4, i64 noundef 5, i128 {{.*}})
138+
// AAPCS: call void @fm_S16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 noundef 4, i64 noundef 5, [2 x i64] {{.*}})
139+
EXTERNC void f_S16(long, struct S16);
140+
EXTERNC void fm_S16(long, long, long, long, long, struct S16);
141+
EXTERNC void g_S16() {
142+
struct S16 s = {6, 7};
143+
f_S16(1, s);
144+
fm_S16(1, 2, 3, 4, 5, s);
145+
}
146+
147+
// Aligned struct with increased natural alignment through an aligned field.
148+
struct SF16 {
149+
__attribute__((aligned(16))) long x;
150+
long y;
151+
};
152+
153+
// CHECK-LABEL: @g_SF16(
154+
// DARWIN: call void @f_SF16(i64 noundef 1, i128 {{.*}})
155+
// AAPCS: call void @f_SF16(i64 noundef 1, i128 {{.*}})
156+
// DARWIN: call void @fm_SF16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 noundef 4, i64 noundef 5, i128 {{.*}})
157+
// AAPCS: call void @fm_SF16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 noundef 4, i64 noundef 5, i128 {{.*}})
158+
EXTERNC void f_SF16(long, struct SF16);
159+
EXTERNC void fm_SF16(long, long, long, long, long, struct SF16);
160+
EXTERNC void g_SF16() {
161+
struct SF16 s = {6, 7};
162+
f_SF16(1, s);
163+
fm_SF16(1, 2, 3, 4, 5, s);
164+
}
165+
166+
#ifdef __cplusplus
167+
// Aligned struct with increased natural alignment through an aligned base class.
168+
struct SB16 : S16 {};
169+
170+
// DARWIN-LABEL: @g_SB16(
171+
// CXX-LABEL: @g_SB16(
172+
// DARWIN: call void @f_SB16(i64 noundef 1, i128 {{.*}})
173+
// CXX: call void @f_SB16(i64 noundef 1, i128 {{.*}})
174+
// DARWIN: call void @fm_SB16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 noundef 4, i64 noundef 5, i128 {{.*}})
175+
// CXX: call void @fm_SB16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 noundef 4, i64 noundef 5, i128 {{.*}})
176+
EXTERNC void f_SB16(long, struct SB16);
177+
EXTERNC void fm_SB16(long, long, long, long, long, struct SB16);
178+
EXTERNC void g_SB16() {
179+
struct SB16 s = {6, 7};
180+
f_SB16(1, s);
181+
fm_SB16(1, 2, 3, 4, 5, s);
182+
}
183+
#endif
184+
185+
// Packed structure.
186+
struct __attribute__((packed)) SP {
187+
int x;
188+
long y;
189+
};
190+
191+
// CHECK-LABEL: @g_SP(
192+
// CHECK: call void @f_SP(i32 noundef 1, [2 x i64] {{.*}})
193+
// CHECK: call void @fm_SP(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, [2 x i64] {{.*}})
194+
EXTERNC void f_SP(int, struct SP);
195+
EXTERNC void fm_SP(int, int, int, int, int, struct SP);
196+
EXTERNC void g_SP() {
197+
struct SP s = {6, 7};
198+
f_SP(1, s);
199+
fm_SP(1, 2, 3, 4, 5, s);
200+
}
201+
202+
// Packed structure, overaligned, same as above.
203+
struct __attribute__((packed, aligned(16))) SP16 {
204+
int x;
205+
long y;
206+
};
207+
208+
// CHECK-LABEL: @g_SP16(
209+
// DARWIN: call void @f_SP16(i32 noundef 1, i128 {{.*}})
210+
// AAPCS: call void @f_SP16(i32 noundef 1, [2 x i64] {{.*}})
211+
// DARWIN: call void @fm_SP16(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, i128 {{.*}})
212+
// AAPCS: call void @fm_SP16(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, [2 x i64] {{.*}})
213+
EXTERNC void f_SP16(int, struct SP16);
214+
EXTERNC void fm_SP16(int, int, int, int, int, struct SP16);
215+
EXTERNC void g_SP16() {
216+
struct SP16 s = {6, 7};
217+
f_SP16(1, s);
218+
fm_SP16(1, 2, 3, 4, 5, s);
219+
}

clang/test/CodeGen/aapcs64-align.cpp

Lines changed: 0 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -12,101 +12,6 @@ extern "C" {
1212
// CHECK: @sizeof_RidiculouslyOverSizedBitfield ={{.*}} global i32 32
1313
// CHECK: @alignof_RidiculouslyOverSizedBitfield ={{.*}} global i32 16
1414

15-
// Base case, nothing interesting.
16-
struct S {
17-
long x, y;
18-
};
19-
20-
void f0(long, S);
21-
void f0m(long, long, long, long, long, S);
22-
void g0() {
23-
S s = {6, 7};
24-
f0(1, s);
25-
f0m(1, 2, 3, 4, 5, s);
26-
}
27-
// CHECK: define{{.*}} void @g0
28-
// CHECK: call void @f0(i64 noundef 1, [2 x i64] [i64 6, i64 7]
29-
// CHECK: call void @f0m{{.*}}[2 x i64] [i64 6, i64 7]
30-
// CHECK: declare void @f0(i64 noundef, [2 x i64])
31-
// CHECK: declare void @f0m(i64 noundef, i64 noundef, i64 noundef, i64 noundef, i64 noundef, [2 x i64])
32-
33-
// Aligned struct, passed according to its natural alignment.
34-
struct __attribute__((aligned(16))) S16 {
35-
long x, y;
36-
} s16;
37-
38-
void f1(long, S16);
39-
void f1m(long, long, long, long, long, S16);
40-
void g1() {
41-
S16 s = {6, 7};
42-
f1(1, s);
43-
f1m(1, 2, 3, 4, 5, s);
44-
}
45-
// CHECK: define{{.*}} void @g1
46-
// CHECK: call void @f1{{.*}}[2 x i64] [i64 6, i64 7]
47-
// CHECK: call void @f1m{{.*}}[2 x i64] [i64 6, i64 7]
48-
// CHECK: declare void @f1(i64 noundef, [2 x i64])
49-
// CHECK: declare void @f1m(i64 noundef, i64 noundef, i64 noundef, i64 noundef, i64 noundef, [2 x i64])
50-
51-
// Increased natural alignment.
52-
struct SF16 {
53-
long x __attribute__((aligned(16)));
54-
long y;
55-
};
56-
57-
void f3(long, SF16);
58-
void f3m(long, long, long, long, long, SF16);
59-
void g3() {
60-
SF16 s = {6, 7};
61-
f3(1, s);
62-
f3m(1, 2, 3, 4, 5, s);
63-
}
64-
// CHECK: define{{.*}} void @g3
65-
// CHECK: call void @f3(i64 noundef 1, i128 129127208515966861318)
66-
// CHECK: call void @f3m(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 noundef 4, i64 noundef 5, i128 129127208515966861318)
67-
// CHECK: declare void @f3(i64 noundef, i128)
68-
// CHECK: declare void @f3m(i64 noundef, i64 noundef, i64 noundef, i64 noundef, i64 noundef, i128)
69-
70-
71-
// Packed structure.
72-
struct __attribute__((packed)) P {
73-
int x;
74-
long u;
75-
};
76-
77-
void f4(int, P);
78-
void f4m(int, int, int, int, int, P);
79-
void g4() {
80-
P s = {6, 7};
81-
f4(1, s);
82-
f4m(1, 2, 3, 4, 5, s);
83-
}
84-
// CHECK: define{{.*}} void @g4()
85-
// CHECK: call void @f4(i32 noundef 1, [2 x i64] [i64 30064771078, i64 0])
86-
// CHECK: void @f4m(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, [2 x i64] [i64 30064771078, i64 0])
87-
// CHECK: declare void @f4(i32 noundef, [2 x i64])
88-
// CHECK: declare void @f4m(i32 noundef, i32 noundef, i32 noundef, i32 noundef, i32 noundef, [2 x i64])
89-
90-
91-
// Packed structure, overaligned, same as above.
92-
struct __attribute__((packed, aligned(16))) P16 {
93-
int x;
94-
long y;
95-
};
96-
97-
void f5(int, P16);
98-
void f5m(int, int, int, int, int, P16);
99-
void g5() {
100-
P16 s = {6, 7};
101-
f5(1, s);
102-
f5m(1, 2, 3, 4, 5, s);
103-
}
104-
// CHECK: define{{.*}} void @g5()
105-
// CHECK: call void @f5(i32 noundef 1, [2 x i64] [i64 30064771078, i64 0])
106-
// CHECK: void @f5m(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, [2 x i64] [i64 30064771078, i64 0])
107-
// CHECK: declare void @f5(i32 noundef, [2 x i64])
108-
// CHECK: declare void @f5m(i32 noundef, i32 noundef, i32 noundef, i32 noundef, i32 noundef, [2 x i64])
109-
11015
//BitInt alignment
11116
struct BITINT129 {
11217
char ch;

clang/test/CodeGen/arm-vfp16-arguments2.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ struct S5 : B1 {
4242
// CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.S1 @_Z2f12S1(%struct.S1 returned %s1.coerce)
4343
struct S1 f1(struct S1 s1) { return s1; }
4444

45-
// CHECK-SOFT: define{{.*}} void @_Z2f22S2(ptr dead_on_unwind noalias writable writeonly sret(%struct.S2) align 8 captures(none) initializes((0, 16)) %agg.result, [4 x i32] %s2.coerce)
45+
// CHECK-SOFT: define{{.*}} void @_Z2f22S2(ptr dead_on_unwind noalias writable writeonly sret(%struct.S2) align 8 captures(none) initializes((0, 16)) %agg.result, [2 x i64] %s2.coerce)
4646
// CHECK-HARD: define{{.*}} arm_aapcs_vfpcc [2 x <2 x i32>] @_Z2f22S2([2 x <2 x i32>] returned %s2.coerce)
4747
// CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.S2 @_Z2f22S2(%struct.S2 %s2.coerce)
4848
struct S2 f2(struct S2 s2) { return s2; }

0 commit comments

Comments
 (0)