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 // the variable that is live throughout the function. With SIL
// optimizations this is not guaranteed and a variable can end up in // optimizations this is not guaranteed and a variable can end up in
// two allocas (for example, one function inlined twice). // two allocas (for example, one function inlined twice).
if (isa<llvm::AllocaInst>(Storage)) { if (auto *Alloca = dyn_cast<llvm::AllocaInst>(Storage)) {
DBuilder.insertDeclare(Storage, Var, Expr, DL, BB); 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; return;
} }

View File

@@ -4,9 +4,9 @@ func markUsed<T>(_ t: T) {}
func main() { func main() {
// CHECK: call void @llvm.dbg.declare(metadata %Any* {{.*}}, metadata ![[S:.*]], metadata !{{[0-9]+}}), !dbg ![[DBG:.*]] // 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: ![[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 s: Any = "hello world"
var n: Any = 12 var n: Any = 12
var t: Any = (1,2) var t: Any = (1,2)

View File

@@ -12,8 +12,8 @@ func main() -> Void
var backward_ptr = var backward_ptr =
// CHECK: define internal {{.*}} i1 @_T04mainAAyyFSbSS_SStcfU_( // CHECK: define internal {{.*}} i1 @_T04mainAAyyFSbSS_SStcfU_(
// CHECK: %[[RANDOM_STR_ADDR:.*]] = alloca %TSS*, align {{(4|8)}} // 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-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: "lhs",{{.*}} line: [[@LINE+5]],
// CHECK-DAG: !DILocalVariable(name: "rhs",{{.*}} line: [[@LINE+4]], // CHECK-DAG: !DILocalVariable(name: "rhs",{{.*}} line: [[@LINE+4]],
// CHECK-DAG: !DILocalVariable(name: "random_string",{{.*}} line: 8, // CHECK-DAG: !DILocalVariable(name: "random_string",{{.*}} line: 8,

View File

@@ -1,7 +1,10 @@
// RUN: %target-swift-frontend -g -emit-ir %s | %FileCheck %s // 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 { for i in 0 ..< 3 {
// CHECK: %[[ALLOCA:[0-9]+]] = alloca %TSiSg // CHECK: %[[ALLOCA:[0-9]+]] = alloca %TSiSg
// CHECK: %i.addr = alloca i{{32|64}} // 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: %[[CAST:[0-9]+]] = bitcast %TSiSg* %[[ALLOCA]] to i{{32|64}}*
// CHECK: %[[LD:[0-9]+]] = load i{{32|64}}, i{{32|64}}* %[[CAST]] // CHECK: %[[LD:[0-9]+]] = load i{{32|64}}, i{{32|64}}* %[[CAST]]
// CHECK: br i1 {{%.*}}, label %[[FAIL:.*]], label %[[SUCCESS:.*]], // CHECK: br i1 {{%.*}}, label %[[FAIL:.*]], label %[[SUCCESS:.*]],
@@ -12,7 +15,5 @@ for i in 0 ..< 3 {
// CHECK: ; <label>:[[NEXT_BB]]: // CHECK: ; <label>:[[NEXT_BB]]:
// CHECK: %[[PHI_VAL:.*]] = phi i{{32|64}} [ %[[LD]], %[[SUCCESS]] ] // CHECK: %[[PHI_VAL:.*]] = phi i{{32|64}} [ %[[LD]], %[[SUCCESS]] ]
// CHECK: store i{{32|64}} %[[PHI_VAL]], i{{32|64}}* %i.addr // 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", // CHECK: ![[I]] = !DILocalVariable(name: "i",
} }

View File

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

View File

@@ -3,13 +3,13 @@ import StdlibUnittest
func foo<T>(_ x: T) -> () { func foo<T>(_ x: T) -> () {
// CHECK: define {{.*}} @_T011generic_arg3fooyxlF // CHECK: define {{.*}} @_T011generic_arg3fooyxlF
// CHECK: %[[T:.*]] = alloca %swift.type* // 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: call void @llvm.dbg.declare(metadata %swift.type** %[[T]],
// CHECK-SAME: metadata ![[T1:.*]], metadata ![[EMPTY:.*]]) // 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: call void @llvm.dbg.declare(metadata %swift.opaque** %[[X]],
// CHECK-SAME: metadata ![[X1:.*]], metadata ![[EMPTY]]) // 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: ![[T1]] = !DILocalVariable(name: "$swift.type.T",
// CHECK-SAME: flags: DIFlagArtificial) // CHECK-SAME: flags: DIFlagArtificial)
// CHECK: ![[EMPTY]] = !DIExpression() // 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) public func f<Type>(_ value : Type)
{ {
// CHECK: define {{.*}}_T012generic_arg31fyxlFxxcfU_ // 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-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. // No deref here: The argument is an Archetype and this implicitly indirect.
// CHECK: ![[EXPR]] = !DIExpression() // CHECK: ![[EXPR]] = !DIExpression()
// CHECK: ![[TY:.*]] = !DICompositeType({{.*}}identifier: "_T012generic_arg31fyxlFQq_D" // CHECK: ![[TY:.*]] = !DICompositeType({{.*}}identifier: "_T012generic_arg31fyxlFQq_D"

View File

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

View File

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

View File

@@ -5,13 +5,13 @@ func use<T>(_ t: T) {}
public func f(_ i : Int?) public func f(_ i : Int?)
{ {
// CHECK: define {{.*}}@_T04main1fySiSgF // CHECK: define {{.*}}@_T04main1fySiSgF
// CHECK: %[[PHI:.*]] = phi
// The shadow copy store should not have a location. // 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: @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: ![[F:.*]] = distinct !DISubprogram(name: "f",
// CHECK: ![[DBG1]] = !DILocation(line: [[@LINE+2]],
// CHECK: ![[DBG0]] = !DILocation(line: 0, scope: ![[F]]) // CHECK: ![[DBG0]] = !DILocation(line: 0, scope: ![[F]])
// CHECK: ![[DBG1]] = !DILocation(line: [[@LINE+1]],
guard let val = i else { return } guard let val = i else { return }
use(val) 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. // Verify that variables bound in the while statements are in distinct scopes.
if let val = yieldValue() { if let val = yieldValue() {
// CHECK: ![[SCOPE1:[0-9]+]] = distinct !DILexicalBlock(scope: ![[MAIN:[0-9]+]] // CHECK: !DILocalVariable(name: "val", scope: ![[SCOPE1:[0-9]+]]
// CHECK: !DILocalVariable(name: "val", scope: ![[SCOPE1]] // CHECK: ![[SCOPE1]] = distinct !DILexicalBlock(scope: ![[MAIN:[0-9]+]]
} }
if let val = yieldValue() { if let val = yieldValue() {
// CHECK: ![[SCOPE2:[0-9]+]] = distinct !DILexicalBlock(scope: ![[MAIN]] // CHECK: !DILocalVariable(name: "val", scope: ![[SCOPE2:[0-9]+]]
// CHECK: !DILocalVariable(name: "val", scope: ![[SCOPE2]] // CHECK: ![[SCOPE2]] = distinct !DILexicalBlock(scope: ![[MAIN]]
} }

View File

@@ -17,8 +17,8 @@ class MyClass {
func filterImage(_ image: UIImage!, _ doSomething:Bool) -> UIImage func filterImage(_ image: UIImage!, _ doSomething:Bool) -> UIImage
{ {
// Test that image is in an alloca, but not an indirect location. // 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: ![[IMAGE]] = !DILocalVariable(name: "image", arg: 1
// CHECK-NOT: flags: // CHECK-NOT: flags:
// CHECK-SAME: line: [[@LINE-7]] // CHECK-SAME: line: [[@LINE-7]]

View File

@@ -12,6 +12,7 @@ import Foundation
// CHECK_NONE: define{{( protected)?}} {{.*}}void {{.*}}none // CHECK_NONE: define{{( protected)?}} {{.*}}void {{.*}}none
public func none(_ a: inout Int64) { public func none(_ a: inout Int64) {
// CHECK_NONE: call void @llvm.dbg{{.*}}, !dbg // CHECK_NONE: call void @llvm.dbg{{.*}}, !dbg
// CHECK_NONE: store{{.*}}, !dbg
// CHECK_NONE: !dbg ![[NONE_INIT:.*]] // CHECK_NONE: !dbg ![[NONE_INIT:.*]]
a -= 2 a -= 2
// CHECK_NONE: ret {{.*}}, !dbg ![[NONE_RET:.*]] // 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 // line 0), but the code to load the value from the inout storage is
// not. // not.
// CHECK: %[[X:.*]] = alloca %Ts5Int64V*, align {{(4|8)}} // CHECK: %[[X:.*]] = alloca %Ts5Int64V*, align {{(4|8)}}
// CHECK-NEXT: call void @llvm.dbg.declare
// CHECK: store %Ts5Int64V* %0, %Ts5Int64V** %[[X]], align {{(4|8)}} // CHECK: store %Ts5Int64V* %0, %Ts5Int64V** %[[X]], align {{(4|8)}}
// CHECK-SAME: !dbg ![[LOC0:.*]] // CHECK-SAME: !dbg ![[LOC0:.*]]
// CHECK-NEXT: call void @llvm.dbg.declare
// CHECK-NEXT: getelementptr inbounds %Ts5Int64V, %Ts5Int64V* %0, i32 0, i32 0, // CHECK-NEXT: getelementptr inbounds %Ts5Int64V, %Ts5Int64V* %0, i32 0, i32 0,
// CHECK-SAME: !dbg ![[LOC1:.*]] // CHECK-SAME: !dbg ![[LOC1:.*]]
// CHECK: ![[LOC0]] = !DILocation(line: 0, // 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. // Verify that variables bound in the while statements are in distinct scopes.
while let val = yieldValues() { while let val = yieldValues() {
// CHECK: ![[SCOPE1:[0-9]+]] = distinct !DILexicalBlock(scope: ![[MAIN:[0-9]+]] // CHECK: !DILocalVariable(name: "val", scope: ![[SCOPE1:[0-9]+]]
// CHECK: !DILocalVariable(name: "val", scope: ![[SCOPE1]] // CHECK: ![[SCOPE1]] = distinct !DILexicalBlock(scope: ![[MAIN:[0-9]+]]
} }
while let val = yieldValues() { while let val = yieldValues() {
// CHECK: ![[SCOPE2:[0-9]+]] = distinct !DILexicalBlock(scope: ![[MAIN]] // CHECK: !DILocalVariable(name: "val", scope: ![[SCOPE2:[0-9]+]]
// CHECK: !DILocalVariable(name: "val", scope: ![[SCOPE2]] // CHECK: ![[SCOPE2]] = distinct !DILexicalBlock(scope: ![[MAIN]]
} }