mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
The initial version of the debugger testing transform instruments
assignments in a way that allows the debugger to sanity-check its
expression evaluator.
Given an assignment expression of the form:
```
a = b
```
The transform rewrites the relevant bits of the AST to look like this:
```
{ () -> () in
a = b
checkExpect("a", stringForPrintObject(a))
}()
```
The purpose of the rewrite is to make it easier to exercise the
debugger's expression evaluator in new contexts. This can be automated
by having the debugger set a breakpoint on checkExpect, running `expr
$Varname`, and comparing the result to the expected value generated by
the runtime.
While the initial version of this testing transform only supports
instrumenting assignments, it should be simple to teach it to do more
interesting rewrites.
There's a driver script available in SWIFT_BIN_DIR/lldb-check-expect to
simplfiy the process of launching and testing instrumented programs.
rdar://36032055
88 lines
2.6 KiB
Swift
88 lines
2.6 KiB
Swift
// RUN: %target-swift-frontend -debugger-testing-transform -Xllvm -sil-full-demangle -emit-sil -module-name M %s | %FileCheck %s -check-prefix=CHECK-SIL
|
|
|
|
// REQUIRES: executable_test
|
|
// RUN: %target-build-swift -Xfrontend -debugger-testing-transform %s -o %t
|
|
// RUN: %target-run %t | %FileCheck %s -check-prefix=CHECK-E2E
|
|
// RUN: rm -rf %t
|
|
|
|
var a = 1001
|
|
a = 1002
|
|
|
|
// CHECK-SIL-LABEL: sil private @$S1MyyXEfU0_ : {{.*}} () -> ()
|
|
// CHECK-SIL: [[int:%.*]] = integer_literal {{.*}}, 1002
|
|
// CHECK-SIL: [[struct:%.*]] = struct $Int ([[int]] : {{.*}})
|
|
// CHECK-SIL: store [[struct]] {{.*}} : $*Int
|
|
// CHECK-SIL: string_literal utf8 "a"
|
|
// CHECK-SIL: [[PO:%.*]] = function_ref {{.*}}_stringForPrintObjectySSypF
|
|
// CHECK-SIL: [[PO_result:%.*]] = apply [[PO]]
|
|
// CHECK-SIL: [[check_expect:%.*]] = function_ref {{.*}}_debuggerTestingCheckExpectyySS_SStF
|
|
// CHECK-SIL: apply [[check_expect]]
|
|
|
|
print("a = \(a)") // CHECK-E2E: a = 1002
|
|
|
|
// CHECK-SIL-LABEL: sil private @$S1MyyXEfU_yyXEfU1_
|
|
({ () -> () in
|
|
a = 1003
|
|
// CHECK-SIL: function_ref {{.*}}_debuggerTestingCheckExpectyySS_SStF
|
|
print("a = \(a)") // CHECK-E2E-NEXT: a = 1003
|
|
})()
|
|
|
|
// CHECK-SIL-LABEL: sil private @$S1MyyXEfU2_
|
|
// CHECK-SIL: function_ref {{.*}}_debuggerTestingCheckExpectyySS_SStF
|
|
a = 1004
|
|
print("a = \(a)") // CHECK-E2E-NEXT: a = 1004
|
|
|
|
// CHECK-SIL-LABEL: sil private @$S1M2f1yyFyyXEfU3_
|
|
func f1() {
|
|
var b = 2001
|
|
b = 2002
|
|
// CHECK-SIL: function_ref {{.*}}_debuggerTestingCheckExpectyySS_SStF
|
|
print("b = \(b)") // CHECK-E2E-NEXT: b = 2002
|
|
}
|
|
|
|
f1()
|
|
|
|
// CHECK-SIL-LABEL: sil private @$S1M2f2yyFyyXEfU_yyXEfU4_
|
|
func f2() {
|
|
var c: Int = 3001
|
|
({ () -> () in
|
|
c = 3002
|
|
// CHECK-SIL: function_ref {{.*}}_debuggerTestingCheckExpectyySS_SStF
|
|
print("c = \(c)") // CHECK-E2E-NEXT: c = 3002
|
|
})()
|
|
}
|
|
|
|
f2()
|
|
|
|
// CHECK-SIL-LABEL: sil private @$S1M2f3yySaySiGzFyyXEfU5_
|
|
func f3(_ d: inout [Int]) {
|
|
d[0] = 4002
|
|
// CHECK-SIL: function_ref {{.*}}_debuggerTestingCheckExpectyySS_SStF
|
|
print("d[0] = \(d[0])") // CHECK-E2E-NEXT: d[0] = 4002
|
|
}
|
|
|
|
var d: [Int] = [4001]
|
|
f3(&d)
|
|
|
|
// CHECK-SIL-LABEL: sil hidden @$S1M2f4yyF
|
|
// CHECK-SIL-NOT: _debuggerTestingCheckExpect
|
|
func f4() {
|
|
// We don't attempt to instrument in this case because we don't try
|
|
// to prove that the var decl is definitively initialized.
|
|
var e: Int
|
|
e = 5001
|
|
print("e = \(e)") // CHECK-E2E-NEXT: e = 5001
|
|
}
|
|
|
|
f4()
|
|
|
|
// CHECK-SIL-LABEL: sil private @$S1M2f5yySSzFyyXEfU6_
|
|
func f5(_ v: inout String) {
|
|
v = "Hello world"
|
|
// CHECK-SIL: function_ref {{.*}}_debuggerTestingCheckExpectyySS_SStF
|
|
print("v = \(v)") // CHECK-E2E-NEXT: v = Hello world
|
|
}
|
|
|
|
var v: String = ""
|
|
f5(&v)
|