[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

John McCall rjmccall at apple.com
Thu Nov 10 00:15:53 PST 2011


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





More information about the cfe-commits mailing list