diff options
author | Alex Bradbury <asb@igalia.com> | 2022-08-19 18:16:24 +0100 |
---|---|---|
committer | Alex Bradbury <asb@igalia.com> | 2022-08-19 20:31:06 +0100 |
commit | bc538320809fb52af12ec0366118c82201af4f40 (patch) | |
tree | fd7d274e5696194593a8f38830ad085b8460dad1 /clang/lib/CodeGen/TargetInfo.cpp | |
parent | ac6a0cdc2e85d69ec20fd31d29f30843db0943bd (diff) | |
download | llvm-bc538320809fb52af12ec0366118c82201af4f40.zip llvm-bc538320809fb52af12ec0366118c82201af4f40.tar.gz llvm-bc538320809fb52af12ec0366118c82201af4f40.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
Diffstat (limited to 'clang/lib/CodeGen/TargetInfo.cpp')
-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 39871b0..1f9c903 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -10979,9 +10979,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()) { |