Skip to content

Commit

Permalink
Push record return type classification into CGCXXABI
Browse files Browse the repository at this point in the history
In the Microsoft C++ ABI, instance methods always return records
indirectly via the second hidden parameter.  This was implemented in
X86_32ABIInfo, but not WinX86_64ABIInfo.

Rather than exposing a handful of boolean methods in the CGCXXABI
interface, we can expose a single method that applies C++ ABI return
value classification rules.

llvm-svn: 208733
  • Loading branch information
rnk committed May 13, 2014
1 parent b4892cd commit 40ca913
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 114 deletions.
5 changes: 3 additions & 2 deletions clang/lib/CodeGen/CGCXXABI.h
Expand Up @@ -93,8 +93,9 @@ class CGCXXABI {
/// when called virtually, and code generation does not support the case.
virtual bool HasThisReturn(GlobalDecl GD) const { return false; }

/// Returns true if the given record type should be returned indirectly.
virtual bool isReturnTypeIndirect(const CXXRecordDecl *RD) const = 0;
/// If the C++ ABI requires the given type be returned in a particular way,
/// this method sets RetAI and returns true.
virtual bool classifyReturnType(CGFunctionInfo &FI) const = 0;

/// Specify how one should pass an argument of a record type.
enum RecordArgABI {
Expand Down
21 changes: 16 additions & 5 deletions clang/lib/CodeGen/ItaniumCXXABI.cpp
Expand Up @@ -52,11 +52,7 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
UseARMGuardVarABI(UseARMGuardVarABI) { }

bool isReturnTypeIndirect(const CXXRecordDecl *RD) const override {
// Structures with either a non-trivial destructor or a non-trivial
// copy constructor are always indirect.
return !RD->hasTrivialDestructor() || RD->hasNonTrivialCopyConstructor();
}
bool classifyReturnType(CGFunctionInfo &FI) const override;

RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override {
// Structures with either a non-trivial destructor or a non-trivial
Expand Down Expand Up @@ -761,6 +757,21 @@ ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
return Result;
}

bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl();
if (!RD)
return false;

// Return indirectly if we have a non-trivial copy ctor or non-trivial dtor.
if (RD->hasNonTrivialDestructor() || RD->hasNonTrivialCopyConstructor()) {
FI.getReturnInfo() = ABIArgInfo::getIndirect(0, /*ByVal=*/false);
return true;
}

// Otherwise, use the normal C ABI rules.
return false;
}

/// The Itanium ABI requires non-zero initialization only for data
/// member pointers, for which '0' is a valid offset.
bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
Expand Down
26 changes: 22 additions & 4 deletions clang/lib/CodeGen/MicrosoftCXXABI.cpp
Expand Up @@ -39,10 +39,7 @@ class MicrosoftCXXABI : public CGCXXABI {

bool HasThisReturn(GlobalDecl GD) const override;

bool isReturnTypeIndirect(const CXXRecordDecl *RD) const override {
// Structures that are not C++03 PODs are always indirect.
return !RD->isPOD();
}
bool classifyReturnType(CGFunctionInfo &FI) const override;

RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override;

Expand Down Expand Up @@ -459,6 +456,27 @@ bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const {
return isa<CXXConstructorDecl>(GD.getDecl());
}

bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl();
if (!RD)
return false;

if (FI.isInstanceMethod()) {
// If it's an instance method, aggregates are always returned indirectly via
// the second parameter.
FI.getReturnInfo() = ABIArgInfo::getIndirect(0, /*ByVal=*/false);
FI.getReturnInfo().setSRetAfterThis(FI.isInstanceMethod());
return true;
} else if (!RD->isPOD()) {
// If it's a free function, non-POD types are returned indirectly.
FI.getReturnInfo() = ABIArgInfo::getIndirect(0, /*ByVal=*/false);
return true;
}

// Otherwise, use the C ABI rules.
return false;
}

void MicrosoftCXXABI::BuildConstructorSignature(
const CXXConstructorDecl *Ctor, CXXCtorType Type, CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) {
Expand Down

0 comments on commit 40ca913

Please sign in to comment.