Skip to content

[LoongArch] Fix ABI mismatch with g++ when handling empty unions #71025

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 4, 2023

Conversation

SixWeining
Copy link
Contributor

In g++, empty unions are not ignored like empty structs when flattening structs to examine whether the structs can be passed via FARs in C++. This patch aligns clang++ with g++.

Fix #70890.

In g++, empty unions are not ignored like empty structs when flattening
structs to examine whether the structs can be passed via FARs in C++.
This patch aligns clang++ with g++.

Fix llvm#70890.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen IR generation bugs: mangling, exceptions, etc. backend:loongarch labels Nov 2, 2023
@llvmbot
Copy link
Member

llvmbot commented Nov 2, 2023

@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-clang

Author: Lu Weining (SixWeining)

Changes

In g++, empty unions are not ignored like empty structs when flattening structs to examine whether the structs can be passed via FARs in C++. This patch aligns clang++ with g++.

Fix #70890.


Full diff: https://github.com/llvm/llvm-project/pull/71025.diff

3 Files Affected:

  • (modified) clang/lib/CodeGen/Targets/LoongArch.cpp (+4-3)
  • (modified) clang/test/CodeGen/LoongArch/abi-lp64d-empty-structs.c (+1-1)
  • (modified) clang/test/CodeGen/LoongArch/abi-lp64d-empty-unions.c (+1-2)
