summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2014-05-01 03:07:18 +0000
committerReid Kleckner <reid@kleckner.net>2014-05-01 03:07:18 +0000
commitac64060c80120c0910f07c452fa38aa836b43860 (patch)
tree747fd95007b45367769d5a6c0ba1bbaa93b0a149 /clang/lib/CodeGen
parentd730500706a9f568ada2b6dee05823e8fff8a641 (diff)
downloadbcm5719-llvm-ac64060c80120c0910f07c452fa38aa836b43860.tar.gz
bcm5719-llvm-ac64060c80120c0910f07c452fa38aa836b43860.zip
MS ABI x64: Don't destroy arguments twice on x64
We were destroying them in the callee, and then again in the caller. We should use an EH-only cleanup and disable it at the point of the call for win64, even though we don't use inalloca. llvm-svn: 207733
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGCall.cpp15
1 files changed, 11 insertions, 4 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index e82b6defa6b..4428b963162 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2286,16 +2286,23 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
// In the Microsoft C++ ABI, aggregate arguments are destructed by the callee.
// However, we still have to push an EH-only cleanup in case we unwind before
// we make it to the call.
- if (HasAggregateEvalKind && args.isUsingInAlloca()) {
- assert(getTarget().getTriple().getArch() == llvm::Triple::x86);
- AggValueSlot Slot = createPlaceholderSlot(*this, type);
+ if (HasAggregateEvalKind &&
+ CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
+ // If we're using inalloca, use the argument memory. Otherwise, use a
+ // temporary. Either way, the aggregate is destroyed externally in the
+ // callee.
+ AggValueSlot Slot;
+ if (args.isUsingInAlloca())
+ Slot = createPlaceholderSlot(*this, type);
+ else
+ Slot = CreateAggTemp(type, "agg.tmp");
Slot.setExternallyDestructed();
EmitAggExpr(E, Slot);
RValue RV = Slot.asRValue();
args.add(RV, type);
const CXXRecordDecl *RD = type->getAsCXXRecordDecl();
- if (RD->hasNonTrivialDestructor()) {
+ if (RD && RD->hasNonTrivialDestructor()) {
// Create a no-op GEP between the placeholder and the cleanup so we can
// RAUW it successfully. It also serves as a marker of the first
// instruction where the cleanup is active.
OpenPOWER on IntegriCloud