r231952 - MS ABI: Implement copy-ctor closures, finish implementing throw
Aaron Ballman
aaron at aaronballman.com
Thu Mar 12 06:53:41 PDT 2015
On Thu, Mar 12, 2015 at 9:33 AM, Aaron Ballman <aaron at aaronballman.com> wrote:
> On Wed, Mar 11, 2015 at 2:36 PM, David Majnemer
> <david.majnemer at gmail.com> wrote:
>> Author: majnemer
>> Date: Wed Mar 11 13:36:39 2015
>> New Revision: 231952
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=231952&view=rev
>> Log:
>> 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
>>
>> Modified:
>> cfe/trunk/include/clang/AST/ASTContext.h
>> cfe/trunk/include/clang/AST/Mangle.h
>> cfe/trunk/include/clang/Basic/ABI.h
>> cfe/trunk/lib/AST/ASTContext.cpp
>> cfe/trunk/lib/AST/CXXABI.h
>> cfe/trunk/lib/AST/ItaniumCXXABI.cpp
>> cfe/trunk/lib/AST/ItaniumMangle.cpp
>> cfe/trunk/lib/AST/MicrosoftCXXABI.cpp
>> cfe/trunk/lib/AST/MicrosoftMangle.cpp
>> cfe/trunk/lib/CodeGen/CGCall.cpp
>> cfe/trunk/lib/CodeGen/CodeGenTypes.h
>> cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
>> cfe/trunk/lib/Sema/SemaExprCXX.cpp
>> cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp
>>
>> Modified: cfe/trunk/include/clang/AST/ASTContext.h
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=231952&r1=231951&r2=231952&view=diff
>> ==============================================================================
>> --- cfe/trunk/include/clang/AST/ASTContext.h (original)
>> +++ cfe/trunk/include/clang/AST/ASTContext.h Wed Mar 11 13:36:39 2015
>> @@ -2201,6 +2201,12 @@ public:
>> void addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
>> CXXConstructorDecl *CD);
>>
>> + void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
>> + unsigned ParmIdx, Expr *DAE);
>> +
>> + Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
>> + unsigned ParmIdx);
>> +
>> void setManglingNumber(const NamedDecl *ND, unsigned Number);
>> unsigned getManglingNumber(const NamedDecl *ND) const;
>>
>>
>> Modified: cfe/trunk/include/clang/AST/Mangle.h
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Mangle.h?rev=231952&r1=231951&r2=231952&view=diff
>> ==============================================================================
>> --- cfe/trunk/include/clang/AST/Mangle.h (original)
>> +++ cfe/trunk/include/clang/AST/Mangle.h Wed Mar 11 13:36:39 2015
>> @@ -204,9 +204,9 @@ public:
>> raw_ostream &Out) = 0;
>>
>> virtual void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD,
>> - uint32_t Size, uint32_t NVOffset,
>> - int32_t VBPtrOffset, uint32_t VBIndex,
>> - raw_ostream &Out) = 0;
>> + CXXCtorType CT, uint32_t Size,
>> + uint32_t NVOffset, int32_t VBPtrOffset,
>> + uint32_t VBIndex, raw_ostream &Out) = 0;
>>
>> virtual void mangleCXXRTTIBaseClassDescriptor(
>> const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
>>
>> Modified: cfe/trunk/include/clang/Basic/ABI.h
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/ABI.h?rev=231952&r1=231951&r2=231952&view=diff
>> ==============================================================================
>> --- cfe/trunk/include/clang/Basic/ABI.h (original)
>> +++ cfe/trunk/include/clang/Basic/ABI.h Wed Mar 11 13:36:39 2015
>> @@ -22,9 +22,11 @@ namespace clang {
>>
>> /// \brief C++ constructor types.
>> enum CXXCtorType {
>> - Ctor_Complete, ///< Complete object ctor
>> - Ctor_Base, ///< Base object ctor
>> - Ctor_Comdat ///< The COMDAT used for ctors
>> + Ctor_Complete, ///< Complete object ctor
>> + Ctor_Base, ///< Base object ctor
>> + Ctor_Comdat, ///< The COMDAT used for ctors
>> + Ctor_CopyingClosure, ///< Copying closure variant of a ctor
>> + Ctor_DefaultClosure, ///< Default closure variant of a ctor
>> };
>>
>> /// \brief C++ destructor types.
>>
>> Modified: cfe/trunk/lib/AST/ASTContext.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=231952&r1=231951&r2=231952&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
>> +++ cfe/trunk/lib/AST/ASTContext.cpp Wed Mar 11 13:36:39 2015
>> @@ -8210,6 +8210,18 @@ void ASTContext::addCopyConstructorForEx
>> 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;
>> }
>>
>> Modified: cfe/trunk/lib/AST/CXXABI.h
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CXXABI.h?rev=231952&r1=231951&r2=231952&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/AST/CXXABI.h (original)
>> +++ cfe/trunk/lib/AST/CXXABI.h Wed Mar 11 13:36:39 2015
>> @@ -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.
>>
>> Modified: cfe/trunk/lib/AST/ItaniumCXXABI.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumCXXABI.cpp?rev=231952&r1=231951&r2=231952&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/AST/ItaniumCXXABI.cpp (original)
>> +++ cfe/trunk/lib/AST/ItaniumCXXABI.cpp Wed Mar 11 13:36:39 2015
>> @@ -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();
>> }
>>
>> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=231952&r1=231951&r2=231952&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
>> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Wed Mar 11 13:36:39 2015
>> @@ -3442,6 +3442,9 @@ void CXXNameMangler::mangleCXXCtorType(C
>> case Ctor_Comdat:
>> Out << "C5";
>> break;
>> + case Ctor_DefaultClosure:
>> + case Ctor_CopyingClosure:
>> + llvm_unreachable("closure constructors don't exist for the Itanium ABI!");
>> }
>> }
>>
>>
>> Modified: cfe/trunk/lib/AST/MicrosoftCXXABI.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftCXXABI.cpp?rev=231952&r1=231951&r2=231952&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/AST/MicrosoftCXXABI.cpp (original)
>> +++ cfe/trunk/lib/AST/MicrosoftCXXABI.cpp Wed Mar 11 13:36:39 2015
>> @@ -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];
>>
>> Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=231952&r1=231951&r2=231952&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
>> +++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Wed Mar 11 13:36:39 2015
>> @@ -67,11 +67,15 @@ static const DeclContext *getEffectivePa
>> 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();
>> +
>> + const auto *FD = cast<FunctionDecl>(ND);
>> + if (const auto *FTD = FD->getPrimaryTemplate())
>> + return FTD->getTemplatedDecl();
>>
>> - return fn;
>> + 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::mangleUnqu
>> 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::mangleFunc
>> 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::mangleFunc
>> mangleQualifiers(Quals, /*IsMember=*/false);
>> }
>>
>> - mangleCallingConvention(T);
>> + mangleCallingConvention(CC);
>>
>> // <return-type> ::= <type>
>> // ::= @ # structors (they have no declared return type)
>> @@ -1597,6 +1624,28 @@ void MicrosoftCXXNameMangler::mangleFunc
>> Out << (PointersAre64Bit ? "PEAXI at Z" : "PAXI at 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::mangleFunc
>> } 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::mangleCall
>> // 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::mangleCall
>> 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::mangleC
>> }
>>
>> 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::mangleC
>> 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::mangleT
>> void MicrosoftMangleContextImpl::mangleCXXCtor(const CXXConstructorDecl *D,
>> CXXCtorType Type,
>> raw_ostream &Out) {
>> - MicrosoftCXXNameMangler mangler(*this, Out);
>> + MicrosoftCXXNameMangler mangler(*this, Out, D, Type);
>> mangler.mangle(D);
>> }
>>
>>
>> Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=231952&r1=231951&r2=231952&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/CGCall.cpp Wed Mar 11 13:36:39 2015
>> @@ -346,6 +346,22 @@ CodeGenTypes::arrangeMSMemberPointerThun
>> FTP->getExtInfo(), RequiredArgs(1));
>> }
>>
>> +const CGFunctionInfo &
>> +CodeGenTypes::arrangeMSCopyCtorClosure(const CXXConstructorDecl *CD) {
>> + CanQual<FunctionProtoType> FTP = GetFormalType(CD);
>> + SmallVector<CanQualType, 2> ArgTys;
>> + const CXXRecordDecl *RD = CD->getParent();
>> + ArgTys.push_back(GetThisType(Context, RD));
>> + ArgTys.push_back(*FTP->param_type_begin());
>> + if (RD->getNumVBases() > 0)
>> + ArgTys.push_back(Context.IntTy);
>> + CallingConv CC = Context.getDefaultCallingConvention(
>> + /*IsVariadic=*/false, /*IsCXXMethod=*/true);
>> + return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/true,
>> + /*chainCall=*/false, ArgTys,
>> + FunctionType::ExtInfo(CC), RequiredArgs::All);
>> +}
>> +
>> /// Arrange a call as unto a free function, except possibly with an
>> /// additional number of formal parameters considered required.
>> static const CGFunctionInfo &
>>
>> Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.h
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.h?rev=231952&r1=231951&r2=231952&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CodeGenTypes.h (original)
>> +++ cfe/trunk/lib/CodeGen/CodeGenTypes.h Wed Mar 11 13:36:39 2015
>> @@ -82,6 +82,9 @@ inline StructorType getFromCtorType(CXXC
>> return StructorType::Base;
>> case Ctor_Comdat:
>> llvm_unreachable("not expecting a COMDAT");
>> + case Ctor_CopyingClosure:
>> + case Ctor_DefaultClosure:
>> + llvm_unreachable("not expecting a closure");
>> }
>> llvm_unreachable("not a CXXCtorType");
>> }
>> @@ -261,6 +264,7 @@ public:
>> const FunctionProtoType *type,
>> RequiredArgs required);
>> const CGFunctionInfo &arrangeMSMemberPointerThunk(const CXXMethodDecl *MD);
>> + const CGFunctionInfo &arrangeMSCopyCtorClosure(const CXXConstructorDecl *CD);
>>
>> const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty);
>> const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionNoProtoType> Ty);
>>
>> Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=231952&r1=231951&r2=231952&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Wed Mar 11 13:36:39 2015
>> @@ -635,6 +635,8 @@ public:
>> return Fn;
>> }
>>
>> + llvm::Function *getAddrOfCXXCopyCtorClosure(const CXXConstructorDecl *CD);
>> +
>> llvm::Constant *getCatchableType(QualType T,
>> uint32_t NVOffset = 0,
>> int32_t VBPtrOffset = -1,
>> @@ -3220,6 +3222,103 @@ void MicrosoftCXXABI::emitCXXStructor(co
>> emitCXXDestructor(CGM, cast<CXXDestructorDecl>(MD), Type);
>> }
>>
>> +llvm::Function *
>> +MicrosoftCXXABI::getAddrOfCXXCopyCtorClosure(const CXXConstructorDecl *CD) {
>> + // Calculate the mangled name.
>> + SmallString<256> ThunkName;
>> + llvm::raw_svector_ostream Out(ThunkName);
>> + getMangleContext().mangleCXXCtor(CD, Ctor_CopyingClosure, Out);
>> + Out.flush();
>> +
>> + // If the thunk has been generated previously, just return it.
>> + if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName))
>> + return cast<llvm::Function>(GV);
>> +
>> + // Create the llvm::Function.
>> + const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeMSCopyCtorClosure(CD);
>> + llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo);
>> + const CXXRecordDecl *RD = CD->getParent();
>> + QualType RecordTy = getContext().getRecordType(RD);
>> + llvm::Function *ThunkFn = llvm::Function::Create(
>> + ThunkTy, getLinkageForRTTI(RecordTy), ThunkName.str(), &CGM.getModule());
>> +
>> + // Start codegen.
>> + CodeGenFunction CGF(CGM);
>> + CGF.CurGD = GlobalDecl(CD, Ctor_Complete);
>> +
>> + // Build FunctionArgs.
>> + FunctionArgList FunctionArgs;
>> +
>> + // A copy constructor always starts with a 'this' pointer as its first
>> + // argument.
>> + buildThisParam(CGF, FunctionArgs);
>> +
>> + // Following the 'this' pointer is a reference to the source object that we
>> + // are copying from.
>> + ImplicitParamDecl SrcParam(
>> + getContext(), nullptr, SourceLocation(), &getContext().Idents.get("src"),
>> + getContext().getLValueReferenceType(RecordTy,
>> + /*SpelledAsLValue=*/true));
>> + FunctionArgs.push_back(&SrcParam);
>> +
>> + // Copy constructors for classes which utilize virtual bases have an
>> + // additional parameter which indicates whether or not it is being delegated
>> + // to by a more derived constructor.
>> + ImplicitParamDecl IsMostDerived(getContext(), nullptr, SourceLocation(),
>> + &getContext().Idents.get("is_most_derived"),
>> + getContext().IntTy);
>> + // Only add the parameter to the list if thie class has virtual bases.
>> + if (RD->getNumVBases() > 0)
>> + FunctionArgs.push_back(&IsMostDerived);
>> +
>> + // Start defining the function.
>> + CGF.StartFunction(GlobalDecl(), FnInfo.getReturnType(), ThunkFn, FnInfo,
>> + FunctionArgs, CD->getLocation(), SourceLocation());
>> + EmitThisParam(CGF);
>> + llvm::Value *This = getThisValue(CGF);
>> +
>> + llvm::Value *SrcVal =
>> + CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&SrcParam), "src");
>> +
>> + CallArgList Args;
>> +
>> + // Push the this ptr.
>> + Args.add(RValue::get(This), CD->getThisType(getContext()));
>> +
>> + // Push the src ptr.
>> + Args.add(RValue::get(SrcVal), SrcParam.getType());
>> +
>> + // Add the rest of the default arguments.
>> + std::vector<Stmt *> ArgVec;
>> + for (unsigned I = 1, E = CD->getNumParams(); I != E; ++I)
>> + ArgVec.push_back(getContext().getDefaultArgExprForConstructor(CD, I));
>> +
>> + CodeGenFunction::RunCleanupsScope Cleanups(CGF);
>> +
>> + const auto *FPT = CD->getType()->castAs<FunctionProtoType>();
>> + ConstExprIterator ArgBegin(ArgVec.data()), ArgEnd(&*ArgVec.end());
>
> Dereferencing std::vector::end() is UB since it is a past-the-end
> value. This is causing failed assertions ("vector iterator not
> dereferencable") with checked STL implementations, such as what you
> get with Visual Studio's debug mode.
I've checked in a fix for this in r232037.
~Aaron
>
> ~Aaron
>
>> + CGF.EmitCallArgs(Args, FPT, ArgBegin, ArgEnd, CD, 1);
>> +
>> + // Insert any ABI-specific implicit constructor arguments.
>> + unsigned ExtraArgs = addImplicitConstructorArgs(CGF, CD, Ctor_Complete,
>> + /*ForVirtualBase=*/false,
>> + /*Delegating=*/false, Args);
>> +
>> + // Call the destructor with our arguments.
>> + llvm::Value *CalleeFn = CGM.getAddrOfCXXStructor(CD, StructorType::Complete);
>> + const CGFunctionInfo &CalleeInfo = CGM.getTypes().arrangeCXXConstructorCall(
>> + Args, CD, Ctor_Complete, ExtraArgs);
>> + CGF.EmitCall(CalleeInfo, CalleeFn, ReturnValueSlot(), Args, CD);
>> +
>> + Cleanups.ForceCleanup();
>> +
>> + // Emit the ret instruction, remove any temporary instructions created for the
>> + // aid of CodeGen.
>> + CGF.FinishFunction(SourceLocation());
>> +
>> + return ThunkFn;
>> +}
>> +
>> llvm::Constant *MicrosoftCXXABI::getCatchableType(QualType T,
>> uint32_t NVOffset,
>> int32_t VBPtrOffset,
>> @@ -3229,27 +3328,43 @@ llvm::Constant *MicrosoftCXXABI::getCatc
>> CXXRecordDecl *RD = T->getAsCXXRecordDecl();
>> const CXXConstructorDecl *CD =
>> RD ? CGM.getContext().getCopyConstructorForExceptionObject(RD) : nullptr;
>> + CXXCtorType CT = Ctor_Complete;
>> + if (CD) {
>> + CallingConv ExpectedCallingConv = getContext().getDefaultCallingConvention(
>> + /*IsVariadic=*/false, /*IsCXXMethod=*/true);
>> + CallingConv ActualCallingConv =
>> + CD->getType()->getAs<FunctionProtoType>()->getCallConv();
>> + if (ExpectedCallingConv != ActualCallingConv || CD->getNumParams() != 1)
>> + CT = Ctor_CopyingClosure;
>> + }
>> +
>> uint32_t Size = getContext().getTypeSizeInChars(T).getQuantity();
>> SmallString<256> MangledName;
>> {
>> llvm::raw_svector_ostream Out(MangledName);
>> - getMangleContext().mangleCXXCatchableType(T, CD, Size, NVOffset,
>> + getMangleContext().mangleCXXCatchableType(T, CD, CT, Size, NVOffset,
>> VBPtrOffset, VBIndex, Out);
>> }
>> if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))
>> return getImageRelativeConstant(GV);
>>
>> - // The TypeDescriptor is used by the runtime to determine of a catch handler
>> + // The TypeDescriptor is used by the runtime to determine if a catch handler
>> // is appropriate for the exception object.
>> llvm::Constant *TD = getImageRelativeConstant(getAddrOfRTTIDescriptor(T));
>>
>> // The runtime is responsible for calling the copy constructor if the
>> // exception is caught by value.
>> - llvm::Constant *CopyCtor =
>> - CD ? llvm::ConstantExpr::getBitCast(
>> - CGM.getAddrOfCXXStructor(CD, StructorType::Complete),
>> - CGM.Int8PtrTy)
>> - : llvm::Constant::getNullValue(CGM.Int8PtrTy);
>> + llvm::Constant *CopyCtor;
>> + if (CD) {
>> + if (CT == Ctor_CopyingClosure)
>> + CopyCtor = getAddrOfCXXCopyCtorClosure(CD);
>> + else
>> + CopyCtor = CGM.getAddrOfCXXStructor(CD, StructorType::Complete);
>> +
>> + CopyCtor = llvm::ConstantExpr::getBitCast(CopyCtor, CGM.Int8PtrTy);
>> + } else {
>> + CopyCtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
>> + }
>> CopyCtor = getImageRelativeConstant(CopyCtor);
>>
>> bool IsScalar = !RD;
>>
>> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=231952&r1=231951&r2=231952&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Mar 11 13:36:39 2015
>> @@ -782,14 +782,51 @@ ExprResult Sema::CheckCXXThrowOperand(So
>> }
>> }
>>
>> + // The MSVC ABI creates a list of all types which can catch the exception
>> + // object. This list also references the appropriate copy constructor to call
>> + // if the object is caught by value and has a non-trivial copy constructor.
>> if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
>> + // We are only interested in the public, unambiguous bases contained within
>> + // the exception object. Bases which are ambiguous or otherwise
>> + // inaccessible are not catchable types.
>> llvm::SmallVector<CXXRecordDecl *, 2> UnambiguousPublicSubobjects;
>> getUnambiguousPublicSubobjects(RD, UnambiguousPublicSubobjects);
>> +
>> for (CXXRecordDecl *Subobject : UnambiguousPublicSubobjects) {
>> - if (CXXConstructorDecl *CD = LookupCopyingConstructor(Subobject, 0)) {
>> - MarkFunctionReferenced(E->getExprLoc(), CD);
>> - if (!CD->isTrivial())
>> - Context.addCopyConstructorForExceptionObject(Subobject, CD);
>> + // Attempt to lookup the copy constructor. Various pieces of machinery
>> + // will spring into action, like template instantiation, which means this
>> + // cannot be a simple walk of the class's decls. Instead, we must perform
>> + // lookup and overload resolution.
>> + CXXConstructorDecl *CD = LookupCopyingConstructor(Subobject, 0);
>> + if (!CD)
>> + continue;
>> +
>> + // Mark the constructor referenced as it is used by this throw expression.
>> + MarkFunctionReferenced(E->getExprLoc(), CD);
>> +
>> + // Skip this copy constructor if it is trivial, we don't need to record it
>> + // in the catchable type data.
>> + if (CD->isTrivial())
>> + continue;
>> +
>> + // The copy constructor is non-trivial, create a mapping from this class
>> + // type to this constructor.
>> + // N.B. The selection of copy constructor is not sensitive to this
>> + // particular throw-site. Lookup will be performed at the catch-site to
>> + // ensure that the copy constructor is, in fact, accessible (via
>> + // friendship or any other means).
>> + Context.addCopyConstructorForExceptionObject(Subobject, CD);
>> +
>> + // We don't keep the instantiated default argument expressions around so
>> + // we must rebuild them here.
>> + for (unsigned I = 1, E = CD->getNumParams(); I != E; ++I) {
>> + // Skip any default arguments that we've already instantiated.
>> + if (Context.getDefaultArgExprForConstructor(CD, I))
>> + continue;
>> +
>> + Expr *DefaultArg =
>> + BuildCXXDefaultArgExpr(ThrowLoc, CD, CD->getParamDecl(I)).get();
>> + Context.addDefaultArgExprForConstructor(CD, I, DefaultArg);
>> }
>> }
>> }
>>
>> Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp?rev=231952&r1=231951&r2=231952&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp (original)
>> +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp Wed Mar 11 13:36:39 2015
>> @@ -1,4 +1,4 @@
>> -// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 %s -fcxx-exceptions | FileCheck %s
>> +// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 -std=c++11 %s -fcxx-exceptions | FileCheck %s
>>
>> // CHECK-DAG: @"\01??_R0?AUY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUY@@\00" }, comdat
>> // CHECK-DAG: @"_CT??_R0?AUY@@@8??0Y@@QAE at ABU0@@Z8" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 4, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUY@@@8" to i8*), i32 0, i32 -1, i32 0, i32 8, i8* bitcast (%struct.Y* (%struct.Y*, %struct.Y*, i32)* @"\01??0Y@@QAE at ABU0@@Z" to i8*) }, section ".xdata", comdat
>> @@ -12,6 +12,9 @@
>> // CHECK-DAG: @"_CT??_R0?AUV@@@81044" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUV@@@8" to i8*), i32 0, i32 4, i32 4, i32 1, i8* null }, section ".xdata", comdat
>> // CHECK-DAG: @"_CTA5?AUY@@" = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.5 { i32 5, [5 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0?AUY@@@8??0Y@@QAE at ABU0@@Z8", %eh.CatchableType* @"_CT??_R0?AUZ@@@81", %eh.CatchableType* @"_CT??_R0?AUW@@@8??0W@@QAE at ABU0@@Z44", %eh.CatchableType* @"_CT??_R0?AUM@@@818", %eh.CatchableType* @"_CT??_R0?AUV@@@81044"] }, section ".xdata", comdat
>> // CHECK-DAG: @"_TI5?AUY@@" = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* bitcast (void (%struct.Y*)* @"\01??_DY@@QAE at XZ" to i8*), i8* null, i8* bitcast (%eh.CatchableTypeArray.5* @"_CTA5?AUY@@" to i8*) }, section ".xdata", comdat
>> +// CHECK-DAG: @"_CT??_R0?AUDefault@@@8??_ODefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor13* @"\01??_R0?AUDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Default*, %struct.Default*)* @"\01??_ODefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
>> +// CHECK-DAG: @"_CT??_R0?AUVariadic@@@8??_OVariadic@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor14* @"\01??_R0?AUVariadic@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Variadic*, %struct.Variadic*)* @"\01??_OVariadic@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
>> +// CHECK-DAG: @"_CT??_R0?AUTemplateWithDefault@@@8??$?_OH at TemplateWithDefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor25* @"\01??_R0?AUTemplateWithDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.TemplateWithDefault*, %struct.TemplateWithDefault*)* @"\01??$?_OH at TemplateWithDefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
>>
>>
>> struct N { ~N(); };
>> @@ -35,3 +38,52 @@ void g(const int *const *y) {
>> // CHECK: call void @_CxxThrowException(i8* %{{.*}}, %eh.ThrowInfo* @_TIC2PAPBH)
>> throw y;
>> }
>> +
>> +struct Default {
>> + Default(Default &, int = 42);
>> +};
>> +
>> +// CHECK-LABEL: @"\01??_ODefault@@QAEXAAU0@@Z"
>> +// CHECK: %[[src_addr:.*]] = alloca
>> +// CHECK: %[[this_addr:.*]] = alloca
>> +// CHECK: store {{.*}} %src, {{.*}} %[[src_addr]], align 4
>> +// CHECK: store {{.*}} %this, {{.*}} %[[this_addr]], align 4
>> +// CHECK: %[[this:.*]] = load {{.*}} %[[this_addr]]
>> +// CHECK: %[[src:.*]] = load {{.*}} %[[src_addr]]
>> +// CHECK: call x86_thiscallcc {{.*}} @"\01??0Default@@QAE at AAU0@H at Z"({{.*}} %[[this]], {{.*}} %[[src]], i32 42)
>> +// CHECK: ret void
>> +
>> +void h(Default &d) {
>> + throw d;
>> +}
>> +
>> +struct Variadic {
>> + Variadic(Variadic &, ...);
>> +};
>> +
>> +void i(Variadic &v) {
>> + throw v;
>> +}
>> +
>> +// CHECK-LABEL: @"\01??_OVariadic@@QAEXAAU0@@Z"
>> +// CHECK: %[[src_addr:.*]] = alloca
>> +// CHECK: %[[this_addr:.*]] = alloca
>> +// CHECK: store {{.*}} %src, {{.*}} %[[src_addr:.*]], align
>> +// CHECK: store {{.*}} %this, {{.*}} %[[this_addr:.*]], align
>> +// CHECK: %[[this:.*]] = load {{.*}} %[[this_addr]]
>> +// CHECK: %[[src:.*]] = load {{.*}} %[[src_addr]]
>> +// CHECK: %call = call {{.*}} @"\01??0Variadic@@QAA at AAU0@ZZ"({{.*}} %[[this]], {{.*}} %[[src]])
>> +// CHECK: ret void
>> +
>> +struct TemplateWithDefault {
>> + template <typename T>
>> + static int f() {
>> + return 0;
>> + }
>> + template <typename T = int>
>> + TemplateWithDefault(TemplateWithDefault &, T = f<T>());
>> +};
>> +
>> +void j(TemplateWithDefault &twd) {
>> + throw twd;
>> +}
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list