forked from OSchip/llvm-project
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
This commit is contained in:
parent
de17db30d8
commit
0f6df00e4d
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]])
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue