Skip to content

Commit f0eef1b

Browse files
committed
Allow reverting ABI change with -fclang-abi-compat=20
1 parent 441052f commit f0eef1b

File tree

3 files changed

+19
-1
lines changed

3 files changed

+19
-1
lines changed

clang/include/clang/Basic/LangOptions.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,8 @@ class LangOptionsBase {
249249

250250
/// Attempt to be ABI-compatible with code generated by Clang 20.x.
251251
/// This causes clang to:
252-
/// - Nothing yet
252+
/// - Ignore empty struct arguments in C++ mode for AArch64, instead of
253+
/// passing them as if they had a size of 1 byte.
253254
Ver20,
254255

255256
/// Conform to the underlying platform's C and C++ ABIs as closely

clang/lib/CodeGen/Targets/ARM.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,11 @@ bool ARMABIInfo::shouldIgnoreEmptyArg(QualType Ty) const {
345345
if (Size == 0)
346346
return true;
347347

348+
// Clang 20.0 and earlier always ignored empty struct arguments in C++ mode.
349+
if (getContext().getLangOpts().getClangABICompat() <=
350+
LangOptions::ClangABI::Ver20)
351+
return true;
352+
348353
// Otherwise, they are passed as if they have a size of 1 byte.
349354
return false;
350355
}

clang/test/CodeGen/arm-empty-args.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - -x c %s | FileCheck %s --check-prefixes=CHECK,C
22
// RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,CXX
3+
// RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - %s -fclang-abi-compat=20 | FileCheck %s --check-prefixes=CHECK,CXXCLANG20
34
// RUN: %clang_cc1 -triple thumbv7k-apple-watchos2.0 -target-abi aapcs16 -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WATCHOS
45

56
// Empty structs are ignored for PCS purposes on WatchOS and in C mode
@@ -17,13 +18,15 @@ struct Empty {};
1718

1819
// C: define{{.*}} i32 @empty_arg(i32 noundef %a)
1920
// CXX: define{{.*}} i32 @empty_arg(i8 %e.coerce, i32 noundef %a)
21+
// CXXCLANG20: define{{.*}} i32 @empty_arg(i32 noundef %a)
2022
// WATCHOS: define{{.*}} i32 @empty_arg(i32 noundef %a)
2123
EXTERNC int empty_arg(struct Empty e, int a) {
2224
return a;
2325
}
2426

2527
// C: define{{.*}} void @empty_ret()
2628
// CXX: define{{.*}} void @empty_ret()
29+
// CXXCLANG20: define{{.*}} void @empty_ret()
2730
// WATCHOS: define{{.*}} void @empty_ret()
2831
EXTERNC struct Empty empty_ret(void) {
2932
struct Empty e;
@@ -40,6 +43,7 @@ struct SuperEmpty {
4043

4144
// C: define{{.*}} i32 @super_empty_arg(i32 noundef %a)
4245
// CXX: define{{.*}} i32 @super_empty_arg(i32 noundef %a)
46+
// CXXCLANG20: define{{.*}} i32 @super_empty_arg(i32 noundef %a)
4347
// WATCHOS: define{{.*}} i32 @super_empty_arg(i32 noundef %a)
4448
EXTERNC int super_empty_arg(struct SuperEmpty e, int a) {
4549
return a;
@@ -51,13 +55,15 @@ struct SortOfEmpty {
5155

5256
// C: define{{.*}} i32 @sort_of_empty_arg(i32 noundef %a)
5357
// CXX: define{{.*}} i32 @sort_of_empty_arg(i8 %e.coerce, i32 noundef %a)
58+
// CXXCLANG20: define{{.*}} i32 @sort_of_empty_arg(i32 noundef %a)
5459
// WATCHOS: define{{.*}} i32 @sort_of_empty_arg(i32 noundef %a)
5560
EXTERNC int sort_of_empty_arg(struct Empty e, int a) {
5661
return a;
5762
}
5863

5964
// C: define{{.*}} void @sort_of_empty_ret()
6065
// CXX: define{{.*}} void @sort_of_empty_ret()
66+
// CXXCLANG20: define{{.*}} void @sort_of_empty_ret()
6167
// WATCHOS: define{{.*}} void @sort_of_empty_ret()
6268
EXTERNC struct SortOfEmpty sort_of_empty_ret(void) {
6369
struct SortOfEmpty e;
@@ -76,6 +82,8 @@ EXTERNC int empty_arg_variadic(int a, ...) {
7682
// C-NOT: {{ getelementptr }}
7783
// CXX: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
7884
// CXX: %argp.next2 = getelementptr inbounds i8, ptr %argp.cur1, i32 4
85+
// CXXCLANG20: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
86+
// CXXCLANG20-NOT: {{ getelementptr }}
7987
// WATCHOS: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
8088
// WATCHOS-NOT: {{ getelementptr }}
8189
va_list vl;
@@ -92,6 +100,8 @@ EXTERNC int super_empty_arg_variadic(int a, ...) {
92100
// C-NOT: {{ getelementptr }}
93101
// CXX: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
94102
// CXX-NOT: {{ getelementptr }}
103+
// CXXCLANG20: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
104+
// CXXCLANG20-NOT: {{ getelementptr }}
95105
// WATCHOS: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
96106
// WATCHOS-NOT: {{ getelementptr }}
97107
va_list vl;
@@ -108,6 +118,8 @@ EXTERNC int sort_of_empty_arg_variadic(int a, ...) {
108118
// C-NOT: {{ getelementptr }}
109119
// CXX: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
110120
// CXX-NOT: {{ getelementptr }}
121+
// CXXCLANG20: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
122+
// CXXCLANG20-NOT: {{ getelementptr }}
111123
// WATCHOS: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
112124
// WATCHOS-NOT: {{ getelementptr }}
113125
va_list vl;

0 commit comments

Comments
 (0)