diff options
author | David Majnemer <david.majnemer@gmail.com> | 2015-03-11 18:36:39 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2015-03-11 18:36:39 +0000 |
commit | dfa6d2067c8c782c83be69a61fe59a0240535df6 (patch) | |
tree | 6223cf5bbe42de63a13b9301deb125b41e56de86 /clang/lib/AST | |
parent | 4320495319466c12543985ff7e653aedf81f8f36 (diff) | |
download | bcm5719-llvm-dfa6d2067c8c782c83be69a61fe59a0240535df6.tar.gz bcm5719-llvm-dfa6d2067c8c782c83be69a61fe59a0240535df6.zip |
MS ABI: Implement copy-ctor closures, finish implementing throw
This adds support for copy-constructor closures. These are generated
when the C++ runtime has to call a copy-constructor with a particular
calling convention or with default arguments substituted in to the call.
Because the runtime has no mechanism to call the function with a
different calling convention or know-how to evaluate the default
arguments at run-time, we create a thunk which will do all the
appropriate work and package it in a way the runtime can use.
Differential Revision: http://reviews.llvm.org/D8225
llvm-svn: 231952
Diffstat (limited to 'clang/lib/AST')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 12 | ||||
-rw-r--r-- | clang/lib/AST/CXXABI.h | 7 | ||||
-rw-r--r-- | clang/lib/AST/ItaniumCXXABI.cpp | 8 | ||||
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 3 | ||||
-rw-r--r-- | clang/lib/AST/MicrosoftCXXABI.cpp | 12 | ||||
-rw-r--r-- | clang/lib/AST/MicrosoftMangle.cpp | 89 |
6 files changed, 113 insertions, 18 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 20d2aa68187..e92b33509f7 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -8210,6 +8210,18 @@ void ASTContext::addCopyConstructorForExceptionObject(CXXRecordDecl *RD, cast<CXXConstructorDecl>(CD->getFirstDecl())); } +void ASTContext::addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, + unsigned ParmIdx, Expr *DAE) { + ABI->addDefaultArgExprForConstructor( + cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx, DAE); +} + +Expr *ASTContext::getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, + unsigned ParmIdx) { + return ABI->getDefaultArgExprForConstructor( + cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx); +} + void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) { ParamIndices[D] = index; } diff --git a/clang/lib/AST/CXXABI.h b/clang/lib/AST/CXXABI.h index 62c96f901e6..dad226474fa 100644 --- a/clang/lib/AST/CXXABI.h +++ b/clang/lib/AST/CXXABI.h @@ -21,6 +21,7 @@ namespace clang { class ASTContext; class CXXConstructorDecl; +class Expr; class MemberPointerType; class MangleNumberingContext; @@ -50,6 +51,12 @@ public: /// Retrieves the mapping from class to copy constructor for this C++ ABI. virtual const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *) = 0; + + virtual void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, + unsigned ParmIdx, Expr *DAE) = 0; + + virtual Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, + unsigned ParmIdx) = 0; }; /// Creates an instance of a C++ ABI class. diff --git a/clang/lib/AST/ItaniumCXXABI.cpp b/clang/lib/AST/ItaniumCXXABI.cpp index 13d4dbf1f46..74207820b3a 100644 --- a/clang/lib/AST/ItaniumCXXABI.cpp +++ b/clang/lib/AST/ItaniumCXXABI.cpp @@ -141,6 +141,14 @@ public: void addCopyConstructorForExceptionObject(CXXRecordDecl *RD, CXXConstructorDecl *CD) override {} + void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, + unsigned ParmIdx, Expr *DAE) override {} + + Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, + unsigned ParmIdx) override { + return nullptr; + } + MangleNumberingContext *createMangleNumberingContext() const override { return new ItaniumNumberingContext(); } diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 13136b36236..f890719c209 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -3442,6 +3442,9 @@ void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) { case Ctor_Comdat: Out << "C5"; break; + case Ctor_DefaultClosure: + case Ctor_CopyingClosure: + llvm_unreachable("closure constructors don't exist for the Itanium ABI!"); } } diff --git a/clang/lib/AST/MicrosoftCXXABI.cpp b/clang/lib/AST/MicrosoftCXXABI.cpp index 71b21bff77c..fb3beff4beb 100644 --- a/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/clang/lib/AST/MicrosoftCXXABI.cpp @@ -64,6 +64,8 @@ public: class MicrosoftCXXABI : public CXXABI { ASTContext &Context; llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor; + llvm::SmallDenseMap<std::pair<const CXXConstructorDecl *, unsigned>, Expr *> + CtorToDefaultArgExpr; public: MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { } @@ -92,6 +94,16 @@ public: Layout.getNonVirtualSize() == PointerSize * 2; } + void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, + unsigned ParmIdx, Expr *DAE) override { + CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)] = DAE; + } + + Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, + unsigned ParmIdx) override { + return CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)]; + } + const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override { return RecordToCopyCtor[RD]; diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 073e798d11f..f56da26a09b 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -67,11 +67,15 @@ static const DeclContext *getEffectiveParentContext(const DeclContext *DC) { return getEffectiveDeclContext(cast<Decl>(DC)); } -static const FunctionDecl *getStructor(const FunctionDecl *fn) { - if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate()) - return ftd->getTemplatedDecl(); +static const FunctionDecl *getStructor(const NamedDecl *ND) { + if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND)) + return FTD->getTemplatedDecl(); - return fn; + const auto *FD = cast<FunctionDecl>(ND); + if (const auto *FTD = FD->getPrimaryTemplate()) + return FTD->getTemplatedDecl(); + + return FD; } static bool isLambda(const NamedDecl *ND) { @@ -115,7 +119,7 @@ public: void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries, raw_ostream &Out) override; void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD, - uint32_t Size, uint32_t NVOffset, + CXXCtorType CT, uint32_t Size, uint32_t NVOffset, int32_t VBPtrOffset, uint32_t VBIndex, raw_ostream &Out) override; void mangleCXXRTTI(QualType T, raw_ostream &Out) override; @@ -224,6 +228,12 @@ public: 64) {} MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_, + const CXXConstructorDecl *D, CXXCtorType Type) + : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), + PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) == + 64) {} + + MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_, const CXXDestructorDecl *D, CXXDtorType Type) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) == @@ -284,6 +294,7 @@ private: void mangleDecayedArrayType(const ArrayType *T); void mangleArrayType(const ArrayType *T); void mangleFunctionClass(const FunctionDecl *FD); + void mangleCallingConvention(CallingConv CC); void mangleCallingConvention(const FunctionType *T); void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean); void mangleExpression(const Expr *E); @@ -770,12 +781,18 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, llvm_unreachable("Can't mangle Objective-C selector names here!"); case DeclarationName::CXXConstructorName: - if (ND == Structor) { - assert(StructorType == Ctor_Complete && - "Should never be asked to mangle a ctor other than complete"); + if (Structor == getStructor(ND)) { + if (StructorType == Ctor_CopyingClosure) { + Out << "?_O"; + return; + } + if (StructorType == Ctor_DefaultClosure) { + Out << "?_F"; + return; + } } Out << "?0"; - break; + return; case DeclarationName::CXXDestructorName: if (ND == Structor) @@ -1566,12 +1583,22 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, SourceRange Range; if (D) Range = D->getSourceRange(); - bool IsStructor = false, HasThisQuals = ForceThisQuals; + bool IsStructor = false, HasThisQuals = ForceThisQuals, IsCtorClosure = false; + CallingConv CC = T->getCallConv(); if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(D)) { if (MD->isInstance()) HasThisQuals = true; - if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) + if (isa<CXXDestructorDecl>(MD)) { + IsStructor = true; + } else if (isa<CXXConstructorDecl>(MD)) { IsStructor = true; + IsCtorClosure = (StructorType == Ctor_CopyingClosure || + StructorType == Ctor_DefaultClosure) && + getStructor(MD) == Structor; + if (IsCtorClosure) + CC = getASTContext().getDefaultCallingConvention( + /*IsVariadic=*/false, /*IsCXXMethod=*/true); + } } // If this is a C++ instance method, mangle the CVR qualifiers for the @@ -1583,7 +1610,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, mangleQualifiers(Quals, /*IsMember=*/false); } - mangleCallingConvention(T); + mangleCallingConvention(CC); // <return-type> ::= <type> // ::= @ # structors (they have no declared return type) @@ -1597,6 +1624,28 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, Out << (PointersAre64Bit ? "PEAXI@Z" : "PAXI@Z"); return; } + if (IsCtorClosure) { + // Default constructor closure and copy constructor closure both return + // void. + Out << 'X'; + + if (StructorType == Ctor_DefaultClosure) { + // Default constructor closure always has no arguments. + Out << 'X'; + } else if (StructorType == Ctor_CopyingClosure) { + // Copy constructor closure always takes an unqualified reference. + mangleArgumentType(getASTContext().getLValueReferenceType( + Proto->getParamType(0) + ->getAs<LValueReferenceType>() + ->getPointeeType(), + /*SpelledAsLValue=*/true), + Range); + } else { + llvm_unreachable("unexpected constructor closure!"); + } + Out << "@Z"; + return; + } Out << '@'; } else { QualType ResultType = Proto->getReturnType(); @@ -1689,7 +1738,7 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) { } else Out << 'Y'; } -void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) { +void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) { // <calling-convention> ::= A # __cdecl // ::= B # __export __cdecl // ::= C # __pascal @@ -1706,7 +1755,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) { // that keyword. (It didn't actually export them, it just made them so // that they could be in a DLL and somebody from another module could call // them.) - CallingConv CC = T->getCallConv(); + switch (CC) { default: llvm_unreachable("Unsupported CC for mangling"); @@ -1720,6 +1769,9 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) { case CC_X86VectorCall: Out << 'Q'; break; } } +void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) { + mangleCallingConvention(T->getCallConv()); +} void MicrosoftCXXNameMangler::mangleThrowSpecification( const FunctionProtoType *FT) { // <throw-spec> ::= Z # throw(...) (default) @@ -2310,8 +2362,9 @@ void MicrosoftMangleContextImpl::mangleCXXCatchableTypeArray( } void MicrosoftMangleContextImpl::mangleCXXCatchableType( - QualType T, const CXXConstructorDecl *CD, uint32_t Size, uint32_t NVOffset, - int32_t VBPtrOffset, uint32_t VBIndex, raw_ostream &Out) { + QualType T, const CXXConstructorDecl *CD, CXXCtorType CT, uint32_t Size, + uint32_t NVOffset, int32_t VBPtrOffset, uint32_t VBIndex, + raw_ostream &Out) { MicrosoftCXXNameMangler Mangler(*this, Out); Mangler.getStream() << "_CT"; @@ -2328,7 +2381,7 @@ void MicrosoftMangleContextImpl::mangleCXXCatchableType( llvm::SmallString<64> CopyCtorMangling; if (CD) { llvm::raw_svector_ostream Stream(CopyCtorMangling); - mangleCXXCtor(CD, Ctor_Complete, Stream); + mangleCXXCtor(CD, CT, Stream); } Mangler.getStream() << CopyCtorMangling.substr(1); @@ -2411,7 +2464,7 @@ void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) { void MicrosoftMangleContextImpl::mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, raw_ostream &Out) { - MicrosoftCXXNameMangler mangler(*this, Out); + MicrosoftCXXNameMangler mangler(*this, Out, D, Type); mangler.mangle(D); } |