]> granicus.if.org Git - clang/commitdiff
Bugfix/Followup for r177086.
authorAdrian Prantl <aprantl@apple.com>
Fri, 29 Mar 2013 19:20:35 +0000 (19:20 +0000)
committerAdrian Prantl <aprantl@apple.com>
Fri, 29 Mar 2013 19:20:35 +0000 (19:20 +0000)
* Store the .block_descriptor (instead of self) in the alloca so we
  can guarantee that all captured variables are available at -O0.
* Add the missing OpDeref for the alloca.
rdar://problem/12767564

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178361 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGBlocks.cpp
lib/CodeGen/CGDebugInfo.cpp
lib/CodeGen/CGDecl.cpp
test/CodeGenCXX/blocks.cpp
test/CodeGenObjC/arc-foreach.m
test/CodeGenObjC/blocks.m
test/CodeGenObjC/debug-info-block-captured-self.m
test/CodeGenObjC/debug-info-blocks.m

index 77e29bd11931494369da1ec9e35b7035a16f5292..d702b856cdc8d8c90d6d3dd39970dfeea4c0567a 100644 (file)
@@ -1138,6 +1138,18 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
   BlockPointer = Builder.CreateBitCast(blockAddr,
                                        blockInfo.StructureType->getPointerTo(),
                                        "block");
+  // At -O0 we generate an explicit alloca for the BlockPointer, so the RA
+  // won't delete the dbg.declare intrinsics for captured variables.
+  llvm::Value *BlockPointerDbgLoc = BlockPointer;
+  if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
+    // Allocate a stack slot for it, so we can point the debugger to it
+    llvm::AllocaInst *Alloca = CreateTempAlloca(BlockPointer->getType(),
+                                                "block.addr");
+    unsigned Align = getContext().getDeclAlign(&selfDecl).getQuantity();
+    Alloca->setAlignment(Align);
+    Builder.CreateAlignedStore(BlockPointer, Alloca, Align);
+    BlockPointerDbgLoc = Alloca;
+  }
 
   // If we have a C++ 'this' reference, go ahead and force it into
   // existence now.
@@ -1161,20 +1173,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
       llvm::Value *selfAddr = Builder.CreateStructGEP(BlockPointer,
                                                       capture.getIndex(),
                                                       "block.captured-self");
-
-      // At -O0 we generate an explicit alloca for self to facilitate debugging.
-      if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
-       llvm::Value *load = Builder.CreateLoad(selfAddr);
-
-       // Allocate a stack slot for it, so we can generate debug info for it
-       llvm::AllocaInst *alloca = CreateTempAlloca(load->getType(),
-                                                   "block.captured-self.addr");
-        unsigned align = getContext().getDeclAlign(self).getQuantity();
-        alloca->setAlignment(align);
-       Builder.CreateAlignedStore(load, alloca, align);
-        LocalDeclMap[self] = alloca;
-      } else
-        LocalDeclMap[self] = selfAddr;
+      LocalDeclMap[self] = selfAddr;
     }
   }
 
@@ -1230,7 +1229,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
           continue;
         }
 
-        DI->EmitDeclareOfBlockDeclRefVariable(variable, BlockPointer,
+        DI->EmitDeclareOfBlockDeclRefVariable(variable, BlockPointerDbgLoc,
                                               Builder, blockInfo);
       }
     }
index 2529ec8dc24ef1cfaf1c966cce95811951cbd65e..a60d7239b209b0f0b7ec6d35c7f598af6490050c 100644 (file)
@@ -2632,6 +2632,8 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD,
 
   SmallVector<llvm::Value *, 9> addr;
   llvm::Type *Int64Ty = CGM.Int64Ty;
+  if (isa<llvm::AllocaInst>(Storage))
+    addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
   addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
   addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
   if (isByRef) {
@@ -2653,6 +2655,7 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD,
     DBuilder.createComplexVariable(llvm::dwarf::DW_TAG_auto_variable, 
                                    llvm::DIDescriptor(LexicalBlockStack.back()),
                                    VD->getName(), Unit, Line, Ty, addr);
+
   // Insert an llvm.dbg.declare into the current block.
   llvm::Instruction *Call =
     DBuilder.insertDeclare(Storage, D, Builder.GetInsertPoint());
@@ -2964,9 +2967,8 @@ void CGDebugInfo::finalize() {
         RepTy = llvm::DIType(cast<llvm::MDNode>(V));
     }
 
-    if (Ty.Verify() && Ty.isForwardDecl() && RepTy.Verify()) {
+    if (Ty.Verify() && Ty.isForwardDecl() && RepTy.Verify())
       Ty.replaceAllUsesWith(RepTy);
-    }
   }
 
   // We keep our own list of retained types, because we need to look
