[cfe-commits] r144268 - in /cfe/trunk: lib/CodeGen/CGBlocks.cpp lib/CodeGen/CGBlocks.h lib/CodeGen/CGDecl.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprAgg.cpp lib/CodeGen/CGExprComplex.cpp lib/CodeGen/CGExprScalar.cpp lib/CodeGen/CGObjC.cpp lib/CodeGen/CGTemporaries.cpp lib/CodeGen/CodeGenFunction.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenObjC/arc-blocks.m test/CodeGenObjC/arc-foreach.m
Devang Patel
dpatel at apple.com
Thu Nov 10 10:53:07 PST 2011
John,
This patch is causing block-5988451.c test failures from gccTestSuite. Please investigate or revert. r144271 has not addressed this.
Thanks!
-
Devang
$ clang -mmacosx-version-min=10.5 -ObjC -fblocks block-5988451.c -o /tmp/b.o
Assertion failed: (head && *head), function findAndRemoveBlockInfo, file /Volumes/Lalgate/clean/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp, line 578.
0 clang 0x00000001021bea52 _ZL15PrintStackTracePv + 34
1 clang 0x00000001021bf049 _ZL13SignalHandleri + 777
2 libsystem_c.dylib 0x00007fff84106cfa _sigtramp + 26
3 libsystem_c.dylib 0x00007fff840cb5c3 szone_free_definite_size + 1815
4 clang 0x00000001021bec96 abort + 22
5 clang 0x00000001021bec57 __assert_rtn + 55
6 clang 0x0000000100f860c8 clang::CodeGen::CodeGenFunction::EmitBlockLiteral(clang::BlockExpr const*) + 456
7 clang 0x0000000101001b67 clang::StmtVisitorBase<clang::make_ptr, (anonymous namespace)::ScalarExprEmitter, llvm::Value*>::Visit(clang::Stmt*) + 14055
8 clang 0x0000000100ff9980 clang::CodeGen::CodeGenFunction::EmitScalarExpr(clang::Expr const*, bool) + 96
9 clang 0x0000000100fd5899 clang::CodeGen::CodeGenFunction::EmitAnyExpr(clang::Expr const*, clang::CodeGen::AggValueSlot, bool) + 57
10 clang 0x0000000100fd6168 clang::CodeGen::CodeGenFunction::EmitAnyExprToTemp(clang::Expr const*) + 136
11 clang 0x0000000100fa8a12 clang::CodeGen::CodeGenFunction::EmitCallArg(clang::CodeGen::CallArgList&, clang::Expr const*, clang::QualType) + 2626
12 clang 0x0000000100fe3f48 void clang::CodeGen::CodeGenFunction::EmitCallArgs<clang::FunctionProtoType>(clang::CodeGen::CallArgList&, clang::FunctionProtoType const*, clang::ConstExprIterator, clang::ConstExprIterator) + 328
13 clang 0x0000000100fe1112 clang::CodeGen::CodeGenFunction::EmitCall(clang::QualType, llvm::Value*, clang::CodeGen::ReturnValueSlot, clang::ConstExprIterator, clang::ConstExprIterator, clang::Decl const*) + 242
14 clang 0x0000000100fe0fd2 clang::CodeGen::CodeGenFunction::EmitCallExpr(clang::CallExpr const*, clang::CodeGen::ReturnValueSlot) + 978
15 clang 0x0000000101005830 (anonymous namespace)::ScalarExprEmitter::VisitCallExpr(clang::CallExpr const*) + 208
16 clang 0x0000000101001da0 clang::StmtVisitorBase<clang::make_ptr, (anonymous namespace)::ScalarExprEmitter, llvm::Value*>::Visit(clang::Stmt*) + 14624
17 clang 0x0000000100ff9980 clang::CodeGen::CodeGenFunction::EmitScalarExpr(clang::Expr const*, bool) + 96
18 clang 0x0000000100fd5899 clang::CodeGen::CodeGenFunction::EmitAnyExpr(clang::Expr const*, clang::CodeGen::AggValueSlot, bool) + 57
19 clang 0x0000000100fd5849 clang::CodeGen::CodeGenFunction::EmitIgnoredExpr(clang::Expr const*) + 41
20 clang 0x000000010104a877 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*) + 391
21 clang 0x000000010104fe5b clang::CodeGen::CodeGenFunction::EmitCompoundStmt(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) + 267
22 clang 0x000000010104acad clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const*) + 141
23 clang 0x000000010104a719 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*) + 41
24 clang 0x000000010100a5aa clang::CodeGen::CodeGenFunction::GenerateObjCMethod(clang::ObjCMethodDecl const*) + 58
25 clang 0x00000001010674c5 clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*) + 693
26 clang 0x000000010108083f (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef) + 127
27 clang 0x00000001010597ca clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef) + 170
28 clang 0x000000010108aa92 clang::ParseAST(clang::Sema&, bool) + 306
29 clang 0x00000001010588f7 clang::CodeGenAction::ExecuteAction() + 1031
30 clang 0x0000000100e5ed9b clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 955
31 clang 0x0000000100e477c8 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) + 2792
32 clang 0x0000000100e3efe7 cc1_main(char const**, char const**, char const*, void*) + 5287
33 clang 0x0000000100e43b52 main + 706
34 clang 0x0000000100e3db34 start + 52
Stack dump:
-------------- next part --------------
A non-text attachment was scrubbed...
Name: block-5988451.c
Type: application/octet-stream
Size: 1080 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20111110/c5c5cdd3/attachment.obj>
-------------- next part --------------
On Nov 10, 2011, at 12:15 AM, John McCall wrote:
> Author: rjmccall
> Date: Thu Nov 10 02:15:53 2011
> New Revision: 144268
>
> URL: http://llvm.org/viewvc/llvm-project?rev=144268&view=rev
> Log:
> Enter the cleanups for a block outside the enclosing
> full-expression. Naturally they're inactive before we enter
> the block literal expression. This restores the intended
> behavior that blocks belong to their enclosing scope.
>
> There's a useful -O0 / compile-time optimization that we're
> missing here with activating cleanups following straight-line
> code from their inactive beginnings.
>
>
> Modified:
> cfe/trunk/lib/CodeGen/CGBlocks.cpp
> cfe/trunk/lib/CodeGen/CGBlocks.h
> cfe/trunk/lib/CodeGen/CGDecl.cpp
> cfe/trunk/lib/CodeGen/CGExpr.cpp
> cfe/trunk/lib/CodeGen/CGExprAgg.cpp
> cfe/trunk/lib/CodeGen/CGExprComplex.cpp
> cfe/trunk/lib/CodeGen/CGExprScalar.cpp
> cfe/trunk/lib/CodeGen/CGObjC.cpp
> cfe/trunk/lib/CodeGen/CGTemporaries.cpp
> cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
> cfe/trunk/lib/CodeGen/CodeGenFunction.h
> cfe/trunk/test/CodeGenObjC/arc-blocks.m
> cfe/trunk/test/CodeGenObjC/arc-foreach.m
>
> Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Thu Nov 10 02:15:53 2011
> @@ -25,13 +25,14 @@
> using namespace clang;
> using namespace CodeGen;
>
> -CGBlockInfo::CGBlockInfo(const BlockExpr *blockExpr, const char *N)
> - : Name(N), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false),
> - HasCXXObject(false), UsesStret(false), StructureType(0), Block(blockExpr) {
> +CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name)
> + : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false),
> + HasCXXObject(false), UsesStret(false), StructureType(0), Block(block) {
>
> - // Skip asm prefix, if any.
> - if (Name && Name[0] == '\01')
> - ++Name;
> + // Skip asm prefix, if any. 'name' is usually taken directly from
> + // the mangled name of the enclosing function.
> + if (!name.empty() && name[0] == '\01')
> + name = name.substr(1);
> }
>
> // Anchor the vtable to this translation unit.
> @@ -483,15 +484,137 @@
> 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) {
> + // 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, blockInfo);
> +
> + // Nothing else to do if it can be global.
> + if (blockInfo.CanBeGlobal) return;
> +
> + // Make the allocation for the block.
> + blockInfo.Address =
> + CGF.CreateTempAlloca(blockInfo.StructureType, "block");
> + blockInfo.Address->setAlignment(blockInfo.BlockAlign.getQuantity());
> +
> + // 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 (BlockDecl::capture_const_iterator ci = block->capture_begin(),
> + ce = block->capture_end(); ci != ce; ++ci) {
> + // 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::DestructionKind dtorKind =
> + variable->getType().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.
> + if (dtorKind == QualType::DK_objc_strong_lifetime) {
> + destroyer = &CodeGenFunction::destroyARCStrongImprecise;
> + } else {
> + destroyer = &CGF.getDestroyer(dtorKind);
> + }
> +
> + // GEP down to the address.
> + llvm::Value *addr = CGF.Builder.CreateStructGEP(blockInfo.Address,
> + capture.getIndex());
> +
> + CleanupKind cleanupKind = InactiveNormalCleanup;
> + bool useArrayEHCleanup = CGF.needsEHCleanup(dtorKind);
> + if (useArrayEHCleanup)
> + cleanupKind = InactiveNormalAndEHCleanup;
> +
> + CGF.pushDestroy(cleanupKind, addr, variable->getType(),
> + *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 ExprWithCleanups *E) {
> + assert(E->getNumObjects() != 0);
> + ArrayRef<ExprWithCleanups::CleanupObject> cleanups = E->getObjects();
> + for (ArrayRef<ExprWithCleanups::CleanupObject>::iterator
> + i = cleanups.begin(), e = cleanups.end(); i != e; ++i) {
> + enterBlockScope(*this, *i);
> + }
> +}
> +
> +/// 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 != 0);
> +}
> +
> /// Emit a block literal expression in the current function.
> llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
> - std::string Name = CurFn->getName();
> - CGBlockInfo blockInfo(blockExpr, Name.c_str());
> + // If the block has no captures, we won't have a pre-computed
> + // layout for it.
> + if (!blockExpr->getBlockDecl()->hasCaptures()) {
> + CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName());
> + computeBlockInfo(CGM, blockInfo);
> + blockInfo.BlockExpression = blockExpr;
> + return EmitBlockLiteral(blockInfo);
> + }
> +
> + // Find the block info for this block and take ownership of it.
> + llvm::OwningPtr<CGBlockInfo> blockInfo;
> + blockInfo.reset(findAndRemoveBlockInfo(&FirstBlockInfo,
> + blockExpr->getBlockDecl()));
>
> - // Compute information about the layout, etc., of this block.
> - computeBlockInfo(CGM, blockInfo);
> + blockInfo->BlockExpression = blockExpr;
> + return EmitBlockLiteral(*blockInfo);
> +}
>
> - // Using that metadata, generate the actual block function.
> +llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
> + // Using the computed layout, generate the actual block function.
> llvm::Constant *blockFn
> = CodeGenFunction(CGM).GenerateBlockFunction(CurGD, blockInfo,
> CurFuncDecl, LocalDeclMap);
> @@ -509,11 +632,8 @@
> // Build the block descriptor.
> llvm::Constant *descriptor = buildBlockDescriptor(CGM, blockInfo);
>
> - llvm::Type *intTy = ConvertType(getContext().IntTy);
> -
> - llvm::AllocaInst *blockAddr =
> - CreateTempAlloca(blockInfo.StructureType, "block");
> - blockAddr->setAlignment(blockInfo.BlockAlign.getQuantity());
> + llvm::AllocaInst *blockAddr = blockInfo.Address;
> + assert(blockAddr && "block has no address!");
>
> // Compute the initial on-stack block flags.
> BlockFlags flags = BLOCK_HAS_SIGNATURE;
> @@ -523,9 +643,9 @@
>
> // Initialize the block literal.
> Builder.CreateStore(isa, Builder.CreateStructGEP(blockAddr, 0, "block.isa"));
> - Builder.CreateStore(llvm::ConstantInt::get(intTy, flags.getBitMask()),
> + Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
> Builder.CreateStructGEP(blockAddr, 1, "block.flags"));
> - Builder.CreateStore(llvm::ConstantInt::get(intTy, 0),
> + Builder.CreateStore(llvm::ConstantInt::get(IntTy, 0),
> Builder.CreateStructGEP(blockAddr, 2, "block.reserved"));
> Builder.CreateStore(blockFn, Builder.CreateStructGEP(blockAddr, 3,
> "block.invoke"));
> @@ -625,28 +745,11 @@
> /*captured by init*/ false);
> }
>
> - // Push a destructor if necessary. The semantics for when this
> - // actually gets run are really obscure.
> + // Activate the cleanup if layout pushed one.
> if (!ci->isByRef()) {
> - switch (QualType::DestructionKind dtorKind = type.isDestructedType()) {
> - case QualType::DK_none:
> - break;
> -
> - // Block captures count as local values and have imprecise semantics.
> - // They also can't be arrays, so need to worry about that.
> - case QualType::DK_objc_strong_lifetime: {
> - // This local is a GCC and MSVC compiler workaround.
> - Destroyer *destroyer = &destroyARCStrongImprecise;
> - pushDestroy(getCleanupKind(dtorKind), blockField, type,
> - *destroyer, /*useEHCleanupForArray*/ false);
> - break;
> - }
> -
> - case QualType::DK_objc_weak_lifetime:
> - case QualType::DK_cxx_destructor:
> - pushDestroy(dtorKind, blockField, type);
> - break;
> - }
> + EHScopeStack::stable_iterator cleanup = capture.getCleanup();
> + if (cleanup.isValid())
> + ActivateCleanupBlock(cleanup);
> }
> }
>
> @@ -800,7 +903,8 @@
> llvm::Constant *
> CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *blockExpr,
> const char *name) {
> - CGBlockInfo blockInfo(blockExpr, name);
> + CGBlockInfo blockInfo(blockExpr->getBlockDecl(), name);
> + blockInfo.BlockExpression = blockExpr;
>
> // Compute information about the layout, etc., of this block.
> computeBlockInfo(*this, blockInfo);
>
> Modified: cfe/trunk/lib/CodeGen/CGBlocks.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.h?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGBlocks.h (original)
> +++ cfe/trunk/lib/CodeGen/CGBlocks.h Thu Nov 10 02:15:53 2011
> @@ -23,6 +23,7 @@
> #include "clang/AST/ExprCXX.h"
> #include "clang/AST/ExprObjC.h"
>
> +#include "CodeGenFunction.h"
> #include "CGBuilder.h"
> #include "CGCall.h"
> #include "CGValue.h"
> @@ -128,13 +129,14 @@
> class CGBlockInfo {
> public:
> /// Name - The name of the block, kindof.
> - const char *Name;
> + llvm::StringRef Name;
>
> /// The field index of 'this' within the block, if there is one.
> unsigned CXXThisIndex;
>
> class Capture {
> uintptr_t Data;
> + EHScopeStack::stable_iterator Cleanup;
>
> public:
> bool isIndex() const { return (Data & 1) != 0; }
> @@ -144,6 +146,14 @@
> assert(isConstant());
> return reinterpret_cast<llvm::Value*>(Data);
> }
> + EHScopeStack::stable_iterator getCleanup() const {
> + assert(isIndex());
> + return Cleanup;
> + }
> + void setCleanup(EHScopeStack::stable_iterator cleanup) {
> + assert(isIndex());
> + Cleanup = cleanup;
> + }
>
> static Capture makeIndex(unsigned index) {
> Capture v;
> @@ -158,9 +168,6 @@
> }
> };
>
> - /// The mapping of allocated indexes within the block.
> - llvm::DenseMap<const VarDecl*, Capture> Captures;
> -
> /// CanBeGlobal - True if the block can be global, i.e. it has
> /// no non-constant captures.
> bool CanBeGlobal : 1;
> @@ -176,22 +183,35 @@
> /// because it gets set later in the block-creation process.
> mutable bool UsesStret : 1;
>
> + /// The mapping of allocated indexes within the block.
> + llvm::DenseMap<const VarDecl*, Capture> Captures;
> +
> + llvm::AllocaInst *Address;
> llvm::StructType *StructureType;
> - const BlockExpr *Block;
> + const BlockDecl *Block;
> + const BlockExpr *BlockExpression;
> CharUnits BlockSize;
> CharUnits BlockAlign;
> + CGBlockInfo *NextBlockInfo;
>
> const Capture &getCapture(const VarDecl *var) const {
> - llvm::DenseMap<const VarDecl*, Capture>::const_iterator
> + return const_cast<CGBlockInfo*>(this)->getCapture(var);
> + }
> + Capture &getCapture(const VarDecl *var) {
> + llvm::DenseMap<const VarDecl*, Capture>::iterator
> it = Captures.find(var);
> assert(it != Captures.end() && "no entry for variable!");
> return it->second;
> }
>
> - const BlockDecl *getBlockDecl() const { return Block->getBlockDecl(); }
> - const BlockExpr *getBlockExpr() const { return Block; }
> + const BlockDecl *getBlockDecl() const { return Block; }
> + const BlockExpr *getBlockExpr() const {
> + assert(BlockExpression);
> + assert(BlockExpression->getBlockDecl() == Block);
> + return BlockExpression;
> + }
>
> - CGBlockInfo(const BlockExpr *blockExpr, const char *Name);
> + CGBlockInfo(const BlockDecl *blockDecl, llvm::StringRef Name);
> };
>
> } // end namespace CodeGen
>
> Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Thu Nov 10 02:15:53 2011
> @@ -496,9 +496,11 @@
>
> // If we're emitting a value with lifetime, we have to do the
> // initialization *before* we leave the cleanup scopes.
> - CodeGenFunction::RunCleanupsScope Scope(*this);
> - if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(init))
> + if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(init)) {
> + enterFullExpression(ewc);
> init = ewc->getSubExpr();
> + }
> + CodeGenFunction::RunCleanupsScope Scope(*this);
>
> // We have to maintain the illusion that the variable is
> // zero-initialized. If the variable might be accessed in its
>
> Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Nov 10 02:15:53 2011
> @@ -229,10 +229,11 @@
> if (const CXXDefaultArgExpr *DAE = dyn_cast<CXXDefaultArgExpr>(E))
> E = DAE->getExpr();
>
> - if (const ExprWithCleanups *TE = dyn_cast<ExprWithCleanups>(E)) {
> + if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(E)) {
> + CGF.enterFullExpression(EWC);
> CodeGenFunction::RunCleanupsScope Scope(CGF);
>
> - return EmitExprForReferenceBinding(CGF, TE->getSubExpr(),
> + return EmitExprForReferenceBinding(CGF, EWC->getSubExpr(),
> ReferenceTemporary,
> ReferenceTemporaryDtor,
> ObjCARCReferenceLifetimeType,
> @@ -677,8 +678,14 @@
> return EmitCXXConstructLValue(cast<CXXConstructExpr>(E));
> case Expr::CXXBindTemporaryExprClass:
> return EmitCXXBindTemporaryLValue(cast<CXXBindTemporaryExpr>(E));
> - case Expr::ExprWithCleanupsClass:
> - return EmitExprWithCleanupsLValue(cast<ExprWithCleanups>(E));
> +
> + case Expr::ExprWithCleanupsClass: {
> + const ExprWithCleanups *cleanups = cast<ExprWithCleanups>(E);
> + enterFullExpression(cleanups);
> + RunCleanupsScope Scope(*this);
> + return EmitLValue(cleanups->getSubExpr());
> + }
> +
> case Expr::CXXScalarValueInitExprClass:
> return EmitNullInitializationLValue(cast<CXXScalarValueInitExpr>(E));
> case Expr::CXXDefaultArgExprClass:
>
> Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Thu Nov 10 02:15:53 2011
> @@ -536,7 +536,9 @@
> }
>
> void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *E) {
> - CGF.EmitExprWithCleanups(E, Dest);
> + CGF.enterFullExpression(E);
> + CodeGenFunction::RunCleanupsScope cleanups(CGF);
> + Visit(E->getSubExpr());
> }
>
> void AggExprEmitter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
>
> Modified: cfe/trunk/lib/CodeGen/CGExprComplex.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprComplex.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprComplex.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprComplex.cpp Thu Nov 10 02:15:53 2011
> @@ -179,7 +179,9 @@
> return Visit(DAE->getExpr());
> }
> ComplexPairTy VisitExprWithCleanups(ExprWithCleanups *E) {
> - return CGF.EmitExprWithCleanups(E).getComplexVal();
> + CGF.enterFullExpression(E);
> + CodeGenFunction::RunCleanupsScope Scope(CGF);
> + return Visit(E->getSubExpr());
> }
> ComplexPairTy VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
> assert(E->getType()->isAnyComplexType() && "Expected complex type!");
>
> Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Thu Nov 10 02:15:53 2011
> @@ -353,7 +353,9 @@
> }
>
> Value *VisitExprWithCleanups(ExprWithCleanups *E) {
> - return CGF.EmitExprWithCleanups(E).getScalarVal();
> + CGF.enterFullExpression(E);
> + CodeGenFunction::RunCleanupsScope Scope(CGF);
> + return Visit(E->getSubExpr());
> }
> Value *VisitCXXNewExpr(const CXXNewExpr *E) {
> return CGF.EmitCXXNewExpr(E);
>
> Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGObjC.cpp Thu Nov 10 02:15:53 2011
> @@ -2177,6 +2177,7 @@
> tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) {
> // Look through cleanups.
> if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) {
> + CGF.enterFullExpression(cleanups);
> CodeGenFunction::RunCleanupsScope scope(CGF);
> return tryEmitARCRetainScalarExpr(CGF, cleanups->getSubExpr());
> }
> @@ -2376,10 +2377,12 @@
> // @throw A().foo;
> // where a full retain+autorelease is required and would
> // otherwise happen after the destructor for the temporary.
> - CodeGenFunction::RunCleanupsScope cleanups(*this);
> - if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(expr))
> + if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(expr)) {
> + enterFullExpression(ewc);
> expr = ewc->getSubExpr();
> + }
>
> + CodeGenFunction::RunCleanupsScope cleanups(*this);
> return EmitARCRetainAutoreleaseScalarExpr(expr);
> }
>
>
> Modified: cfe/trunk/lib/CodeGen/CGTemporaries.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGTemporaries.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGTemporaries.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGTemporaries.cpp Thu Nov 10 02:15:53 2011
> @@ -35,15 +35,3 @@
> Temporary->getDestructor(),
> Ptr);
> }
> -
> -RValue
> -CodeGenFunction::EmitExprWithCleanups(const ExprWithCleanups *E,
> - AggValueSlot Slot) {
> - RunCleanupsScope Scope(*this);
> - return EmitAnyExpr(E->getSubExpr(), Slot);
> -}
> -
> -LValue CodeGenFunction::EmitExprWithCleanupsLValue(const ExprWithCleanups *E) {
> - RunCleanupsScope Scope(*this);
> - return EmitLValue(E->getSubExpr());
> -}
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Thu Nov 10 02:15:53 2011
> @@ -33,7 +33,7 @@
> : CodeGenTypeCache(cgm), CGM(cgm),
> Target(CGM.getContext().getTargetInfo()), Builder(cgm.getModule().getContext()),
> AutoreleaseResult(false), BlockInfo(0), BlockPointer(0),
> - NormalCleanupDest(0), NextCleanupDestIndex(1),
> + NormalCleanupDest(0), NextCleanupDestIndex(1), FirstBlockInfo(0),
> EHResumeBlock(0), ExceptionSlot(0), EHSelectorSlot(0),
> DebugInfo(0), DisableDebugInfo(false), DidCallStackSave(false),
> IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0),
> @@ -45,6 +45,14 @@
> CGM.getCXXABI().getMangleContext().startNewFunction();
> }
>
> +CodeGenFunction::~CodeGenFunction() {
> + // If there are any unclaimed block infos, go ahead and destroy them
> + // now. This can happen if IR-gen gets clever and skips evaluating
> + // something.
> + if (FirstBlockInfo)
> + destroyBlockInfos(FirstBlockInfo);
> +}
> +
>
> llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) {
> return CGM.getTypes().ConvertTypeForMem(T);
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Nov 10 02:15:53 2011
> @@ -45,6 +45,7 @@
> namespace clang {
> class APValue;
> class ASTContext;
> + class BlockDecl;
> class CXXDestructorDecl;
> class CXXForRangeStmt;
> class CXXTryStmt;
> @@ -610,6 +611,9 @@
>
> unsigned NextCleanupDestIndex;
>
> + /// FirstBlockInfo - The head of a singly-linked-list of block layouts.
> + CGBlockInfo *FirstBlockInfo;
> +
> /// EHResumeBlock - Unified block containing a call to llvm.eh.resume.
> llvm::BasicBlock *EHResumeBlock;
>
> @@ -1169,6 +1173,7 @@
>
> public:
> CodeGenFunction(CodeGenModule &cgm);
> + ~CodeGenFunction();
>
> CodeGenTypes &getTypes() const { return CGM.getTypes(); }
> ASTContext &getContext() const { return CGM.getContext(); }
> @@ -1297,6 +1302,8 @@
> //===--------------------------------------------------------------------===//
>
> llvm::Value *EmitBlockLiteral(const BlockExpr *);
> + llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info);
> + static void destroyBlockInfos(CGBlockInfo *info);
> llvm::Constant *BuildDescriptorBlockDecl(const BlockExpr *,
> const CGBlockInfo &Info,
> llvm::StructType *,
> @@ -2074,7 +2081,6 @@
>
> LValue EmitCXXConstructLValue(const CXXConstructExpr *E);
> LValue EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E);
> - LValue EmitExprWithCleanupsLValue(const ExprWithCleanups *E);
> LValue EmitCXXTypeidLValue(const CXXTypeidExpr *E);
>
> LValue EmitObjCMessageExprLValue(const ObjCMessageExpr *E);
> @@ -2348,8 +2354,11 @@
> void EmitSynthesizedCXXCopyCtor(llvm::Value *Dest, llvm::Value *Src,
> const Expr *Exp);
>
> - RValue EmitExprWithCleanups(const ExprWithCleanups *E,
> - AggValueSlot Slot =AggValueSlot::ignored());
> + void enterFullExpression(const ExprWithCleanups *E) {
> + if (E->getNumObjects() == 0) return;
> + enterNonTrivialFullExpression(E);
> + }
> + void enterNonTrivialFullExpression(const ExprWithCleanups *E);
>
> void EmitCXXThrowExpr(const CXXThrowExpr *E);
>
>
> Modified: cfe/trunk/test/CodeGenObjC/arc-blocks.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-blocks.m?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/arc-blocks.m (original)
> +++ cfe/trunk/test/CodeGenObjC/arc-blocks.m Thu Nov 10 02:15:53 2011
> @@ -25,15 +25,19 @@
> // CHECK: define void @test2(
> // CHECK: [[X:%.*]] = alloca i8*,
> // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
> +// CHECK-NEXT: alloca i1
> +// CHECK-NEXT: store i1 false
> // CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}})
> // CHECK-NEXT: store i8* [[PARM]], i8** [[X]]
> +// CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
> // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
> // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]],
> // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
> // CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]],
> +// CHECK-NEXT: store i1 true
> // CHECK-NEXT: bitcast
> // CHECK-NEXT: call void @test2_helper(
> -// CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOT]]
> +// CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOTREL]]
> // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release
> // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]]
> // CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release
> @@ -233,8 +237,8 @@
> // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeak(i8** [[VAR]])
> // CHECK-NEXT: call i8* @objc_initWeak(i8** [[SLOT]], i8* [[T0]])
> // CHECK: call void @test7_helper(
> - // CHECK-NEXT: call void @objc_destroyWeak(i8** [[SLOT]])
> - // CHECK-NEXT: call void @objc_destroyWeak(i8** [[VAR]])
> + // CHECK-NEXT: call void @objc_destroyWeak(i8** {{%.*}})
> + // CHECK: call void @objc_destroyWeak(i8** [[VAR]])
> // CHECK-NEXT: ret void
>
> // CHECK: define internal void @__test7_block_invoke_
> @@ -262,15 +266,17 @@
> // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
> // CHECK: store
> // CHECK-NEXT: store
> +// CHECK: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
> // CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
> // CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]** [[SELF]],
> // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8*
> // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]])
> // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[TEST8]]*
> // CHECK-NEXT: store [[TEST8]]* [[T4]], [[TEST8]]** [[T0]]
> +// CHECK-NEXT: store i1 true,
> // CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to
> // CHECK: call void @test8_helper(
> -// CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]** [[T0]]
> +// CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]** [[D0]]
> // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8*
> // CHECK-NEXT: call void @objc_release(i8* [[T2]])
> // CHECK-NEXT: ret void
>
> Modified: cfe/trunk/test/CodeGenObjC/arc-foreach.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-foreach.m?rev=144268&r1=144267&r2=144268&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/arc-foreach.m (original)
> +++ cfe/trunk/test/CodeGenObjC/arc-foreach.m Thu Nov 10 02:15:53 2011
> @@ -29,6 +29,9 @@
> // CHECK-LP64-NEXT: [[BUFFER:%.*]] = alloca [16 x i8*], align 8
> // CHECK-LP64-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
>
> +// CHECK-LP64-NEXT: [[CAP_ACTIVE:%.*]] = alloca i1
> +// CHECK-LP64-NEXT: store i1 false, i1* [[CAP_ACTIVE]]
> +
> // Initialize 'array'.
> // CHECK-LP64-NEXT: [[T0:%.*]] = bitcast [[ARRAY_T:%.*]]* {{%.*}} to i8*
> // CHECK-LP64-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
> @@ -60,13 +63,15 @@
> // CHECK-LP64-NEXT: [[T3:%.*]] = load i8** [[T2]]
> // CHECK-LP64-NEXT: store i8* [[T3]], i8** [[X]]
>
> +// CHECK-LP64: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
> // CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
> // CHECK-LP64-NEXT: [[T1:%.*]] = load i8** [[X]]
> // CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
> // CHECK-LP64-NEXT: store i8* [[T2]], i8** [[T0]]
> +// CHECK-LP64-NEXT: store i1 true, i1* [[CAP_ACTIVE]]
> // CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]]
> // CHECK-LP64: call void @use_block(
> -// CHECK-LP64-NEXT: [[T1:%.*]] = load i8** [[T0]]
> +// CHECK-LP64-NEXT: [[T1:%.*]] = load i8** [[D0]]
> // CHECK-LP64-NEXT: call void @objc_release(i8* [[T1]])
>
> // CHECK-LP64: [[T0:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_
> @@ -108,13 +113,15 @@
> // CHECK-LP64-NEXT: [[T3:%.*]] = load i8** [[T2]]
> // CHECK-LP64-NEXT: call i8* @objc_initWeak(i8** [[X]], i8* [[T3]])
>
> +// CHECK-LP64: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
> // CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
> // CHECK-LP64-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[X]])
> // CHECK-LP64-NEXT: call i8* @objc_initWeak(i8** [[T0]], i8* [[T1]])
> +// CHECK-LP64-NEXT: store i1 true,
> // CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to
> // CHECK-LP64: call void @use_block
> -// CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[T0]])
> -// CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[X]])
> +// CHECK-LP64: call void @objc_destroyWeak(i8** [[D0]])
> +// CHECK-LP64: call void @objc_destroyWeak(i8** [[X]])
>
> // rdar://problem/9817306
> @interface Test2
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list