mirror of
https://github.com/apple/swift.git
synced 2026-06-20 15:42:51 +02:00
370d0dc771
This tuple salvage logic is the same as the struct salvage logic. Assisted-by: Claude
126 lines
5.4 KiB
Plaintext
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"
|