diff options
| author | Reid Kleckner <reid@kleckner.net> | 2014-05-01 03:07:18 +0000 |
|---|---|---|
| committer | Reid Kleckner <reid@kleckner.net> | 2014-05-01 03:07:18 +0000 |
| commit | ac64060c80120c0910f07c452fa38aa836b43860 (patch) | |
| tree | 747fd95007b45367769d5a6c0ba1bbaa93b0a149 /clang/lib/CodeGen | |
| parent | d730500706a9f568ada2b6dee05823e8fff8a641 (diff) | |
| download | bcm5719-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.cpp | 15 |
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. |

