Files
swift-mirror/test/DebugInfo/debug_transform_block.sil
Emil Pedersen 370d0dc771 [DebugInfo] Fix salvage tuple when a debug block exists
This tuple salvage logic is the same as the struct salvage logic.

Assisted-by: Claude
2026-06-01 11:37:41 +02:00

126 lines
5.4 KiB
Plaintext

// RUN: %target-swift-frontend -disable-debugger-shadow-copies -primary-file %s -emit-ir -g -o - | %FileCheck %s
sil_stage canonical
import Builtin
import Swift
struct MyStruct {
@_hasStorage var x: Int64 { get set }
@_hasStorage var y: Int64 { get set }
init(x: Int64, y: Int64)
}
sil_scope 1 { loc "file.swift":1:6 parent @test_transform_const : $@convention(thin) () -> () }
sil_scope 2 { loc "file.swift":5:6 parent @test_transform_add : $@convention(thin) (Builtin.Int64) -> () }
sil_scope 3 { loc "file.swift":10:6 parent @test_transform_multi : $@convention(thin) (Builtin.Int64) -> () }
sil_scope 4 { loc "file.swift":15:6 parent @test_transform_struct_extract : $@convention(thin) (Int64) -> () }
sil_scope 5 { loc "file.swift":20:6 parent @test_transform_tuple_extract : $@convention(thin) (Int64) -> () }
// CHECK-LABEL: define {{.*}} @test_transform_const
sil @test_transform_const : $@convention(thin) () -> () {
bb0:
// The transform block produces a constant i64 42 that is used in #dbg_value.
// CHECK: #dbg_value(i64 42, ![[VAR1:[0-9]+]]
debug_value undef : $Builtin.Int64, let, name "x", type $Int64, expr op_fragment:#Int64._value, transform {
bb0:
%0 = integer_literal $Builtin.Int64, 42
return %0 : $Builtin.Int64
}, loc "file.swift":2:3, scope 1
%r = tuple ()
return %r : $(), loc "file.swift":3:3, scope 1
}
// CHECK-LABEL: define {{.*}} @test_transform_add
sil @test_transform_add : $@convention(thin) (Builtin.Int64) -> () {
bb0(%arg : $Builtin.Int64):
// The transform block adds 10 to the argument. The add instruction should be
// salvaged into a DWARF expression and erased from the IR.
// CHECK-NOT: add {{.*}} 10
// CHECK: #dbg_value(i64 %0, ![[VAR2:[0-9]+]], !DIExpression(DW_OP_plus_uconst, 10, DW_OP_stack_value)
debug_value %arg : $Builtin.Int64, let, name "y", type $Int64, expr op_fragment:#Int64._value, transform {
bb0(%0 : $Builtin.Int64):
%1 = integer_literal $Builtin.Int64, 10
%2 = builtin "add_Int64"(%0 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int64
return %2 : $Builtin.Int64
}, loc "file.swift":6:3, scope 2
%r = tuple ()
return %r : $(), loc "file.swift":7:3, scope 2
}
// CHECK-LABEL: define {{.*}} @test_transform_multi
sil @test_transform_multi : $@convention(thin) (Builtin.Int64) -> () {
bb0(%arg : $Builtin.Int64):
// Multiple arithmetic instructions that all get salvaged and erased.
// `(x + 10) * 2 + 3`: three real LLVM instructions, all must be erased.
// CHECK-NOT: add
// CHECK-NOT: mul
// CHECK: #dbg_value(i64 %0, ![[VAR3:[0-9]+]], !DIExpression(DW_OP_plus_uconst, 10, DW_OP_constu, 2, DW_OP_mul, DW_OP_plus_uconst, 3, DW_OP_stack_value)
debug_value %arg : $Builtin.Int64, let, name "z", type $Int64, expr op_fragment:#Int64._value, transform {
bb0(%0 : $Builtin.Int64):
%1 = integer_literal $Builtin.Int64, 10
%2 = builtin "add_Int64"(%0 : $Builtin.Int64, %1 : $Builtin.Int64) : $Builtin.Int64
%3 = integer_literal $Builtin.Int64, 2
%4 = builtin "mul_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int64
%5 = integer_literal $Builtin.Int64, 3
%6 = builtin "add_Int64"(%4 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int64
return %6 : $Builtin.Int64
}, loc "file.swift":11:3, scope 3
%r = tuple ()
return %r : $(), loc "file.swift":12:3, scope 3
}
// CHECK-LABEL: define {{.*}} @test_transform_struct_extract
sil @test_transform_struct_extract : $@convention(thin) (Int64) -> () {
bb0(%arg : $Int64):
// struct + struct_extract of the same field should cancel out.
// CHECK: #dbg_value(i64 %0, ![[VAR4:[0-9]+]]
debug_value %arg : $Int64, let, name "x", transform {
bb0(%0 : $Int64):
%1 = struct $MyStruct (%0 : $Int64, undef : $Int64)
%2 = struct_extract %1 : $MyStruct, #MyStruct.x
return %2 : $Int64
}, loc "file.swift":16:3, scope 4
// struct + struct_extract of a different field should yield undef.
// CHECK: #dbg_value(i64 undef, ![[VAR5:[0-9]+]]
debug_value %arg : $Int64, let, name "y", transform {
bb0(%0 : $Int64):
%1 = struct $MyStruct (%0 : $Int64, undef : $Int64)
%2 = struct_extract %1 : $MyStruct, #MyStruct.y
return %2 : $Int64
}, loc "file.swift":18:3, scope 4
%r = tuple ()
return %r : $(), loc "file.swift":17:3, scope 4
}
// CHECK-LABEL: define {{.*}} @test_transform_tuple_extract
sil @test_transform_tuple_extract : $@convention(thin) (Int64) -> () {
bb0(%arg : $Int64):
// tuple + tuple_extract of the same element should cancel out.
// CHECK: #dbg_value(i64 %0, ![[VAR6:[0-9]+]]
debug_value %arg : $Int64, let, name "x", transform {
bb0(%0 : $Int64):
%1 = tuple (%0 : $Int64, undef : $Int64)
%2 = tuple_extract %1 : $(Int64, Int64), 0
return %2 : $Int64
}, loc "file.swift":21:3, scope 5
// tuple + tuple_extract of the undef element should yield undef.
// CHECK: #dbg_value(i64 undef, ![[VAR7:[0-9]+]]
debug_value %arg : $Int64, let, name "y", transform {
bb0(%0 : $Int64):
%1 = tuple (%0 : $Int64, undef : $Int64)
%2 = tuple_extract %1 : $(Int64, Int64), 1
return %2 : $Int64
}, loc "file.swift":23:3, scope 5
%r = tuple ()
return %r : $(), loc "file.swift":24:3, scope 5
}
// CHECK-DAG: ![[VAR1]] = !DILocalVariable(name: "x"
// CHECK-DAG: ![[VAR2]] = !DILocalVariable(name: "y"
// CHECK-DAG: ![[VAR3]] = !DILocalVariable(name: "z"
// CHECK-DAG: ![[VAR4]] = !DILocalVariable(name: "x"
// CHECK-DAG: ![[VAR5]] = !DILocalVariable(name: "y"
// CHECK-DAG: ![[VAR6]] = !DILocalVariable(name: "x"
// CHECK-DAG: ![[VAR7]] = !DILocalVariable(name: "y"