diff options
author | Alex Bradbury <asb@igalia.com> | 2022-08-19 18:16:24 +0100 |
---|---|---|
committer | Tobias Hieta <tobias@hieta.se> | 2022-08-22 11:35:31 +0200 |
commit | 43fb0d7193ad13200db4048b3d266ecb8ba0fc2c (patch) | |
tree | ef5aaa83c94a18a0887e17545f608b4dd7a1d2eb /clang/lib | |
parent | 89be541e31b04b07298ea86922550b09b90a7d1a (diff) | |
download | llvm-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.cpp | 15 |
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()) { |