diff options
Diffstat (limited to 'clang/lib/CodeGen/CGBlocks.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGBlocks.cpp | 223 |
1 files changed, 76 insertions, 147 deletions
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 11f54d1f7fb2..615b78235041 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -36,7 +36,7 @@ CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name) : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false), HasCXXObject(false), UsesStret(false), HasCapturedVariableLayout(false), CapturesNonExternalType(false), LocalAddress(Address::invalid()), - StructureType(nullptr), Block(block), DominatingIP(nullptr) { + StructureType(nullptr), Block(block) { // Skip asm prefix, if any. 'name' is usually taken directly from // the mangled name of the enclosing function. @@ -775,151 +775,23 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF, llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); } -/// Enter the scope of a block. This should be run at the entrance to -/// a full-expression so that the block's cleanups are pushed at the -/// right place in the stack. -static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) { - assert(CGF.HaveInsertPoint()); - - // Allocate the block info and place it at the head of the list. - CGBlockInfo &blockInfo = - *new CGBlockInfo(block, CGF.CurFn->getName()); - blockInfo.NextBlockInfo = CGF.FirstBlockInfo; - CGF.FirstBlockInfo = &blockInfo; - - // Compute information about the layout, etc., of this block, - // pushing cleanups as necessary. - computeBlockInfo(CGF.CGM, &CGF, blockInfo); - - // Nothing else to do if it can be global. - if (blockInfo.CanBeGlobal) return; - - // Make the allocation for the block. - blockInfo.LocalAddress = CGF.CreateTempAlloca(blockInfo.StructureType, - blockInfo.BlockAlign, "block"); - - // If there are cleanups to emit, enter them (but inactive). - if (!blockInfo.NeedsCopyDispose) return; - - // Walk through the captures (in order) and find the ones not - // captured by constant. - for (const auto &CI : block->captures()) { - // Ignore __block captures; there's nothing special in the - // on-stack block that we need to do for them. - if (CI.isByRef()) continue; - - // Ignore variables that are constant-captured. - const VarDecl *variable = CI.getVariable(); - CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); - if (capture.isConstant()) continue; - - // Ignore objects that aren't destructed. - QualType VT = getCaptureFieldType(CGF, CI); - QualType::DestructionKind dtorKind = VT.isDestructedType(); - if (dtorKind == QualType::DK_none) continue; - - CodeGenFunction::Destroyer *destroyer; - - // Block captures count as local values and have imprecise semantics. - // They also can't be arrays, so need to worry about that. - // - // For const-qualified captures, emit clang.arc.use to ensure the captured - // object doesn't get released while we are still depending on its validity - // within the block. - if (VT.isConstQualified() && - VT.getObjCLifetime() == Qualifiers::OCL_Strong && - CGF.CGM.getCodeGenOpts().OptimizationLevel != 0) { - assert(CGF.CGM.getLangOpts().ObjCAutoRefCount && - "expected ObjC ARC to be enabled"); - destroyer = CodeGenFunction::emitARCIntrinsicUse; - } else if (dtorKind == QualType::DK_objc_strong_lifetime) { - destroyer = CodeGenFunction::destroyARCStrongImprecise; - } else { - destroyer = CGF.getDestroyer(dtorKind); - } - - // GEP down to the address. - Address addr = - CGF.Builder.CreateStructGEP(blockInfo.LocalAddress, capture.getIndex()); - - // We can use that GEP as the dominating IP. - if (!blockInfo.DominatingIP) - blockInfo.DominatingIP = cast<llvm::Instruction>(addr.getPointer()); - - CleanupKind cleanupKind = InactiveNormalCleanup; - bool useArrayEHCleanup = CGF.needsEHCleanup(dtorKind); - if (useArrayEHCleanup) - cleanupKind = InactiveNormalAndEHCleanup; - - CGF.pushDestroy(cleanupKind, addr, VT, - destroyer, useArrayEHCleanup); - - // Remember where that cleanup was. - capture.setCleanup(CGF.EHStack.stable_begin()); - } -} - -/// Enter a full-expression with a non-trivial number of objects to -/// clean up. This is in this file because, at the moment, the only -/// kind of cleanup object is a BlockDecl*. -void CodeGenFunction::enterNonTrivialFullExpression(const FullExpr *E) { - if (const auto EWC = dyn_cast<ExprWithCleanups>(E)) { - assert(EWC->getNumObjects() != 0); - for (const ExprWithCleanups::CleanupObject &C : EWC->getObjects()) - enterBlockScope(*this, C); - } -} - -/// Find the layout for the given block in a linked list and remove it. -static CGBlockInfo *findAndRemoveBlockInfo(CGBlockInfo **head, - const BlockDecl *block) { - while (true) { - assert(head && *head); - CGBlockInfo *cur = *head; - - // If this is the block we're looking for, splice it out of the list. - if (cur->getBlockDecl() == block) { - *head = cur->NextBlockInfo; - return cur; - } - - head = &cur->NextBlockInfo; - } -} - -/// Destroy a chain of block layouts. -void CodeGenFunction::destroyBlockInfos(CGBlockInfo *head) { - assert(head && "destroying an empty chain"); - do { - CGBlockInfo *cur = head; - head = cur->NextBlockInfo; - delete cur; - } while (head != nullptr); -} - /// Emit a block literal expression in the current function. llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { // If the block has no captures, we won't have a pre-computed // layout for it. - if (!blockExpr->getBlockDecl()->hasCaptures()) { + if (!blockExpr->getBlockDecl()->hasCaptures()) // The block literal is emitted as a global variable, and the block invoke // function has to be extracted from its initializer. - if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmitted(blockExpr)) { + if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmitted(blockExpr)) return Block; - } - CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName()); - computeBlockInfo(CGM, this, blockInfo); - blockInfo.BlockExpression = blockExpr; - return EmitBlockLiteral(blockInfo); - } - - // Find the block info for this block and take ownership of it. - std::unique_ptr<CGBlockInfo> blockInfo; - blockInfo.reset(findAndRemoveBlockInfo(&FirstBlockInfo, - blockExpr->getBlockDecl())); - blockInfo->BlockExpression = blockExpr; - return EmitBlockLiteral(*blockInfo); + CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName()); + computeBlockInfo(CGM, this, blockInfo); + blockInfo.BlockExpression = blockExpr; + if (!blockInfo.CanBeGlobal) + blockInfo.LocalAddress = CreateTempAlloca(blockInfo.StructureType, + blockInfo.BlockAlign, "block"); + return EmitBlockLiteral(blockInfo); } llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { @@ -1161,12 +1033,64 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { /*captured by init*/ false); } - // Activate the cleanup if layout pushed one. - if (!CI.isByRef()) { - EHScopeStack::stable_iterator cleanup = capture.getCleanup(); - if (cleanup.isValid()) - ActivateCleanupBlock(cleanup, blockInfo.DominatingIP); + // Push a cleanup for the capture if necessary. + if (!blockInfo.NeedsCopyDispose) + continue; + + // Ignore __block captures; there's nothing special in the on-stack block + // that we need to do for them. + if (CI.isByRef()) + continue; + + // Ignore objects that aren't destructed. + QualType::DestructionKind dtorKind = type.isDestructedType(); + if (dtorKind == QualType::DK_none) + continue; + + CodeGenFunction::Destroyer *destroyer; + + // Block captures count as local values and have imprecise semantics. + // They also can't be arrays, so need to worry about that. + // + // For const-qualified captures, emit clang.arc.use to ensure the captured + // object doesn't get released while we are still depending on its validity + // within the block. + if (type.isConstQualified() && + type.getObjCLifetime() == Qualifiers::OCL_Strong && + CGM.getCodeGenOpts().OptimizationLevel != 0) { + assert(CGM.getLangOpts().ObjCAutoRefCount && + "expected ObjC ARC to be enabled"); + destroyer = emitARCIntrinsicUse; + } else if (dtorKind == QualType::DK_objc_strong_lifetime) { + destroyer = destroyARCStrongImprecise; + } else { + destroyer = getDestroyer(dtorKind); } + + CleanupKind cleanupKind = NormalCleanup; + bool useArrayEHCleanup = needsEHCleanup(dtorKind); + if (useArrayEHCleanup) + cleanupKind = NormalAndEHCleanup; + + // Extend the lifetime of the capture to the end of the scope enclosing the + // block expression except when the block decl is in the list of RetExpr's + // cleanup objects, in which case its lifetime ends after the full + // expression. + auto IsBlockDeclInRetExpr = [&]() { + auto *EWC = llvm::dyn_cast_or_null<ExprWithCleanups>(RetExpr); + if (EWC) + for (auto &C : EWC->getObjects()) + if (auto *BD = C.dyn_cast<BlockDecl *>()) + if (BD == blockDecl) + return true; + return false; + }; + + if (IsBlockDeclInRetExpr()) + pushDestroy(cleanupKind, blockField, type, destroyer, useArrayEHCleanup); + else + pushLifetimeExtendedDestroy(cleanupKind, blockField, type, destroyer, + useArrayEHCleanup); } // Cast to the converted block-pointer type, which happens (somewhat @@ -1449,7 +1373,8 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, llvm::IRBuilder<> b(llvm::BasicBlock::Create(CGM.getLLVMContext(), "entry", Init)); b.CreateAlignedStore(CGM.getNSConcreteGlobalBlock(), - b.CreateStructGEP(literal, 0), CGM.getPointerAlign().getQuantity()); + b.CreateStructGEP(literal, 0), + CGM.getPointerAlign().getAsAlign()); b.CreateRetVoid(); // We can't use the normal LLVM global initialisation array, because we // need to specify that this runs early in library initialisation. @@ -2031,11 +1956,13 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { FunctionDecl *FD = FunctionDecl::Create( C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II, FunctionTy, nullptr, SC_Static, false, false); - setBlockHelperAttributesVisibility(blockInfo.CapturesNonExternalType, Fn, FI, CGM); + // This is necessary to avoid inheriting the previous line number. + FD->setImplicit(); StartFunction(FD, ReturnTy, Fn, FI, args); - ApplyDebugLocation NL{*this, blockInfo.getBlockExpr()->getBeginLoc()}; + auto AL = ApplyDebugLocation::CreateArtificial(*this); + llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); Address src = GetAddrOfLocalVar(&SrcDecl); @@ -2226,10 +2153,12 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { setBlockHelperAttributesVisibility(blockInfo.CapturesNonExternalType, Fn, FI, CGM); + // This is necessary to avoid inheriting the previous line number. + FD->setImplicit(); StartFunction(FD, ReturnTy, Fn, FI, args); markAsIgnoreThreadCheckingAtRuntime(Fn); - ApplyDebugLocation NL{*this, blockInfo.getBlockExpr()->getBeginLoc()}; + auto AL = ApplyDebugLocation::CreateArtificial(*this); llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); |