aprantl created this revision. LLVM now interprets DIExpressions correctly and no longer determines the location description kind by looking at whether the first operator is a DW_OP_deref.
The code that emitted debug info for block captures used to rely on this and used the presence of an alloca (which was only emitted when optimizations were enabled) as a proxy for tweaking the expression in a way the resulted in the backend doing the right thing. This is now unnecessary and this patch unconditionally emits an alloca for block descriptors, which is then elided by mem2reg. https://bugs.llvm.org/show_bug.cgi?id=32382 rdar://problem/31205000 https://reviews.llvm.org/D31440 Files: lib/CodeGen/CGBlocks.cpp lib/CodeGen/CGDebugInfo.cpp lib/CodeGen/CGDebugInfo.h test/CodeGenObjC/debug-info-block-captured-self.m test/CodeGenObjC/debug-info-blocks.m
Index: test/CodeGenObjC/debug-info-blocks.m =================================================================== --- test/CodeGenObjC/debug-info-blocks.m +++ test/CodeGenObjC/debug-info-blocks.m @@ -4,11 +4,18 @@ // Test that we generate the proper debug location for a captured self. // The second half of this test 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 -// CHECK-NEXT: store <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %[[BLOCK]], <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>** %[[ALLOCA:.*]], align -// CHECK-NEXT: call void @llvm.dbg.declare(metadata <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>** %[[ALLOCA]], metadata ![[SELF:[0-9]+]], metadata !{{.*}}) -// CHECK-NEXT: call void @llvm.dbg.declare(metadata %1** %d, metadata ![[D:[0-9]+]], metadata !{{.*}}) +// CHECK: define {{.*}}[A init]_block_invoke +// CHECK-NEXT: entry +// CHECK-NEXT: %[[DESC_ALLOCA:.*]] = alloca i8*, align 8 +// CHECK-NEXT: %[[BLOCK_ALLOCA:.*]] = alloca <{{.*}}>*, align 8 +// CHECK: store i8* %.block_descriptor, i8** %[[ALLOCA:.*]], align 8 +// CHECK: call void @llvm.dbg.declare(metadata i8** %[[DESC_ALLOCA]], +// CHECK-SAME: metadata ![[BLOCK_VAR:[0-9]+]], +// CHECK: call void @llvm.dbg.declare( +// CHECK-SAME: metadata <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>** +// CHECK-SAME: %[[BLOCK_ALLOCA]], metadata ![[SELF_VAR:[0-9]+]], +// CHECK-SAME: metadata ![[SELF_EXPR:[0-9]+]]) +// CHECK: call void @llvm.dbg.declare(metadata %1** %d, metadata ![[D_VAR:[0-9]+]], // rdar://problem/14386148 // Test that we don't emit bogus line numbers for the helper functions. @@ -22,11 +29,13 @@ // CHECK-NOT: ret // CHECK: load {{.*}}, !dbg ![[DESTROY_LINE:[0-9]+]] -// CHECK-DAG: [[DBG_LINE]] = !DILocation(line: 0, scope: ![[COPY_SP:[0-9]+]]) -// CHECK-DAG: [[COPY_LINE]] = !DILocation(line: 0, scope: ![[COPY_SP:[0-9]+]]) -// CHECK-DAG: [[COPY_SP]] = distinct !DISubprogram(name: "__copy_helper_block_" -// CHECK-DAG: [[DESTROY_LINE]] = !DILocation(line: 0, scope: ![[DESTROY_SP:[0-9]+]]) -// CHECK-DAG: [[DESTROY_SP]] = distinct !DISubprogram(name: "__destroy_helper_block_" +// CHECK-DAG: ![[DBG_LINE]] = !DILocation(line: 0, scope: ![[COPY_SP:[0-9]+]]) +// CHECK-DAG: ![[COPY_LINE]] = !DILocation(line: 0, scope: ![[COPY_SP:[0-9]+]]) +// CHECK-DAG: ![[COPY_SP]] = distinct !DISubprogram(name: "__copy_helper_block_" +// CHECK-DAG: ![[DESTROY_LINE]] = !DILocation(line: 0, scope: ![[DESTROY_SP:[0-9]+]]) +// CHECK-DAG: ![[DESTROY_SP]] = distinct !DISubprogram(name: "__destroy_helper_block_" +// CHECK-DAG: ![[BLOCK_VAR]] = !DILocalVariable(name: ".block_descriptor" +// CHECK-DAG: ![[SELF_EXPR]] = !DIExpression(DW_OP_plus, 32, DW_OP_deref) typedef unsigned int NSUInteger; @protocol NSObject @@ -61,8 +70,8 @@ { if ((self = [super init])) { run(^{ - // CHECK-DAG: ![[SELF]] = !DILocalVariable(name: "self", scope:{{.*}}, line: [[@LINE+4]], - // CHECK-DAG: ![[D]] = !DILocalVariable(name: "d", scope:{{.*}}, line: [[@LINE+1]], + // CHECK-DAG: ![[SELF_VAR]] = !DILocalVariable(name: "self", scope:{{.*}}, line: [[@LINE+4]], + // CHECK-DAG: ![[D_VAR]] = !DILocalVariable(name: "d", scope:{{.*}}, line: [[@LINE+1]], NSMutableDictionary *d = [[NSMutableDictionary alloc] init]; ivar = 42 + (int)[d count]; }); Index: test/CodeGenObjC/debug-info-block-captured-self.m =================================================================== --- test/CodeGenObjC/debug-info-block-captured-self.m +++ test/CodeGenObjC/debug-info-block-captured-self.m @@ -56,16 +56,22 @@ // CHECK-NEXT: [[DBGADDR:%.*]] = alloca [[BLOCK_T:<{.*}>]]*, align 8 // CHECK: store i8* [[BLOCK_DESC:%.*]], i8** %[[MEM1]], align 8 // CHECK: %[[TMP0:.*]] = load i8*, i8** %[[MEM1]] -// CHECK: call void @llvm.dbg.value(metadata i8* %[[TMP0]], i64 0, metadata ![[BDMD:[0-9]+]], metadata !{{.*}}) -// CHECK: call void @llvm.dbg.declare(metadata i8* [[BLOCK_DESC]], metadata ![[BDMD:[0-9]+]], metadata !{{.*}}) +// CHECK: call void @llvm.dbg.declare(metadata i8** %[[MEM1]], +// CHECK-SAME: metadata ![[BDMD:[0-9]+]], +// CHECK-SAME: metadata ![[EMPTY:[0-9]+]]) // CHECK: store [[BLOCK_T]]* {{%.*}}, [[BLOCK_T]]** [[DBGADDR]], align 8 -// CHECK: call void @llvm.dbg.declare(metadata [[BLOCK_T]]** [[DBGADDR]], metadata ![[SELF:.*]], metadata !{{.*}}) +// CHECK: call void @llvm.dbg.declare(metadata [[BLOCK_T]]** [[DBGADDR]], +// CHECK-SAME: metadata ![[SELF:[0-9]+]], +// CHECK-SAME: metadata ![[EXPR:[0-9]+]]) + // make sure we are still in the same function // CHECK: define {{.*}}__copy_helper_block_ // Metadata // CHECK: ![[MAIN:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Main" // CHECK-SAME: line: 23, // CHECK: ![[PMAIN:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[MAIN]], +// CHECK: ![[EMPTY]] = !DIExpression() +// CHECK: ![[EXPR]] = !DIExpression(DW_OP_plus, 32, DW_OP_deref) // CHECK: ![[BDMD]] = !DILocalVariable(name: ".block_descriptor", arg: // CHECK: ![[SELF]] = !DILocalVariable(name: "self" // CHECK-NOT: arg: Index: lib/CodeGen/CGDebugInfo.h =================================================================== --- lib/CodeGen/CGDebugInfo.h +++ lib/CodeGen/CGDebugInfo.h @@ -397,8 +397,9 @@ /// Emit call to \c llvm.dbg.declare for the block-literal argument /// to a block invocation function. void EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, - llvm::Value *Arg, unsigned ArgNo, - llvm::Value *LocalAddr, + StringRef Name, + llvm::Value *Storage, + unsigned ArgNo, CGBuilderTy &Builder); /// Emit information about a global variable. Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -3473,11 +3473,11 @@ offset = CGM.getContext().toCharUnitsFromBits( CGM.getTarget().getPointerWidth(0)); Expr.push_back(offset.getQuantity()); - Expr.push_back(llvm::dwarf::DW_OP_deref); Expr.push_back(llvm::dwarf::DW_OP_plus); // offset of x field offset = CGM.getContext().toCharUnitsFromBits(XOffset); Expr.push_back(offset.getQuantity()); + Expr.push_back(llvm::dwarf::DW_OP_deref); // Create the descriptor for the variable. auto *D = ArgNo @@ -3596,22 +3596,21 @@ ->getElementOffset(blockInfo.getCapture(VD).getIndex())); SmallVector<int64_t, 9> addr; - if (isa<llvm::AllocaInst>(Storage)) - addr.push_back(llvm::dwarf::DW_OP_deref); addr.push_back(llvm::dwarf::DW_OP_plus); - addr.push_back(offset.getQuantity()); + addr.push_back(offset.getQuantity()); + addr.push_back(llvm::dwarf::DW_OP_deref); if (isByRef) { - addr.push_back(llvm::dwarf::DW_OP_deref); - addr.push_back(llvm::dwarf::DW_OP_plus); + addr.push_back(llvm::dwarf::DW_OP_plus); // offset of __forwarding field offset = CGM.getContext().toCharUnitsFromBits(target.getPointerSizeInBits(0)); - addr.push_back(offset.getQuantity()); + addr.push_back(offset.getQuantity()); addr.push_back(llvm::dwarf::DW_OP_deref); addr.push_back(llvm::dwarf::DW_OP_plus); // offset of x field offset = CGM.getContext().toCharUnitsFromBits(XOffset); addr.push_back(offset.getQuantity()); + addr.push_back(llvm::dwarf::DW_OP_deref); } // Create the descriptor for the variable. @@ -3649,9 +3648,9 @@ } void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, - llvm::Value *Arg, + StringRef Name, + llvm::Value *Storage, unsigned ArgNo, - llvm::Value *LocalAddr, CGBuilderTy &Builder) { assert(DebugKind >= codegenoptions::LimitedDebugInfo); ASTContext &C = CGM.getContext(); @@ -3783,19 +3782,10 @@ // Create the descriptor for the parameter. auto *debugVar = DBuilder.createParameterVariable( - scope, Arg->getName(), ArgNo, tunit, line, type, - CGM.getLangOpts().Optimize, flags); - - if (LocalAddr) { - // Insert an llvm.dbg.value into the current block. - DBuilder.insertDbgValueIntrinsic( - LocalAddr, 0, debugVar, DBuilder.createExpression(), - llvm::DebugLoc::get(line, column, scope, CurInlinedAt), - Builder.GetInsertBlock()); - } + scope, Name, ArgNo, tunit, line, type, CGM.getLangOpts().Optimize, flags); // Insert an llvm.dbg.declare into the current block. - DBuilder.insertDeclare(Arg, debugVar, DBuilder.createExpression(), + DBuilder.insertDeclare(Storage, debugVar, DBuilder.createExpression(), llvm::DebugLoc::get(line, column, scope, CurInlinedAt), Builder.GetInsertBlock()); } Index: lib/CodeGen/CGBlocks.cpp =================================================================== --- lib/CodeGen/CGBlocks.cpp +++ lib/CodeGen/CGBlocks.cpp @@ -1170,30 +1170,25 @@ llvm::Value *arg) { assert(BlockInfo && "not emitting prologue of block invocation function?!"); - llvm::Value *localAddr = nullptr; - if (CGM.getCodeGenOpts().OptimizationLevel == 0) { - // Allocate a stack slot to let the debug info survive the RA. - Address alloc = CreateMemTemp(D->getType(), D->getName() + ".addr"); - Builder.CreateStore(arg, alloc); - localAddr = Builder.CreateLoad(alloc); - } + // Allocate a stack slot to let the debug info survive the RA. + Address LocalAddrAlloca = CreateMemTemp(D->getType(), D->getName() + ".addr"); + Builder.CreateStore(arg, LocalAddrAlloca); + auto *localAddr = Builder.CreateLoad(LocalAddrAlloca); if (CGDebugInfo *DI = getDebugInfo()) { - if (CGM.getCodeGenOpts().getDebugInfo() >= - codegenoptions::LimitedDebugInfo) { - DI->setLocation(D->getLocation()); - DI->EmitDeclareOfBlockLiteralArgVariable(*BlockInfo, arg, argNum, - localAddr, Builder); - } + DI->setLocation(D->getLocation()); + DI->EmitDeclareOfBlockLiteralArgVariable(*BlockInfo, arg->getName(), + LocalAddrAlloca.getPointer(), + argNum, Builder); } SourceLocation StartLoc = BlockInfo->getBlockExpr()->getBody()->getLocStart(); ApplyDebugLocation Scope(*this, StartLoc); // Instead of messing around with LocalDeclMap, just set the value // directly as BlockPointer. BlockPointer = Builder.CreatePointerCast( - arg, + localAddr, BlockInfo->StructureType->getPointerTo( getContext().getLangOpts().OpenCL ? getContext().getTargetAddressSpace(LangAS::opencl_generic) @@ -1275,21 +1270,15 @@ blockInfo.getBlockExpr()->getBody()->getLocStart()); // Okay. Undo some of what StartFunction did. - - // 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 - Address Alloca = CreateTempAlloca(BlockPointer->getType(), - getPointerAlign(), - "block.addr"); - // Set the DebugLocation to empty, so the store is recognized as a - // frame setup instruction by llvm::DwarfDebug::beginFunction(). - auto NL = ApplyDebugLocation::CreateEmpty(*this); - Builder.CreateStore(BlockPointer, Alloca); - BlockPointerDbgLoc = Alloca.getPointer(); - } + // Allocate a stack slot for it, so we can point the debugger to it + Address Alloca = CreateTempAlloca(BlockPointer->getType(), getPointerAlign(), + "block.addr"); + // Set the DebugLocation to empty, so the store is recognized as a + // frame setup instruction by llvm::DwarfDebug::beginFunction(). + auto NL = ApplyDebugLocation::CreateEmpty(*this); + Builder.CreateStore(BlockPointer, Alloca); + BlockPointerDbgLoc = Alloca.getPointer(); // If we have a C++ 'this' reference, go ahead and force it into // existence now.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits