summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2016-11-18 01:08:24 +0000
committerJohn McCall <rjmccall@apple.com>2016-11-18 01:08:24 +0000
commit811b291d8c3d262b8705b6d57ccd0ca7392765d8 (patch)
treeb7c88ab232fe72c2f5dd0fb8e31b81892661e6f7 /clang/lib/CodeGen
parent2d2292009ff6715e1432a29e28d1303a1e36dacc (diff)
downloadbcm5719-llvm-811b291d8c3d262b8705b6d57ccd0ca7392765d8.tar.gz
bcm5719-llvm-811b291d8c3d262b8705b6d57ccd0ca7392765d8.zip
Forward ns_consumed delegate arguments with a move.
StartFunction enters a release cleanup for ns_consumed arguments in ARC, so we need to balance that somehow. We could teach StartFunction that it's emitting a delegating function, so that the cleanup is unnecessary, but that would be invasive and somewhat fraught. We could balance the consumed argument with an extra retain, but clearing the original variable should be easier to optimize and avoid some extra work at -O0. And there shouldn't be any difference as long as nothing else uses the argument, which should always be true for the places we emit delegate arguments. Fixes PR 27887. llvm-svn: 287291
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGCall.cpp24
1 files changed, 21 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 2fc16049f6b..54468d939d3 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2912,12 +2912,30 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args,
assert(!isInAllocaArgument(CGM.getCXXABI(), type) &&
"cannot emit delegate call arguments for inalloca arguments!");
+ // GetAddrOfLocalVar returns a pointer-to-pointer for references,
+ // but the argument needs to be the original pointer.
+ if (type->isReferenceType()) {
+ args.add(RValue::get(Builder.CreateLoad(local)), type);
+
+ // In ARC, move out of consumed arguments so that the release cleanup
+ // entered by StartFunction doesn't cause an over-release. This isn't
+ // optimal -O0 code generation, but it should get cleaned up when
+ // optimization is enabled. This also assumes that delegate calls are
+ // performed exactly once for a set of arguments, but that should be safe.
+ } else if (getLangOpts().ObjCAutoRefCount &&
+ param->hasAttr<NSConsumedAttr>() &&
+ type->isObjCRetainableType()) {
+ llvm::Value *ptr = Builder.CreateLoad(local);
+ auto null =
+ llvm::ConstantPointerNull::get(cast<llvm::PointerType>(ptr->getType()));
+ Builder.CreateStore(null, local);
+ args.add(RValue::get(ptr), type);
+
// For the most part, we just need to load the alloca, except that
// aggregate r-values are actually pointers to temporaries.
- if (type->isReferenceType())
- args.add(RValue::get(Builder.CreateLoad(local)), type);
- else
+ } else {
args.add(convertTempToRValue(local, type, loc), type);
+ }
}
static bool isProvablyNull(llvm::Value *addr) {
OpenPOWER on IntegriCloud