Skip to content

[ARM, AArch64] Fix passing of structures with aligned base classes #18091

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
wants to merge 1 commit into
base: sycl
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions clang/include/clang/AST/RecordLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/RecordLayoutBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
111 changes: 109 additions & 2 deletions clang/test/CodeGen/AArch64/args.cpp
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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);
}
95 changes: 0 additions & 95 deletions clang/test/CodeGen/aapcs64-align.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/arm-vfp16-arguments2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down