|
| 1 | +// RUN: %empty-directory(%t) |
| 2 | + |
| 3 | +// RUN: %target-swift-frontend -typecheck %S/stored-properties.swift -module-name StoredProperties -emit-parseable-module-interface-path %t/StoredProperties.swiftinterface |
| 4 | +// RUN: %target-swift-frontend -emit-ir %s -I %t -enable-parseable-module-interface | %FileCheck %s -check-prefix CHECK -check-prefix COMMON |
| 5 | + |
| 6 | +// RUN: %target-swift-frontend -typecheck %S/stored-properties.swift -enable-resilience -module-name StoredProperties -emit-parseable-module-interface-path %t/StoredProperties.swiftinterface |
| 7 | +// RUN: %target-swift-frontend -emit-ir %s -I %t -enable-parseable-module-interface | %FileCheck %s -check-prefix RESILIENT -check-prefix COMMON |
| 8 | + |
| 9 | +import StoredProperties |
| 10 | + |
| 11 | +/// This test makes sure clients of a parseable interface see correct type |
| 12 | +/// layout and use the right access patterns in the presence of a |
| 13 | +/// .swiftinterface file, in both resilient and non-resilient cases. |
| 14 | + |
| 15 | +// COMMON: %[[BAGOFVARIABLES:T16StoredProperties14BagOfVariablesV]] = type <{ %TSi, %TSb, [{{(3|7)}} x i8], %TSi }> |
| 16 | + |
| 17 | +// This type is non-@_fixed_layout, so it becomes opaque in a resilient module |
| 18 | +// CHECK: %[[HASSTOREDPROPERTIES:T16StoredProperties03HasaB0V]] = type <{ %TSi, %TSi, %TSb, [{{(3|7)}} x i8], %TSi, %TSb }> |
| 19 | +// RESILIENT: %[[HASSTOREDPROPERTIES:swift.opaque]] = type opaque |
| 20 | + |
| 21 | +// COMMON: %[[HASSTOREDPROPERTIESFIXEDLAYOUT:T16StoredProperties03HasaB11FixedLayoutV]] = type <{ %[[BAGOFVARIABLES]], %[[BAGOFVARIABLES]] }> |
| 22 | + |
| 23 | +// These are here just to make sure the compiler doesn't optimize away accesses. |
| 24 | +// They're overloaded instead of generic so we avoid generic dispatch. |
| 25 | + |
| 26 | +@inline(never) |
| 27 | +func _blackHole(_ value: Int) {} |
| 28 | + |
| 29 | +@inline(never) |
| 30 | +func _blackHole(_ value: Bool) {} |
| 31 | + |
| 32 | +@inline(never) |
| 33 | +func _blackHole(_ value: BagOfVariables) {} |
| 34 | + |
| 35 | +/// In the following code, getting and setting is split because otherwise |
| 36 | +/// the resulting IR is ordered differently. |
| 37 | + |
| 38 | +/// Test that we call the correct accessors in a resilient module, and that |
| 39 | +/// we use trivial storage accesses in a non-resilient module. |
| 40 | + |
| 41 | +func testGetting() { |
| 42 | + // CHECK: %[[VALUE:.*]] = alloca %[[HASSTOREDPROPERTIES]] |
| 43 | + // CHECK: call swiftcc void @"$s16StoredProperties03HasaB0VACycfC"(%[[HASSTOREDPROPERTIES]]* {{.*}} %[[VALUE]]) |
| 44 | + // RESILIENT: %[[VALUE:.*]] = alloca i8, [[WORD:i[0-9]+]] %size |
| 45 | + // RESILIENT: %[[VALUECAST:.*]] = bitcast i8* %value to %[[HASSTOREDPROPERTIES]]* |
| 46 | + // RESILIENT: call swiftcc void @"$s16StoredProperties03HasaB0VACycfC"(%[[HASSTOREDPROPERTIES]]* noalias nocapture sret %[[VALUECAST]]) |
| 47 | + var value = HasStoredProperties() |
| 48 | + |
| 49 | + // CHECK: getelementptr inbounds %[[HASSTOREDPROPERTIES]], %[[HASSTOREDPROPERTIES]]* %[[VALUE]], i32 0, i32 1 |
| 50 | + // CHECK: getelementptr inbounds %[[HASSTOREDPROPERTIES]], %[[HASSTOREDPROPERTIES]]* %[[VALUE]], i32 0, i32 2 |
| 51 | + |
| 52 | + // These are accessed in declaration order so the IR is emitted in the same |
| 53 | + // order. |
| 54 | + |
| 55 | + // COMMON: call swiftcc [[WORD:i[0-9]+]] @"$s16StoredProperties03HasaB0V14computedGetterSivg" |
| 56 | + _blackHole(value.computedGetter) |
| 57 | + |
| 58 | + // COMMON: call swiftcc [[WORD]] @"$s16StoredProperties03HasaB0V14computedGetSetSivg" |
| 59 | + _blackHole(value.computedGetSet) |
| 60 | + |
| 61 | + // CHECK: getelementptr inbounds %[[HASSTOREDPROPERTIES]], %[[HASSTOREDPROPERTIES]]* %[[VALUE]], i32 0, i32 0 |
| 62 | + // CHECK: getelementptr inbounds %[[HASSTOREDPROPERTIES]], %[[HASSTOREDPROPERTIES]]* %[[VALUE]], i32 0, i32 4 |
| 63 | + |
| 64 | + // RESILIENT: call swiftcc [[WORD]] @"$s16StoredProperties03HasaB0V06simpleA9ImmutableSivg" |
| 65 | + _blackHole(value.simpleStoredImmutable) |
| 66 | + |
| 67 | + // RESILIENT: call swiftcc [[WORD]] @"$s16StoredProperties03HasaB0V06simpleA7MutableSivg" |
| 68 | + _blackHole(value.simpleStoredMutable) |
| 69 | + |
| 70 | + // RESILIENT: call swiftcc i1 @"$s16StoredProperties03HasaB0V19storedWithObserversSbvg" |
| 71 | + _blackHole(value.storedWithObservers) |
| 72 | + |
| 73 | + // RESILIENT: call swiftcc [[WORD]] @"$s16StoredProperties03HasaB0V16storedPrivateSetSivg" |
| 74 | + _blackHole(value.storedPrivateSet) |
| 75 | +} |
| 76 | + |
| 77 | +func testSetting() { |
| 78 | + // CHECK: call swiftcc void @"$s16StoredProperties03HasaB0VACycfC"(%[[HASSTOREDPROPERTIES]]* {{.*}}) |
| 79 | + // RESILIENT: call swiftcc %swift.metadata_response @"$s16StoredProperties03HasaB0VMa"([[WORD]] 0) |
| 80 | + // RESILIENT: %[[VALUEALLOC:.*]] = alloca i8, [[WORD]] %size |
| 81 | + // RESILIENT: bitcast i8* %[[VALUEALLOC]] to %[[HASSTOREDPROPERTIES]]* |
| 82 | + var value = HasStoredProperties() |
| 83 | + |
| 84 | + // COMMON: call swiftcc void @"$s16StoredProperties03HasaB0V19storedWithObserversSbvs"(i1 false, %[[HASSTOREDPROPERTIES]]* {{.*}}) |
| 85 | + value.storedWithObservers = false |
| 86 | + |
| 87 | + // COMMON-NEXT: call swiftcc void @"$s16StoredProperties03HasaB0V14computedGetSetSivs"([[WORD]] 4, %[[HASSTOREDPROPERTIES]]* {{.*}}) |
| 88 | + value.computedGetSet = 4 |
| 89 | + |
| 90 | + // CHECK: %[[MUTABLE_PTR:.*]] = getelementptr inbounds %[[HASSTOREDPROPERTIES]], %[[HASSTOREDPROPERTIES]]* {{.*}}, i32 0, i32 1 |
| 91 | + // CHECK: %[[MUTABLE_INT_PTR:.*]] = getelementptr inbounds %TSi, %TSi* %[[MUTABLE_PTR]], i32 0, i32 0 |
| 92 | + // CHECK: store [[WORD]] 4, [[WORD]]* %[[MUTABLE_INT_PTR]] |
| 93 | + // RESILIENT: call swiftcc void @"$s16StoredProperties03HasaB0V06simpleA7MutableSivs"([[WORD]] 4, %[[HASSTOREDPROPERTIES]]* {{.*}}) |
| 94 | + value.simpleStoredMutable = 4 |
| 95 | +} |
| 96 | + |
| 97 | +testGetting() |
| 98 | +testSetting() |
| 99 | + |
| 100 | +/// Test that we always use trivial access patterns for @_fixed_layout types |
| 101 | +/// in resilient or non-resilient modules. |
| 102 | + |
| 103 | +func testFixedLayoutGetting() { |
| 104 | + // COMMON: %[[VALUEALLOCA:.*]] = alloca %[[HASSTOREDPROPERTIESFIXEDLAYOUT]] |
| 105 | + // COMMON: call swiftcc void @"$s16StoredProperties03HasaB11FixedLayoutVACycfC"(%[[HASSTOREDPROPERTIESFIXEDLAYOUT]]* {{.*}} %[[VALUEALLOCA]]) |
| 106 | + var value = HasStoredPropertiesFixedLayout() |
| 107 | + |
| 108 | + // These next two tests just make sure we don't use resilient access patterns |
| 109 | + // for these fixed_layout structs. |
| 110 | + |
| 111 | + // COMMON: getelementptr inbounds %[[HASSTOREDPROPERTIESFIXEDLAYOUT]], %[[HASSTOREDPROPERTIESFIXEDLAYOUT]]* %[[VALUEALLOCA]], i32 0, i32 0 |
| 112 | + // COMMON: getelementptr inbounds %[[HASSTOREDPROPERTIESFIXEDLAYOUT]], %[[HASSTOREDPROPERTIESFIXEDLAYOUT]]* %[[VALUEALLOCA]], i32 0, i32 1 |
| 113 | + |
| 114 | + // COMMON: call swiftcc void @"$s4main10_blackHoleyy16StoredProperties14BagOfVariablesVF"([[WORD]] %{{.*}}, i1 %{{.*}}, [[WORD]] %{{.*}}) |
| 115 | + _blackHole(value.simpleStoredMutable) |
| 116 | + |
| 117 | + // COMMON: call swiftcc void @"$s4main10_blackHoleyy16StoredProperties14BagOfVariablesVF"([[WORD]] %{{.*}}, i1 %{{.*}}, [[WORD]] %{{.*}}) |
| 118 | + _blackHole(value.storedWithObservers) |
| 119 | +} |
| 120 | + |
| 121 | +func testFixedLayoutSetting() { |
| 122 | + // COMMON: %[[VALUEALLOCA:.*]] = alloca %[[HASSTOREDPROPERTIESFIXEDLAYOUT]] |
| 123 | + // COMMON: call swiftcc void @"$s16StoredProperties03HasaB11FixedLayoutVACycfC"(%[[HASSTOREDPROPERTIESFIXEDLAYOUT]]* {{.*}} %[[VALUEALLOCA]]) |
| 124 | + var value = HasStoredPropertiesFixedLayout() |
| 125 | + |
| 126 | + // COMMON: call swiftcc void @"$s16StoredProperties03HasaB11FixedLayoutV19storedWithObserversAA14BagOfVariablesVvs" |
| 127 | + value.storedWithObservers = BagOfVariables() |
| 128 | + |
| 129 | + // COMMON: %[[PROP:.*]] = getelementptr inbounds %[[HASSTOREDPROPERTIESFIXEDLAYOUT]], %[[HASSTOREDPROPERTIESFIXEDLAYOUT]]* %value, i32 0, i32 0 |
| 130 | + // COMMON: %[[PROPA:.*]] = getelementptr inbounds %[[BAGOFVARIABLES]], %[[BAGOFVARIABLES]]* %[[PROP]], i32 0, i32 0 |
| 131 | + // COMMON: %[[PROPAVAL:.*]] = getelementptr inbounds %TSi, %TSi* %[[PROPA]], i32 0, i32 0 |
| 132 | + // COMMON: store [[WORD]] {{.*}} %[[PROPAVAL]] |
| 133 | + // COMMON: %[[PROPB:.*]] = getelementptr inbounds %[[BAGOFVARIABLES]], %[[BAGOFVARIABLES]]* %[[PROP]], i32 0, i32 1 |
| 134 | + // COMMON: %[[PROPBVAL:.*]] = getelementptr inbounds %TSb, %TSb* %[[PROPB]], i32 0, i32 0 |
| 135 | + // COMMON: store i1 {{.*}} %[[PROPBVAL]] |
| 136 | + // COMMON: %[[PROPC:.*]] = getelementptr inbounds %[[BAGOFVARIABLES]], %[[BAGOFVARIABLES]]* %[[PROP]], i32 0, i32 3 |
| 137 | + // COMMON: %[[PROPCVAL:.*]] = getelementptr inbounds %TSi, %TSi* %[[PROPC]], i32 0, i32 0 |
| 138 | + // COMMON: store [[WORD]] {{.*}} %[[PROPCVAL]] |
| 139 | + value.simpleStoredMutable = BagOfVariables() |
| 140 | +} |
| 141 | + |
| 142 | +testFixedLayoutGetting() |
| 143 | +testFixedLayoutSetting() |
0 commit comments