asb created this revision.
asb added reviewers: kito-cheng, reames, jrtc27, craig.topper, luke.
Herald added subscribers: wingo, pmatos, VincentWu, vkmr, frasercrmck, evandro, 
luismarques, apazos, sameer.abuasal, s.egerton, Jim, benna, psnobl, jocewei, 
PkmX, the_o, brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, 
shiva0217, niosHD, sabuasal, simoncook, johnrusso, rbar, arichardson.
Herald added a project: All.
asb requested review of this revision.
Herald added subscribers: cfe-commits, pcwang-thead, eopXD, MaskRay.
Herald added a project: clang.

As reported in https://github.com/llvm/llvm-project/issues/58929, Clang 
currently differs from GCC in the handling of empty structs. This commit adds 
some test coverage for the handling of such structs.

Posting for review rather than committing directly because more eyes on our 
test coverage for in these areas would be useful.

A follow-up patch implements a fix to match g++.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142326

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

Index: clang/test/CodeGen/RISCV/abi-empty-structs.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/RISCV/abi-empty-structs.c
@@ -0,0 +1,141 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --filter "^define |^entry:"
+// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \
+// RUN:   | FileCheck -check-prefixes=CHECK-C,CHECK32-C %s
+// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \
+// RUN:   | FileCheck -check-prefixes=CHECK-C,CHECK32-C
+// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm %s -o - \
+// RUN:   | FileCheck -check-prefixes=CHECK-C,CHECK64-C %s
+// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d -target-abi lp64d -emit-llvm %s -o - \
+// RUN:   | FileCheck -check-prefixes=CHECK-C,CHECK64-C
+// RUN: %clang_cc1 -x c++ -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \
+// RUN:   | FileCheck -check-prefixes=CHECK-CXX,CHECK32-CXX %s
+// RUN: %clang_cc1 -x c++ -triple riscv32 -target-feature +f -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \
+// RUN:   | FileCheck -check-prefixes=CHECK-CXX,CHECK32-CXX
+// RUN: %clang_cc1 -x c++ -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm %s -o - \
+// RUN:   | FileCheck -check-prefixes=CHECK-CXX,CHECK64-CXX %s
+// RUN: %clang_cc1 -x c++ -triple riscv64 -target-feature +f -target-feature +d -target-abi lp64d -emit-llvm %s -o - \
+// RUN:   | FileCheck -check-prefixes=CHECK-CXX,CHECK64-CXX
+
+#include <stdint.h>
+
+// Fields containing empty structs or unions are ignored when flattening
+// structs for the hard FP ABIs, even in C++.
+// FIXME: This isn't currently respected.
+
+struct empty { struct { struct { } e; }; };
+struct s1 { struct empty e; float f; };
+
+// CHECK-C-LABEL: define dso_local float @test_s1
+// CHECK-C-SAME: (float [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-C:  entry:
+//
+// CHECK32-CXX-LABEL: define dso_local [2 x i32] @_Z7test_s12s1
+// CHECK32-CXX-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK32-CXX:  entry:
+//
+// CHECK64-CXX-LABEL: define dso_local i64 @_Z7test_s12s1
+// CHECK64-CXX-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK64-CXX:  entry:
+//
+struct s1 test_s1(struct s1 a) {
+  return a;
+}
+
+struct s2 { struct empty e; int32_t i; float f; };
+
+// CHECK-C-LABEL: define dso_local { i32, float } @test_s2
+// CHECK-C-SAME: (i32 [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
+// CHECK-C:  entry:
+//
+// CHECK32-CXX-LABEL: define dso_local void @_Z7test_s22s2
+// CHECK32-CXX-SAME: (ptr noalias sret([[STRUCT_S2:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK32-CXX:  entry:
+//
+// CHECK64-CXX-LABEL: define dso_local [2 x i64] @_Z7test_s22s2
+// CHECK64-CXX-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK64-CXX:  entry:
+//
+struct s2 test_s2(struct s2 a) {
+  return a;
+}
+
+struct s3 { struct empty e; float f; float g; };
+
+// CHECK-C-LABEL: define dso_local { float, float } @test_s3
+// CHECK-C-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
+// CHECK-C:  entry:
+//
+// CHECK32-CXX-LABEL: define dso_local void @_Z7test_s32s3
+// CHECK32-CXX-SAME: (ptr noalias sret([[STRUCT_S3:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK32-CXX:  entry:
+//
+// CHECK64-CXX-LABEL: define dso_local [2 x i64] @_Z7test_s32s3
+// CHECK64-CXX-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK64-CXX:  entry:
+//
+struct s3 test_s3(struct s3 a) {
+  return a;
+}
+
+struct s4 { struct empty e; float __complex__ c; };
+
+// CHECK-C-LABEL: define dso_local { float, float } @test_s4
+// CHECK-C-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] {
+// CHECK-C:  entry:
+//
+// CHECK32-CXX-LABEL: define dso_local void @_Z7test_s42s4
+// CHECK32-CXX-SAME: (ptr noalias sret([[STRUCT_S4:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]]) #[[ATTR0]] {
+// CHECK32-CXX:  entry:
+//
+// CHECK64-CXX-LABEL: define dso_local [2 x i64] @_Z7test_s42s4
+// CHECK64-CXX-SAME: ([2 x i64] [[A_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK64-CXX:  entry:
+//
+struct s4 test_s4(struct s4 a) {
+  return a;
+}
+
+// An array of empty fields isn't ignored in C++ (this isn't explicit in the
+// psABI, but matches observed g++ behaviour).
+
+struct s5 { struct empty e[1]; float f; };
+
+// CHECK-C-LABEL: define dso_local float @test_s5
+// CHECK-C-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {
+// CHECK-C:  entry:
+//
+// CHECK32-CXX-LABEL: define dso_local [2 x i32] @_Z7test_s52s5
+// CHECK32-CXX-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK32-CXX:  entry:
+//
+// CHECK64-CXX-LABEL: define dso_local i64 @_Z7test_s52s5
+// CHECK64-CXX-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK64-CXX:  entry:
+//
+struct s5 test_s5(struct s5 a) {
+  return a;
+}
+
+struct empty_arr { struct { struct { } e[1]; }; };
+struct s6 { struct empty_arr e; float f; };
+
+// CHECK-C-LABEL: define dso_local float @test_s6
+// CHECK-C-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] {
+// CHECK-C:  entry:
+//
+// CHECK32-CXX-LABEL: define dso_local [2 x i32] @_Z7test_s62s6
+// CHECK32-CXX-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK32-CXX:  entry:
+//
+// CHECK64-CXX-LABEL: define dso_local i64 @_Z7test_s62s6
+// CHECK64-CXX-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] {
+// CHECK64-CXX:  entry:
+//
+struct s6 test_s6(struct s6 a) {
+  return a;
+}
+
+//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+// CHECK-CXX: {{.*}}
+// CHECK32-C: {{.*}}
+// CHECK64-C: {{.*}}
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to