blob: d739e886e226b8a976dfbad6513308835f9e7713 [file] [log] [blame]
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -typecheck %S/stored-properties.swift -module-name StoredProperties -emit-parseable-module-interface-path %t/StoredProperties.swiftinterface
// RUN: %target-swift-frontend -emit-ir %s -I %t | %FileCheck %s -check-prefix CHECK -check-prefix COMMON
// RUN: %target-swift-frontend -typecheck %S/stored-properties.swift -enable-library-evolution -module-name StoredProperties -emit-parseable-module-interface-path %t/StoredProperties.swiftinterface
// RUN: %target-swift-frontend -emit-ir %s -I %t | %FileCheck %s -check-prefix RESILIENT -check-prefix COMMON
// REQUIRES: rdar_46486517
import StoredProperties
/// This test makes sure clients of a parseable interface see correct type
/// layout and use the right access patterns in the presence of a
/// .swiftinterface file, in both resilient and non-resilient cases.
// COMMON: %[[BAGOFVARIABLES:T16StoredProperties14BagOfVariablesV]] = type <{ %TSi, %TSb, [{{(3|7)}} x i8], %TSi }>
// This type is non-@_fixed_layout, so it becomes opaque in a resilient module
// CHECK: %[[HASSTOREDPROPERTIES:T16StoredProperties03HasaB0V]] = type <{ %TSi, %TSi, %TSb, [{{(3|7)}} x i8], %TSi, %TSb, [{{3|7}} x i8], %TSi }>
// RESILIENT: %[[HASSTOREDPROPERTIES:swift.opaque]] = type opaque
// COMMON: %[[HASSTOREDPROPERTIESFIXEDLAYOUT:T16StoredProperties03HasaB11FixedLayoutV]] = type <{ %[[BAGOFVARIABLES]], %[[BAGOFVARIABLES]] }>
// These are here just to make sure the compiler doesn't optimize away accesses.
// They're overloaded instead of generic so we avoid generic dispatch.
@inline(never)
func _blackHole(_ value: Int) {}
@inline(never)
func _blackHole(_ value: Bool) {}
@inline(never)
func _blackHole(_ value: BagOfVariables) {}
/// In the following code, getting and setting is split because otherwise
/// the resulting IR is ordered differently.
/// Test that we call the correct accessors in a resilient module, and that
/// we use trivial storage accesses in a non-resilient module.
func testGetting() {
// CHECK: %[[VALUE:.*]] = alloca %[[HASSTOREDPROPERTIES]]
// CHECK: call swiftcc void @"$s16StoredProperties03HasaB0VACycfC"(%[[HASSTOREDPROPERTIES]]* {{.*}} %[[VALUE]])
// RESILIENT: %[[VALUE:.*]] = alloca i8, [[WORD:i[0-9]+]] %size
// RESILIENT: %[[VALUECAST:.*]] = bitcast i8* %value to %[[HASSTOREDPROPERTIES]]*
// RESILIENT: call swiftcc void @"$s16StoredProperties03HasaB0VACycfC"(%[[HASSTOREDPROPERTIES]]* noalias nocapture sret %[[VALUECAST]])
var value = HasStoredProperties()
// CHECK: getelementptr inbounds %[[HASSTOREDPROPERTIES]], %[[HASSTOREDPROPERTIES]]* %[[VALUE]], i32 0, i32 1
// CHECK: getelementptr inbounds %[[HASSTOREDPROPERTIES]], %[[HASSTOREDPROPERTIES]]* %[[VALUE]], i32 0, i32 2
// These are accessed in declaration order so the IR is emitted in the same
// order.
// COMMON: call swiftcc [[WORD:i[0-9]+]] @"$s16StoredProperties03HasaB0V14computedGetterSivg"
_blackHole(value.computedGetter)
// COMMON: call swiftcc [[WORD]] @"$s16StoredProperties03HasaB0V14computedGetSetSivg"
_blackHole(value.computedGetSet)
// CHECK: getelementptr inbounds %[[HASSTOREDPROPERTIES]], %[[HASSTOREDPROPERTIES]]* %[[VALUE]], i32 0, i32 0
// CHECK: getelementptr inbounds %[[HASSTOREDPROPERTIES]], %[[HASSTOREDPROPERTIES]]* %[[VALUE]], i32 0, i32 4
// RESILIENT: call swiftcc [[WORD]] @"$s16StoredProperties03HasaB0V06simpleA9ImmutableSivg"
_blackHole(value.simpleStoredImmutable)
// RESILIENT: call swiftcc [[WORD]] @"$s16StoredProperties03HasaB0V06simpleA7MutableSivg"
_blackHole(value.simpleStoredMutable)
// RESILIENT: call swiftcc i1 @"$s16StoredProperties03HasaB0V19storedWithObserversSbvg"
_blackHole(value.storedWithObservers)
// RESILIENT: call swiftcc [[WORD]] @"$s16StoredProperties03HasaB0V16storedPrivateSetSivg"
_blackHole(value.storedPrivateSet)
}
func testSetting() {
// CHECK: call swiftcc void @"$s16StoredProperties03HasaB0VACycfC"(%[[HASSTOREDPROPERTIES]]* {{.*}})
// RESILIENT: call swiftcc %swift.metadata_response @"$s16StoredProperties03HasaB0VMa"([[WORD]] 0)
// RESILIENT: %[[VALUEALLOC:.*]] = alloca i8, [[WORD]] %size
// RESILIENT: bitcast i8* %[[VALUEALLOC]] to %[[HASSTOREDPROPERTIES]]*
var value = HasStoredProperties()
// COMMON: call swiftcc void @"$s16StoredProperties03HasaB0V19storedWithObserversSbvs"(i1 false, %[[HASSTOREDPROPERTIES]]* {{.*}})
value.storedWithObservers = false
// COMMON-NEXT: call swiftcc void @"$s16StoredProperties03HasaB0V14computedGetSetSivs"([[WORD]] 4, %[[HASSTOREDPROPERTIES]]* {{.*}})
value.computedGetSet = 4
// CHECK: %[[MUTABLE_PTR:.*]] = getelementptr inbounds %[[HASSTOREDPROPERTIES]], %[[HASSTOREDPROPERTIES]]* {{.*}}, i32 0, i32 1
// CHECK: %[[MUTABLE_INT_PTR:.*]] = getelementptr inbounds %TSi, %TSi* %[[MUTABLE_PTR]], i32 0, i32 0
// CHECK: store [[WORD]] 4, [[WORD]]* %[[MUTABLE_INT_PTR]]
// RESILIENT: call swiftcc void @"$s16StoredProperties03HasaB0V06simpleA7MutableSivs"([[WORD]] 4, %[[HASSTOREDPROPERTIES]]* {{.*}})
value.simpleStoredMutable = 4
}
testGetting()
testSetting()
/// Test that we always use trivial access patterns for @_fixed_layout types
/// in resilient or non-resilient modules.
func testFixedLayoutGetting() {
// COMMON: %[[VALUEALLOCA:.*]] = alloca %[[HASSTOREDPROPERTIESFIXEDLAYOUT]]
// COMMON: call swiftcc void @"$s16StoredProperties03HasaB11FixedLayoutVACycfC"(%[[HASSTOREDPROPERTIESFIXEDLAYOUT]]* {{.*}} %[[VALUEALLOCA]])
var value = HasStoredPropertiesFixedLayout()
// These next two tests just make sure we don't use resilient access patterns
// for these fixed_layout structs.
// COMMON: getelementptr inbounds %[[HASSTOREDPROPERTIESFIXEDLAYOUT]], %[[HASSTOREDPROPERTIESFIXEDLAYOUT]]* %[[VALUEALLOCA]], i32 0, i32 0
// COMMON: getelementptr inbounds %[[HASSTOREDPROPERTIESFIXEDLAYOUT]], %[[HASSTOREDPROPERTIESFIXEDLAYOUT]]* %[[VALUEALLOCA]], i32 0, i32 1
// COMMON: call swiftcc void @"$s4main10_blackHoleyy16StoredProperties14BagOfVariablesVF"([[WORD]] %{{.*}}, i1 %{{.*}}, [[WORD]] %{{.*}})
_blackHole(value.simpleStoredMutable)
// COMMON: call swiftcc void @"$s4main10_blackHoleyy16StoredProperties14BagOfVariablesVF"([[WORD]] %{{.*}}, i1 %{{.*}}, [[WORD]] %{{.*}})
_blackHole(value.storedWithObservers)
}
func testFixedLayoutSetting() {
// COMMON: %[[VALUEALLOCA:.*]] = alloca %[[HASSTOREDPROPERTIESFIXEDLAYOUT]]
// COMMON: call swiftcc void @"$s16StoredProperties03HasaB11FixedLayoutVACycfC"(%[[HASSTOREDPROPERTIESFIXEDLAYOUT]]* {{.*}} %[[VALUEALLOCA]])
var value = HasStoredPropertiesFixedLayout()
// COMMON: call swiftcc void @"$s16StoredProperties03HasaB11FixedLayoutV19storedWithObserversAA14BagOfVariablesVvs"
value.storedWithObservers = BagOfVariables()
// COMMON: %[[PROP:.*]] = getelementptr inbounds %[[HASSTOREDPROPERTIESFIXEDLAYOUT]], %[[HASSTOREDPROPERTIESFIXEDLAYOUT]]* %value, i32 0, i32 0
// COMMON: %[[PROPA:.*]] = getelementptr inbounds %[[BAGOFVARIABLES]], %[[BAGOFVARIABLES]]* %[[PROP]], i32 0, i32 0
// COMMON: %[[PROPAVAL:.*]] = getelementptr inbounds %TSi, %TSi* %[[PROPA]], i32 0, i32 0
// COMMON: store [[WORD]] {{.*}} %[[PROPAVAL]]
// COMMON: %[[PROPB:.*]] = getelementptr inbounds %[[BAGOFVARIABLES]], %[[BAGOFVARIABLES]]* %[[PROP]], i32 0, i32 1
// COMMON: %[[PROPBVAL:.*]] = getelementptr inbounds %TSb, %TSb* %[[PROPB]], i32 0, i32 0
// COMMON: store i1 {{.*}} %[[PROPBVAL]]
// COMMON: %[[PROPC:.*]] = getelementptr inbounds %[[BAGOFVARIABLES]], %[[BAGOFVARIABLES]]* %[[PROP]], i32 0, i32 3
// COMMON: %[[PROPCVAL:.*]] = getelementptr inbounds %TSi, %TSi* %[[PROPC]], i32 0, i32 0
// COMMON: store [[WORD]] {{.*}} %[[PROPCVAL]]
value.simpleStoredMutable = BagOfVariables()
}
testFixedLayoutGetting()
testFixedLayoutSetting()