|
| 1 | +// RUN: %target-sil-opt %s -accessed-storage-dump -enable-sil-verify-all -o /dev/null | %FileCheck %s |
| 2 | + |
| 3 | +sil_stage canonical |
| 4 | + |
| 5 | +import Builtin |
| 6 | +import Swift |
| 7 | +import SwiftShims |
| 8 | + |
| 9 | +struct MyStruct { |
| 10 | + @_hasStorage @_hasInitialValue var i: Int64 { get set } |
| 11 | + @_hasStorage @_hasInitialValue var j: Int64 { get set } |
| 12 | +} |
| 13 | + |
| 14 | +// CHECK-LABEL: @testStructPhiCommon |
| 15 | +// CHECK: store |
| 16 | +// CHECK: Argument %0 = argument of bb0 : $*MyStruct |
| 17 | +sil hidden @testStructPhiCommon : $@convention(thin) (@inout MyStruct) -> () { |
| 18 | +bb0(%0 : $*MyStruct): |
| 19 | + %2 = struct_element_addr %0 : $*MyStruct, #MyStruct.i |
| 20 | + cond_br undef, bb1, bb2 |
| 21 | + |
| 22 | +bb1: |
| 23 | + %3 = address_to_pointer %2 : $*Int64 to $Builtin.RawPointer |
| 24 | + br bb3(%3 : $Builtin.RawPointer) |
| 25 | + |
| 26 | +bb2: |
| 27 | + %5 = address_to_pointer %2 : $*Int64 to $Builtin.RawPointer |
| 28 | + br bb3(%5 : $Builtin.RawPointer) |
| 29 | + |
| 30 | +bb3(%6 : $Builtin.RawPointer) : |
| 31 | + %7 = pointer_to_address %6 : $Builtin.RawPointer to $*Int64 |
| 32 | + %8 = integer_literal $Builtin.Int64, 2 |
| 33 | + %9 = struct $Int64 (%8 : $Builtin.Int64) |
| 34 | + store %9 to %7 : $*Int64 |
| 35 | + %22 = tuple () |
| 36 | + return %22 : $() |
| 37 | +} |
| 38 | + |
| 39 | +// A pointer phi leading to different access paths should be |
| 40 | +// considered illegal, but we don't have a way to verify it yet. |
| 41 | +// |
| 42 | +// CHECK-LABEL: @testStructPhiDivergent |
| 43 | +// CHECK: store |
| 44 | +// CHECK: INVALID |
| 45 | +sil hidden @testStructPhiDivergent : $@convention(thin) (@inout MyStruct) -> () { |
| 46 | +bb0(%0 : $*MyStruct): |
| 47 | + cond_br undef, bb1, bb2 |
| 48 | + |
| 49 | +bb1: |
| 50 | + %2 = struct_element_addr %0 : $*MyStruct, #MyStruct.i |
| 51 | + %3 = address_to_pointer %2 : $*Int64 to $Builtin.RawPointer |
| 52 | + br bb3(%3 : $Builtin.RawPointer) |
| 53 | + |
| 54 | +bb2: |
| 55 | + %4 = struct_element_addr %0 : $*MyStruct, #MyStruct.j |
| 56 | + %5 = address_to_pointer %4 : $*Int64 to $Builtin.RawPointer |
| 57 | + br bb3(%5 : $Builtin.RawPointer) |
| 58 | + |
| 59 | +bb3(%6 : $Builtin.RawPointer) : |
| 60 | + %7 = pointer_to_address %6 : $Builtin.RawPointer to $*Int64 |
| 61 | + %8 = integer_literal $Builtin.Int64, 2 |
| 62 | + %9 = struct $Int64 (%8 : $Builtin.Int64) |
| 63 | + store %9 to %7 : $*Int64 |
| 64 | + %22 = tuple () |
| 65 | + return %22 : $() |
| 66 | +} |
| 67 | + |
| 68 | +// Test FindPhiStorageVisitor with a combination of |
| 69 | +// - valid storage for address_to_pointer %1 |
| 70 | +// - invalid common definition between #MyStruct.i and #MyStruct.j |
| 71 | +// |
| 72 | +// Make sure that visiting the invalid common definition also |
| 73 | +// invalidates storage. |
| 74 | +// |
| 75 | +// CHECK-LABEL: @testStructPhiChained |
| 76 | +// CHECK: store |
| 77 | +// CHECK: INVALID |
| 78 | +sil hidden @testStructPhiChained : $@convention(thin) (@inout MyStruct, @inout Int64) -> () { |
| 79 | +bb0(%0 : $*MyStruct, %1 : $*Int64): |
| 80 | + cond_br undef, bb1, bb5 |
| 81 | + |
| 82 | +bb1: |
| 83 | + cond_br undef, bb2, bb3 |
| 84 | + |
| 85 | +bb2: |
| 86 | + %2 = address_to_pointer %1 : $*Int64 to $Builtin.RawPointer |
| 87 | + br bb4(%2 : $Builtin.RawPointer) |
| 88 | + |
| 89 | +bb3: |
| 90 | + %3 = struct_element_addr %0 : $*MyStruct, #MyStruct.i |
| 91 | + %4 = address_to_pointer %3 : $*Int64 to $Builtin.RawPointer |
| 92 | + br bb4(%4 : $Builtin.RawPointer) |
| 93 | + |
| 94 | +bb4(%6 : $Builtin.RawPointer) : |
| 95 | + br bb6(%6 : $Builtin.RawPointer) |
| 96 | + |
| 97 | +bb5: |
| 98 | + %7 = struct_element_addr %0 : $*MyStruct, #MyStruct.j |
| 99 | + %8 = address_to_pointer %7 : $*Int64 to $Builtin.RawPointer |
| 100 | + br bb6(%8 : $Builtin.RawPointer) |
| 101 | + |
| 102 | +bb6(%9 : $Builtin.RawPointer) : |
| 103 | + %10 = pointer_to_address %9 : $Builtin.RawPointer to $*Int64 |
| 104 | + %11 = integer_literal $Builtin.Int64, 2 |
| 105 | + %12 = struct $Int64 (%11 : $Builtin.Int64) |
| 106 | + store %12 to %10 : $*Int64 |
| 107 | + %22 = tuple () |
| 108 | + return %22 : $() |
| 109 | +} |
| 110 | + |
| 111 | +struct _MyBridgeStorage { |
| 112 | + @_hasStorage var rawValue : Builtin.BridgeObject |
| 113 | +} |
| 114 | + |
| 115 | +struct _MyArrayBuffer<T> { |
| 116 | + @_hasStorage var _storage : _MyBridgeStorage |
| 117 | +} |
| 118 | + |
| 119 | + |
| 120 | +struct MyArray<T> { |
| 121 | + @_hasStorage var _buffer : _MyArrayBuffer<T> |
| 122 | +} |
| 123 | + |
| 124 | +// CHECK-LABEL: @arrayValue |
| 125 | +// CHECK: load [trivial] %{{.*}} : $*Builtin.Int64 |
| 126 | +// CHECK: Unidentified %{{.*}} = ref_tail_addr [immutable] [[REF:%[0-9]+]] : $__ContiguousArrayStorageBase, $Int64 |
| 127 | +// CHECK: load [trivial] %{{.*}} : $*Builtin.Int64 |
| 128 | +// CHECK: Unidentified %{{.*}} = ref_tail_addr [immutable] [[REF]] : $__ContiguousArrayStorageBase, $Int64 |
| 129 | +sil [ossa] @arrayValue : $@convention(thin) (@guaranteed MyArray<Int64>) -> Int64 { |
| 130 | +bb0(%0 : @guaranteed $MyArray<Int64>): |
| 131 | + %1 = integer_literal $Builtin.Word, 3 |
| 132 | + %2 = integer_literal $Builtin.Word, 4 |
| 133 | + %3 = integer_literal $Builtin.Int1, -1 |
| 134 | + %4 = struct_extract %0 : $MyArray<Int64>, #MyArray._buffer |
| 135 | + %5 = struct_extract %4 : $_MyArrayBuffer<Int64>, #_MyArrayBuffer._storage |
| 136 | + %6 = struct_extract %5 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue |
| 137 | + %7 = unchecked_ref_cast %6 : $Builtin.BridgeObject to $__ContiguousArrayStorageBase |
| 138 | + %8 = ref_tail_addr [immutable] %7 : $__ContiguousArrayStorageBase, $Int64 |
| 139 | + %9 = index_addr %8 : $*Int64, %1 : $Builtin.Word |
| 140 | + %10 = struct_element_addr %9 : $*Int64, #Int64._value |
| 141 | + %11 = load [trivial] %10 : $*Builtin.Int64 |
| 142 | + %12 = index_addr %8 : $*Int64, %2 : $Builtin.Word |
| 143 | + %13 = struct_element_addr %12 : $*Int64, #Int64._value |
| 144 | + %14 = load [trivial] %13 : $*Builtin.Int64 |
| 145 | + %15 = builtin "sadd_with_overflow_Int64"(%11 : $Builtin.Int64, %14 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) |
| 146 | + %16 = tuple_extract %15 : $(Builtin.Int64, Builtin.Int1), 0 |
| 147 | + %17 = tuple_extract %15 : $(Builtin.Int64, Builtin.Int1), 1 |
| 148 | + cond_fail %17 : $Builtin.Int1, "arithmetic overflow" |
| 149 | + %19 = struct $Int64 (%16 : $Builtin.Int64) |
| 150 | + return %19 : $Int64 |
| 151 | +} |
0 commit comments