Skip to content

Commit d65f423

Browse files
authored
[RISCV] Handle empty structs/unions passing in C++ (#97315)
According to RISC-V integer calling convention empty structs or union arguments or return values are ignored by C compilers which support them as a non-standard extension. This is not the case for C++, which requires them to be sized types. Fixes #97285
1 parent f1905f0 commit d65f423

File tree

3 files changed

+61
-4
lines changed

3 files changed

+61
-4
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,7 @@ RISC-V Support
10841084

10851085
- ``__attribute__((rvv_vector_bits(N)))`` is now supported for RVV vbool*_t types.
10861086
- Profile names in ``-march`` option are now supported.
1087+
- Passing empty structs/unions as arguments in C++ is now handled correctly. The behavior is similar to GCC's.
10871088

10881089
CUDA/HIP Language Changes
10891090
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/CodeGen/Targets/RISCV.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -361,12 +361,13 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
361361
CGCXXABI::RAA_DirectInMemory);
362362
}
363363

364-
// Ignore empty structs/unions.
365-
if (isEmptyRecord(getContext(), Ty, true))
366-
return ABIArgInfo::getIgnore();
367-
368364
uint64_t Size = getContext().getTypeSize(Ty);
369365

366+
// Ignore empty structs/unions whose size is zero. According to the calling
367+
// convention empty structs/unions are required to be sized types in C++.
368+
if (isEmptyRecord(getContext(), Ty, true) && Size == 0)
369+
return ABIArgInfo::getIgnore();
370+
370371
// Pass floating point values via FPRs if possible.
371372
if (IsFixed && Ty->isFloatingType() && !Ty->isComplexType() &&
372373
FLen >= Size && ArgFPRsLeft) {

clang/test/CodeGen/RISCV/abi-empty-structs.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,61 @@ struct s9 {
167167
//
168168
void test_s9(struct s9 a) {}
169169

170+
struct s10 { };
171+
// CHECK-C-LABEL: define dso_local void @test_s10
172+
// CHECK-C-SAME: () #[[ATTR0]] {
173+
// CHECK-C: entry:
174+
//
175+
// CHECK32-CXX-LABEL: define dso_local i32 @_Z8test_s103s10
176+
// CHECK32-CXX-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
177+
// CHECK32-CXX: entry:
178+
//
179+
// CHECK64-CXX-LABEL: define dso_local i64 @_Z8test_s103s10
180+
// CHECK64-CXX-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
181+
// CHECK64-CXX: entry:
182+
//
183+
struct s10 test_s10(struct s10 a) {
184+
return a;
185+
}
186+
187+
struct s11 { int : 0; };
188+
// CHECK-C-LABEL: define dso_local void @test_s11
189+
// CHECK-C-SAME: () #[[ATTR0]] {
190+
// CHECK-C: entry:
191+
//
192+
// CHECK32-CXX-LABEL: define dso_local i32 @_Z8test_s113s11
193+
// CHECK32-CXX-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] {
194+
// CHECK32-CXX: entry:
195+
//
196+
// CHECK64-CXX-LABEL: define dso_local i64 @_Z8test_s113s11
197+
// CHECK64-CXX-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
198+
// CHECK64-CXX: entry:
199+
//
200+
struct s11 test_s11(struct s11 a) {
201+
return a;
202+
}
203+
204+
struct s12 {int x[0];};
205+
// CHECK32-C-LABEL: define dso_local i32 @test_s12
206+
// CHECK32-C-SAME: (i32 noundef [[I1:%.*]], i32 noundef [[I2:%.*]]) #[[ATTR0]] {
207+
// CHECK32-C: entry:
208+
//
209+
// CHECK64-C-LABEL: define dso_local signext i32 @test_s12
210+
// CHECK64-C-SAME: (i32 noundef signext [[I1:%.*]], i32 noundef signext [[I2:%.*]]) #[[ATTR0]] {
211+
// CHECK64-C: entry:
212+
//
213+
// CHECK32-CXX-LABEL: define dso_local noundef i32 @_Z8test_s12i3s12i
214+
// CHECK32-CXX-SAME: (i32 noundef [[I1:%.*]], i32 noundef [[I2:%.*]]) #[[ATTR0]] {
215+
// CHECK32-CXX: entry:
216+
//
217+
// CHECK64-CXX-LABEL: define dso_local noundef signext i32 @_Z8test_s12i3s12i
218+
// CHECK64-CXX-SAME: (i32 noundef signext [[I1:%.*]], i32 noundef signext [[I2:%.*]]) #[[ATTR0]] {
219+
// CHECK64-CXX: entry:
220+
//
221+
int test_s12(int32_t i1, struct s12 a, int32_t i2) {
222+
return i2;
223+
}
224+
170225
//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
171226
// CHECK32-C: {{.*}}
172227
// CHECK64-C: {{.*}}

0 commit comments

Comments
 (0)