diff options
Diffstat (limited to 'lib/CodeGen')
| -rw-r--r-- | lib/CodeGen/CGCXXABI.cpp | 31 | ||||
| -rw-r--r-- | lib/CodeGen/ItaniumCXXABI.cpp | 13 | ||||
| -rw-r--r-- | lib/CodeGen/MicrosoftCXXABI.cpp | 52 | 
3 files changed, 30 insertions, 66 deletions
| diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp index e29e525edd24..033258643ddf 100644 --- a/lib/CodeGen/CGCXXABI.cpp +++ b/lib/CodeGen/CGCXXABI.cpp @@ -30,38 +30,9 @@ void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) {  }  bool CGCXXABI::canCopyArgument(const CXXRecordDecl *RD) const { -  // If RD has a non-trivial move or copy constructor, we cannot copy the -  // argument. -  if (RD->hasNonTrivialCopyConstructor() || RD->hasNonTrivialMoveConstructor()) -    return false; - -  // If RD has a non-trivial destructor, we cannot copy the argument. -  if (RD->hasNonTrivialDestructor()) -    return false; -    // We can only copy the argument if there exists at least one trivial,    // non-deleted copy or move constructor. -  // FIXME: This assumes that all lazily declared copy and move constructors are -  // not deleted.  This assumption might not be true in some corner cases. -  bool CopyDeleted = false; -  bool MoveDeleted = false; -  for (const CXXConstructorDecl *CD : RD->ctors()) { -    if (CD->isCopyConstructor() || CD->isMoveConstructor()) { -      assert(CD->isTrivial()); -      // We had at least one undeleted trivial copy or move ctor.  Return -      // directly. -      if (!CD->isDeleted()) -        return true; -      if (CD->isCopyConstructor()) -        CopyDeleted = true; -      else -        MoveDeleted = true; -    } -  } - -  // If all trivial copy and move constructors are deleted, we cannot copy the -  // argument. -  return !(CopyDeleted && MoveDeleted); +  return RD->canPassInRegisters();  }  llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) { diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index c82b9677eacf..e7963674fc29 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -63,11 +63,8 @@ public:    bool classifyReturnType(CGFunctionInfo &FI) const override;    RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override { -    // Structures with either a non-trivial destructor or a non-trivial -    // copy constructor are always indirect. -    // FIXME: Use canCopyArgument() when it is fixed to handle lazily declared -    // special members. -    if (RD->hasNonTrivialDestructor() || RD->hasNonTrivialCopyConstructor()) +    // If C++ prohibits us from making a copy, pass by address. +    if (!canCopyArgument(RD))        return RAA_Indirect;      return RAA_Default;    } @@ -998,10 +995,8 @@ bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI) const {    if (!RD)      return false; -  // Return indirectly if we have a non-trivial copy ctor or non-trivial dtor. -  // FIXME: Use canCopyArgument() when it is fixed to handle lazily declared -  // special members. -  if (RD->hasNonTrivialDestructor() || RD->hasNonTrivialCopyConstructor()) { +  // If C++ prohibits us from making a copy, return by address. +  if (!canCopyArgument(RD)) {      auto Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());      FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);      return true; diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 78b510bb4665..1bd2937e4747 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -819,46 +819,44 @@ MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const {      return RAA_Default;    case llvm::Triple::x86_64: -    // Win64 passes objects with non-trivial copy ctors indirectly. -    if (RD->hasNonTrivialCopyConstructor()) -      return RAA_Indirect; - -    // If an object has a destructor, we'd really like to pass it indirectly +    // If a class has a destructor, we'd really like to pass it indirectly      // because it allows us to elide copies.  Unfortunately, MSVC makes that      // impossible for small types, which it will pass in a single register or      // stack slot. Most objects with dtors are large-ish, so handle that early.      // We can't call out all large objects as being indirect because there are      // multiple x64 calling conventions and the C++ ABI code shouldn't dictate      // how we pass large POD types. +    // +    // Note: This permits small classes with nontrivial destructors to be +    // passed in registers, which is non-conforming.      if (RD->hasNonTrivialDestructor() &&          getContext().getTypeSize(RD->getTypeForDecl()) > 64)        return RAA_Indirect; -    // If this is true, the implicit copy constructor that Sema would have -    // created would not be deleted. FIXME: We should provide a more direct way -    // for CodeGen to ask whether the constructor was deleted. -    if (!RD->hasUserDeclaredCopyConstructor() && -        !RD->hasUserDeclaredMoveConstructor() && -        !RD->needsOverloadResolutionForMoveConstructor() && -        !RD->hasUserDeclaredMoveAssignment() && -        !RD->needsOverloadResolutionForMoveAssignment()) -      return RAA_Default; - -    // Otherwise, Sema should have created an implicit copy constructor if -    // needed. -    assert(!RD->needsImplicitCopyConstructor()); - -    // We have to make sure the trivial copy constructor isn't deleted. -    for (const CXXConstructorDecl *CD : RD->ctors()) { -      if (CD->isCopyConstructor()) { -        assert(CD->isTrivial()); -        // We had at least one undeleted trivial copy ctor.  Return directly. -        if (!CD->isDeleted()) -          return RAA_Default; +    // If a class has at least one non-deleted, trivial copy constructor, it +    // is passed according to the C ABI. Otherwise, it is passed indirectly. +    // +    // Note: This permits classes with non-trivial copy or move ctors to be +    // passed in registers, so long as they *also* have a trivial copy ctor, +    // which is non-conforming. +    if (RD->needsImplicitCopyConstructor()) { +      // If the copy ctor has not yet been declared, we can read its triviality +      // off the AST. +      if (!RD->defaultedCopyConstructorIsDeleted() && +          RD->hasTrivialCopyConstructor()) +        return RAA_Default; +    } else { +      // Otherwise, we need to find the copy constructor(s) and ask. +      for (const CXXConstructorDecl *CD : RD->ctors()) { +        if (CD->isCopyConstructor()) { +          // We had at least one nondeleted trivial copy ctor.  Return directly. +          if (!CD->isDeleted() && CD->isTrivial()) +            return RAA_Default; +        }        }      } -    // The trivial copy constructor was deleted.  Return indirectly. +    // We have no trivial, non-deleted copy constructor.      return RAA_Indirect;    } | 
