Author: Harald van Dijk
Date: 2025-04-18T02:11:02+01:00
New Revision: ca9ec7dfc3a5ebad9e5c25b30511b2ed73287f61

URL: 
https://github.com/llvm/llvm-project/commit/ca9ec7dfc3a5ebad9e5c25b30511b2ed73287f61
DIFF: 
https://github.com/llvm/llvm-project/commit/ca9ec7dfc3a5ebad9e5c25b30511b2ed73287f61.diff

LOG: [ARM, AArch64] Fix passing of structures with aligned base classes 
(#135564)

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.

Fixes #135551.

Added: 
    

Modified: 
    clang/include/clang/AST/RecordLayout.h
    clang/lib/AST/RecordLayoutBuilder.cpp
    clang/test/CodeGen/AArch64/args.cpp
    clang/test/CodeGen/aapcs64-align.cpp
    clang/test/CodeGen/arm-vfp16-arguments2.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/AST/RecordLayout.h 
b/clang/include/clang/AST/RecordLayout.h
index dd18f9c49f84f..6cf08e76396e2 100644
--- a/clang/include/clang/AST/RecordLayout.h
+++ b/clang/include/clang/AST/RecordLayout.h
@@ -75,8 +75,9 @@ class ASTRecordLayout {
   // performance or backwards compatibility preserving (e.g. AIX-ABI).
   CharUnits PreferredAlignment;
 
-  // UnadjustedAlignment - Maximum of the alignments of the record members in
-  // characters.
+  // UnadjustedAlignment - Alignment of record in characters before alignment
+  // adjustments. Maximum of the alignments of the record members and base
+  // classes in characters.
   CharUnits UnadjustedAlignment;
 
   /// RequiredAlignment - The required alignment of the object.  In the MS-ABI
@@ -186,7 +187,7 @@ class ASTRecordLayout {
   CharUnits getPreferredAlignment() const { return PreferredAlignment; }
 
   /// getUnadjustedAlignment - Get the record alignment in characters, before
-  /// alignment adjustement.
+  /// alignment adjustment.
   CharUnits getUnadjustedAlignment() const { return UnadjustedAlignment; }
 
   /// getSize - Get the record size in characters.

diff  --git a/clang/lib/AST/RecordLayoutBuilder.cpp 
b/clang/lib/AST/RecordLayoutBuilder.cpp
index ea353f88a8aec..dd932f6179f88 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -1302,6 +1302,7 @@ ItaniumRecordLayoutBuilder::LayoutBase(const 
BaseSubobjectInfo *Base) {
     setSize(std::max(getSize(), Offset + Layout.getSize()));
 
   // Remember max struct/class alignment.
+  UnadjustedAlignment = std::max(UnadjustedAlignment, BaseAlign);
   UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
 
   return Offset;

diff  --git a/clang/test/CodeGen/AArch64/args.cpp 
b/clang/test/CodeGen/AArch64/args.cpp
index 6f1f3d5e2a062..3cb62d3119ecf 100644
--- a/clang/test/CodeGen/AArch64/args.cpp
+++ b/clang/test/CodeGen/AArch64/args.cpp
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -triple arm64-apple-ios7.0 -target-abi darwinpcs -emit-llvm 
-o - %s | FileCheck %s --check-prefixes=CHECK,DARWIN
-// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - -x c %s | 
FileCheck %s --check-prefixes=CHECK,C
-// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - %s | FileCheck %s 
--check-prefixes=CHECK,CXX
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - -x c %s | 
FileCheck %s --check-prefixes=CHECK,C,AAPCS
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - %s | FileCheck %s 
--check-prefixes=CHECK,CXX,AAPCS
 
 // Empty structs are ignored for PCS purposes on Darwin and in C mode 
elsewhere.
 // 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, ...) {
   return b;
 }
 
+// Base case, nothing interesting.
+struct S {
+  long x, y;
+};
+
+// CHECK-LABEL: @g_S(
+// CHECK: call void @f_S(i64 noundef 1, [2 x i64] {{.*}})
+// CHECK: call void @fm_S(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 
noundef 4, i64 noundef 5, [2 x i64] {{.*}})
+EXTERNC void f_S(long, struct S);
+EXTERNC void fm_S(long, long, long, long, long, struct S);
+EXTERNC void g_S() {
+  struct S s = {6, 7};
+  f_S(1, s);
+  fm_S(1, 2, 3, 4, 5, s);
+}
+
+// Aligned struct passed according to its natural alignment.
+struct __attribute__((aligned(16))) S16 {
+  long x, y;
+};
+
+// CHECK-LABEL: @g_S16(
+// DARWIN: call void @f_S16(i64 noundef 1, i128 {{.*}})
+// AAPCS: call void @f_S16(i64 noundef 1, [2 x i64] {{.*}})
+// DARWIN: call void @fm_S16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 
noundef 4, i64 noundef 5, i128 {{.*}})
+// AAPCS: call void @fm_S16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 
noundef 4, i64 noundef 5, [2 x i64] {{.*}})
+EXTERNC void f_S16(long, struct S16);
+EXTERNC void fm_S16(long, long, long, long, long, struct S16);
+EXTERNC void g_S16() {
+  struct S16 s = {6, 7};
+  f_S16(1, s);
+  fm_S16(1, 2, 3, 4, 5, s);
+}
+
+// Aligned struct with increased natural alignment through an aligned field.
+struct SF16 {
+  __attribute__((aligned(16))) long x;
+  long y;
+};
+
+// CHECK-LABEL: @g_SF16(
+// DARWIN: call void @f_SF16(i64 noundef 1, i128 {{.*}})
+// AAPCS: call void @f_SF16(i64 noundef 1, i128 {{.*}})
+// DARWIN: call void @fm_SF16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 
noundef 4, i64 noundef 5, i128 {{.*}})
+// AAPCS: call void @fm_SF16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 
noundef 4, i64 noundef 5, i128 {{.*}})
+EXTERNC void f_SF16(long, struct SF16);
+EXTERNC void fm_SF16(long, long, long, long, long, struct SF16);
+EXTERNC void g_SF16() {
+  struct SF16 s = {6, 7};
+  f_SF16(1, s);
+  fm_SF16(1, 2, 3, 4, 5, s);
+}
+
+#ifdef __cplusplus
+// Aligned struct with increased natural alignment through an aligned base 
class.
+struct SB16 : S16 {};
+
+// DARWIN-LABEL: @g_SB16(
+// CXX-LABEL: @g_SB16(
+// DARWIN: call void @f_SB16(i64 noundef 1, i128 {{.*}})
+// CXX: call void @f_SB16(i64 noundef 1, i128 {{.*}})
+// DARWIN: call void @fm_SB16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 
noundef 4, i64 noundef 5, i128 {{.*}})
+// CXX: call void @fm_SB16(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 
noundef 4, i64 noundef 5, i128 {{.*}})
+EXTERNC void f_SB16(long, struct SB16);
+EXTERNC void fm_SB16(long, long, long, long, long, struct SB16);
+EXTERNC void g_SB16() {
+  struct SB16 s = {6, 7};
+  f_SB16(1, s);
+  fm_SB16(1, 2, 3, 4, 5, s);
+}
+#endif
+
+// Packed structure.
+struct  __attribute__((packed)) SP {
+  int x;
+  long y;
+};
+
+// CHECK-LABEL: @g_SP(
+// CHECK: call void @f_SP(i32 noundef 1, [2 x i64] {{.*}})
+// CHECK: call void @fm_SP(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 
noundef 4, i32 noundef 5, [2 x i64] {{.*}})
+EXTERNC void f_SP(int, struct SP);
+EXTERNC void fm_SP(int, int, int, int, int, struct SP);
+EXTERNC void g_SP() {
+  struct SP s = {6, 7};
+  f_SP(1, s);
+  fm_SP(1, 2, 3, 4, 5, s);
+}
+
+// Packed structure, overaligned, same as above.
+struct  __attribute__((packed, aligned(16))) SP16 {
+  int x;
+  long y;
+};
+
+// CHECK-LABEL: @g_SP16(
+// DARWIN: call void @f_SP16(i32 noundef 1, i128 {{.*}})
+// AAPCS: call void @f_SP16(i32 noundef 1, [2 x i64] {{.*}})
+// DARWIN: call void @fm_SP16(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 
noundef 4, i32 noundef 5, i128 {{.*}})
+// AAPCS: call void @fm_SP16(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 
noundef 4, i32 noundef 5, [2 x i64] {{.*}})
+EXTERNC void f_SP16(int, struct SP16);
+EXTERNC void fm_SP16(int, int, int, int, int, struct SP16);
+EXTERNC void g_SP16() {
+  struct SP16 s = {6, 7};
+  f_SP16(1, s);
+  fm_SP16(1, 2, 3, 4, 5, s);
+}

