summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2013-12-04 19:23:12 +0000
committerReid Kleckner <reid@kleckner.net>2013-12-04 19:23:12 +0000
commit739756c0f925fbb967109f4ba289d26be69c9c0a (patch)
tree6f6102249a4aee2dd120cafc29141fbb42feb290 /clang/lib
parent91a9b247d473cebc23cee55309aecc56a0c29f64 (diff)
downloadbcm5719-llvm-739756c0f925fbb967109f4ba289d26be69c9c0a.tar.gz
bcm5719-llvm-739756c0f925fbb967109f4ba289d26be69c9c0a.zip
[ms-cxxabi] Construct and destroy call arguments in the correct order
Summary: MSVC destroys arguments in the callee from left to right. Because C++ objects have to be destroyed in the reverse order of construction, Clang has to construct arguments from right to left and destroy arguments from left to right. This patch fixes the ordering by reversing the order of evaluation of all call arguments under the MS C++ ABI. Fixes PR18035. Reviewers: rsmith Differential Revision: http://llvm-reviews.chandlerc.com/D2275 llvm-svn: 196402
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGCall.cpp66
-rw-r--r--clang/lib/CodeGen/CGClass.cpp25
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp2
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp31
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h96
-rw-r--r--clang/lib/Sema/SemaChecking.cpp5
6 files changed, 123 insertions, 102 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 22f2467021e..726e808ed08 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1246,6 +1246,12 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
++AI;
}
+ // Create a pointer value for every parameter declaration. This usually
+ // entails copying one or more LLVM IR arguments into an alloca. Don't push
+ // any cleanups or do anything that might unwind. We do that separately, so
+ // we can push the cleanups in the correct order for the ABI.
+ SmallVector<llvm::Value *, 16> ArgVals;
+ ArgVals.reserve(Args.size());
assert(FI.arg_size() == Args.size() &&
"Mismatch between function signature & arguments.");
unsigned ArgNo = 1;
@@ -1299,7 +1305,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
if (isPromoted)
V = emitArgumentDemotion(*this, Arg, V);
}
- EmitParmDecl(*Arg, V, ArgNo);
+ ArgVals.push_back(V);
break;
}
@@ -1340,7 +1346,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
if (V->getType() != LTy)
V = Builder.CreateBitCast(V, LTy);
- EmitParmDecl(*Arg, V, ArgNo);
+ ArgVals.push_back(V);
break;
}
@@ -1413,7 +1419,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
if (isPromoted)
V = emitArgumentDemotion(*this, Arg, V);
}
- EmitParmDecl(*Arg, V, ArgNo);
+ ArgVals.push_back(V);
continue; // Skip ++AI increment, already done.
}
@@ -1426,7 +1432,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
Alloca->setAlignment(Align.getQuantity());
LValue LV = MakeAddrLValue(Alloca, Ty, Align);
llvm::Function::arg_iterator End = ExpandTypeFromArgs(Ty, LV, AI);
- EmitParmDecl(*Arg, Alloca, ArgNo);
+ ArgVals.push_back(Alloca);
// Name the arguments used in expansion and increment AI.
unsigned Index = 0;
@@ -1438,10 +1444,9 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
case ABIArgInfo::Ignore:
// Initialize the local variable appropriately.
if (!hasScalarEvaluationKind(Ty))
- EmitParmDecl(*Arg, CreateMemTemp(Ty), ArgNo);
+ ArgVals.push_back(CreateMemTemp(Ty));
else
- EmitParmDecl(*Arg, llvm::UndefValue::get(ConvertType(Arg->getType())),
- ArgNo);
+ ArgVals.push_back(llvm::UndefValue::get(ConvertType(Arg->getType())));
// Skip increment, no matching LLVM parameter.
continue;
@@ -1450,6 +1455,14 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
++AI;
}
assert(AI == Fn->arg_end() && "Argument mismatch!");
+
+ if (getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
+ for (int I = Args.size() - 1; I >= 0; --I)
+ EmitParmDecl(*Args[I], ArgVals[I], I + 1);
+ } else {
+ for (unsigned I = 0, E = Args.size(); I != E; ++I)
+ EmitParmDecl(*Args[I], ArgVals[I], I + 1);
+ }
}
static void eraseUnusedBitCasts(llvm::Instruction *insn) {
@@ -1859,7 +1872,7 @@ static void emitWritebacks(CodeGenFunction &CGF,
static void deactivateArgCleanupsBeforeCall(CodeGenFunction &CGF,
const CallArgList &CallArgs) {
- assert(CGF.getTarget().getCXXABI().isArgumentDestroyedByCallee());
+ assert(CGF.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee());
ArrayRef<CallArgList::CallArgCleanup> Cleanups =
CallArgs.getCleanupsToDeactivate();
// Iterate in reverse to increase the likelihood of popping the cleanup.
@@ -2004,6 +2017,41 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
args.add(RValue::get(finalArgument), CRE->getType());
}
+void CodeGenFunction::EmitCallArgs(CallArgList &Args,
+ ArrayRef<QualType> ArgTypes,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd,
+ bool ForceColumnInfo) {
+ CGDebugInfo *DI = getDebugInfo();
+ SourceLocation CallLoc;
+ if (DI) CallLoc = DI->getLocation();
+
+ // 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()) {
+ size_t CallArgsStart = Args.size();
+ for (int I = ArgTypes.size() - 1; I >= 0; --I) {
+ CallExpr::const_arg_iterator Arg = ArgBeg + I;
+ EmitCallArg(Args, *Arg, ArgTypes[I]);
+ // Restore the debug location.
+ if (DI) DI->EmitLocation(Builder, CallLoc, ForceColumnInfo);
+ }
+
+ // Un-reverse the arguments we just evaluated so they match up with the LLVM
+ // IR function.
+ std::reverse(Args.begin() + CallArgsStart, Args.end());
+ return;
+ }
+
+ for (unsigned I = 0, E = ArgTypes.size(); I != E; ++I) {
+ CallExpr::const_arg_iterator Arg = ArgBeg + I;
+ assert(Arg != ArgEnd);
+ EmitCallArg(Args, *Arg, ArgTypes[I]);
+ // Restore the debug location.
+ if (DI) DI->EmitLocation(Builder, CallLoc, ForceColumnInfo);
+ }
+}
+
void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
QualType type) {
if (const ObjCIndirectCopyRestoreExpr *CRE
@@ -2027,7 +2075,7 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
// However, we still have to push an EH-only cleanup in case we unwind before
// we make it to the call.
if (HasAggregateEvalKind &&
- CGM.getTarget().getCXXABI().isArgumentDestroyedByCallee()) {
+ CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
const CXXRecordDecl *RD = type->getAsCXXRecordDecl();
if (RD && RD->hasNonTrivialDestructor()) {
AggValueSlot Slot = CreateAggTemp(type, "agg.arg.tmp");
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 27aefe482f2..d503d332e7d 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1703,38 +1703,23 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
assert(D->isInstance() &&
"Trying to emit a member call expr on a static method!");
- const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>();
+ const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>();
CallArgList Args;
// Push the this ptr.
Args.add(RValue::get(This), D->getThisType(getContext()));
-
// Push the src ptr.
QualType QT = *(FPT->arg_type_begin());
llvm::Type *t = CGM.getTypes().ConvertType(QT);
Src = Builder.CreateBitCast(Src, t);
Args.add(RValue::get(Src), QT);
-
+
// Skip over first argument (Src).
- ++ArgBeg;
- CallExpr::const_arg_iterator Arg = ArgBeg;
- for (FunctionProtoType::arg_type_iterator I = FPT->arg_type_begin()+1,
- E = FPT->arg_type_end(); I != E; ++I, ++Arg) {
- assert(Arg != ArgEnd && "Running over edge of argument list!");
- EmitCallArg(Args, *Arg, *I);
- }
- // Either we've emitted all the call args, or we have a call to a
- // variadic function.
- assert((Arg == ArgEnd || FPT->isVariadic()) &&
- "Extra arguments in non-variadic function!");
- // If we still have any arguments, emit them using the type of the argument.
- for (; Arg != ArgEnd; ++Arg) {
- QualType ArgType = Arg->getType();
- EmitCallArg(Args, *Arg, ArgType);
- }
-
+ EmitCallArgs(Args, FPT->isVariadic(), FPT->arg_type_begin() + 1,
+ FPT->arg_type_end(), ArgBeg + 1, ArgEnd);
+
EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, RequiredArgs::All),
Callee, ReturnValueSlot(), Args, D);
}
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 66d6b33eb6f..374cd026b85 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1647,7 +1647,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
DeclPtr = Arg;
// Push a destructor cleanup for this parameter if the ABI requires it.
if (HasNonScalarEvalKind &&
- getTarget().getCXXABI().isArgumentDestroyedByCallee()) {
+ getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
if (const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl()) {
if (RD->hasNonTrivialDestructor())
pushDestroy(QualType::DK_cxx_destructor, DeclPtr, Ty);
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index a748620ee7f..d4e1e33d734 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -1129,35 +1129,12 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
allocatorArgs.add(RValue::get(allocSize), sizeType);
- // Emit the rest of the arguments.
- // FIXME: Ideally, this should just use EmitCallArgs.
- CXXNewExpr::const_arg_iterator placementArg = E->placement_arg_begin();
-
- // First, use the types from the function type.
// We start at 1 here because the first argument (the allocation size)
// has already been emitted.
- for (unsigned i = 1, e = allocatorType->getNumArgs(); i != e;
- ++i, ++placementArg) {
- QualType argType = allocatorType->getArgType(i);
-
- assert(getContext().hasSameUnqualifiedType(argType.getNonReferenceType(),
- placementArg->getType()) &&
- "type mismatch in call argument!");
-
- EmitCallArg(allocatorArgs, *placementArg, argType);
- }
-
- // Either we've emitted all the call args, or we have a call to a
- // variadic function.
- assert((placementArg == E->placement_arg_end() ||
- allocatorType->isVariadic()) &&
- "Extra arguments to non-variadic function!");
-
- // If we still have any arguments, emit them using the type of the argument.
- for (CXXNewExpr::const_arg_iterator placementArgsEnd = E->placement_arg_end();
- placementArg != placementArgsEnd; ++placementArg) {
- EmitCallArg(allocatorArgs, *placementArg, placementArg->getType());
- }
+ EmitCallArgs(allocatorArgs, allocatorType->isVariadic(),
+ allocatorType->arg_type_begin() + 1,
+ allocatorType->arg_type_end(), E->placement_arg_begin(),
+ E->placement_arg_end());
// Emit the allocation call. If the allocator is a global placement
// operator, just "inline" it directly.
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index db291e3b1dd..2ddb1b9460d 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2493,68 +2493,78 @@ private:
SourceLocation Loc);
/// EmitCallArgs - Emit call arguments for a function.
- /// The CallArgTypeInfo parameter is used for iterating over the known
- /// argument types of the function being called.
- template<typename T>
- void EmitCallArgs(CallArgList& Args, const T* CallArgTypeInfo,
+ template <typename T>
+ void EmitCallArgs(CallArgList &Args, const T *CallArgTypeInfo,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd,
bool ForceColumnInfo = false) {
- CGDebugInfo *DI = getDebugInfo();
- SourceLocation CallLoc;
- if (DI) CallLoc = DI->getLocation();
+ if (CallArgTypeInfo) {
+ EmitCallArgs(Args, CallArgTypeInfo->isVariadic(),
+ CallArgTypeInfo->arg_type_begin(),
+ CallArgTypeInfo->arg_type_end(), ArgBeg, ArgEnd,
+ ForceColumnInfo);
+ } else {
+ // T::arg_type_iterator might not have a default ctor.
+ const QualType *NoIter = 0;
+ EmitCallArgs(Args, /*AllowExtraArguments=*/true, NoIter, NoIter, ArgBeg,
+ ArgEnd, ForceColumnInfo);
+ }
+ }
+ template<typename ArgTypeIterator>
+ void EmitCallArgs(CallArgList& Args,
+ bool AllowExtraArguments,
+ ArgTypeIterator ArgTypeBeg,
+ ArgTypeIterator ArgTypeEnd,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd,
+ bool ForceColumnInfo = false) {
+ SmallVector<QualType, 16> ArgTypes;
CallExpr::const_arg_iterator Arg = ArgBeg;
// First, use the argument types that the type info knows about
- if (CallArgTypeInfo) {
- for (typename T::arg_type_iterator I = CallArgTypeInfo->arg_type_begin(),
- E = CallArgTypeInfo->arg_type_end(); I != E; ++I, ++Arg) {
- assert(Arg != ArgEnd && "Running over edge of argument list!");
- QualType ArgType = *I;
+ for (ArgTypeIterator I = ArgTypeBeg, E = ArgTypeEnd; I != E; ++I, ++Arg) {
+ assert(Arg != ArgEnd && "Running over edge of argument list!");
#ifndef NDEBUG
- QualType ActualArgType = Arg->getType();
- if (ArgType->isPointerType() && ActualArgType->isPointerType()) {
- QualType ActualBaseType =
+ QualType ArgType = *I;
+ QualType ActualArgType = Arg->getType();
+ if (ArgType->isPointerType() && ActualArgType->isPointerType()) {
+ QualType ActualBaseType =
ActualArgType->getAs<PointerType>()->getPointeeType();
- QualType ArgBaseType =
+ QualType ArgBaseType =
ArgType->getAs<PointerType>()->getPointeeType();
- if (ArgBaseType->isVariableArrayType()) {
- if (const VariableArrayType *VAT =
- getContext().getAsVariableArrayType(ActualBaseType)) {
- if (!VAT->getSizeExpr())
- ActualArgType = ArgType;
- }
+ if (ArgBaseType->isVariableArrayType()) {
+ if (const VariableArrayType *VAT =
+ getContext().getAsVariableArrayType(ActualBaseType)) {
+ if (!VAT->getSizeExpr())
+ ActualArgType = ArgType;
}
}
- assert(getContext().getCanonicalType(ArgType.getNonReferenceType()).
- getTypePtr() ==
- getContext().getCanonicalType(ActualArgType).getTypePtr() &&
- "type mismatch in call argument!");
-#endif
- EmitCallArg(Args, *Arg, ArgType);
-
- // Each argument expression could modify the debug
- // location. Restore it.
- if (DI) DI->EmitLocation(Builder, CallLoc, ForceColumnInfo);
}
-
- // Either we've emitted all the call args, or we have a call to a
- // variadic function.
- assert((Arg == ArgEnd || CallArgTypeInfo->isVariadic()) &&
- "Extra arguments in non-variadic function!");
-
+ assert(getContext().getCanonicalType(ArgType.getNonReferenceType()).
+ getTypePtr() ==
+ getContext().getCanonicalType(ActualArgType).getTypePtr() &&
+ "type mismatch in call argument!");
+#endif
+ ArgTypes.push_back(*I);
}
+ // Either we've emitted all the call args, or we have a call to variadic
+ // function or some other call that allows extra arguments.
+ assert((Arg == ArgEnd || AllowExtraArguments) &&
+ "Extra arguments in non-variadic function!");
+
// If we still have any arguments, emit them using the type of the argument.
- for (; Arg != ArgEnd; ++Arg) {
- EmitCallArg(Args, *Arg, Arg->getType());
+ for (; Arg != ArgEnd; ++Arg)
+ ArgTypes.push_back(Arg->getType());
- // Restore the debug location.
- if (DI) DI->EmitLocation(Builder, CallLoc, ForceColumnInfo);
- }
+ EmitCallArgs(Args, ArgTypes, ArgBeg, ArgEnd, ForceColumnInfo);
}
+ void EmitCallArgs(CallArgList &Args, ArrayRef<QualType> ArgTypes,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd, bool ForceColumnInfo);
+
const TargetCodeGenInfo &getTargetHooks() const {
return CGM.getTargetCodeGenInfo();
}
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 0b95c48d4f8..9e711c63321 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -6190,8 +6190,9 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P,
// MSVC destroys objects passed by value in the callee. Therefore a
// function definition which takes such a parameter must be able to call the
// object's destructor.
- if (getLangOpts().CPlusPlus &&
- Context.getTargetInfo().getCXXABI().isArgumentDestroyedByCallee()) {
+ if (getLangOpts().CPlusPlus && Context.getTargetInfo()
+ .getCXXABI()
+ .areArgsDestroyedLeftToRightInCallee()) {
if (const RecordType *RT = Param->getType()->getAs<RecordType>())
FinalizeVarWithDestructor(Param, RT);
}
OpenPOWER on IntegriCloud