Add SIL syntax for declaring debug variables.

Debug variable info may be attached to debug_value, debug_value_addr,
alloc_box, and alloc_stack instructions.

In order to write textual SIL -> SIL testcases that exercise the handling
of debug information by SIL passes, we need to make a couple of additions
to the textual SIL language. In memory, the debug information attached to
SIL instructions references information from the AST. If we want to create
debug info from parsing a textual .sil file, these bits need to be made
explicit.

Performance Notes: This is memory neutral for compilations from Swift
source code, because the variable name is still stored in the AST. For
compilations from textual source the variable name is stored in tail-
allocated memory following the SIL instruction that introduces the
variable.

<rdar://problem/22707128>
This commit is contained in:
Adrian Prantl
2015-12-14 09:59:13 -08:00
parent e6442dc9b2
commit 64cbec3805
79 changed files with 593 additions and 414 deletions

View File

@@ -564,12 +564,12 @@ func testRequireExprPattern(a : Int) {
// CHECK-LABEL: sil hidden @_TF10statements20testRequireOptional1FGSqSi_Si
// CHECK: bb0(%0 : $Optional<Int>):
// CHECK-NEXT: debug_value %0 : $Optional<Int> // let a
// CHECK-NEXT: debug_value %0 : $Optional<Int>, let, name "a"
// CHECK-NEXT: switch_enum %0 : $Optional<Int>, case #Optional.Some!enumelt.1: bb1, default bb2
func testRequireOptional1(a : Int?) -> Int {
// CHECK: bb1(%3 : $Int):
// CHECK-NEXT: debug_value %3 : $Int // let t
// CHECK-NEXT: debug_value %3 : $Int, let, name "t"
// CHECK-NEXT: return %3 : $Int
guard let t = a else { abort() }
@@ -583,14 +583,14 @@ func testRequireOptional1(a : Int?) -> Int {
// CHECK-LABEL: sil hidden @_TF10statements20testRequireOptional2FGSqSS_SS
// CHECK: bb0(%0 : $Optional<String>):
// CHECK-NEXT: debug_value %0 : $Optional<String> // let a
// CHECK-NEXT: debug_value %0 : $Optional<String>, let, name "a"
// CHECK-NEXT: retain_value %0 : $Optional<String>
// CHECK-NEXT: switch_enum %0 : $Optional<String>, case #Optional.Some!enumelt.1: bb1, default bb2
func testRequireOptional2(a : String?) -> String {
guard let t = a else { abort() }
// CHECK: bb1(%4 : $String):
// CHECK-NEXT: debug_value %4 : $String // let t
// CHECK-NEXT: debug_value %4 : $String, let, name "t"
// CHECK-NEXT: release_value %0 : $Optional<String>
// CHECK-NEXT: return %4 : $String
@@ -608,8 +608,8 @@ enum MyOpt<T> {
// CHECK-LABEL: sil hidden @_TF10statements28testAddressOnlyEnumInRequire
// CHECK: bb0(%0 : $*T, %1 : $*MyOpt<T>):
// CHECK-NEXT: debug_value_addr %1 : $*MyOpt<T> // let a
// CHECK-NEXT: %3 = alloc_stack $T // let t
// CHECK-NEXT: debug_value_addr %1 : $*MyOpt<T>, let, name "a"
// CHECK-NEXT: %3 = alloc_stack $T, let, name "t"
// CHECK-NEXT: %4 = alloc_stack $MyOpt<T>
// CHECK-NEXT: copy_addr %1 to [initialization] %4#1 : $*MyOpt<T>
// CHECK-NEXT: switch_enum_addr %4#1 : $*MyOpt<T>, case #MyOpt.Some!enumelt.1: bb2, default bb1
@@ -667,7 +667,7 @@ func test_as_pattern(y : BaseClass) -> DerivedClass {
// CHECK: bb{{.*}}([[PTR:%[0-9]+]] : $DerivedClass):
// CHECK-NEXT: debug_value [[PTR]] : $DerivedClass // let result
// CHECK-NEXT: debug_value [[PTR]] : $DerivedClass, let, name "result"
// CHECK-NEXT: strong_release %0 : $BaseClass
// CHECK-NEXT: return [[PTR]] : $DerivedClass
return result
@@ -676,7 +676,7 @@ func test_as_pattern(y : BaseClass) -> DerivedClass {
func let_else_tuple_binding(a : (Int, Int)?) -> Int {
// CHECK: bb0(%0 : $Optional<(Int, Int)>):
// CHECK-NEXT: debug_value %0 : $Optional<(Int, Int)> // let a
// CHECK-NEXT: debug_value %0 : $Optional<(Int, Int)>, let, name "a"
// CHECK-NEXT: switch_enum %0 : $Optional<(Int, Int)>, case #Optional.Some!enumelt.1: bb1, default bb2
guard let (x, y) = a else { }
@@ -685,9 +685,9 @@ func let_else_tuple_binding(a : (Int, Int)?) -> Int {
// CHECK: bb1(%3 : $(Int, Int)):
// CHECK-NEXT: %4 = tuple_extract %3 : $(Int, Int), 0
// CHECK-NEXT: debug_value %4 : $Int // let x
// CHECK-NEXT: debug_value %4 : $Int, let, name "x"
// CHECK-NEXT: %6 = tuple_extract %3 : $(Int, Int), 1
// CHECK-NEXT: debug_value %6 : $Int // let y
// CHECK-NEXT: debug_value %6 : $Int, let, name "y"
// CHECK-NEXT: return %4 : $Int
}