diff  --git a/clang/test/CodeGen/aapcs64-align.cpp 
b/clang/test/CodeGen/aapcs64-align.cpp
index e69faf231936c..1c26d68e434f4 100644
--- a/clang/test/CodeGen/aapcs64-align.cpp
+++ b/clang/test/CodeGen/aapcs64-align.cpp
@@ -12,101 +12,6 @@ extern "C" {
 // CHECK: @sizeof_RidiculouslyOverSizedBitfield ={{.*}} global i32 32
 // CHECK: @alignof_RidiculouslyOverSizedBitfield ={{.*}} global i32 16
 
-// Base case, nothing interesting.
-struct S {
-  long x, y;
-};
-
-void f0(long, S);
-void f0m(long, long, long, long, long, S);
-void g0() {
-  S s = {6, 7};
-  f0(1, s);
-  f0m(1, 2, 3, 4, 5, s);
-}
-// CHECK: define{{.*}} void @g0
-// CHECK: call void @f0(i64 noundef 1, [2 x i64] [i64 6, i64 7]
-// CHECK: call void @f0m{{.*}}[2 x i64] [i64 6, i64 7]
-// CHECK: declare void @f0(i64 noundef, [2 x i64])
-// CHECK: declare void @f0m(i64 noundef, i64 noundef, i64 noundef, i64 
noundef, i64 noundef, [2 x i64])
-
-// Aligned struct, passed according to its natural alignment.
-struct __attribute__((aligned(16))) S16 {
-  long x, y;
-} s16;
-
-void f1(long, S16);
-void f1m(long, long, long, long, long, S16);
-void g1() {
-  S16 s = {6, 7};
-  f1(1, s);
-  f1m(1, 2, 3, 4, 5, s);
-}
-// CHECK: define{{.*}} void @g1
-// CHECK: call void @f1{{.*}}[2 x i64] [i64 6, i64 7]
-// CHECK: call void @f1m{{.*}}[2 x i64] [i64 6, i64 7]
-// CHECK: declare void @f1(i64 noundef, [2 x i64])
-// CHECK: declare void @f1m(i64 noundef, i64 noundef, i64 noundef, i64 
noundef, i64 noundef, [2 x i64])
-
-// Increased natural alignment.
-struct SF16 {
-  long x __attribute__((aligned(16)));
-  long y;
-};
-
-void f3(long, SF16);
-void f3m(long, long, long, long, long, SF16);
-void g3() {
-  SF16 s = {6, 7};
-  f3(1, s);
-  f3m(1, 2, 3, 4, 5, s);
-}
-// CHECK: define{{.*}} void @g3
-// CHECK: call void @f3(i64 noundef 1, i128 129127208515966861318)
-// CHECK: call void @f3m(i64 noundef 1, i64 noundef 2, i64 noundef 3, i64 
noundef 4, i64 noundef 5, i128 129127208515966861318)
-// CHECK: declare void @f3(i64 noundef, i128)
-// CHECK: declare void @f3m(i64 noundef, i64 noundef, i64 noundef, i64 
noundef, i64 noundef, i128)
-
-
-// Packed structure.
-struct  __attribute__((packed)) P {
-  int x;
-  long u;
-};
-
-void f4(int, P);
-void f4m(int, int, int, int, int, P);
-void g4() {
-  P s = {6, 7};
-  f4(1, s);
-  f4m(1, 2, 3, 4, 5, s);
-}
-// CHECK: define{{.*}} void @g4()
-// CHECK: call void @f4(i32 noundef 1, [2 x i64] [i64 30064771078, i64 0])
-// 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])
-// CHECK: declare void @f4(i32 noundef, [2 x i64])
-// CHECK: declare void @f4m(i32 noundef, i32 noundef, i32 noundef, i32 
noundef, i32 noundef, [2 x i64])
-
-
-// Packed structure, overaligned, same as above.
-struct  __attribute__((packed, aligned(16))) P16 {
-  int x;
-  long y;
-};
-
-void f5(int, P16);
-void f5m(int, int, int, int, int, P16);
-  void g5() {
-    P16 s = {6, 7};
-    f5(1, s);
-    f5m(1, 2, 3, 4, 5, s);
-}
-// CHECK: define{{.*}} void @g5()
-// CHECK: call void @f5(i32 noundef 1, [2 x i64] [i64 30064771078, i64 0])
-// 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])
-// CHECK: declare void @f5(i32 noundef, [2 x i64])
-// CHECK: declare void @f5m(i32 noundef, i32 noundef, i32 noundef, i32 
noundef, i32 noundef, [2 x i64])
-
 //BitInt alignment
 struct BITINT129 {
     char ch;

diff  --git a/clang/test/CodeGen/arm-vfp16-arguments2.cpp 
b/clang/test/CodeGen/arm-vfp16-arguments2.cpp
index 6e9a24e70c141..7273f64effa92 100644
--- a/clang/test/CodeGen/arm-vfp16-arguments2.cpp
+++ b/clang/test/CodeGen/arm-vfp16-arguments2.cpp
@@ -42,7 +42,7 @@ struct S5 : B1 {
 // CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.S1 @_Z2f12S1(%struct.S1 
returned %s1.coerce)
 struct S1 f1(struct S1 s1) { return s1; }
 
-// 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)
+// 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)
 // CHECK-HARD: define{{.*}} arm_aapcs_vfpcc [2 x <2 x i32>] @_Z2f22S2([2 x <2 
x i32>] returned %s2.coerce)
 // CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.S2 @_Z2f22S2(%struct.S2 
%s2.coerce)
 struct S2 f2(struct S2 s2) { return s2; }


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to