summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGCall.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGCall.cpp')
-rw-r--r--clang/lib/CodeGen/CGCall.cpp65
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);
}
}
OpenPOWER on IntegriCloud