aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
authorAlex Bradbury <asb@igalia.com>2022-08-19 18:16:24 +0100
committerTobias Hieta <tobias@hieta.se>2022-08-22 11:35:31 +0200
commit43fb0d7193ad13200db4048b3d266ecb8ba0fc2c (patch)
treeef5aaa83c94a18a0887e17545f608b4dd7a1d2eb /clang/lib
parent89be541e31b04b07298ea86922550b09b90a7d1a (diff)
downloadllvm-43fb0d7193ad13200db4048b3d266ecb8ba0fc2c.zip
llvm-43fb0d7193ad13200db4048b3d266ecb8ba0fc2c.tar.gz
llvm-43fb0d7193ad13200db4048b3d266ecb8ba0fc2c.tar.bz2
[clang][RISCV] Fix incorrect ABI lowering for inherited structs under hard-float ABIs
The hard float ABIs have a rule that if a flattened struct contains either a single fp value, or an int+fp, or fp+fp then it may be passed in a pair of registers (if sufficient GPRs+FPRs are available). detectFPCCEligibleStruct and the helper it calls, detectFPCCEligibleStructHelper examine the type of the argument/return value to determine if it complies with the requirements for this ABI rule. As reported in bug #57084, this logic produces incorrect results for C++ structs that inherit from other structs. This is because only the fields of the struct were examined, but enumerating RD->fields misses any fields in inherited C++ structs. This patch corrects that issue by adding appropriate logic to enumerate any included base structs. Differential Revision: https://reviews.llvm.org/D131677 (cherry picked from commit bc538320809fb52af12ec0366118c82201af4f40)
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp15
1 files changed, 14 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 195ad8c..36e10e4df 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -11002,9 +11002,22 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff,
// Unions aren't eligible unless they're empty (which is caught above).
if (RD->isUnion())
return false;
+ const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
+ // If this is a C++ record, check the bases first.
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ for (const CXXBaseSpecifier &B : CXXRD->bases()) {
+ const auto *BDecl =
+ cast<CXXRecordDecl>(B.getType()->castAs<RecordType>()->getDecl());
+ CharUnits BaseOff = Layout.getBaseClassOffset(BDecl);
+ bool Ret = detectFPCCEligibleStructHelper(B.getType(), CurOff + BaseOff,
+ Field1Ty, Field1Off, Field2Ty,
+ Field2Off);
+ if (!Ret)
+ return false;
+ }
+ }
int ZeroWidthBitFieldCount = 0;
for (const FieldDecl *FD : RD->fields()) {
- const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
uint64_t FieldOffInBits = Layout.getFieldOffset(FD->getFieldIndex());
QualType QTy = FD->getType();
if (FD->isBitField()) {