mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
introduce a common superclass, SILNode. This is in preparation for allowing instructions to have multiple results. It is also a somewhat more elegant representation for instructions that have zero results. Instructions that are known to have exactly one result inherit from a class, SingleValueInstruction, that subclasses both ValueBase and SILInstruction. Some care must be taken when working with SILNode pointers and testing for equality; please see the comment on SILNode for more information. A number of SIL passes needed to be updated in order to handle this new distinction between SIL values and SIL instructions. Note that the SIL parser is now stricter about not trying to assign a result value from an instruction (like 'return' or 'strong_retain') that does not produce any.
264 lines
8.9 KiB
Plaintext
264 lines
8.9 KiB
Plaintext
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-expand-all %s -lslocation-dump -ml=only-expansion | %FileCheck %s
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
|
|
///////////////////////
|
|
// Type Declarations //
|
|
///////////////////////
|
|
|
|
struct Int {
|
|
var value : Builtin.Int64
|
|
}
|
|
|
|
struct Int64 {
|
|
var value : Builtin.Int64
|
|
}
|
|
|
|
struct Bool {
|
|
var value : Builtin.Int1
|
|
}
|
|
|
|
class B {
|
|
var i : Builtin.Int32
|
|
init()
|
|
}
|
|
|
|
struct S1 {
|
|
var a: Int
|
|
init(a: Int, b: Int)
|
|
init()
|
|
}
|
|
|
|
struct S2 {
|
|
var a: Int
|
|
var b: Int
|
|
init(a: Int, b: Int)
|
|
init()
|
|
}
|
|
|
|
struct S3 {
|
|
var a: S2
|
|
var b: Int
|
|
var c: S2
|
|
init(a: S2, b: Int, c: S2)
|
|
init()
|
|
}
|
|
|
|
struct S4 {
|
|
var x: S3
|
|
var y: S3
|
|
init(x: S3, y: S3)
|
|
init()
|
|
}
|
|
|
|
class SelfLoop {
|
|
var a: Int
|
|
var b: Int
|
|
var c: SelfLoop
|
|
deinit
|
|
init()
|
|
}
|
|
|
|
struct S5 {
|
|
var a: SelfLoop
|
|
init(a: SelfLoop)
|
|
init()
|
|
}
|
|
|
|
sil @S1_init : $@convention(thin) (@thin S1.Type) -> S1
|
|
sil @S2_init : $@convention(thin) (@thin S2.Type) -> S2
|
|
sil @S3_init : $@convention(thin) (@thin S3.Type) -> S3
|
|
sil @S4_init : $@convention(thin) (@thin S4.Type) -> S4
|
|
sil @S5_init : $@convention(thin) (@thin S5.Type) -> S5
|
|
|
|
// CHECK-LABEL: @stack_store
|
|
// CHECK: #0 store
|
|
// CHECK-NEXT: alloc_stack
|
|
sil @stack_store : $@convention(thin) () -> () {
|
|
%1 = alloc_stack $Builtin.Int64
|
|
%9 = integer_literal $Builtin.Int64, 0
|
|
store %9 to %1 : $*Builtin.Int64
|
|
%4 = tuple()
|
|
dealloc_stack %1 : $*Builtin.Int64 // id: %13
|
|
return %4 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @store_after_store
|
|
// CHECK: #0 store
|
|
// CHECK-NEXT: [[RET0:%.+]] = alloc_box
|
|
// CHECK: #1 store
|
|
// CHECK-NEXT: [[RET0:%.+]] = alloc_box
|
|
sil @store_after_store : $@convention(thin) (@owned B) -> () {
|
|
bb0(%0 : $B):
|
|
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <B>
|
|
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <B>, 0
|
|
store %0 to %1a : $*B
|
|
store %0 to %1a : $*B
|
|
%4 = tuple()
|
|
return %4 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @store_after_store_struct
|
|
// CHECK: #0 store
|
|
// CHECK-NEXT: [[RET0:%.+]] = alloc_stack
|
|
// CHECK-NEXT: Projection Path [$*S1
|
|
// CHECK-NEXT: Field: var a: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK: #1 store
|
|
// CHECK-NEXT: [[RET0:%.+]] = alloc_stack
|
|
// CHECK-NEXT: Projection Path [$*S1
|
|
// CHECK-NEXT: Field: var a: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
sil @store_after_store_struct : $@convention(thin) () -> () {
|
|
%1 = alloc_stack $S1
|
|
%9 = integer_literal $Builtin.Int64, 0 // user: %10
|
|
%10 = struct $Int (%9 : $Builtin.Int64) // user: %12
|
|
%11 = struct_element_addr %1 : $*S1, #S1.a // user: %12
|
|
store %10 to %11 : $*Int // id: %12
|
|
store %10 to %11 : $*Int
|
|
%4 = tuple()
|
|
dealloc_stack %1 : $*S1 // id: %13
|
|
return %4 : $()
|
|
}
|
|
|
|
// Make sure all the structs get expanded correctly.
|
|
//
|
|
// CHECK-LABEL: @many_struct_allocs
|
|
// CHECK: #0 store
|
|
// CHECK-NEXT: alloc_stack $S2
|
|
// CHECK-NEXT: Projection Path [$*S2
|
|
// CHECK-NEXT: Field: var b: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK-NEXT: alloc_stack $S2
|
|
// CHECK-NEXT: Projection Path [$*S2
|
|
// CHECK-NEXT: Field: var a: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK: #1 store
|
|
// CHECK-NEXT: alloc_stack $S3
|
|
// CHECK-NEXT: Projection Path [$*S3
|
|
// CHECK-NEXT: Field: var c: S2 of: $*S2
|
|
// CHECK-NEXT: Field: var b: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK-NEXT: alloc_stack $S3
|
|
// CHECK-NEXT: Projection Path [$*S3
|
|
// CHECK-NEXT: Field: var c: S2 of: $*S2
|
|
// CHECK-NEXT: Field: var a: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK-NEXT: alloc_stack $S3
|
|
// CHECK-NEXT: Projection Path [$*S3
|
|
// CHECK-NEXT: Field: var b: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK-NEXT: alloc_stack $S3
|
|
// CHECK-NEXT: Projection Path [$*S3
|
|
// CHECK-NEXT: Field: var a: S2 of: $*S2
|
|
// CHECK-NEXT: Field: var b: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK-NEXT: alloc_stack $S3
|
|
// CHECK-NEXT: Projection Path [$*S3
|
|
// CHECK-NEXT: Field: var a: S2 of: $*S2
|
|
// CHECK-NEXT: Field: var a: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK: #2 store
|
|
// CHECK-NEXT: alloc_stack $S4
|
|
// CHECK-NEXT: Projection Path [$*S4
|
|
// CHECK-NEXT: Field: var y: S3 of: $*S3
|
|
// CHECK-NEXT: Field: var c: S2 of: $*S2
|
|
// CHECK-NEXT: Field: var b: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK-NEXT: alloc_stack $S4
|
|
// CHECK-NEXT: Projection Path [$*S4
|
|
// CHECK-NEXT: Field: var y: S3 of: $*S3
|
|
// CHECK-NEXT: Field: var c: S2 of: $*S2
|
|
// CHECK-NEXT: Field: var a: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK-NEXT: alloc_stack $S4
|
|
// CHECK-NEXT: Projection Path [$*S4
|
|
// CHECK-NEXT: Field: var y: S3 of: $*S3
|
|
// CHECK-NEXT: Field: var b: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK-NEXT: alloc_stack $S4
|
|
// CHECK-NEXT: Projection Path [$*S4
|
|
// CHECK-NEXT: Field: var y: S3 of: $*S3
|
|
// CHECK-NEXT: Field: var a: S2 of: $*S2
|
|
// CHECK-NEXT: Field: var b: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK-NEXT: alloc_stack $S4
|
|
// CHECK-NEXT: Projection Path [$*S4
|
|
// CHECK-NEXT: Field: var y: S3 of: $*S3
|
|
// CHECK-NEXT: Field: var a: S2 of: $*S2
|
|
// CHECK-NEXT: Field: var a: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK-NEXT: alloc_stack $S4
|
|
// CHECK-NEXT: Projection Path [$*S4
|
|
// CHECK-NEXT: Field: var x: S3 of: $*S3
|
|
// CHECK-NEXT: Field: var c: S2 of: $*S2
|
|
// CHECK-NEXT: Field: var b: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK-NEXT: alloc_stack $S4
|
|
// CHECK-NEXT: Projection Path [$*S4
|
|
// CHECK-NEXT: Field: var x: S3 of: $*S3
|
|
// CHECK-NEXT: Field: var c: S2 of: $*S2
|
|
// CHECK-NEXT: Field: var a: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK-NEXT: alloc_stack $S4
|
|
// CHECK-NEXT: Projection Path [$*S4
|
|
// CHECK-NEXT: Field: var x: S3 of: $*S3
|
|
// CHECK-NEXT: Field: var b: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK-NEXT: alloc_stack $S4
|
|
// CHECK-NEXT: Projection Path [$*S4
|
|
// CHECK-NEXT: Field: var x: S3 of: $*S3
|
|
// CHECK-NEXT: Field: var a: S2 of: $*S2
|
|
// CHECK-NEXT: Field: var b: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
// CHECK-NEXT: alloc_stack $S4
|
|
// CHECK-NEXT: Projection Path [$*S4
|
|
// CHECK-NEXT: Field: var x: S3 of: $*S3
|
|
// CHECK-NEXT: Field: var a: S2 of: $*S2
|
|
// CHECK-NEXT: Field: var a: Int of: $*Int
|
|
// CHECK-NEXT: Field: var value: Int64 of: $*Builtin.Int64]
|
|
sil hidden @many_struct_allocs : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = alloc_stack $S2, var, name "a" // users: %6, %18
|
|
%1 = alloc_stack $S3, var, name "b" // users: %10, %17
|
|
%2 = alloc_stack $S4, var, name "c" // users: %14, %16
|
|
%3 = function_ref @S2_init : $@convention(thin) (@thin S2.Type) -> S2 // user: %5
|
|
%4 = metatype $@thin S2.Type // user: %5
|
|
%5 = apply %3(%4) : $@convention(thin) (@thin S2.Type) -> S2 // user: %6
|
|
store %5 to %0 : $*S2 // id: %6
|
|
// function_ref struct.S3.init (struct.S3.Type)() -> struct.S3
|
|
%7 = function_ref @S3_init : $@convention(thin) (@thin S3.Type) -> S3 // user: %9
|
|
%8 = metatype $@thin S3.Type // user: %9
|
|
%9 = apply %7(%8) : $@convention(thin) (@thin S3.Type) -> S3 // user: %10
|
|
store %9 to %1 : $*S3 // id: %10
|
|
%11 = function_ref @S4_init : $@convention(thin) (@thin S4.Type) -> S4 // user: %13
|
|
%12 = metatype $@thin S4.Type // user: %13
|
|
%13 = apply %11(%12) : $@convention(thin) (@thin S4.Type) -> S4 // user: %14
|
|
store %13 to %2 : $*S4 // id: %14
|
|
%15 = tuple () // user: %19
|
|
dealloc_stack %2 : $*S4 // id: %16
|
|
dealloc_stack %1 : $*S3 // id: %17
|
|
dealloc_stack %0 : $*S2 // id: %18
|
|
return %15 : $() // id: %19
|
|
}
|
|
|
|
// CHECK-LABEL: self_loop
|
|
// CHECK: #0 store
|
|
// CHECK-NEXT: alloc_stack $S5, var, name "b"{{.*}} // users: %7, %4
|
|
// CHECK-NEXT: Projection Path [$*S5
|
|
// CHECK-NEXT: Field: var a: SelfLoop of: $*SelfLoop]
|
|
sil hidden @self_loop : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = alloc_stack $S5, var, name "b" // users: %4, %7
|
|
%1 = function_ref @S5_init : $@convention(thin) (@thin S5.Type) -> S5 // user: %3
|
|
%2 = metatype $@thin S5.Type // user: %3
|
|
%3 = apply %1(%2) : $@convention(thin) (@thin S5.Type) -> S5 // users: %4, %5
|
|
store %3 to %0 : $*S5 // id: %4
|
|
release_value %3 : $S5 // id: %5
|
|
%6 = tuple () // user: %8
|
|
dealloc_stack %0 : $*S5 // id: %7
|
|
return %6 : $() // id: %8
|
|
}
|