diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprComplex.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjC.cpp | 70 |
6 files changed, 80 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 7ae95331ad5..520b1bbfb8a 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -2061,7 +2061,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CK_AnyPointerToBlockPointerCast: case CK_ObjCProduceObject: case CK_ObjCConsumeObject: - case CK_ObjCReclaimReturnedObject: { + case CK_ObjCReclaimReturnedObject: + case CK_ObjCExtendBlockObject: { // These casts only produce lvalues when we're binding a reference to a // temporary realized from a (converted) pure rvalue. Emit the expression // as a value, copy it into a temporary, and return an lvalue referring to diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index fe6dfcd28fd..93c7bd8af6f 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -382,6 +382,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { case CK_ObjCProduceObject: case CK_ObjCConsumeObject: case CK_ObjCReclaimReturnedObject: + case CK_ObjCExtendBlockObject: llvm_unreachable("cast kind invalid for aggregate types"); } } diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 90e288a4508..326fcfa15bf 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -414,6 +414,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastExpr::CastKind CK, Expr *Op, case CK_ObjCProduceObject: case CK_ObjCConsumeObject: case CK_ObjCReclaimReturnedObject: + case CK_ObjCExtendBlockObject: llvm_unreachable("invalid cast kind for complex value"); case CK_FloatingRealToComplex: diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index b51ff386562..7ab77709e03 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -589,6 +589,7 @@ public: case CK_ObjCProduceObject: case CK_ObjCConsumeObject: case CK_ObjCReclaimReturnedObject: + case CK_ObjCExtendBlockObject: return 0; // These might need to be supported for constexpr. diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 35876d8c319..6741f433660 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -1027,7 +1027,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { ConvertType(CGF.getContext().getPointerType(DestTy))); return EmitLoadOfLValue(CGF.MakeAddrLValue(V, DestTy)); } - + case CK_CPointerToObjCPointerCast: case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: @@ -1124,6 +1124,10 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { value = CGF.EmitARCRetainAutoreleasedReturnValue(value); return CGF.EmitObjCConsumeObject(E->getType(), value); } + case CK_ObjCExtendBlockObject: { + llvm::Value *value = CGF.EmitARCRetainScalarExpr(E); + return CGF.EmitObjCConsumeObject(E->getType(), value); + } case CK_FloatingRealToComplex: case CK_FloatingComplexCast: diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 17ace4fc1ac..037eed04305 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -1959,6 +1959,42 @@ static llvm::Value *emitARCRetainAfterCall(CodeGenFunction &CGF, } } +/// Determine whether it might be important to emit a separate +/// objc_retain_block on the result of the given expression, or +/// whether it's okay to just emit it in a +1 context. +static bool shouldEmitSeparateBlockRetain(const Expr *e) { + assert(e->getType()->isBlockPointerType()); + e = e->IgnoreParens(); + + // For future goodness, emit block expressions directly in +1 + // contexts if we can. + if (isa<BlockExpr>(e)) + return false; + + if (const CastExpr *cast = dyn_cast<CastExpr>(e)) { + switch (cast->getCastKind()) { + // Emitting these operations in +1 contexts is goodness. + case CK_LValueToRValue: + case CK_ObjCReclaimReturnedObject: + case CK_ObjCConsumeObject: + case CK_ObjCProduceObject: + return false; + + // These operations preserve a block type. + case CK_NoOp: + case CK_BitCast: + return shouldEmitSeparateBlockRetain(cast->getSubExpr()); + + // These operations are known to be bad (or haven't been considered). + case CK_AnyPointerToBlockPointerCast: + default: + return true; + } + } + + return true; +} + static TryEmitResult tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) { // Look through cleanups. @@ -2015,6 +2051,40 @@ tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) { return TryEmitResult(result, true); } + // Block extends are net +0. Naively, we could just recurse on + // the subexpression, but actually we need to ensure that the + // value is copied as a block, so there's a little filter here. + case CK_ObjCExtendBlockObject: { + llvm::Value *result; // will be a +0 value + + // If we can't safely assume the sub-expression will produce a + // block-copied value, emit the sub-expression at +0. + if (shouldEmitSeparateBlockRetain(ce->getSubExpr())) { + result = CGF.EmitScalarExpr(ce->getSubExpr()); + + // Otherwise, try to emit the sub-expression at +1 recursively. + } else { + TryEmitResult subresult + = tryEmitARCRetainScalarExpr(CGF, ce->getSubExpr()); + result = subresult.getPointer(); + + // If that produced a retained value, just use that, + // possibly casting down. + if (subresult.getInt()) { + if (resultType) + result = CGF.Builder.CreateBitCast(result, resultType); + return TryEmitResult(result, true); + } + + // Otherwise it's +0. + } + + // Retain the object as a block, then cast down. + result = CGF.EmitARCRetainBlock(result); + if (resultType) result = CGF.Builder.CreateBitCast(result, resultType); + return TryEmitResult(result, true); + } + // For reclaims, emit the subexpression as a retained call and // skip the consumption. case CK_ObjCReclaimReturnedObject: { |