diff --git a/clang/lib/CodeGen/Targets/LoongArch.cpp b/clang/lib/CodeGen/Targets/LoongArch.cpp
index c4d886eb40725f8..7b2c31139b0b2a3 100644
--- a/clang/lib/CodeGen/Targets/LoongArch.cpp
+++ b/clang/lib/CodeGen/Targets/LoongArch.cpp
@@ -170,10 +170,11 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper(
     // copy constructor are not eligible for the FP calling convention.
     if (getRecordArgABI(Ty, CGT.getCXXABI()))
       return false;
-    if (isEmptyRecord(getContext(), Ty, true, true))
-      return true;
     const RecordDecl *RD = RTy->getDecl();
-    // Unions aren't eligible unless they're empty (which is caught above).
+    if (isEmptyRecord(getContext(), Ty, true, true) &&
+        (!RD->isUnion() || !isa<CXXRecordDecl>(RD)))
+      return true;
+    // Unions aren't eligible unless they're empty in C (which is caught above).
     if (RD->isUnion())
       return false;
     const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
diff --git a/clang/test/CodeGen/LoongArch/abi-lp64d-empty-structs.c b/clang/test/CodeGen/LoongArch/abi-lp64d-empty-structs.c
index 281b7b15841a999..2f7596f0ebdc8be 100644
--- a/clang/test/CodeGen/LoongArch/abi-lp64d-empty-structs.c
+++ b/clang/test/CodeGen/LoongArch/abi-lp64d-empty-structs.c
@@ -3,7 +3,7 @@
 // RUN: %clang_cc1 -triple loongarch64 -target-feature +f -target-feature +d -target-abi lp64d -emit-llvm %s -o - -x c++ | \
 // RUN:   FileCheck --check-prefix=CHECK-CXX %s
 
-// Fields containing empty structs or unions are ignored when flattening
+// Fields containing empty structs are ignored when flattening
 // structs to examine whether the structs can be passed via FARs, even in C++.
 // But there is an exception that non-zero-length array of empty structures are
 // not ignored in C++. These rules are not documented in psABI <https://www.github.com/loongson/la-abi-specs>
diff --git a/clang/test/CodeGen/LoongArch/abi-lp64d-empty-unions.c b/clang/test/CodeGen/LoongArch/abi-lp64d-empty-unions.c
index b0607425336e285..363e37efb64691e 100644
--- a/clang/test/CodeGen/LoongArch/abi-lp64d-empty-unions.c
+++ b/clang/test/CodeGen/LoongArch/abi-lp64d-empty-unions.c
@@ -19,8 +19,7 @@ struct s1 {
 };
 
 // CHECK-C: define{{.*}} { i32, float } @test2(i32{{[^,]*}}, float{{[^,]*}})
-/// FIXME: This doesn't match g++.
-// CHECK-CXX: define{{.*}} { i32, float } @_Z5test22s1(i32{{[^,]*}}, float{{[^,]*}})
+// CHECK-CXX: define{{.*}} [2 x i64] @_Z5test22s1([2 x i64]{{[^,]*}})
 struct s1 test2(struct s1 a) {
   return a;
 }

@llvmbot
Copy link
Member

llvmbot commented Nov 2, 2023

@llvm/pr-subscribers-backend-loongarch

Author: Lu Weining (SixWeining)

Changes

In g++, empty unions are not ignored like empty structs when flattening structs to examine whether the structs can be passed via FARs in C++. This patch aligns clang++ with g++.

Fix #70890.


Full diff: https://github.com/llvm/llvm-project/pull/71025.diff

3 Files Affected:

  • (modified) clang/lib/CodeGen/Targets/LoongArch.cpp (+4-3)
  • (modified) clang/test/CodeGen/LoongArch/abi-lp64d-empty-structs.c (+1-1)
  • (modified) clang/test/CodeGen/LoongArch/abi-lp64d-empty-unions.c (+1-2)
diff --git a/clang/lib/CodeGen/Targets/LoongArch.cpp b/clang/lib/CodeGen/Targets/LoongArch.cpp
index c4d886eb40725f8..7b2c31139b0b2a3 100644
--- a/clang/lib/CodeGen/Targets/LoongArch.cpp
+++ b/clang/lib/CodeGen/Targets/LoongArch.cpp
@@ -170,10 +170,11 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper(
     // copy constructor are not eligible for the FP calling convention.
     if (getRecordArgABI(Ty, CGT.getCXXABI()))
       return false;
-    if (isEmptyRecord(getContext(), Ty, true, true))
-      return true;
     const RecordDecl *RD = RTy->getDecl();
-    // Unions aren't eligible unless they're empty (which is caught above).
+    if (isEmptyRecord(getContext(), Ty, true, true) &&
+        (!RD->isUnion() || !isa<CXXRecordDecl>(RD)))
+      return true;
+    // Unions aren't eligible unless they're empty in C (which is caught above).
     if (RD->isUnion())
       return false;
     const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
diff --git a/clang/test/CodeGen/LoongArch/abi-lp64d-empty-structs.c b/clang/test/CodeGen/LoongArch/abi-lp64d-empty-structs.c
index 281b7b15841a999..2f7596f0ebdc8be 100644
--- a/clang/test/CodeGen/LoongArch/abi-lp64d-empty-structs.c
+++ b/clang/test/CodeGen/LoongArch/abi-lp64d-empty-structs.c
@@ -3,7 +3,7 @@
 // RUN: %clang_cc1 -triple loongarch64 -target-feature +f -target-feature +d -target-abi lp64d -emit-llvm %s -o - -x c++ | \
 // RUN:   FileCheck --check-prefix=CHECK-CXX %s
 
-// Fields containing empty structs or unions are ignored when flattening
+// Fields containing empty structs are ignored when flattening
 // structs to examine whether the structs can be passed via FARs, even in C++.
 // But there is an exception that non-zero-length array of empty structures are
 // not ignored in C++. These rules are not documented in psABI <https://www.github.com/loongson/la-abi-specs>
diff --git a/clang/test/CodeGen/LoongArch/abi-lp64d-empty-unions.c b/clang/test/CodeGen/LoongArch/abi-lp64d-empty-unions.c
index b0607425336e285..363e37efb64691e 100644
--- a/clang/test/CodeGen/LoongArch/abi-lp64d-empty-unions.c
+++ b/clang/test/CodeGen/LoongArch/abi-lp64d-empty-unions.c
@@ -19,8 +19,7 @@ struct s1 {
 };
 
 // CHECK-C: define{{.*}} { i32, float } @test2(i32{{[^,]*}}, float{{[^,]*}})
-/// FIXME: This doesn't match g++.
-// CHECK-CXX: define{{.*}} { i32, float } @_Z5test22s1(i32{{[^,]*}}, float{{[^,]*}})
+// CHECK-CXX: define{{.*}} [2 x i64] @_Z5test22s1([2 x i64]{{[^,]*}})
 struct s1 test2(struct s1 a) {
   return a;
 }

@SixWeining
Copy link
Contributor Author

Hi @xen0n @xry111, please help to review this. Thanks.

@SixWeining SixWeining merged commit 4253fdc into llvm:main Nov 4, 2023
@SixWeining SixWeining deleted the union-abi branch November 4, 2023 02:04
leecheechen pushed a commit to leecheechen/llvm-project that referenced this pull request Jun 9, 2025
…m#71025)

In g++, empty unions are not ignored like empty structs when flattening
structs to examine whether the structs can be passed via FARs in C++.
This patch aligns clang++ with g++.

Fix llvm#70890.

(cherry picked from commit 4253fdc)
Change-Id: Ib9b0cc6e74f8e52ff394fc53b7fc9f4602d64096
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:loongarch clang:codegen IR generation bugs: mangling, exceptions, etc. clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[LoongArch] ABI mismtach between clang++ and g++ against empty union
3 participants