mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
to be consistent with AccessPath and AccessBase. Otherwise, the arbitrary name difference adds constant friction.
479 lines
20 KiB
Plaintext
479 lines
20 KiB
Plaintext
// RUN: %target-sil-opt %s -access-storage-dump -enable-sil-verify-all -o /dev/null | %FileCheck %s
|
|
// RUN: %target-sil-opt %s -access-path-verification -o /dev/null
|
|
|
|
// REQUIRES: PTRSIZE=64
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
import SwiftShims
|
|
|
|
struct MyStruct {
|
|
@_hasStorage @_hasInitialValue var i: Int64 { get set }
|
|
@_hasStorage @_hasInitialValue var j: Int64 { get set }
|
|
}
|
|
|
|
// CHECK-LABEL: @testStructPhiCommon
|
|
// CHECK: store
|
|
// CHECK: Argument %0 = argument of bb0 : $*MyStruct
|
|
// CHECK: Base: %0 = argument of bb0 : $*MyStruct
|
|
// CHECK: Storage: Argument %0 = argument of bb0 : $*MyStruct
|
|
// CHECK: Path: (#0)
|
|
sil hidden [ossa] @testStructPhiCommon : $@convention(thin) (@inout MyStruct) -> () {
|
|
bb0(%0 : $*MyStruct):
|
|
%2 = struct_element_addr %0 : $*MyStruct, #MyStruct.i
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%3 = address_to_pointer %2 : $*Int64 to $Builtin.RawPointer
|
|
br bb3(%3 : $Builtin.RawPointer)
|
|
|
|
bb2:
|
|
%5 = address_to_pointer %2 : $*Int64 to $Builtin.RawPointer
|
|
br bb3(%5 : $Builtin.RawPointer)
|
|
|
|
bb3(%6 : $Builtin.RawPointer) :
|
|
%7 = pointer_to_address %6 : $Builtin.RawPointer to $*Int64
|
|
%8 = integer_literal $Builtin.Int64, 2
|
|
%9 = struct $Int64 (%8 : $Builtin.Int64)
|
|
store %9 to [trivial] %7 : $*Int64
|
|
%22 = tuple ()
|
|
return %22 : $()
|
|
}
|
|
|
|
// A pointer phi leading to different access paths should be
|
|
// considered illegal, but we don't have a way to verify it yet.
|
|
//
|
|
// CHECK-LABEL: @testStructPhiDivergent
|
|
// CHECK: store
|
|
// CHECK: INVALID
|
|
// CHECK: INVALID
|
|
sil hidden [ossa] @testStructPhiDivergent : $@convention(thin) (@inout MyStruct) -> () {
|
|
bb0(%0 : $*MyStruct):
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%2 = struct_element_addr %0 : $*MyStruct, #MyStruct.i
|
|
%3 = address_to_pointer %2 : $*Int64 to $Builtin.RawPointer
|
|
br bb3(%3 : $Builtin.RawPointer)
|
|
|
|
bb2:
|
|
%4 = struct_element_addr %0 : $*MyStruct, #MyStruct.j
|
|
%5 = address_to_pointer %4 : $*Int64 to $Builtin.RawPointer
|
|
br bb3(%5 : $Builtin.RawPointer)
|
|
|
|
bb3(%6 : $Builtin.RawPointer) :
|
|
%7 = pointer_to_address %6 : $Builtin.RawPointer to $*Int64
|
|
%8 = integer_literal $Builtin.Int64, 2
|
|
%9 = struct $Int64 (%8 : $Builtin.Int64)
|
|
store %9 to [trivial] %7 : $*Int64
|
|
%22 = tuple ()
|
|
return %22 : $()
|
|
}
|
|
|
|
// Test FindPhiStorageVisitor with a combination of
|
|
// - valid storage for address_to_pointer %1
|
|
// - invalid common definition between #MyStruct.i and #MyStruct.j
|
|
//
|
|
// Make sure that visiting the invalid common definition also
|
|
// invalidates storage.
|
|
//
|
|
// CHECK-LABEL: @testStructPhiChained
|
|
// CHECK: store
|
|
// CHECK: INVALID
|
|
// CHECK: INVALID
|
|
sil hidden [ossa] @testStructPhiChained : $@convention(thin) (@inout MyStruct, @inout Int64) -> () {
|
|
bb0(%0 : $*MyStruct, %1 : $*Int64):
|
|
cond_br undef, bb1, bb5
|
|
|
|
bb1:
|
|
cond_br undef, bb2, bb3
|
|
|
|
bb2:
|
|
%2 = address_to_pointer %1 : $*Int64 to $Builtin.RawPointer
|
|
br bb4(%2 : $Builtin.RawPointer)
|
|
|
|
bb3:
|
|
%3 = struct_element_addr %0 : $*MyStruct, #MyStruct.i
|
|
%4 = address_to_pointer %3 : $*Int64 to $Builtin.RawPointer
|
|
br bb4(%4 : $Builtin.RawPointer)
|
|
|
|
bb4(%6 : $Builtin.RawPointer) :
|
|
br bb6(%6 : $Builtin.RawPointer)
|
|
|
|
bb5:
|
|
%7 = struct_element_addr %0 : $*MyStruct, #MyStruct.j
|
|
%8 = address_to_pointer %7 : $*Int64 to $Builtin.RawPointer
|
|
br bb6(%8 : $Builtin.RawPointer)
|
|
|
|
bb6(%9 : $Builtin.RawPointer) :
|
|
%10 = pointer_to_address %9 : $Builtin.RawPointer to $*Int64
|
|
%11 = integer_literal $Builtin.Int64, 2
|
|
%12 = struct $Int64 (%11 : $Builtin.Int64)
|
|
store %12 to [trivial] %10 : $*Int64
|
|
%22 = tuple ()
|
|
return %22 : $()
|
|
}
|
|
|
|
struct _MyBridgeStorage {
|
|
@_hasStorage var rawValue : Builtin.BridgeObject
|
|
}
|
|
|
|
struct _MyArrayBuffer<T> {
|
|
@_hasStorage var _storage : _MyBridgeStorage
|
|
}
|
|
|
|
|
|
struct MyArray<T> {
|
|
@_hasStorage var _buffer : _MyArrayBuffer<T>
|
|
}
|
|
|
|
// CHECK-LABEL: @arrayValue
|
|
// CHECK: load [trivial] %{{.*}} : $*Builtin.Int64
|
|
// CHECK: Tail %{{.*}} = struct_extract %{{.*}} : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
|
|
// CHECK: Base: %{{.*}} = ref_tail_addr [immutable] %{{.*}} : $__ContiguousArrayStorageBase, $Int64
|
|
// CHECK: Storage: Tail %{{.*}} = struct_extract %{{.*}} : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
|
|
// CHECK: Path: (@3,#0)
|
|
// CHECK: load [trivial] %{{.*}} : $*Builtin.Int64
|
|
// CHECK: Tail %{{.*}} = struct_extract %5 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
|
|
// CHECK: Base: %{{.*}} = ref_tail_addr [immutable] %{{.*}} : $__ContiguousArrayStorageBase, $Int64
|
|
// CHECK: Storage: Tail %{{.*}} = struct_extract %5 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
|
|
// CHECK: Path: (@4,#0)
|
|
sil [ossa] @arrayValue : $@convention(thin) (@guaranteed MyArray<Int64>) -> Int64 {
|
|
bb0(%0 : @guaranteed $MyArray<Int64>):
|
|
%1 = integer_literal $Builtin.Word, 3
|
|
%2 = integer_literal $Builtin.Word, 4
|
|
%3 = integer_literal $Builtin.Int1, -1
|
|
%4 = struct_extract %0 : $MyArray<Int64>, #MyArray._buffer
|
|
%5 = struct_extract %4 : $_MyArrayBuffer<Int64>, #_MyArrayBuffer._storage
|
|
%6 = struct_extract %5 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
|
|
%7 = unchecked_ref_cast %6 : $Builtin.BridgeObject to $__ContiguousArrayStorageBase
|
|
%8 = ref_tail_addr [immutable] %7 : $__ContiguousArrayStorageBase, $Int64
|
|
%9 = index_addr %8 : $*Int64, %1 : $Builtin.Word
|
|
%10 = struct_element_addr %9 : $*Int64, #Int64._value
|
|
%11 = load [trivial] %10 : $*Builtin.Int64
|
|
%12 = index_addr %8 : $*Int64, %2 : $Builtin.Word
|
|
%13 = struct_element_addr %12 : $*Int64, #Int64._value
|
|
%14 = load [trivial] %13 : $*Builtin.Int64
|
|
%15 = builtin "sadd_with_overflow_Int64"(%11 : $Builtin.Int64, %14 : $Builtin.Int64, %3 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
|
|
%16 = tuple_extract %15 : $(Builtin.Int64, Builtin.Int1), 0
|
|
%17 = tuple_extract %15 : $(Builtin.Int64, Builtin.Int1), 1
|
|
cond_fail %17 : $Builtin.Int1, "arithmetic overflow"
|
|
%19 = struct $Int64 (%16 : $Builtin.Int64)
|
|
return %19 : $Int64
|
|
}
|
|
|
|
// CHECK-LABEL: @staticIndexAddrChain
|
|
// CHECK: %{{.*}} = load [trivial] %{{.*}} : $*Int64
|
|
// CHECK: Argument %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Base: %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Storage: Argument %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Path: (@1,#0)
|
|
// CHECK: %{{.*}} = load [trivial] %{{.*}} : $*Int64
|
|
// CHECK: Argument %{{.*}} = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Base: %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Storage: Argument %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Path: (@2,#0)
|
|
sil [ossa] @staticIndexAddrChain : $@convention(thin) (Builtin.RawPointer) -> () {
|
|
bb0(%0 : $Builtin.RawPointer):
|
|
%1 = pointer_to_address %0 : $Builtin.RawPointer to $*MyStruct
|
|
%2 = integer_literal $Builtin.Word, 1
|
|
%3 = index_addr %1 : $*MyStruct, %2 : $Builtin.Word
|
|
%4 = struct_element_addr %3 : $*MyStruct, #MyStruct.i
|
|
%5 = load [trivial] %4 : $*Int64
|
|
%6 = index_addr %3 : $*MyStruct, %2 : $Builtin.Word
|
|
%7 = struct_element_addr %6 : $*MyStruct, #MyStruct.i
|
|
%8 = load [trivial] %7 : $*Int64
|
|
%99 = tuple ()
|
|
return %99 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @staticIndexAddrSubobject
|
|
// CHECK: ###For MemOp: %5 = load [trivial] %4 : $*Int64
|
|
// CHECK: Argument %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: INVALID
|
|
sil [ossa] @staticIndexAddrSubobject : $@convention(thin) (Builtin.RawPointer) -> () {
|
|
bb0(%0 : $Builtin.RawPointer):
|
|
%1 = pointer_to_address %0 : $Builtin.RawPointer to $*MyStruct
|
|
%2 = struct_element_addr %1 : $*MyStruct, #MyStruct.i
|
|
%3 = integer_literal $Builtin.Word, 1
|
|
%4 = index_addr %2 : $*Int64, %3 : $Builtin.Word
|
|
%5 = load [trivial] %4 : $*Int64
|
|
%99 = tuple ()
|
|
return %99 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @dynamicIndexAddrChain
|
|
// CHECK: %{{.*}} = load [trivial] %{{.*}} : $*Int64
|
|
// CHECK: Argument %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Base: %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Storage: Argument %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Path: (@Unknown,#0)
|
|
// CHECK: %{{.*}} = load [trivial] %{{.*}} : $*Int64
|
|
// CHECK: Argument %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Base: %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Storage: Argument %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Path: (@Unknown,#0)
|
|
sil [ossa] @dynamicIndexAddrChain : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> () {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
|
|
%2 = pointer_to_address %0 : $Builtin.RawPointer to $*MyStruct
|
|
%3 = index_addr %2 : $*MyStruct, %1 : $Builtin.Word
|
|
%4 = struct_element_addr %3 : $*MyStruct, #MyStruct.i
|
|
%5 = load [trivial] %4 : $*Int64
|
|
%6 = integer_literal $Builtin.Word, 1
|
|
%7 = index_addr %3 : $*MyStruct, %6 : $Builtin.Word
|
|
%8 = struct_element_addr %7 : $*MyStruct, #MyStruct.i
|
|
%9 = load [trivial] %8 : $*Int64
|
|
%99 = tuple ()
|
|
return %99 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @staticIndexAddrCancel
|
|
// CHECK: %{{.*}} = load [trivial] %{{.*}} : $*Int64
|
|
// CHECK: Argument %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Base: %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Storage: Argument %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Path: (@1,#0)
|
|
// CHECK: %{{.*}} = load [trivial] %{{.*}} : $*Int64
|
|
// CHECK: Argument %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Base: %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Storage: Argument %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Path: (@2,#0)
|
|
sil [ossa] @staticIndexAddrCancel : $@convention(thin) (Builtin.RawPointer) -> () {
|
|
bb0(%0 : $Builtin.RawPointer):
|
|
%1 = pointer_to_address %0 : $Builtin.RawPointer to $*MyStruct
|
|
%2 = integer_literal $Builtin.Word, 1
|
|
%3 = index_addr %1 : $*MyStruct, %2 : $Builtin.Word
|
|
%4 = struct_element_addr %3 : $*MyStruct, #MyStruct.i
|
|
%5 = load [trivial] %4 : $*Int64
|
|
%6 = integer_literal $Builtin.Word, -1
|
|
%7 = index_addr %3 : $*MyStruct, %2 : $Builtin.Word
|
|
%8 = struct_element_addr %7 : $*MyStruct, #MyStruct.i
|
|
%9 = load [trivial] %8 : $*Int64
|
|
%99 = tuple ()
|
|
return %99 : $()
|
|
}
|
|
|
|
class A {
|
|
var prop0: Int64
|
|
}
|
|
class B : A {
|
|
var prop1: Int64
|
|
}
|
|
|
|
// CHECK-LABEL: @testNonUniquePropertyIndex
|
|
// CHECK: store %0 to [trivial] %{{.*}} : $*Int64
|
|
// CHECK: Class %{{.*}} = alloc_ref $B
|
|
// CHECK: Field: var prop1: Int64 Index: 1
|
|
// CHECK: Base: %{{.*}} = ref_element_addr %{{.*}} : $B, #B.prop1
|
|
// CHECK: Storage: Class %{{.*}} = alloc_ref $B
|
|
// CHECK: Field: var prop1: Int64 Index: 1
|
|
// CHECK: Path: ()
|
|
// CHECK: store %0 to [trivial] %{{.*}} : $*Int64
|
|
// CHECK: Class %{{.*}} = alloc_ref $B
|
|
// CHECK: Field: var prop0: Int64 Index: 0
|
|
// CHECK: Base: %{{.*}} = ref_element_addr %{{.*}} : $A, #A.prop0
|
|
// CHECK: Storage: Class %{{.*}} = alloc_ref $B
|
|
// CHECK: Field: var prop0: Int64 Index: 0
|
|
// CHECK: Path: ()
|
|
sil [ossa] @testNonUniquePropertyIndex : $@convention(thin) (Int64) -> () {
|
|
bb0(%0 : $Int64):
|
|
%1 = alloc_ref $B
|
|
%borrow = begin_borrow %1 : $B
|
|
%3 = ref_element_addr %borrow : $B, #B.prop1
|
|
store %0 to [trivial] %3 : $*Int64
|
|
end_borrow %borrow : $B
|
|
%6 = upcast %1 : $B to $A
|
|
%borrow2 = begin_borrow %6 : $A
|
|
%8 = ref_element_addr %borrow2 : $A, #A.prop0
|
|
store %0 to [trivial] %8 : $*Int64
|
|
end_borrow %borrow2 : $A
|
|
destroy_value %6 : $A
|
|
%99 = tuple ()
|
|
return %99 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @testRefTailAndStruct0
|
|
// CHECK: %{{.*}} = load [trivial] %{{.*}} : $*Builtin.Int64
|
|
// CHECK: Class **%{{.*}}** = destructure_struct %{{.*}} : $_MyBridgeStorage
|
|
// CHECK: Index: 0
|
|
// CHECK: Base: %{{.*}} = ref_element_addr [immutable] %{{.*}} : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity
|
|
// CHECK: Storage: Class **%{{.*}}** = destructure_struct %{{.*}} : $_MyBridgeStorage
|
|
// CHECK: Index: 0
|
|
// CHECK: Path: (#0,#0,#0)
|
|
// CHECK: %{{.*}} = load [copy] %{{.*}} : $*_StringGuts
|
|
// CHECK: Tail **%{{.*}}** = destructure_struct %{{.*}} : $_MyBridgeStorage
|
|
// CHECK: Base: %{{.*}} = ref_tail_addr [immutable] %{{.*}} : $__ContiguousArrayStorageBase, $String
|
|
// CHECK: Storage: Tail **%{{.*}}** = destructure_struct %{{.*}} : $_MyBridgeStorage
|
|
// CHECK: Path: (#0)
|
|
// CHECK: %{{.*}} = load [copy] %{{.*}} : $*String
|
|
// CHECK: Tail **%{{.*}}** = destructure_struct %{{.*}} : $_MyBridgeStorage
|
|
// CHECK: Base: %{{.*}} = ref_tail_addr [immutable] %{{.*}} : $__ContiguousArrayStorageBase, $String
|
|
// CHECK: Storage: Tail **%{{.*}}** = destructure_struct %{{.*}} : $_MyBridgeStorage
|
|
// CHECK: Path: ()
|
|
sil hidden [noinline] [ossa] @testRefTailAndStruct0 : $@convention(thin) (@owned MyArray<String>) -> () {
|
|
bb0(%0 : @owned $MyArray<String>):
|
|
%1 = destructure_struct %0 : $MyArray<String> // #MyArray._buffer
|
|
%2 = destructure_struct %1 : $_MyArrayBuffer<String> // #_MyArrayBuffer._storage
|
|
%3 = destructure_struct %2 : $_MyBridgeStorage // #_MyBridgeStorage.rawValue
|
|
%4 = unchecked_ref_cast %3 : $Builtin.BridgeObject to $__ContiguousArrayStorageBase
|
|
%borrow = begin_borrow %4 : $__ContiguousArrayStorageBase
|
|
%5 = ref_element_addr [immutable] %borrow : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity
|
|
%6 = struct_element_addr %5 : $*_ArrayBody, #_ArrayBody._storage
|
|
%7 = struct_element_addr %6 : $*_SwiftArrayBodyStorage, #_SwiftArrayBodyStorage.count
|
|
%8 = struct_element_addr %7 : $*Int, #Int._value
|
|
%9 = load [trivial] %8 : $*Builtin.Int64
|
|
end_borrow %borrow : $__ContiguousArrayStorageBase
|
|
%borrow2 = begin_borrow %4 : $__ContiguousArrayStorageBase
|
|
%10 = ref_tail_addr [immutable] %borrow2 : $__ContiguousArrayStorageBase, $String
|
|
%11 = struct_element_addr %10 : $*String, #String._guts
|
|
%12 = load [copy] %11 : $*_StringGuts
|
|
%13 = load [copy] %10 : $*String
|
|
end_borrow %borrow2 : $__ContiguousArrayStorageBase
|
|
destroy_value %4 : $__ContiguousArrayStorageBase
|
|
destroy_value %12 : $_StringGuts
|
|
destroy_value %13 : $String
|
|
%14 = tuple ()
|
|
return %14 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @testPointerDynamicIndex
|
|
// CHECK: ###For MemOp: %{{.*}} = load [trivial] %{{.*}} : $*MyStruct
|
|
// CHECK: Base: %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Storage: Argument %0 = argument of bb0 : $Builtin.RawPointer
|
|
// CHECK: Path: (@Unknown)
|
|
sil [serialized] [ossa] @testPointerDynamicIndex : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> () {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
|
|
%2 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*MyStruct
|
|
%3 = index_addr %2 : $*MyStruct, %1 : $Builtin.Word
|
|
%4 = address_to_pointer %3 : $*MyStruct to $Builtin.RawPointer
|
|
%5 = pointer_to_address %4 : $Builtin.RawPointer to [strict] $*MyStruct
|
|
%6 = load [trivial] %5 : $*MyStruct
|
|
%7 = tuple ()
|
|
return %7 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @testAddressToPointer
|
|
// CHECK: ###For MemOp: %3 = load [trivial] %{{.*}} : $*MyStruct
|
|
// CHECK: Base: %0 = argument of bb0 : $*MyStruct
|
|
// CHECK: Storage: Argument %0 = argument of bb0 : $*MyStruct
|
|
// CHECK: Path: ()
|
|
// CHECK: ###For MemOp: %5 = load [trivial] %4 : $*Int64
|
|
// CHECK: Base: %0 = argument of bb0 : $*MyStruct
|
|
// CHECK: Storage: Argument %0 = argument of bb0 : $*MyStruct
|
|
// CHECK: Path: (#0)
|
|
sil [serialized] [ossa] @testAddressToPointer : $@convention(thin) (@in MyStruct) -> () {
|
|
bb18(%0 : $*MyStruct):
|
|
%1 = address_to_pointer %0 : $*MyStruct to $Builtin.RawPointer
|
|
%2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*MyStruct
|
|
%3 = load [trivial] %2 : $*MyStruct
|
|
%4 = struct_element_addr %0 : $*MyStruct, #MyStruct.i
|
|
%5 = load [trivial] %4 : $*Int64
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @testIndexLoop
|
|
// CHECK: ###For MemOp: %3 = load [copy] %2 : $*AnyObject
|
|
// CHECK: Base: %1 = struct_extract %0 : $UnsafeMutablePointer<AnyObject>, #UnsafeMutablePointer._rawValue
|
|
// CHECK: Storage: Unidentified %1 = struct_extract %0 : $UnsafeMutablePointer<AnyObject>, #UnsafeMutablePointer._rawValue
|
|
// CHECK: Path: ()
|
|
// CHECK: ###For MemOp: %7 = load [copy] %6 : $*AnyObject
|
|
// CHECK: Base: %1 = struct_extract %0 : $UnsafeMutablePointer<AnyObject>, #UnsafeMutablePointer._rawValue
|
|
// CHECK: Storage: Unidentified %1 = struct_extract %0 : $UnsafeMutablePointer<AnyObject>, #UnsafeMutablePointer._rawValue
|
|
// CHECK: Path: (@Unknown)
|
|
// CHECK: ###For MemOp: store %7 to [assign] %6 : $*AnyObject // id: %8
|
|
// CHECK: Base: %1 = struct_extract %0 : $UnsafeMutablePointer<AnyObject>, #UnsafeMutablePointer._rawValue
|
|
// CHECK: Storage: Unidentified %1 = struct_extract %0 : $UnsafeMutablePointer<AnyObject>, #UnsafeMutablePointer._rawValue
|
|
// CHECK: Path: (@Unknown)
|
|
sil shared [ossa] @testIndexLoop : $@convention(thin) (UnsafeMutablePointer<AnyObject>) -> UnsafeMutablePointer<AnyObject> {
|
|
bb0(%0 : $UnsafeMutablePointer<AnyObject>):
|
|
%1 = struct_extract %0 : $UnsafeMutablePointer<AnyObject>, #UnsafeMutablePointer._rawValue
|
|
%2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*AnyObject
|
|
%3 = load [copy] %2 : $*AnyObject
|
|
br bb1(%1 : $Builtin.RawPointer)
|
|
|
|
bb1(%5 : $Builtin.RawPointer):
|
|
%6 = pointer_to_address %5 : $Builtin.RawPointer to [strict] $*AnyObject
|
|
%7 = load [copy] %6 : $*AnyObject
|
|
store %7 to [assign] %6 : $*AnyObject
|
|
%9 = integer_literal $Builtin.Word, 1
|
|
%10 = index_addr %6 : $*AnyObject, %9 : $Builtin.Word
|
|
%11 = address_to_pointer %10 : $*AnyObject to $Builtin.RawPointer
|
|
cond_br undef, bb2, bb3
|
|
|
|
bb2:
|
|
br bb1(%11 : $Builtin.RawPointer)
|
|
|
|
bb3:
|
|
destroy_value %3 : $AnyObject
|
|
%15 = struct $UnsafeMutablePointer<AnyObject> (%11 : $Builtin.RawPointer)
|
|
return %15 : $UnsafeMutablePointer<AnyObject>
|
|
}
|
|
|
|
// Handle index_addr boundary conditions
|
|
// Most will end up as "unknown" offset, but we shouldn't crash.
|
|
// CHECK-LABEL: @indexAddrBoundaries
|
|
// CHECK: ###For MemOp: %4 = load [trivial] %3 : $*Int
|
|
// CHECK: Path: (@Unknown)
|
|
// CHECK: ###For MemOp: %7 = load [trivial] %6 : $*Int
|
|
// CHECK: Path: (@Unknown)
|
|
// CHECK: ###For MemOp: %10 = load [trivial] %9 : $*Int
|
|
// CHECK: Path: (@Unknown)
|
|
// CHECK: ###For MemOp: %13 = load [trivial] %12 : $*Int
|
|
// CHECK: Path: (@Unknown)
|
|
// CHECK: ###For MemOp: %16 = load [trivial] %15 : $*Int
|
|
// CHECK: Path: (@1073741823)
|
|
// CHECK: ###For MemOp: %19 = load [trivial] %18 : $*Int
|
|
// CHECK: Path: (@Unknown)
|
|
// CHECK: ###For MemOp: %22 = load [trivial] %21 : $*Int
|
|
// CHECK: Path: (@Unknown)
|
|
// CHECK: ###For MemOp: %25 = load [trivial] %24 : $*Int
|
|
// CHECK: Path: (@-1073741823)
|
|
// CHECK: ###For MemOp: %28 = load [trivial] %27 : $*Int
|
|
// CHECK: Path: (@-1)
|
|
sil [ossa] @indexAddrBoundaries : $@convention(thin) (Builtin.RawPointer) -> () {
|
|
bb0(%0 : $Builtin.RawPointer):
|
|
%1 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*Int
|
|
// INT_MIN (IndexTrie root)
|
|
%2 = integer_literal $Builtin.Word, 2147483648 // '0x80000000'
|
|
%3 = index_addr %1 : $*Int, %2 : $Builtin.Word
|
|
%4 = load [trivial] %3 : $*Int
|
|
// INT_MIN (IndexTrie root)
|
|
%5 = integer_literal $Builtin.Word, -2147483648 // '0x80000000'
|
|
%6 = index_addr %1 : $*Int, %5 : $Builtin.Word
|
|
%7 = load [trivial] %6 : $*Int
|
|
// INT_MAX (TailIndex)
|
|
%8 = integer_literal $Builtin.Word, 2147483647 // '0x7fffffff'
|
|
%9 = index_addr %1 : $*Int, %8 : $Builtin.Word
|
|
%10 = load [trivial] %9 : $*Int
|
|
// Largest unsigned offset + 1
|
|
%11 = integer_literal $Builtin.Word, 1073741824 // '0x40000000'
|
|
%12 = index_addr %1 : $*Int, %11 : $Builtin.Word
|
|
%13 = load [trivial] %12 : $*Int
|
|
// Largest unsigned offset
|
|
%14 = integer_literal $Builtin.Word, 1073741823 // '0x3fffffff'
|
|
%15 = index_addr %1 : $*Int, %14 : $Builtin.Word
|
|
%16 = load [trivial] %15 : $*Int
|
|
// Smallest signed offset - 1
|
|
%17 = integer_literal $Builtin.Word, -1073741825 // '0xbfffffff'
|
|
%18 = index_addr %1 : $*Int, %17 : $Builtin.Word
|
|
%19 = load [trivial] %18 : $*Int
|
|
// Smallest signed offset (Unknown offset)
|
|
%20 = integer_literal $Builtin.Word, -1073741824 // '0xc0000000'
|
|
%21 = index_addr %1 : $*Int, %20 : $Builtin.Word
|
|
%22 = load [trivial] %21 : $*Int
|
|
// Smallest signed offset + 1 (concrete offset)
|
|
%23 = integer_literal $Builtin.Word, -1073741823 // '0xc0000001'
|
|
%24 = index_addr %1 : $*Int, %23 : $Builtin.Word
|
|
%25 = load [trivial] %24 : $*Int
|
|
// Largest Negative
|
|
%26 = integer_literal $Builtin.Word, -1 // '0xffffffff'
|
|
%27 = index_addr %1 : $*Int, %26 : $Builtin.Word
|
|
%28 = load [trivial] %27 : $*Int
|
|
//
|
|
%99 = tuple ()
|
|
return %99 : $()
|
|
}
|