blob: cb8759034446673c5b4127e00143258226cd4874 [file] [log] [blame]
// RUN: %target-sil-opt %s -lslocation-dump -ml=only-type-expansion | %FileCheck %s
// RUN: %target-sil-opt %s -lslocation-dump-use-new-projection -lslocation-dump -ml=only-type-expansion | %FileCheck %s
sil_stage canonical
import Builtin
struct Int {
var value : Builtin.Int64
}
struct Int32{
var value : Builtin.Int32
}
struct Int64 {
var value : Builtin.Int64
}
struct Bool {
var value : Builtin.Int1
}
struct S1 {
var a: Int
var b: Int
init(a: Int, b: Int)
init()
}
struct S2 {
var a: Int
var b: S1
init(a: Int, b: S1)
init()
}
class C1 {
var a : Int
deinit
init(a: Int)
}
struct S3 {
var c: C1
var a: S2
var b: C1
init(c: C1, a: S2, b: C1)
init()
}
struct S4 {
var c: (Int, Int, S1)
init(c: (Int, Int, S1))
init()
}
struct S5 {
var c: (Int, Int, S3)
init(c: (Int, Int, S3))
init()
}
struct S6 {
var tuple: (Int, Int)
}
enum Example {
case A(Int64)
case B(Int32)
}
sil @S1_init : $@convention(thin) (@thin S1.Type) -> S1
sil @S2_init : $@convention(thin) (@thin S2.Type) -> S2
sil @C1_init : $@convention(thin) (@thick C1.Type) -> @owned C1
sil @S3_init : $@convention(thin) (@thin S3.Type) -> @owned S3
sil @S4_init : $@convention(thin) (@thin S4.Type) -> @owned S4
sil @S5_init : $@convention(thin) (@thin S5.Type) -> @owned S5
sil @S6_init : $@convention(thin) (@thin S6.Type) -> S6
// CHECK-LABEL: @test_struct_type_expansion
// CHECK: #0 store
// CHECK-NEXT: Projection Path [$*S1
// CHECK-NEXT: Field: var b: Int in: $*Int
// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
// 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: Projection Path [$*S2
// CHECK-NEXT: Field: var b: S1 in: $*S1
// CHECK-NEXT: Field: var b: Int in: $*Int
// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
// CHECK-NEXT: Projection Path [$*S2
// CHECK-NEXT: Field: var b: S1 in: $*S1
// CHECK-NEXT: Field: var a: Int in: $*Int
// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
// CHECK-NEXT: Projection Path [$*S2
// CHECK-NEXT: Field: var a: Int in: $*Int
// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
sil hidden @test_struct_type_expansion : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $S1, var, name "a" // users: %5, %12
%1 = alloc_stack $S2, var, name "b" // users: %9, %11
%2 = function_ref @S1_init : $@convention(thin) (@thin S1.Type) -> S1 // user: %4
%3 = metatype $@thin S1.Type // user: %4
%4 = apply %2(%3) : $@convention(thin) (@thin S1.Type) -> S1 // user: %5
store %4 to %0 : $*S1 // id: %5
%6 = function_ref @S2_init : $@convention(thin) (@thin S2.Type) -> S2 // user: %8
%7 = metatype $@thin S2.Type // user: %8
%8 = apply %6(%7) : $@convention(thin) (@thin S2.Type) -> S2 // user: %9
store %8 to %1 : $*S2 // id: %9
%10 = tuple () // user: %13
dealloc_stack %1 : $*S2 // id: %11
dealloc_stack %0 : $*S1 // id: %12
return %10 : $() // id: %13
}
// Make sure we do not expand the reference type.
//
// CHECK-LABEL: test_class_stack_slot
// CHECK: #0 store
// CHECK-NOT: var
// CHECK: #1 store
sil hidden @test_class_stack_slot : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $C1, var, name "a" // users: %4, %7
%1 = function_ref @C1_init : $@convention(thin) (@thick C1.Type) -> @owned C1 // user: %3
%2 = metatype $@thick C1.Type // user: %3
%3 = apply %1(%2) : $@convention(thin) (@thick C1.Type) -> @owned C1 // users: %4, %5
store %3 to %0 : $*C1 // id: %4
store %3 to %0 : $*C1 // id: %4
strong_release %3 : $C1 // id: %5
%6 = tuple () // user: %8
dealloc_stack %0 : $*C1 // id: %7
return %6 : $() // id: %8
}
// CHECK-LABEL: test_struct_and_class_slot
// CHECK: #0 store
// CHECK-NEXT: Projection Path [$*S3
// CHECK-NEXT: Field: var b: C1 in: $*C1]
// CHECK-NEXT: Projection Path [$*S3
// CHECK-NEXT: Field: var a: S2 in: $*S2
// CHECK-NEXT: Field: var b: S1 in: $*S1
// CHECK-NEXT: Field: var b: Int in: $*Int
// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
// CHECK-NEXT: Projection Path [$*S3
// CHECK-NEXT: Field: var a: S2 in: $*S2
// CHECK-NEXT: Field: var b: S1 in: $*S1
// CHECK-NEXT: Field: var a: Int in: $*Int
// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
// 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-NEXT: Projection Path [$*S3
// CHECK-NEXT: Field: var c: C1 in: $*C1]
sil hidden @test_struct_and_class_slot : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $S3, var, name "a" // users: %4, %7
// function_ref test.S3.init (test.S3.Type)() -> test.S3
%1 = function_ref @S3_init : $@convention(thin) (@thin S3.Type) -> @owned S3 // user: %3
%2 = metatype $@thin S3.Type // user: %3
%3 = apply %1(%2) : $@convention(thin) (@thin S3.Type) -> @owned S3 // users: %4, %5
store %3 to %0 : $*S3 // id: %4
release_value %3 : $S3 // id: %5
%6 = tuple () // user: %8
dealloc_stack %0 : $*S3 // id: %7
return %6 : $() // id: %8
}
// Test tuple expansion.
//
// CHECK-LABEL: test_tuple
// CHECK: #0 store
// CHECK-NEXT: Projection Path [$*S4
// CHECK-NEXT: Field: var c: (Int, Int, S1) in: $*(Int, Int, S1)
// CHECK-NEXT: Index: 2 in: $*S1
// CHECK-NEXT: Field: var b: Int in: $*Int
// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
// CHECK-NEXT: Projection Path [$*S4
// CHECK-NEXT: Field: var c: (Int, Int, S1) in: $*(Int, Int, S1)
// CHECK-NEXT: Index: 2 in: $*S1
// CHECK-NEXT: Field: var a: Int in: $*Int
// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
// CHECK-NEXT: Projection Path [$*S4
// CHECK-NEXT: Field: var c: (Int, Int, S1) in: $*(Int, Int, S1)
// CHECK-NEXT: Index: 1 in: $*Int
// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
// CHECK-NEXT: Projection Path [$*S4
// CHECK-NEXT: Field: var c: (Int, Int, S1) in: $*(Int, Int, S1)
// CHECK-NEXT: Index: 0 in: $*Int
// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
sil hidden @test_tuple : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $S4, var, name "x" // users: %4, %7
// function_ref test.S4.init (test.S4.Type)() -> test.S4
%1 = function_ref @S4_init : $@convention(thin) (@thin S4.Type) -> @owned S4 // user: %3
%2 = metatype $@thin S4.Type // user: %3
%3 = apply %1(%2) : $@convention(thin) (@thin S4.Type) -> @owned S4 // users: %4, %5
store %3 to %0 : $*S4 // id: %4
release_value %3 : $S4 // id: %5
%6 = tuple () // user: %8
dealloc_stack %0 : $*S4 // id: %7
return %6 : $() // id: %8
}
// CHECK-LABEL: tuple_test_with_reference
// CHECK: #0 store
// CHECK-NEXT: Projection Path [$*S5
// CHECK-NEXT: Field: var c: (Int, Int, S3) in: $*(Int, Int, S3)
// CHECK-NEXT: Index: 2 in: $*S3
// CHECK-NEXT: Field: var b: C1 in: $*C1]
// CHECK-NEXT: Projection Path [$*S5
// CHECK-NEXT: Field: var c: (Int, Int, S3) in: $*(Int, Int, S3)
// CHECK-NEXT: Index: 2 in: $*S3
// CHECK-NEXT: Field: var a: S2 in: $*S2
// CHECK-NEXT: Field: var b: S1 in: $*S1
// CHECK-NEXT: Field: var b: Int in: $*Int
// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
// CHECK-NEXT: Projection Path [$*S5
// CHECK-NEXT: Field: var c: (Int, Int, S3) in: $*(Int, Int, S3)
// CHECK-NEXT: Index: 2 in: $*S3
// CHECK-NEXT: Field: var a: S2 in: $*S2
// CHECK-NEXT: Field: var b: S1 in: $*S1
// CHECK-NEXT: Field: var a: Int in: $*Int
// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
// CHECK-NEXT: Projection Path [$*S5
// CHECK-NEXT: Field: var c: (Int, Int, S3) in: $*(Int, Int, S3)
// CHECK-NEXT: Index: 2 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: Projection Path [$*S5
// CHECK-NEXT: Field: var c: (Int, Int, S3) in: $*(Int, Int, S3)
// CHECK-NEXT: Index: 2 in: $*S3
// CHECK-NEXT: Field: var c: C1 in: $*C1]
// CHECK-NEXT: Projection Path [$*S5
// CHECK-NEXT: Field: var c: (Int, Int, S3) in: $*(Int, Int, S3)
// CHECK-NEXT: Index: 1 in: $*Int
// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
// CHECK-NEXT: Projection Path [$*S5
// CHECK-NEXT: Field: var c: (Int, Int, S3) in: $*(Int, Int, S3)
// CHECK-NEXT: Index: 0 in: $*Int
// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
sil hidden @tuple_test_with_reference : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $S5, var, name "x" // users: %4, %7
// function_ref test.S5.init (test.S5.Type)() -> test.S5
%1 = function_ref @S5_init : $@convention(thin) (@thin S5.Type) -> @owned S5 // user: %3
%2 = metatype $@thin S5.Type // user: %3
%3 = apply %1(%2) : $@convention(thin) (@thin S5.Type) -> @owned 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
}
/// CHECK-LABEL: tuple_inside_struct
/// CHECK: #0 store
/// CHECK-NEXT: Projection Path [$*S6
/// CHECK-NEXT: Field: var tuple: (Int, Int) in: $*(Int, Int)
/// CHECK-NEXT: Index: 1 in: $*Int
/// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
/// CHECK-NEXT: Projection Path [$*S6
/// CHECK-NEXT: Field: var tuple: (Int, Int) in: $*(Int, Int)
/// CHECK-NEXT: Index: 0 in: $*Int
/// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
sil hidden @tuple_inside_struct : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $S6, var, name "x" // users: %4, %7
%1 = function_ref @S6_init : $@convention(thin) (@thin S6.Type) -> S6 // user: %3
%2 = metatype $@thin S6.Type // user: %3
%3 = apply %1(%2) : $@convention(thin) (@thin S6.Type) -> S6 // users: %4, %5
store %3 to %0 : $*S6 // id: %4
%6 = tuple () // user: %8
dealloc_stack %0 : $*S6 // id: %7
return %6 : $() // id: %8
}
/// Given an enum type, we expands it into nothing as its meaningless to call
/// getStoredProperties on enum without specifying the tag. Enum is sort of
/// like union in C, i.e. its memory can be interpreted differently depending
/// on the chosen tag.
///
/// CHECK-LABEL: enum_test
/// CHECK: #0 store
/// CHECK-NOT: Int64
/// CHECK-NOT: Int32
/// CHECK: #1 store
/// CHECK-NEXT: Projection Path [$*Int
/// CHECK-NEXT: Field: var value: Int64 in: $*Builtin.Int64]
sil hidden @enum_test : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $Example, var, name "ee" // users: %5, %11
%1 = alloc_stack $Int, var, name "a" // users: %8, %10
%2 = integer_literal $Builtin.Int64, 10 // user: %3
%3 = struct $Int64 (%2 : $Builtin.Int64) // user: %4
%4 = enum $Example, #Example.A!enumelt.1, %3 : $Int64 // user: %5
store %4 to %0 : $*Example // id: %5
%6 = integer_literal $Builtin.Int64, 10 // user: %7
%7 = struct $Int (%6 : $Builtin.Int64) // user: %8
store %7 to %1 : $*Int // id: %8
%9 = tuple () // user: %12
dealloc_stack %1 : $*Int // id: %10
dealloc_stack %0 : $*Example // id: %11
return %9 : $() // id: %12
}