index 5f388e0b28624280962fefeb8b74f6ced4f6db75..d59c876d71c26d1db25eea1ea0fbe5a25954d053 100644 (file)
@@ -1578,7 +1578,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
       LocalDeclMap[&D] = Arg;
       llvm::Value *LocalAddr = 0;
       if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
-        // Allocate a stack slot to let debug info survive the RA.
+        // Allocate a stack slot to let the debug info survive the RA.
         llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertTypeForMem(Ty),
                                                    D.getName() + ".addr");
         Alloc->setAlignment(getContext().getDeclAlign(&D).getQuantity());
index 914c0695cca7eab7e3f566b00e93d1d109ba11fd..81eef0e0282260af5a0e07d0241f902c69011301 100644 (file)
@@ -124,7 +124,7 @@ namespace test4 {
   // CHECK-NEXT: store i8* [[BLOCKDESC:%.*]], i8** {{.*}}, align 8
   // CHECK-NEXT: load i8*
   // CHECK-NEXT: bitcast i8* [[BLOCKDESC]] to <{ i8*, i32, i32, i8*, %struct.__block_descriptor* }>*
-  // CHECK-NEXT: call void @_ZN5test41AC1Ev([[A]]* [[TMP]])
+  // CHECK:      call void @_ZN5test41AC1Ev([[A]]* [[TMP]])
   // CHECK-NEXT: call void @_ZN5test43fooENS_1AE([[A]]* [[TMP]])
   // CHECK-NEXT: call void @_ZN5test41AD1Ev([[A]]* [[TMP]])
   // CHECK-NEXT: ret void
index b81cbbd74a49a4f3a6f6b9af5de4f01c73b8e970..176b28d3a2781c97389bec2c54bfb8c7c25b7bc0 100644 (file)
@@ -84,7 +84,8 @@ void test0(NSArray *array) {
 
 // CHECK-LP64:    define internal void @__test0_block_invoke
 // CHECK-LP64:      [[BLOCK:%.*]] = bitcast i8* {{%.*}} to [[BLOCK_T]]*
-// CHECK-LP64-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+// CHECK-LP64-NOT:  ret
+// CHECK-LP64:      [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
 // CHECK-LP64-NEXT: [[T2:%.*]] = load i8** [[T0]], align 8 
 // CHECK-LP64-NEXT: call void @use(i8* [[T2]])
 
index f072c48669e2dc805ffc1f41c69702369d4a8d71..3718ad590a53933887c7fcd57c7eb942c00efb41 100644 (file)
@@ -93,7 +93,8 @@ void test2(Test2 *x) {
 // doesn't require a read barrier.
 // CHECK:    define internal void @__test2_block_invoke
 // CHECK:      [[BLOCK:%.*]] = bitcast i8* {{%.*}} to [[BLOCK_T]]*
-// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+// CHECK-NOT:  bitcast
+// CHECK:      [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
 // CHECK-NEXT: [[T1:%.*]] = load i8** [[T0]]
 // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[WEAK_T]]{{.*}}*
 // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[WEAK_T]]{{.*}}* [[T2]], i32 0, i32 1
index 99568822ff00eb3633e830602b4eff6bda9e2648..0316013b3102b096c64d56f76dd92606eb0248bc 100644 (file)
@@ -51,15 +51,20 @@ typedef enum {
 
 // inner block:
 // CHECK: define internal void {{.*}}_block_invoke{{.*}}
-// CHECK:        [[MEM1:%.*]] = alloca i8*, align 8
-// CHECK-NEXT:   [[MEM2:%.*]] = alloca i8*, align 8
-// CHECK-NEXT:   [[MEM3:%.*]] = alloca %{{.*}}*, align 8
-// CHECK:        store i8* [[BLOCK_DESC:%.*]], i8** [[MEM1]], align 8
-// CHECK:        [[TMP0:%.*]] = load i8** [[MEM1]]
-// CHECK:        call void @llvm.dbg.value(metadata !{i8* [[TMP0]]}, i64 0, metadata [[BDMD:![0-9]+]])
-// CHECK:        call void @llvm.dbg.declare(metadata !{i8* [[BLOCK_DESC]]}, metadata [[BDMD:![0-9]+]])
-// CHECK:        [[TMP1:%.*]] = bitcast
-// CHECK-NEXT:   [[TMP2:%.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* [[TMP1]]
-// CHECK-NEXT:   [[TMP3:%.*]] = load %0** [[TMP2]]
-// CHECK-NEXT:   store {{.*}}* [[TMP3]], %{{.*}}** [[MEM3]], align 8
-// CHECK:        [[BDMD]] = metadata {{.*}}.block_descriptor
+// CHECK:        %[[MEM1:.*]] = alloca i8*, align 8
+// CHECK-NEXT:   %[[MEM2:.*]] = alloca i8*, align 8
+// CHECK:        store i8* [[BLOCK_DESC:%.*]], i8** %[[MEM1]], align 8
+// CHECK:        %[[TMP0:.*]] = load i8** %[[MEM1]]
+// CHECK:        call void @llvm.dbg.value(metadata !{i8* %[[TMP0]]}, i64 0, metadata ![[BDMD:[0-9]+]])
+// CHECK:        call void @llvm.dbg.declare(metadata !{i8* [[BLOCK_DESC]]}, metadata ![[BDMD:[0-9]+]])
+// CHECK:        %[[TMP1:.*]] = bitcast
+// CHECK-NEXT:   store
+// CHECK-NEXT:   %[[TMP2:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %[[TMP1]]
+// CHECK:        call void @llvm.dbg.declare(metadata !{<{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>** {{.*}}}, metadata ![[SELF:.*]])
+// make sure we are still in the same function
+// CHECK: define {{.*}}__copy_helper_block_
+// Metadata
+// CHECK:        ![[MAIN:.*]] = {{.*}}!"Main"{{.*}}DW_TAG_structure_type{{.*}}line 23
+// CHECK:        ![[PMAIN:.*]] = {{.*}}![[MAIN]]} ; [ DW_TAG_pointer_type ]{{.*}}from Main
+// CHECK:        ![[BDMD]] = metadata {{.*}}.block_descriptor
+// CHECK:        ![[SELF]] = {{.*}}![[PMAIN]]{{.*}}[ DW_TAG_auto_variable ] [self] [line 40]
index 71ae8a610ee8b097e0e22208cf3a17912203dfa9..faddfd2d730e87d1cb177f5030b62f2f18fdc921 100644 (file)
@@ -1,9 +1,17 @@
-// REQUIRES: x86-64-registered-target
-// RUN: %clang_cc1 -masm-verbose -S -fblocks -g  -triple x86_64-apple-darwin10 -fobjc-dispatch-method=mixed  %s -o - | FileCheck %s
-
-//Radar 9279956
-//CHECK:       ## DW_OP_deref
-//CHECK-NEXT:  ## DW_OP_plus_uconst
+// RUN: %clang_cc1 -emit-llvm -fblocks -g  -triple x86_64-apple-darwin10 -fobjc-dispatch-method=mixed  %s -o - | FileCheck %s
+
+// rdar://problem/9279956
+// Test that we generate the proper debug location for a captured self.
+// The second half of this patch is in llvm/tests/DebugInfo/debug-info-blocks.ll
+
+// CHECK: define {{.*}}_block_invoke
+// CHECK: %[[BLOCK:.*]] = bitcast i8* %.block_descriptor to <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>*, !dbg !88
+// CHECK-NEXT: store <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %[[BLOCK]], <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>** %[[ALLOCA:.*]], align
+// CHECK-NEXT: getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %[[BLOCK]], i32 0, i32 5
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata !{<{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>** %[[ALLOCA]]}, metadata ![[SELF:[0-9]+]])
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata !{%1** %d}, metadata ![[D:[0-9]+]])
+// CHECK: ![[SELF]] = {{.*}} [ DW_TAG_auto_variable ] [self] [line 52]
+// CHECK: ![[D]] = {{.*}} [d] [line 50]
 
 typedef unsigned int NSUInteger;