diff options
Diffstat (limited to 'clang/lib/CodeGen/CGCall.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 65 |
1 files changed, 55 insertions, 10 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 70cb4713e69..80f88fb8d15 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -92,15 +92,41 @@ CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> FTNP) { FTNP->getExtInfo(), RequiredArgs(0)); } +/// Adds the formal paramaters in FPT to the given prefix. If any parameter in +/// FPT has pass_object_size attrs, then we'll add parameters for those, too. +static void appendParameterTypes(const CodeGenTypes &CGT, + SmallVectorImpl<CanQualType> &prefix, + const CanQual<FunctionProtoType> &FPT, + const FunctionDecl *FD) { + // Fast path: unknown target. + if (FD == nullptr) { + prefix.append(FPT->param_type_begin(), FPT->param_type_end()); + return; + } + + // In the vast majority cases, we'll have precisely FPT->getNumParams() + // parameters; the only thing that can change this is the presence of + // pass_object_size. So, we preallocate for the common case. + prefix.reserve(prefix.size() + FPT->getNumParams()); + + assert(FD->getNumParams() == FPT->getNumParams()); + for (unsigned I = 0, E = FPT->getNumParams(); I != E; ++I) { + prefix.push_back(FPT->getParamType(I)); + if (FD->getParamDecl(I)->hasAttr<PassObjectSizeAttr>()) + prefix.push_back(CGT.getContext().getSizeType()); + } +} + /// Arrange the LLVM function layout for a value of the given function /// type, on top of any implicit parameters already stored. static const CGFunctionInfo & arrangeLLVMFunctionInfo(CodeGenTypes &CGT, bool instanceMethod, SmallVectorImpl<CanQualType> &prefix, - CanQual<FunctionProtoType> FTP) { + CanQual<FunctionProtoType> FTP, + const FunctionDecl *FD) { RequiredArgs required = RequiredArgs::forPrototypePlus(FTP, prefix.size()); // FIXME: Kill copy. - prefix.append(FTP->param_type_begin(), FTP->param_type_end()); + appendParameterTypes(CGT, prefix, FTP, FD); CanQualType resultType = FTP->getReturnType().getUnqualifiedType(); return CGT.arrangeLLVMFunctionInfo(resultType, instanceMethod, /*chainCall=*/false, prefix, @@ -110,10 +136,11 @@ arrangeLLVMFunctionInfo(CodeGenTypes &CGT, bool instanceMethod, /// Arrange the argument and result information for a value of the /// given freestanding function type. const CGFunctionInfo & -CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> FTP) { +CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> FTP, + const FunctionDecl *FD) { SmallVector<CanQualType, 16> argTypes; return ::arrangeLLVMFunctionInfo(*this, /*instanceMethod=*/false, argTypes, - FTP); + FTP, FD); } static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) { @@ -156,7 +183,8 @@ static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) { /// constructor or destructor. const CGFunctionInfo & CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD, - const FunctionProtoType *FTP) { + const FunctionProtoType *FTP, + const CXXMethodDecl *MD) { SmallVector<CanQualType, 16> argTypes; // Add the 'this' pointer. @@ -167,7 +195,7 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD, return ::arrangeLLVMFunctionInfo( *this, true, argTypes, - FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>()); + FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>(), MD); } /// Arrange the argument and result information for a declaration or @@ -184,10 +212,10 @@ CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) { if (MD->isInstance()) { // The abstract case is perfectly fine. const CXXRecordDecl *ThisType = TheCXXABI.getThisArgumentTypeForMethod(MD); - return arrangeCXXMethodType(ThisType, prototype.getTypePtr()); + return arrangeCXXMethodType(ThisType, prototype.getTypePtr(), MD); } - return arrangeFreeFunctionType(prototype); + return arrangeFreeFunctionType(prototype, MD); } const CGFunctionInfo & @@ -208,7 +236,7 @@ CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD, CanQual<FunctionProtoType> FTP = GetFormalType(MD); // Add the formal parameters. - argTypes.append(FTP->param_type_begin(), FTP->param_type_end()); + appendParameterTypes(*this, argTypes, FTP, MD); TheCXXABI.buildStructorSignature(MD, Type, argTypes); @@ -274,7 +302,7 @@ CodeGenTypes::arrangeFunctionDeclaration(const FunctionDecl *FD) { } assert(isa<FunctionProtoType>(FTy)); - return arrangeFreeFunctionType(FTy.getAs<FunctionProtoType>()); + return arrangeFreeFunctionType(FTy.getAs<FunctionProtoType>(), FD); } /// Arrange the argument and result information for the declaration or @@ -2803,6 +2831,21 @@ void CodeGenFunction::EmitCallArgs( llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange, const FunctionDecl *CalleeDecl, unsigned ParamsToSkip) { assert((int)ArgTypes.size() == (ArgRange.end() - ArgRange.begin())); + + auto MaybeEmitImplicitObjectSize = [&](unsigned I, const Expr *Arg) { + if (CalleeDecl == nullptr || I >= CalleeDecl->getNumParams()) + return; + auto *PS = CalleeDecl->getParamDecl(I)->getAttr<PassObjectSizeAttr>(); + if (PS == nullptr) + return; + + const auto &Context = getContext(); + auto SizeTy = Context.getSizeType(); + auto T = Builder.getIntNTy(Context.getTypeSize(SizeTy)); + llvm::Value *V = evaluateOrEmitBuiltinObjectSize(Arg, PS->getType(), T); + Args.add(RValue::get(V), SizeTy); + }; + // We *have* to evaluate arguments from right to left in the MS C++ ABI, // because arguments are destroyed left to right in the callee. if (CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) { @@ -2823,6 +2866,7 @@ void CodeGenFunction::EmitCallArgs( EmitCallArg(Args, *Arg, ArgTypes[I]); EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], (*Arg)->getExprLoc(), CalleeDecl, ParamsToSkip + I); + MaybeEmitImplicitObjectSize(I, *Arg); } // Un-reverse the arguments we just evaluated so they match up with the LLVM @@ -2837,6 +2881,7 @@ void CodeGenFunction::EmitCallArgs( EmitCallArg(Args, *Arg, ArgTypes[I]); EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], (*Arg)->getExprLoc(), CalleeDecl, ParamsToSkip + I); + MaybeEmitImplicitObjectSize(I, *Arg); } } |

