| // RUN: %target-sil-opt -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 in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK: #1 store |
| // CHECK-NEXT: [[RET0:%.+]] = alloc_stack |
| // CHECK-NEXT: Projection Path [$*S1 |
| // CHECK-NEXT: Field: var a: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*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 in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK-NEXT: alloc_stack $S2 |
| // CHECK-NEXT: Projection Path [$*S2 |
| // CHECK-NEXT: Field: var a: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK: #1 store |
| // CHECK-NEXT: alloc_stack $S3 |
| // CHECK-NEXT: Projection Path [$*S3 |
| // CHECK-NEXT: Field: var c: S2 in: $*S2 |
| // CHECK-NEXT: Field: var b: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK-NEXT: alloc_stack $S3 |
| // CHECK-NEXT: Projection Path [$*S3 |
| // CHECK-NEXT: Field: var c: S2 in: $*S2 |
| // CHECK-NEXT: Field: var a: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK-NEXT: alloc_stack $S3 |
| // CHECK-NEXT: Projection Path [$*S3 |
| // CHECK-NEXT: Field: var b: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK-NEXT: alloc_stack $S3 |
| // CHECK-NEXT: Projection Path [$*S3 |
| // CHECK-NEXT: Field: var a: S2 in: $*S2 |
| // CHECK-NEXT: Field: var b: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK-NEXT: alloc_stack $S3 |
| // CHECK-NEXT: Projection Path [$*S3 |
| // CHECK-NEXT: Field: var a: S2 in: $*S2 |
| // CHECK-NEXT: Field: var a: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK: #2 store |
| // CHECK-NEXT: alloc_stack $S4 |
| // CHECK-NEXT: Projection Path [$*S4 |
| // CHECK-NEXT: Field: var y: S3 in: $*S3 |
| // CHECK-NEXT: Field: var c: S2 in: $*S2 |
| // CHECK-NEXT: Field: var b: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK-NEXT: alloc_stack $S4 |
| // CHECK-NEXT: Projection Path [$*S4 |
| // CHECK-NEXT: Field: var y: S3 in: $*S3 |
| // CHECK-NEXT: Field: var c: S2 in: $*S2 |
| // CHECK-NEXT: Field: var a: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK-NEXT: alloc_stack $S4 |
| // CHECK-NEXT: Projection Path [$*S4 |
| // CHECK-NEXT: Field: var y: S3 in: $*S3 |
| // CHECK-NEXT: Field: var b: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK-NEXT: alloc_stack $S4 |
| // CHECK-NEXT: Projection Path [$*S4 |
| // CHECK-NEXT: Field: var y: S3 in: $*S3 |
| // CHECK-NEXT: Field: var a: S2 in: $*S2 |
| // CHECK-NEXT: Field: var b: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK-NEXT: alloc_stack $S4 |
| // CHECK-NEXT: Projection Path [$*S4 |
| // CHECK-NEXT: Field: var y: S3 in: $*S3 |
| // CHECK-NEXT: Field: var a: S2 in: $*S2 |
| // CHECK-NEXT: Field: var a: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK-NEXT: alloc_stack $S4 |
| // CHECK-NEXT: Projection Path [$*S4 |
| // CHECK-NEXT: Field: var x: S3 in: $*S3 |
| // CHECK-NEXT: Field: var c: S2 in: $*S2 |
| // CHECK-NEXT: Field: var b: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK-NEXT: alloc_stack $S4 |
| // CHECK-NEXT: Projection Path [$*S4 |
| // CHECK-NEXT: Field: var x: S3 in: $*S3 |
| // CHECK-NEXT: Field: var c: S2 in: $*S2 |
| // CHECK-NEXT: Field: var a: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK-NEXT: alloc_stack $S4 |
| // CHECK-NEXT: Projection Path [$*S4 |
| // CHECK-NEXT: Field: var x: S3 in: $*S3 |
| // CHECK-NEXT: Field: var b: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK-NEXT: alloc_stack $S4 |
| // CHECK-NEXT: Projection Path [$*S4 |
| // CHECK-NEXT: Field: var x: S3 in: $*S3 |
| // CHECK-NEXT: Field: var a: S2 in: $*S2 |
| // CHECK-NEXT: Field: var b: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64] |
| // CHECK-NEXT: alloc_stack $S4 |
| // CHECK-NEXT: Projection Path [$*S4 |
| // CHECK-NEXT: Field: var x: S3 in: $*S3 |
| // CHECK-NEXT: Field: var a: S2 in: $*S2 |
| // CHECK-NEXT: Field: var a: Int in: $*Int |
| // CHECK-NEXT: Field: var value: Int64 in: $*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 in: $*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 |
| } |