blob: 552c3cc9b33f72aff8572fd0ce13337ed59b7449 [file] [log] [blame]
// RUN: %target-sil-opt -let-properties-opt -enable-sil-verify-all %s | %FileCheck %s
sil_stage canonical
import Builtin
import Swift
// Test initialization of a constant aggregate "let".
// <rdar://problem/45691574> [SR-9146] IBAnimatable - SILCloner crash in LetPropertiesOpt.
struct Point {
var x: Int64
var y: Int64
}
class HasCenter {
let centerPoint: Point = Point(x: 0, y: 0)
public func getCenter() -> Int64
}
sil hidden [ossa] @$s19let_properties_opts5PointV1x1yACSi_SitcfC : $@convention(method) (Int64, Int64, @thin Point.Type) -> Point {
bb0(%0 : $Int64, %1 : $Int64, %2 : $@thin Point.Type):
%3 = struct $Point (%0 : $Int64, %1 : $Int64)
return %3 : $Point
}
// variable initialization expression of HasCenter.centerPoint
sil hidden [transparent] [ossa] @$s19let_properties_opts9HasCenterC11centerPointAA0E0Vvpfi : $@convention(thin) () -> Point {
bb0:
%0 = integer_literal $Builtin.Int64, 0
%1 = struct $Int64 (%0 : $Builtin.Int64)
%2 = struct $Point (%1 : $Int64, %1 : $Int64)
return %2 : $Point
}
// HasCenter.centerPoint.getter
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s19let_properties_opts9HasCenterC11centerPointAA0E0Vvg : $@convention(method) (@guaranteed HasCenter) -> Point {
// CHECK: bb0(%0 : @guaranteed $HasCenter):
// CHECK: [[LIT:%.*]] = integer_literal $Builtin.Int64, 0
// CHECK: [[INT:%.*]] = struct $Int64 ([[LIT]] : $Builtin.Int64)
// CHECK: [[PNT:%.*]] = struct $Point ([[INT]] : $Int64, [[INT]] : $Int64)
// CHECK: return [[PNT]] : $Point
// CHECK-LABEL: } // end sil function '$s19let_properties_opts9HasCenterC11centerPointAA0E0Vvg'
sil hidden [transparent] [ossa] @$s19let_properties_opts9HasCenterC11centerPointAA0E0Vvg : $@convention(method) (@guaranteed HasCenter) -> Point {
bb0(%0 : @guaranteed $HasCenter):
%1 = ref_element_addr %0 : $HasCenter, #HasCenter.centerPoint
%2 = load [trivial] %1 : $*Point
return %2 : $Point
}
// HasCenter.getCenter()
// CHECK-LABEL: sil hidden [ossa] @$s19let_properties_opts9HasCenterC9getCenterSiyF : $@convention(method) (@guaranteed HasCenter) -> Int64 {
// CHECK: [[LIT:%.*]] = integer_literal $Builtin.Int64, 0
// CHECK: [[INT:%.*]] = struct $Int64 ([[LIT]] : $Builtin.Int64)
// CHECK: [[PNT:%.*]] = struct $Point ([[INT]] : $Int64, [[INT]] : $Int64)
// CHECK: [[X:%.*]] = struct_extract [[PNT]] : $Point, #Point.x
// CHECK: return [[X]] : $Int64
// CHECK-LABEL: } // end sil function '$s19let_properties_opts9HasCenterC9getCenterSiyF'
sil hidden [ossa] @$s19let_properties_opts9HasCenterC9getCenterSiyF : $@convention(method) (@guaranteed HasCenter) -> Int64 {
bb0(%0 : @guaranteed $HasCenter):
%1 = ref_element_addr %0 : $HasCenter, #HasCenter.centerPoint
%2 = struct_element_addr %1 : $*Point, #Point.x
%3 = load [trivial] %2 : $*Int64
return %3 : $Int64
}
// HasCenter.init()
sil hidden [ossa] @$s19let_properties_opts9HasCenterCACycfc : $@convention(method) (@owned HasCenter) -> @owned HasCenter {
bb0(%0 : @owned $HasCenter):
%1 = integer_literal $Builtin.Int64, 0
%3 = struct $Int64 (%1 : $Builtin.Int64)
%4 = struct $Point (%3 : $Int64, %3 : $Int64)
%5 = begin_borrow %0 : $HasCenter
%6 = ref_element_addr %5 : $HasCenter, #HasCenter.centerPoint
store %4 to [trivial] %6 : $*Point
end_borrow %5 : $HasCenter
%9 = copy_value %0 : $HasCenter
destroy_value %0 : $HasCenter
return %9 : $HasCenter
}
// -----------------------------------------------------------------------------
// Test that struct 'let's are not replaced with constants. A struct
// 'let' is part of a larger mutable value.
private struct Inner {
@_hasStorage let val: Int32 { get }
init(val: Int32)
}
private struct Outer {
@_hasStorage @_hasInitialValue var inner: Inner { get set }
init(inner: Inner)
}
sil [transparent] @initInnerLet : $@convention(thin) () -> Inner {
bb0:
%0 = integer_literal $Builtin.Int32, 1
%1 = struct $Int32 (%0 : $Builtin.Int32)
%2 = struct $Inner (%1 : $Int32)
return %2 : $Inner
}
// Check that the returned value is reloaded from inner.val after the memcpy.
//
// CHECK-LABEL: sil hidden @testStructLet : $@convention(thin) (@inout Outer) -> Int32 {
// CHECK: bb0(%0 : $*Outer):
// CHECK: [[OUTADR:%.*]] = address_to_pointer %0 : $*Outer to $Builtin.RawPointer
// CHECK: builtin "int_memcpy_RawPointer_RawPointer_Int64"([[OUTADR]] : $Builtin.RawPointer, %{{.*}} : $Builtin.RawPointer, %{{.*}} : $Builtin.Int64, %{{.*}} : $Builtin.Int1) : $()
// CHECK: [[INADR:%.*]] = struct_element_addr %0 : $*Outer, #Outer.inner
// CHECK: [[VALADR:%.*]] = struct_element_addr [[INADR]] : $*Inner, #Inner.val
// CHECK: [[VAL:%.*]] = load %22 : $*Int32
// CHECK: return [[VAL]] : $Int32
// CHECK-LABEL: } // end sil function 'testStructLet'
sil hidden @testStructLet : $@convention(thin) (@inout Outer) -> Int32 {
bb0(%0 : $*Outer):
%1 = address_to_pointer %0 : $*Outer to $Builtin.RawPointer
%2 = metatype $@thick Outer.Type
%3 = builtin "sizeof"<Outer>(%2 : $@thick Outer.Type) : $Builtin.Word
%4 = builtin "sextOrBitCast_Word_Int64"(%3 : $Builtin.Word) : $Builtin.Int64
%5 = integer_literal $Builtin.Int64, 0
%6 = builtin "cmp_slt_Int64"(%4 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int1
cond_fail %6 : $Builtin.Int1, "UnsafeMutableRawBufferPointer with negative count"
%8 = integer_literal $Builtin.Int32, 0
%9 = struct $Int32 (%8 : $Builtin.Int32)
%10 = integer_literal $Builtin.Int1, 0
%11 = alloc_stack $Int32
store %9 to %11 : $*Int32
%13 = address_to_pointer %11 : $*Int32 to $Builtin.RawPointer
%14 = metatype $@thick Int32.Type
%15 = builtin "sizeof"<Int32>(%14 : $@thick Int32.Type) : $Builtin.Word
%16 = builtin "sextOrBitCast_Word_Int64"(%15 : $Builtin.Word) : $Builtin.Int64
%17 = builtin "cmp_slt_Int64"(%16 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int1
cond_fail %17 : $Builtin.Int1, "Negative value is not representable"
%19 = builtin "int_memcpy_RawPointer_RawPointer_Int64"(%1 : $Builtin.RawPointer, %13 : $Builtin.RawPointer, %16 : $Builtin.Int64, %10 : $Builtin.Int1) : $()
dealloc_stack %11 : $*Int32
%21 = struct_element_addr %0 : $*Outer, #Outer.inner
%22 = struct_element_addr %21 : $*Inner, #Inner.val
%23 = load %22 : $*Int32
return %23 : $Int32
}