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/CodeGen | |
| 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/CodeGen')
| -rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 16 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.h | 4 | ||||
| -rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 129 |
3 files changed, 142 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 0060c769c71..67849642118 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -346,6 +346,22 @@ CodeGenTypes::arrangeMSMemberPointerThunk(const CXXMethodDecl *MD) { 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 & diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h index 64c5799ccec..f9cd3837fe9 100644 --- a/clang/lib/CodeGen/CodeGenTypes.h +++ b/clang/lib/CodeGen/CodeGenTypes.h @@ -82,6 +82,9 @@ inline StructorType getFromCtorType(CXXCtorType T) { 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); diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 7092e1803bd..1ec37f41311 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -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(const CXXMethodDecl *MD, 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()); + 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::getCatchableType(QualType T, 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; |

