Emit llvm.dbg.declare intrisics immediately after the described alloca.

This cleanup change doesn't change the semantics, but it makes the
resulting IR much easier to read and debug.
This commit is contained in:
Adrian Prantl
2017-05-23 09:23:41 -07:00
parent 664948eb3c
commit 8660fd489a
15 changed files with 47 additions and 38 deletions

View File

@@ -1998,8 +1998,13 @@ void IRGenDebugInfoImpl::emitDbgIntrinsic(
// the variable that is live throughout the function. With SIL
// optimizations this is not guaranteed and a variable can end up in
// two allocas (for example, one function inlined twice).
if (isa<llvm::AllocaInst>(Storage)) {
DBuilder.insertDeclare(Storage, Var, Expr, DL, BB);
if (auto *Alloca = dyn_cast<llvm::AllocaInst>(Storage)) {
auto *ParentBB = Alloca->getParent();
auto InsertBefore = std::next(Alloca->getIterator());
if (InsertBefore != ParentBB->end())
DBuilder.insertDeclare(Alloca, Var, Expr, DL, &*InsertBefore);
else
DBuilder.insertDeclare(Alloca, Var, Expr, DL, ParentBB);
return;
}

View File

@@ -4,9 +4,9 @@ func markUsed<T>(_ t: T) {}
func main() {
// CHECK: call void @llvm.dbg.declare(metadata %Any* {{.*}}, metadata ![[S:.*]], metadata !{{[0-9]+}}), !dbg ![[DBG:.*]]
// CHECK: ![[S]] = !DILocalVariable(name: "s", {{.*}}line: [[@LINE+3]]
// CHECK: ![[SCOPE:.*]] = distinct !DILexicalBlock({{.*}}line: 5, column: 13)
// CHECK: ![[S]] = !DILocalVariable(name: "s", {{.*}}line: [[@LINE+2]]
// CHECK: ![[DBG]] = !DILocation(line: [[@LINE+1]], column: 7, scope: ![[SCOPE]])
// CHECK: ![[DBG]] = !DILocation(line: [[@LINE+1]], column: 7, scope: ![[SCOPE:.*]])
var s: Any = "hello world"
var n: Any = 12
var t: Any = (1,2)

View File

@@ -12,8 +12,8 @@ func main() -> Void
var backward_ptr =
// CHECK: define internal {{.*}} i1 @_T04mainAAyyFSbSS_SStcfU_(
// CHECK: %[[RANDOM_STR_ADDR:.*]] = alloca %TSS*, align {{(4|8)}}
// CHECK: store %TSS* %{{.*}}, %TSS** %[[RANDOM_STR_ADDR]], align {{(4|8)}}
// CHECK-NEXT: call void @llvm.dbg.declare(metadata %TSS** %[[RANDOM_STR_ADDR]], metadata !{{.*}}, metadata !{{[0-9]+}}), !dbg
// CHECK: store %TSS* %{{.*}}, %TSS** %[[RANDOM_STR_ADDR]], align {{(4|8)}}
// CHECK-DAG: !DILocalVariable(name: "lhs",{{.*}} line: [[@LINE+5]],
// CHECK-DAG: !DILocalVariable(name: "rhs",{{.*}} line: [[@LINE+4]],
// CHECK-DAG: !DILocalVariable(name: "random_string",{{.*}} line: 8,

View File

@@ -1,7 +1,10 @@
// RUN: %target-swift-frontend -g -emit-ir %s | %FileCheck %s
// FIXME: This test should be testing a non-shadow-copied value instead.
for i in 0 ..< 3 {
// CHECK: %[[ALLOCA:[0-9]+]] = alloca %TSiSg
// CHECK: %i.addr = alloca i{{32|64}}
// CHECK-NEXT: call void @llvm.dbg.declare(metadata i{{32|64}}* %i.addr,
// CHECK-SAME: metadata ![[I:[0-9]+]],
// CHECK: %[[CAST:[0-9]+]] = bitcast %TSiSg* %[[ALLOCA]] to i{{32|64}}*
// CHECK: %[[LD:[0-9]+]] = load i{{32|64}}, i{{32|64}}* %[[CAST]]
// CHECK: br i1 {{%.*}}, label %[[FAIL:.*]], label %[[SUCCESS:.*]],
@@ -12,7 +15,5 @@ for i in 0 ..< 3 {
// CHECK: ; <label>:[[NEXT_BB]]:
// CHECK: %[[PHI_VAL:.*]] = phi i{{32|64}} [ %[[LD]], %[[SUCCESS]] ]
// CHECK: store i{{32|64}} %[[PHI_VAL]], i{{32|64}}* %i.addr
// CHECK-NEXT: call void @llvm.dbg.declare(metadata i{{32|64}}* %i.addr,
// CHECK-SAME: metadata ![[I:[0-9]+]],
// CHECK: ![[I]] = !DILocalVariable(name: "i",
}

View File

@@ -10,8 +10,8 @@
// CHECK: define {{.*}}_T016debug_value_addr4testyxlF
// CHECK: entry:
// CHECK-NEXT: %[[TADDR:.*]] = alloca
// CHECK: store %swift.opaque* %0, %swift.opaque** %[[TADDR:.*]], align
// CHECK-NEXT: call void @llvm.dbg.declare({{.*}}%[[TADDR]]
// CHECK: store %swift.opaque* %0, %swift.opaque** %[[TADDR:.*]], align
struct S<T> {
var a : T

View File

@@ -3,13 +3,13 @@ import StdlibUnittest
func foo<T>(_ x: T) -> () {
// CHECK: define {{.*}} @_T011generic_arg3fooyxlF
// CHECK: %[[T:.*]] = alloca %swift.type*
// CHECK: %[[X:.*]] = alloca %swift.opaque*
// CHECK: store %swift.type* %T, %swift.type** %[[T]],
// CHECK: call void @llvm.dbg.declare(metadata %swift.type** %[[T]],
// CHECK-SAME: metadata ![[T1:.*]], metadata ![[EMPTY:.*]])
// CHECK: store %swift.opaque* %0, %swift.opaque** %[[X]],
// CHECK: %[[X:.*]] = alloca %swift.opaque*
// CHECK: call void @llvm.dbg.declare(metadata %swift.opaque** %[[X]],
// CHECK-SAME: metadata ![[X1:.*]], metadata ![[EMPTY]])
// CHECK: store %swift.type* %T, %swift.type** %[[T]],
// CHECK: store %swift.opaque* %0, %swift.opaque** %[[X]],
// CHECK: ![[T1]] = !DILocalVariable(name: "$swift.type.T",
// CHECK-SAME: flags: DIFlagArtificial)
// CHECK: ![[EMPTY]] = !DIExpression()

View File

@@ -5,9 +5,9 @@ func apply<Type>(_ T : Type, fn: (Type) -> Type) -> Type { return fn(T) }
public func f<Type>(_ value : Type)
{
// CHECK: define {{.*}}_T012generic_arg31fyxlFxxcfU_
// CHECK: store %swift.opaque* %1, %swift.opaque** %[[ALLOCA:.*]], align
// CHECK: call void @llvm.dbg.declare(metadata %swift.opaque** %[[ALLOCA]],
// CHECK: call void @llvm.dbg.declare(metadata %swift.opaque** %[[ALLOCA:[^,]+]],
// CHECK-SAME: metadata ![[ARG:.*]], metadata ![[EXPR:.*]])
// CHECK: store %swift.opaque* %1, %swift.opaque** %[[ALLOCA]], align
// No deref here: The argument is an Archetype and this implicitly indirect.
// CHECK: ![[EXPR]] = !DIExpression()
// CHECK: ![[TY:.*]] = !DICompositeType({{.*}}identifier: "_T012generic_arg31fyxlFQq_D"

View File

@@ -3,14 +3,15 @@
public struct Q<T> {
let x: T
}
// CHECK: define {{.*}}_T012generic_arg43fooySayAA1QVyxGGlF
// CHECK: store %[[TY:.*]]* %0, %[[TY]]** %[[ALLOCA:.*]], align
// CHECK: call void @llvm.dbg.declare(metadata %[[TY]]** %[[ALLOCA]],
// CHECK-SAME: metadata ![[ARG:.*]], metadata ![[EXPR:.*]])
// No deref here: the array argument is passed by value.
// CHECK: ![[EXPR]] = !DIExpression()
// CHECK: ![[ARG]] = !DILocalVariable(name: "arg", arg: 1,
// CHECK-SAME: line: [[@LINE+2]], type: ![[TY:.*]])
// CHECK: ![[TY]] = !DICompositeType({{.*}}identifier: "_T0Say12generic_arg41QVyAA3fooySayACyxGGlFQq_GGD")
// CHECK: define {{.*}}_T012generic_arg43fooySayAA1QVyxGGlF
// CHECK: call void @llvm.dbg.declare
// CHECK: call void @llvm.dbg.declare(metadata %[[TY:.*]]** %[[ALLOCA:[^,]+]],
// CHECK-SAME: metadata ![[ARG:.*]], metadata ![[EXPR:.*]])
// CHECK: store %[[TY]]* %0, %[[TY]]** %[[ALLOCA]], align
// No deref here: the array argument is passed by value.
// CHECK: ![[EXPR]] = !DIExpression()
// CHECK: ![[ARG]] = !DILocalVariable(name: "arg", arg: 1,
// CHECK-SAME: line: [[@LINE+2]], type: ![[TY:.*]])
// CHECK: ![[TY]] = !DICompositeType({{.*}}identifier: "_T0Say12generic_arg41QVyAA3fooySayACyxGGlFQq_GGD")
public func foo<T>(_ arg: [Q<T>]) {
}

View File

@@ -7,9 +7,10 @@ public struct S<Type>
public func foo<Type>(_ values : [S<Type>])
{
// CHECK: define {{.*}}_T012generic_arg53fooySayAA1SVyxGGlFAESgAEcfU_
// CHECK: store %[[TY:.*]]* %1, %[[TY]]** %[[ALLOCA:.*]], align
// CHECK: call void @llvm.dbg.declare(metadata %[[TY]]** %[[ALLOCA]],
// CHECK: call void @llvm.dbg.declare
// CHECK: call void @llvm.dbg.declare(metadata %[[TY:.*]]** %[[ALLOCA:[^,]+]],
// CHECK-SAME: metadata ![[ARG:.*]], metadata ![[EXPR:.*]])
// CHECK: store %[[TY]]* %1, %[[TY]]** %[[ALLOCA]], align
// The argument is a by-ref struct and thus needs to be dereferenced.
// CHECK: ![[ARG]] = !DILocalVariable(name: "arg", arg: 1,
// CHECK-SAME: line: [[@LINE+4]],

View File

@@ -5,13 +5,13 @@ func use<T>(_ t: T) {}
public func f(_ i : Int?)
{
// CHECK: define {{.*}}@_T04main1fySiSgF
// CHECK: %[[PHI:.*]] = phi
// The shadow copy store should not have a location.
// CHECK: store {{(i32|i64)}} %[[PHI]], {{(i32|i64)}}* %val.addr, align {{(4|8)}}, !dbg ![[DBG0:.*]]
// CHECK: @llvm.dbg.declare(metadata {{(i32|i64)}}* %val.addr, {{.*}}, !dbg ![[DBG1:.*]]
// CHECK: %[[PHI:.*]] = phi
// CHECK: store {{(i32|i64)}} %[[PHI]], {{(i32|i64)}}* %val.addr, align {{(4|8)}}, !dbg ![[DBG0:.*]]
// CHECK: ![[F:.*]] = distinct !DISubprogram(name: "f",
// CHECK: ![[DBG1]] = !DILocation(line: [[@LINE+2]],
// CHECK: ![[DBG0]] = !DILocation(line: 0, scope: ![[F]])
// CHECK: ![[DBG1]] = !DILocation(line: [[@LINE+1]],
guard let val = i else { return }
use(val)
}

View File

@@ -4,10 +4,10 @@ func yieldValue() -> Int64? { return 23 }
// Verify that variables bound in the while statements are in distinct scopes.
if let val = yieldValue() {
// CHECK: ![[SCOPE1:[0-9]+]] = distinct !DILexicalBlock(scope: ![[MAIN:[0-9]+]]
// CHECK: !DILocalVariable(name: "val", scope: ![[SCOPE1]]
// CHECK: !DILocalVariable(name: "val", scope: ![[SCOPE1:[0-9]+]]
// CHECK: ![[SCOPE1]] = distinct !DILexicalBlock(scope: ![[MAIN:[0-9]+]]
}
if let val = yieldValue() {
// CHECK: ![[SCOPE2:[0-9]+]] = distinct !DILexicalBlock(scope: ![[MAIN]]
// CHECK: !DILocalVariable(name: "val", scope: ![[SCOPE2]]
// CHECK: !DILocalVariable(name: "val", scope: ![[SCOPE2:[0-9]+]]
// CHECK: ![[SCOPE2]] = distinct !DILexicalBlock(scope: ![[MAIN]]
}

View File

@@ -17,8 +17,8 @@ class MyClass {
func filterImage(_ image: UIImage!, _ doSomething:Bool) -> UIImage
{
// Test that image is in an alloca, but not an indirect location.
// CHECK: store {{(i32|i64)}} %0, {{(i32|i64)}}* %[[ALLOCA:.*]], align
// CHECK: call void @llvm.dbg.declare(metadata {{(i32|i64)}}* %[[ALLOCA]], metadata ![[IMAGE:.*]], metadata !{{[0-9]+}})
// CHECK: call void @llvm.dbg.declare(metadata {{(i32|i64)}}* %[[ALLOCA:.*]], metadata ![[IMAGE:.*]], metadata !{{[0-9]+}})
// CHECK: store {{(i32|i64)}} %0, {{(i32|i64)}}* %[[ALLOCA]], align
// CHECK: ![[IMAGE]] = !DILocalVariable(name: "image", arg: 1
// CHECK-NOT: flags:
// CHECK-SAME: line: [[@LINE-7]]

View File

@@ -12,6 +12,7 @@ import Foundation
// CHECK_NONE: define{{( protected)?}} {{.*}}void {{.*}}none
public func none(_ a: inout Int64) {
// CHECK_NONE: call void @llvm.dbg{{.*}}, !dbg
// CHECK_NONE: store{{.*}}, !dbg
// CHECK_NONE: !dbg ![[NONE_INIT:.*]]
a -= 2
// CHECK_NONE: ret {{.*}}, !dbg ![[NONE_RET:.*]]

View File

@@ -7,9 +7,9 @@ func foo(_ x: inout Int64) {
// line 0), but the code to load the value from the inout storage is
// not.
// CHECK: %[[X:.*]] = alloca %Ts5Int64V*, align {{(4|8)}}
// CHECK-NEXT: call void @llvm.dbg.declare
// CHECK: store %Ts5Int64V* %0, %Ts5Int64V** %[[X]], align {{(4|8)}}
// CHECK-SAME: !dbg ![[LOC0:.*]]
// CHECK-NEXT: call void @llvm.dbg.declare
// CHECK-NEXT: getelementptr inbounds %Ts5Int64V, %Ts5Int64V* %0, i32 0, i32 0,
// CHECK-SAME: !dbg ![[LOC1:.*]]
// CHECK: ![[LOC0]] = !DILocation(line: 0,

View File

@@ -4,10 +4,10 @@ func yieldValues() -> Int64? { return .none }
// Verify that variables bound in the while statements are in distinct scopes.
while let val = yieldValues() {
// CHECK: ![[SCOPE1:[0-9]+]] = distinct !DILexicalBlock(scope: ![[MAIN:[0-9]+]]
// CHECK: !DILocalVariable(name: "val", scope: ![[SCOPE1]]
// CHECK: !DILocalVariable(name: "val", scope: ![[SCOPE1:[0-9]+]]
// CHECK: ![[SCOPE1]] = distinct !DILexicalBlock(scope: ![[MAIN:[0-9]+]]
}
while let val = yieldValues() {
// CHECK: ![[SCOPE2:[0-9]+]] = distinct !DILexicalBlock(scope: ![[MAIN]]
// CHECK: !DILocalVariable(name: "val", scope: ![[SCOPE2]]
// CHECK: !DILocalVariable(name: "val", scope: ![[SCOPE2:[0-9]+]]
// CHECK: ![[SCOPE2]] = distinct !DILexicalBlock(scope: ![[MAIN]]
}