Simplify codegen and debug info generation for block context parameters.
The exisiting code goes out of its way to put block parameters into an alloca only at -O0, and then describes the funciton argument with a dbg.declare, which is undocumented in the LLVM-CFE contract and does not actually behave as intended after LLVM r642022. This patch just generates the alloca unconditionally, the mem2reg pass will eliminate it at -O1 and up anyway and points the dbg.declare to the alloca as intended (which mem2reg will then correctly rewrite into a dbg.value). This reapplies r316684 with some dead code removed. rdar://problem/35043980 Differential Revision: https://reviews.llvm.org/D39305 llvm-svn: 316689
This commit is contained in:
parent
86cf0856ae
commit
356347b58d
|
@ -1293,20 +1293,17 @@ void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D,
|
|||
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 like for any local variable to guarantee optimal
|
||||
// debug info at -O0. The mem2reg pass will eliminate it when optimizing.
|
||||
Address alloc = CreateMemTemp(D->getType(), D->getName() + ".addr");
|
||||
Builder.CreateStore(arg, alloc);
|
||||
if (CGDebugInfo *DI = getDebugInfo()) {
|
||||
if (CGM.getCodeGenOpts().getDebugInfo() >=
|
||||
codegenoptions::LimitedDebugInfo) {
|
||||
DI->setLocation(D->getLocation());
|
||||
DI->EmitDeclareOfBlockLiteralArgVariable(*BlockInfo, arg, argNum,
|
||||
localAddr, Builder);
|
||||
DI->EmitDeclareOfBlockLiteralArgVariable(
|
||||
*BlockInfo, D->getName(), argNum,
|
||||
cast<llvm::AllocaInst>(alloc.getPointer()), Builder);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3694,9 +3694,9 @@ bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) {
|
|||
}
|
||||
|
||||
void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
|
||||
llvm::Value *Arg,
|
||||
StringRef Name,
|
||||
unsigned ArgNo,
|
||||
llvm::Value *LocalAddr,
|
||||
llvm::AllocaInst *Alloca,
|
||||
CGBuilderTy &Builder) {
|
||||
assert(DebugKind >= codegenoptions::LimitedDebugInfo);
|
||||
ASTContext &C = CGM.getContext();
|
||||
|
@ -3828,19 +3828,11 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
|
|||
|
||||
// Create the descriptor for the parameter.
|
||||
auto *debugVar = DBuilder.createParameterVariable(
|
||||
scope, Arg->getName(), ArgNo, tunit, line, type,
|
||||
scope, Name, ArgNo, tunit, line, type,
|
||||
CGM.getLangOpts().Optimize, flags);
|
||||
|
||||
if (LocalAddr) {
|
||||
// Insert an llvm.dbg.value into the current block.
|
||||
DBuilder.insertDbgValueIntrinsic(
|
||||
LocalAddr, debugVar, DBuilder.createExpression(),
|
||||
llvm::DebugLoc::get(line, column, scope, CurInlinedAt),
|
||||
Builder.GetInsertBlock());
|
||||
}
|
||||
|
||||
// Insert an llvm.dbg.declare into the current block.
|
||||
DBuilder.insertDeclare(Arg, debugVar, DBuilder.createExpression(),
|
||||
DBuilder.insertDeclare(Alloca, debugVar, DBuilder.createExpression(),
|
||||
llvm::DebugLoc::get(line, column, scope, CurInlinedAt),
|
||||
Builder.GetInsertBlock());
|
||||
}
|
||||
|
|
|
@ -398,8 +398,8 @@ public:
|
|||
/// 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, unsigned ArgNo,
|
||||
llvm::AllocaInst *LocalAddr,
|
||||
CGBuilderTy &Builder);
|
||||
|
||||
/// Emit information about a global variable.
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
// RUN: %clang_cc1 -x c -fblocks -debug-info-kind=standalone -emit-llvm -O0 \
|
||||
// RUN: -triple x86_64-apple-darwin -o - %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c -fblocks -debug-info-kind=standalone -emit-llvm -O1 \
|
||||
// RUN: -triple x86_64-apple-darwin -o - %s \
|
||||
// RUN: | FileCheck --check-prefix=CHECK-OPT %s
|
||||
|
||||
// CHECK: define internal void @__f_block_invoke(i8* %.block_descriptor)
|
||||
// CHECK: %.block_descriptor.addr = alloca i8*, align 8
|
||||
// CHECK: %block.addr = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor* }>*, align 8
|
||||
// CHECK: store i8* %.block_descriptor, i8** %.block_descriptor.addr, align 8
|
||||
// CHECK: call void @llvm.dbg.declare(metadata i8** %.block_descriptor.addr,
|
||||
// CHECK-SAME: metadata !DIExpression())
|
||||
// CHECK-OPT-NOT: alloca
|
||||
// CHECK-OPT: call void @llvm.dbg.value(metadata i8* %.block_descriptor,
|
||||
// CHECK-OPT-SAME: metadata !DIExpression())
|
||||
void f() {
|
||||
a(^{
|
||||
b();
|
||||
});
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
// RUN: %clang_cc1 -fblocks -debug-info-kind=limited -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s
|
||||
//
|
||||
// Test that debug location is generated for a captured "self" inside
|
||||
// a block.
|
||||
//
|
||||
// This test is split into two parts, this one for the frontend, and
|
||||
// then llvm/test/DebugInfo/debug-info-block-captured-self.ll to
|
||||
// ensure that DW_AT_location is generated for the captured self.
|
||||
@class T;
|
||||
@interface S
|
||||
@end
|
||||
@interface Mode
|
||||
-(int) count;
|
||||
@end
|
||||
@interface Context
|
||||
@end
|
||||
@interface ViewController
|
||||
@property (nonatomic, readwrite, strong) Context *context;
|
||||
@end
|
||||
typedef enum {
|
||||
Unknown = 0,
|
||||
} State;
|
||||
@interface Main : ViewController
|
||||
{
|
||||
T * t1;
|
||||
T * t2;
|
||||
}
|
||||
@property(readwrite, nonatomic) State state;
|
||||
@end
|
||||
@implementation Main
|
||||
- (id) initWithContext:(Context *) context
|
||||
{
|
||||
t1 = [self.context withBlock:^(id obj){
|
||||
id *mode1;
|
||||
t2 = [mode1 withBlock:^(id object){
|
||||
Mode *mode2 = object;
|
||||
if ([mode2 count] != 0) {
|
||||
self.state = 0;
|
||||
}
|
||||
}];
|
||||
}];
|
||||
}
|
||||
@end
|
||||
// The important part of this test is that there is a dbg.value
|
||||
// intrinsic associated with the implicit .block_descriptor argument
|
||||
// of the block. We also test that this value gets alloca'd, so the
|
||||
// register llocator won't accidentally kill it.
|
||||
|
||||
// outer block:
|
||||
// CHECK: define internal void {{.*}}_block_invoke{{.*}}
|
||||
|
||||
// inner block:
|
||||
// CHECK: define internal void {{.*}}_block_invoke{{.*}}
|
||||
// CHECK: %[[MEM1:.*]] = alloca i8*, align 8
|
||||
// CHECK-NEXT: %[[MEM2:.*]] = alloca i8*, align 8
|
||||
// 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]], metadata ![[BDMD:[0-9]+]], metadata !{{.*}})
|
||||
// CHECK: call void @llvm.dbg.declare(metadata i8* [[BLOCK_DESC]], metadata ![[BDMD:[0-9]+]], metadata !{{.*}})
|
||||
// CHECK: store [[BLOCK_T]]* {{%.*}}, [[BLOCK_T]]** [[DBGADDR]], align 8
|
||||
// CHECK: call void @llvm.dbg.declare(metadata [[BLOCK_T]]** [[DBGADDR]], metadata ![[SELF:.*]], metadata !{{.*}})
|
||||
// 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: ![[BDMD]] = !DILocalVariable(name: ".block_descriptor", arg:
|
||||
// CHECK: ![[SELF]] = !DILocalVariable(name: "self"
|
||||
// CHECK-NOT: arg:
|
||||
// CHECK-SAME: line: 40,
|
Loading…
Reference in New Issue