Skip to content

Commit c9a52de

Browse files
committed
[CodeGen] Simplify the way lifetime of block captures is extended
Rather than pushing inactive cleanups for the block captures at the entry of a full expression and activating them during the creation of the block literal, just call pushLifetimeExtendedDestroy to ensure the cleanups are popped at the end of the scope enclosing the block expression. rdar://problem/63996471 Differential Revision: https://reviews.llvm.org/D81624
1 parent 8d8ec55 commit c9a52de

21 files changed

+148
-245
lines changed

clang/lib/CodeGen/CGBlocks.cpp

Lines changed: 67 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name)
3636
: Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false),
3737
HasCXXObject(false), UsesStret(false), HasCapturedVariableLayout(false),
3838
CapturesNonExternalType(false), LocalAddress(Address::invalid()),
39-
StructureType(nullptr), Block(block), DominatingIP(nullptr) {
39+
StructureType(nullptr), Block(block) {
4040

4141
// Skip asm prefix, if any. 'name' is usually taken directly from
4242
// the mangled name of the enclosing function.
@@ -775,151 +775,23 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
775775
llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
776776
}
777777

778-
/// Enter the scope of a block. This should be run at the entrance to
779-
/// a full-expression so that the block's cleanups are pushed at the
780-
/// right place in the stack.
781-
static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) {
782-
assert(CGF.HaveInsertPoint());
783-
784-
// Allocate the block info and place it at the head of the list.
785-
CGBlockInfo &blockInfo =
786-
*new CGBlockInfo(block, CGF.CurFn->getName());
787-
blockInfo.NextBlockInfo = CGF.FirstBlockInfo;
788-
CGF.FirstBlockInfo = &blockInfo;
789-
790-
// Compute information about the layout, etc., of this block,
791-
// pushing cleanups as necessary.
792-
computeBlockInfo(CGF.CGM, &CGF, blockInfo);
793-
794-
// Nothing else to do if it can be global.
795-
if (blockInfo.CanBeGlobal) return;
796-
797-
// Make the allocation for the block.
798-
blockInfo.LocalAddress = CGF.CreateTempAlloca(blockInfo.StructureType,
799-
blockInfo.BlockAlign, "block");
800-
801-
// If there are cleanups to emit, enter them (but inactive).
802-
if (!blockInfo.NeedsCopyDispose) return;
803-
804-
// Walk through the captures (in order) and find the ones not
805-
// captured by constant.
806-
for (const auto &CI : block->captures()) {
807-
// Ignore __block captures; there's nothing special in the
808-
// on-stack block that we need to do for them.
809-
if (CI.isByRef()) continue;
810-
811-
// Ignore variables that are constant-captured.
812-
const VarDecl *variable = CI.getVariable();
813-
CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
814-
if (capture.isConstant()) continue;
815-
816-
// Ignore objects that aren't destructed.
817-
QualType VT = getCaptureFieldType(CGF, CI);
818-
QualType::DestructionKind dtorKind = VT.isDestructedType();
819-
if (dtorKind == QualType::DK_none) continue;
820-
821-
CodeGenFunction::Destroyer *destroyer;
822-
823-
// Block captures count as local values and have imprecise semantics.
824-
// They also can't be arrays, so need to worry about that.
825-
//
826-
// For const-qualified captures, emit clang.arc.use to ensure the captured
827-
// object doesn't get released while we are still depending on its validity
828-
// within the block.
829-
if (VT.isConstQualified() &&
830-
VT.getObjCLifetime() == Qualifiers::OCL_Strong &&
831-
CGF.CGM.getCodeGenOpts().OptimizationLevel != 0) {
832-
assert(CGF.CGM.getLangOpts().ObjCAutoRefCount &&
833-
"expected ObjC ARC to be enabled");
834-
destroyer = CodeGenFunction::emitARCIntrinsicUse;
835-
} else if (dtorKind == QualType::DK_objc_strong_lifetime) {
836-
destroyer = CodeGenFunction::destroyARCStrongImprecise;
837-
} else {
838-
destroyer = CGF.getDestroyer(dtorKind);
839-
}
840-
841-
// GEP down to the address.
842-
Address addr =
843-
CGF.Builder.CreateStructGEP(blockInfo.LocalAddress, capture.getIndex());
844-
845-
// We can use that GEP as the dominating IP.
846-
if (!blockInfo.DominatingIP)
847-
blockInfo.DominatingIP = cast<llvm::Instruction>(addr.getPointer());
848-
849-
CleanupKind cleanupKind = InactiveNormalCleanup;
850-
bool useArrayEHCleanup = CGF.needsEHCleanup(dtorKind);
851-
if (useArrayEHCleanup)
852-
cleanupKind = InactiveNormalAndEHCleanup;
853-
854-
CGF.pushDestroy(cleanupKind, addr, VT,
855-
destroyer, useArrayEHCleanup);
856-
857-
// Remember where that cleanup was.
858-
capture.setCleanup(CGF.EHStack.stable_begin());
859-
}
860-
}
861-
862-
/// Enter a full-expression with a non-trivial number of objects to
863-
/// clean up.
864-
void CodeGenFunction::enterNonTrivialFullExpression(const FullExpr *E) {
865-
if (const auto EWC = dyn_cast<ExprWithCleanups>(E)) {
866-
assert(EWC->getNumObjects() != 0);
867-
for (const ExprWithCleanups::CleanupObject &C : EWC->getObjects())
868-
if (auto *BD = C.dyn_cast<BlockDecl *>())
869-
enterBlockScope(*this, BD);
870-
}
871-
}
872-
873-
/// Find the layout for the given block in a linked list and remove it.
874-
static CGBlockInfo *findAndRemoveBlockInfo(CGBlockInfo **head,
875-
const BlockDecl *block) {
876-
while (true) {
877-
assert(head && *head);
878-
CGBlockInfo *cur = *head;
879-
880-
// If this is the block we're looking for, splice it out of the list.
881-
if (cur->getBlockDecl() == block) {
882-
*head = cur->NextBlockInfo;
883-
return cur;
884-
}
885-
886-
head = &cur->NextBlockInfo;
887-
}
888-
}
889-
890-
/// Destroy a chain of block layouts.
891-
void CodeGenFunction::destroyBlockInfos(CGBlockInfo *head) {
892-
assert(head && "destroying an empty chain");
893-
do {
894-
CGBlockInfo *cur = head;
895-
head = cur->NextBlockInfo;
896-
delete cur;
897-
} while (head != nullptr);
898-
}
899-
900778
/// Emit a block literal expression in the current function.
901779
llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
902780
// If the block has no captures, we won't have a pre-computed
903781
// layout for it.
904-
if (!blockExpr->getBlockDecl()->hasCaptures()) {
782+
if (!blockExpr->getBlockDecl()->hasCaptures())
905783
// The block literal is emitted as a global variable, and the block invoke
906784
// function has to be extracted from its initializer.
907-
if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmitted(blockExpr)) {
785+
if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmitted(blockExpr))
908786
return Block;
909-
}
910-
CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName());
911-
computeBlockInfo(CGM, this, blockInfo);
912-
blockInfo.BlockExpression = blockExpr;
913-
return EmitBlockLiteral(blockInfo);
914-
}
915-
916-
// Find the block info for this block and take ownership of it.
917-
std::unique_ptr<CGBlockInfo> blockInfo;
918-
blockInfo.reset(findAndRemoveBlockInfo(&FirstBlockInfo,
919-
blockExpr->getBlockDecl()));
920787

921-
blockInfo->BlockExpression = blockExpr;
922-
return EmitBlockLiteral(*blockInfo);
788+
CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName());
789+
computeBlockInfo(CGM, this, blockInfo);
790+
blockInfo.BlockExpression = blockExpr;
791+
if (!blockInfo.CanBeGlobal)
792+
blockInfo.LocalAddress = CreateTempAlloca(blockInfo.StructureType,
793+
blockInfo.BlockAlign, "block");
794+
return EmitBlockLiteral(blockInfo);
923795
}
924796

925797
llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
@@ -1161,12 +1033,64 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
11611033
/*captured by init*/ false);
11621034
}
11631035

1164-
// Activate the cleanup if layout pushed one.
1165-
if (!CI.isByRef()) {
1166-
EHScopeStack::stable_iterator cleanup = capture.getCleanup();
1167-
if (cleanup.isValid())
1168-
ActivateCleanupBlock(cleanup, blockInfo.DominatingIP);
1036+
// Push a cleanup for the capture if necessary.
1037+
if (!blockInfo.NeedsCopyDispose)
1038+
continue;
1039+
1040+
// Ignore __block captures; there's nothing special in the on-stack block
1041+
// that we need to do for them.
1042+
if (CI.isByRef())
1043+
continue;
1044+
1045+
// Ignore objects that aren't destructed.
1046+
QualType::DestructionKind dtorKind = type.isDestructedType();
1047+
if (dtorKind == QualType::DK_none)
1048+
continue;
1049+
1050+
CodeGenFunction::Destroyer *destroyer;
1051+
1052+
// Block captures count as local values and have imprecise semantics.
1053+
// They also can't be arrays, so need to worry about that.
1054+
//
1055+
// For const-qualified captures, emit clang.arc.use to ensure the captured
1056+
// object doesn't get released while we are still depending on its validity
1057+
// within the block.
1058+
if (type.isConstQualified() &&
1059+
type.getObjCLifetime() == Qualifiers::OCL_Strong &&
1060+
CGM.getCodeGenOpts().OptimizationLevel != 0) {
1061+
assert(CGM.getLangOpts().ObjCAutoRefCount &&
1062+
"expected ObjC ARC to be enabled");
1063+
destroyer = emitARCIntrinsicUse;
1064+
} else if (dtorKind == QualType::DK_objc_strong_lifetime) {
1065+
destroyer = destroyARCStrongImprecise;
1066+
} else {
1067+
destroyer = getDestroyer(dtorKind);
11691068
}
1069+
1070+
CleanupKind cleanupKind = NormalCleanup;
1071+
bool useArrayEHCleanup = needsEHCleanup(dtorKind);
1072+
if (useArrayEHCleanup)
1073+
cleanupKind = NormalAndEHCleanup;
1074+
1075+
// Extend the lifetime of the capture to the end of the scope enclosing the
1076+
// block expression except when the block decl is in the list of RetExpr's
1077+
// cleanup objects, in which case its lifetime ends after the full
1078+
// expression.
1079+
auto IsBlockDeclInRetExpr = [&]() {
1080+
auto *EWC = llvm::dyn_cast_or_null<ExprWithCleanups>(RetExpr);
1081+
if (EWC)
1082+
for (auto &C : EWC->getObjects())
1083+
if (auto *BD = C.dyn_cast<BlockDecl *>())
1084+
if (BD == blockDecl)
1085+
return true;
1086+
return false;
1087+
};
1088+
1089+
if (IsBlockDeclInRetExpr())
1090+
pushDestroy(cleanupKind, blockField, type, destroyer, useArrayEHCleanup);
1091+
else
1092+
pushLifetimeExtendedDestroy(cleanupKind, blockField, type, destroyer,
1093+
useArrayEHCleanup);
11701094
}
11711095

11721096
// Cast to the converted block-pointer type, which happens (somewhat

clang/lib/CodeGen/CGBlocks.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,6 @@ class CGBlockInfo {
257257
// This could be zero if no forced alignment is required.
258258
CharUnits BlockHeaderForcedGapSize;
259259

260-
/// An instruction which dominates the full-expression that the
261-
/// block is inside.
262-
llvm::Instruction *DominatingIP;
263-
264260
/// The next block in the block-info chain. Invalid if this block
265261
/// info is not part of the CGF's block-info chain, which is true
266262
/// if it corresponds to a global block or a block whose expression

clang/lib/CodeGen/CGCleanup.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,10 @@ void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) {
179179
char *Buffer = allocate(EHCleanupScope::getSizeForCleanupSize(Size));
180180
bool IsNormalCleanup = Kind & NormalCleanup;
181181
bool IsEHCleanup = Kind & EHCleanup;
182-
bool IsActive = !(Kind & InactiveCleanup);
183182
bool IsLifetimeMarker = Kind & LifetimeMarker;
184183
EHCleanupScope *Scope =
185184
new (Buffer) EHCleanupScope(IsNormalCleanup,
186185
IsEHCleanup,
187-
IsActive,
188186
Size,
189187
BranchFixups.size(),
190188
InnermostNormalCleanup,

clang/lib/CodeGen/CGCleanup.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,16 +284,16 @@ class alignas(8) EHCleanupScope : public EHScope {
284284
return sizeof(EHCleanupScope) + CleanupBits.CleanupSize;
285285
}
286286

287-
EHCleanupScope(bool isNormal, bool isEH, bool isActive,
288-
unsigned cleanupSize, unsigned fixupDepth,
287+
EHCleanupScope(bool isNormal, bool isEH, unsigned cleanupSize,
288+
unsigned fixupDepth,
289289
EHScopeStack::stable_iterator enclosingNormal,
290290
EHScopeStack::stable_iterator enclosingEH)
291291
: EHScope(EHScope::Cleanup, enclosingEH),
292292
EnclosingNormal(enclosingNormal), NormalBlock(nullptr),
293293
ActiveFlag(nullptr), ExtInfo(nullptr), FixupDepth(fixupDepth) {
294294
CleanupBits.IsNormalCleanup = isNormal;
295295
CleanupBits.IsEHCleanup = isEH;
296-
CleanupBits.IsActive = isActive;
296+
CleanupBits.IsActive = true;
297297
CleanupBits.IsLifetimeMarker = false;
298298
CleanupBits.TestFlagInNormalCleanup = false;
299299
CleanupBits.TestFlagInEHCleanup = false;

clang/lib/CodeGen/CGDecl.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -762,10 +762,9 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
762762

763763
// If we're emitting a value with lifetime, we have to do the
764764
// initialization *before* we leave the cleanup scopes.
765-
if (const FullExpr *fe = dyn_cast<FullExpr>(init)) {
766-
enterFullExpression(fe);
765+
if (const FullExpr *fe = dyn_cast<FullExpr>(init))
767766
init = fe->getSubExpr();
768-
}
767+
769768
CodeGenFunction::RunCleanupsScope Scope(*this);
770769

771770
// We have to maintain the illusion that the variable is

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1330,7 +1330,6 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
13301330

13311331
case Expr::ExprWithCleanupsClass: {
13321332
const auto *cleanups = cast<ExprWithCleanups>(E);
1333-
enterFullExpression(cleanups);
13341333
RunCleanupsScope Scope(*this);
13351334
LValue LV = EmitLValue(cleanups->getSubExpr());
13361335
if (LV.isSimple()) {

clang/lib/CodeGen/CGExprAgg.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1349,7 +1349,6 @@ AggExprEmitter::VisitLambdaExpr(LambdaExpr *E) {
13491349
}
13501350

13511351
void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *E) {
1352-
CGF.enterFullExpression(E);
13531352
CodeGenFunction::RunCleanupsScope cleanups(CGF);
13541353
Visit(E->getSubExpr());
13551354
}

clang/lib/CodeGen/CGExprComplex.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,6 @@ class ComplexExprEmitter
222222
return Visit(DIE->getExpr());
223223
}
224224
ComplexPairTy VisitExprWithCleanups(ExprWithCleanups *E) {
225-
CGF.enterFullExpression(E);
226225
CodeGenFunction::RunCleanupsScope Scope(CGF);
227226
ComplexPairTy Vals = Visit(E->getSubExpr());
228227
// Defend against dominance problems caused by jumps out of expression

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2342,7 +2342,6 @@ Value *ScalarExprEmitter::VisitStmtExpr(const StmtExpr *E) {
23422342
}
23432343

23442344
Value *ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *E) {
2345-
CGF.enterFullExpression(E);
23462345
CodeGenFunction::RunCleanupsScope Scope(CGF);
23472346
Value *V = Visit(E->getSubExpr());
23482347
// Defend against dominance problems caused by jumps out of expression

clang/lib/CodeGen/CGObjC.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3256,7 +3256,6 @@ static llvm::Value *emitARCRetainLoadOfScalar(CodeGenFunction &CGF,
32563256
llvm::Value *CodeGenFunction::EmitARCRetainScalarExpr(const Expr *e) {
32573257
// The retain needs to happen within the full-expression.
32583258
if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) {
3259-
enterFullExpression(cleanups);
32603259
RunCleanupsScope scope(*this);
32613260
return EmitARCRetainScalarExpr(cleanups->getSubExpr());
32623261
}
@@ -3272,7 +3271,6 @@ llvm::Value *
32723271
CodeGenFunction::EmitARCRetainAutoreleaseScalarExpr(const Expr *e) {
32733272
// The retain needs to happen within the full-expression.
32743273
if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) {
3275-
enterFullExpression(cleanups);
32763274
RunCleanupsScope scope(*this);
32773275
return EmitARCRetainAutoreleaseScalarExpr(cleanups->getSubExpr());
32783276
}
@@ -3383,7 +3381,6 @@ static llvm::Value *emitARCUnsafeUnretainedScalarExpr(CodeGenFunction &CGF,
33833381
llvm::Value *CodeGenFunction::EmitARCUnsafeUnretainedScalarExpr(const Expr *e) {
33843382
// Look through full-expressions.
33853383
if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) {
3386-
enterFullExpression(cleanups);
33873384
RunCleanupsScope scope(*this);
33883385
return emitARCUnsafeUnretainedScalarExpr(*this, cleanups->getSubExpr());
33893386
}

clang/lib/CodeGen/CGStmt.cpp

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,19 @@ void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
10701070
EmitBranchThroughCleanup(ReturnBlock);
10711071
}
10721072

1073+
namespace {
1074+
// RAII struct used to save and restore a return statment's result expression.
1075+
struct SaveRetExprRAII {
1076+
SaveRetExprRAII(const Expr *RetExpr, CodeGenFunction &CGF)
1077+
: OldRetExpr(CGF.RetExpr), CGF(CGF) {
1078+
CGF.RetExpr = RetExpr;
1079+
}
1080+
~SaveRetExprRAII() { CGF.RetExpr = OldRetExpr; }
1081+
const Expr *OldRetExpr;
1082+
CodeGenFunction &CGF;
1083+
};
1084+
} // namespace
1085+
10731086
/// EmitReturnStmt - Note that due to GCC extensions, this can have an operand
10741087
/// if the function returns void, or may be missing one if the function returns
10751088
/// non-void. Fun stuff :).
@@ -1095,15 +1108,19 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
10951108
// Emit the result value, even if unused, to evaluate the side effects.
10961109
const Expr *RV = S.getRetValue();
10971110

1098-
// Treat block literals in a return expression as if they appeared
1099-
// in their own scope. This permits a small, easily-implemented
1100-
// exception to our over-conservative rules about not jumping to
1101-
// statements following block literals with non-trivial cleanups.
1111+
// Record the result expression of the return statement. The recorded
1112+
// expression is used to determine whether a block capture's lifetime should
1113+
// end at the end of the full expression as opposed to the end of the scope
1114+
// enclosing the block expression.
1115+
//
1116+
// This permits a small, easily-implemented exception to our over-conservative
1117+
// rules about not jumping to statements following block literals with
1118+
// non-trivial cleanups.
1119+
SaveRetExprRAII SaveRetExpr(RV, *this);
1120+
11021121
RunCleanupsScope cleanupScope(*this);
1103-
if (const FullExpr *fe = dyn_cast_or_null<FullExpr>(RV)) {
1104-
enterFullExpression(fe);
1122+
if (const FullExpr *fe = dyn_cast_or_null<FullExpr>(RV))
11051123
RV = fe->getSubExpr();
1106-
}
11071124

11081125
// FIXME: Clean this up by using an LValue for ReturnTemp,
11091126
// EmitStoreThroughLValue, and EmitAnyExpr.

0 commit comments

Comments
 (0)