Skip to content

Commit

Permalink
[LoongArch] Fix ABI mismatch with gcc/g++ about empty structs passing (
Browse files Browse the repository at this point in the history
…#70320)

How empty structs (not as fields of container struct) are passed in C++
is not explicitly documented in psABI. However, this patch fixes the
mismatch with g++.

Note that the unnamed bitfield case `struct { int : 1; }` in C is also
fixed. Previously clang regards it as an empty struct and then ignores
it when passing. Now size of the struct is counted; since it's size is
not 0, clang will not ignore it even in C.

While https://reviews.llvm.org/D156116 fixed the handling of empty
struct when considering eligibility of the container struct for the FP
calling convention ('flattening'), this patch fixes the handling of
passing the empty struct itself.

Fix #70319
  • Loading branch information
SixWeining authored Oct 31, 2023
1 parent 562ce8b commit 9ca6bf3
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 8 deletions.
10 changes: 6 additions & 4 deletions clang/lib/CodeGen/Targets/LoongArch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,14 @@ ABIArgInfo LoongArchABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
CGCXXABI::RAA_DirectInMemory);
}

// Ignore empty structs/unions.
if (isEmptyRecord(getContext(), Ty, true))
return ABIArgInfo::getIgnore();

uint64_t Size = getContext().getTypeSize(Ty);

// Ignore empty struct or union whose size is zero, e.g. `struct { }` in C or
// `struct { int a[0]; }` in C++. In C++, `struct { }` is empty but it's size
// is 1 byte and g++ doesn't ignore it; clang++ matches this behaviour.
if (isEmptyRecord(getContext(), Ty, true) && Size == 0)
return ABIArgInfo::getIgnore();

// Pass floating point values via FARs if possible.
if (IsFixed && Ty->isFloatingType() && !Ty->isComplexType() &&
FRLen >= Size && FARsLeft) {
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGen/LoongArch/abi-lp64d-empty-structs.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ struct s9 test_s9(struct s9 a) {
}

// CHECK-C: define{{.*}} void @test_s10()
// CHECK-CXX: define{{.*}} void @_Z8test_s103s10()
// CHECK-CXX: define{{.*}} i64 @_Z8test_s103s10(i64 {{.*}})
struct s10 { };
struct s10 test_s10(struct s10 a) {
return a;
Expand Down Expand Up @@ -128,14 +128,14 @@ struct s14 test_s14(struct s14 a) {
}

// CHECK-C: define{{.*}} void @test_s15()
// CHECK-CXX: define{{.*}} void @_Z8test_s153s15()
// CHECK-CXX: define{{.*}} i64 @_Z8test_s153s15(i64 {{.*}})
struct s15 { int : 0; };
struct s15 test_s15(struct s15 a) {
return a;
}

// CHECK-C: define{{.*}} void @test_s16()
// CHECK-CXX: define{{.*}} void @_Z8test_s163s16()
// CHECK-C: define{{.*}} i64 @test_s16(i64 {{.*}})
// CHECK-CXX: define{{.*}} i64 @_Z8test_s163s16(i64 {{.*}})
struct s16 { int : 1; };
struct s16 test_s16(struct s16 a) {
return a;
Expand Down

0 comments on commit 9ca6bf3

Please sign in to comment.