From 0f6df00e4d64e74ebb9621edf9beb0ced42e1697 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 29 Mar 2013 19:20:35 +0000 Subject: [PATCH] Bugfix/Followup for r177086. * 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 llvm-svn: 178361 --- clang/lib/CodeGen/CGBlocks.cpp | 29 +++++++++---------- clang/lib/CodeGen/CGDebugInfo.cpp | 6 ++-- clang/lib/CodeGen/CGDecl.cpp | 2 +- clang/test/CodeGenCXX/blocks.cpp | 2 +- clang/test/CodeGenObjC/arc-foreach.m | 3 +- clang/test/CodeGenObjC/blocks.m | 3 +- .../debug-info-block-captured-self.m | 29 +++++++++++-------- clang/test/CodeGenObjC/debug-info-blocks.m | 18 ++++++++---- 8 files changed, 54 insertions(+), 38 deletions(-) diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 77e29bd11931..d702b856cdc8 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -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); } } diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 2529ec8dc24e..a60d7239b209 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2632,6 +2632,8 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD, SmallVector addr; llvm::Type *Int64Ty = CGM.Int64Ty; + if (isa(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(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 diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 5f388e0b2862..d59c876d71c2 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -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()); diff --git a/clang/test/CodeGenCXX/blocks.cpp b/clang/test/CodeGenCXX/blocks.cpp index 914c0695cca7..81eef0e02822 100644 --- a/clang/test/CodeGenCXX/blocks.cpp +++ b/clang/test/CodeGenCXX/blocks.cpp @@ -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 diff --git a/clang/test/CodeGenObjC/arc-foreach.m b/clang/test/CodeGenObjC/arc-foreach.m index b81cbbd74a49..176b28d3a278 100644 --- a/clang/test/CodeGenObjC/arc-foreach.m +++ b/clang/test/CodeGenObjC/arc-foreach.m @@ -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]]) diff --git a/clang/test/CodeGenObjC/blocks.m b/clang/test/CodeGenObjC/blocks.m index f072c48669e2..3718ad590a53 100644 --- a/clang/test/CodeGenObjC/blocks.m +++ b/clang/test/CodeGenObjC/blocks.m @@ -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 diff --git a/clang/test/CodeGenObjC/debug-info-block-captured-self.m b/clang/test/CodeGenObjC/debug-info-block-captured-self.m index 99568822ff00..0316013b3102 100644 --- a/clang/test/CodeGenObjC/debug-info-block-captured-self.m +++ b/clang/test/CodeGenObjC/debug-info-block-captured-self.m @@ -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] diff --git a/clang/test/CodeGenObjC/debug-info-blocks.m b/clang/test/CodeGenObjC/debug-info-blocks.m index 71ae8a610ee8..faddfd2d730e 100644 --- a/clang/test/CodeGenObjC/debug-info-blocks.m +++ b/clang/test/CodeGenObjC/debug-info-blocks.m @@ -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 +// RUN: %clang_cc1 -emit-llvm -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 +// 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;