blob: 9067004664e22ea9a2d69eba20f7b7e75c641d77 [file] [log] [blame]
// RUN: %target-sil-opt %s -escapes-dump -escapes-internal-verify -o /dev/null | %FileCheck %s
// REQUIRES: asserts
// REQUIRES: OS=macosx
// REQUIRES: PTRSIZE=64
sil_stage canonical
import Builtin
import Swift
import SwiftShims
// =============================================================================
// Test call to array.uninitialized that has "extra" release_value uses
class C {
var c: C
}
class DummyArrayStorage<Element> {
@_hasStorage var count: Int { get }
@_hasStorage var capacity: Int { get }
init()
}
// init_any_array_with_buffer
sil [_semantics "array.uninitialized"] @init_any_array_with_buffer : $@convention(thin) (@owned DummyArrayStorage<AnyObject>, Int32, @thin Array<AnyObject>.Type) -> (@owned Array<AnyObject>, UnsafeMutablePointer<AnyObject>)
// CHECK-LABEL: CG of testBadArrayUninit
// CHECK-NEXT: Val [ref] %2 Esc: , Succ: (%2.1)
// CHECK-NEXT: Con [int] %2.1 Esc: G, Succ: (%2.2)
// CHECK-NEXT: Con [ref] %2.2 Esc: G, Succ:
// CHECK-NEXT: Val %5 Esc: , Succ: (%5.1)
// CHECK-NEXT: Con %5.1 Esc: G, Succ: %10
// CHECK-NEXT: Val [ref] %10 Esc: G, Succ: (%10.1)
// CHECK-NEXT: Con %10.1 Esc: G, Succ:
// CHECK-LABEL: End
sil hidden @testBadArrayUninit : $@convention(thin) (Builtin.Word, Int32) -> () {
bb0(%0 : $Builtin.Word, %1 : $Int32):
// create an array
%2 = alloc_ref [tail_elems $AnyObject * %0 : $Builtin.Word] $DummyArrayStorage<AnyObject>
%3 = metatype $@thin Array<AnyObject>.Type
%4 = function_ref @init_any_array_with_buffer : $@convention(thin) (@owned DummyArrayStorage<AnyObject>, Int32, @thin Array<AnyObject>.Type) -> (@owned Array<AnyObject>, UnsafeMutablePointer<AnyObject>)
%5 = apply %4(%2, %1, %3) : $@convention(thin) (@owned DummyArrayStorage<AnyObject>, Int32, @thin Array<AnyObject>.Type) -> (@owned Array<AnyObject>, UnsafeMutablePointer<AnyObject>)
%6 = tuple_extract %5 : $(Array<AnyObject>, UnsafeMutablePointer<AnyObject>), 0
%7 = tuple_extract %5 : $(Array<AnyObject>, UnsafeMutablePointer<AnyObject>), 1
%8 = struct_extract %7 : $UnsafeMutablePointer<AnyObject>, #UnsafeMutablePointer._rawValue
%9 = pointer_to_address %8 : $Builtin.RawPointer to [strict] $*AnyObject
// store an elt
%10 = alloc_ref $C
%11 = init_existential_ref %10 : $C : $C, $AnyObject
store %11 to %9 : $*AnyObject
// extra use of the call
release_value %5 : $(Array<AnyObject>, UnsafeMutablePointer<AnyObject>) // id: %228
%13 = tuple ()
return %13 : $()
}
// =============================================================================
// testArrayEscapeToBox: test that an array is marked escaping when
// assigned to a box. When multiple arrays are merged into the same
// box, ensure that a previous mapping from the project_box address to
// the box's content is not lost during the merge.
class ElementClass {
init()
}
class StagedContext {
init()
}
class VFSStagedContext : StagedContext {
override init()
}
// specialized Array.init()
sil @$sS2ayxGycfCSo12ElementClassC_Tg5 : $@convention(method) (@thin Array<ElementClass>.Type) -> @owned Array<ElementClass>
// specialized Array._getCount()
sil @$sSa9_getCountSiyFSo12ElementClassC_Tg5 : $@convention(method) (@guaranteed Array<ElementClass>) -> Int
// specialized static Array._adoptStorage(_:count:)
sil shared [_semantics "array.uninitialized"] @$sSa13_adoptStorage_5countSayxG_SpyxGts016_ContiguousArrayB0CyxGn_SitFZSo12ElementClassC_Tg5 : $@convention(method) (@owned _ContiguousArrayStorage<ElementClass>, Int, @thin Array<ElementClass>.Type) -> (@owned Array<ElementClass>, UnsafeMutablePointer<ElementClass>) {
// %0 // users: %13, %3
// %1 // users: %9, %4
bb0(%0 : $_ContiguousArrayStorage<ElementClass>, %1 : $Int, %2 : $@thin Array<ElementClass>.Type):
%3 = upcast %0 : $_ContiguousArrayStorage<ElementClass> to $__ContiguousArrayStorageBase // users: %17, %11
%4 = struct_extract %1 : $Int, #Int._value // user: %6
%5 = integer_literal $Builtin.Int64, 1 // users: %7, %6
%6 = builtin "shl_Int64"(%4 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int64 // user: %7
%7 = builtin "or_Int64"(%6 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int64 // user: %8
%8 = struct $UInt (%7 : $Builtin.Int64) // user: %9
%9 = struct $_SwiftArrayBodyStorage (%1 : $Int, %8 : $UInt) // user: %10
%10 = struct $_ArrayBody (%9 : $_SwiftArrayBodyStorage) // user: %12
%11 = ref_element_addr %3 : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity // user: %12
store %10 to %11 : $*_ArrayBody // id: %12
%13 = unchecked_ref_cast %0 : $_ContiguousArrayStorage<ElementClass> to $Builtin.BridgeObject // user: %14
%14 = struct $_BridgeStorage<__ContiguousArrayStorageBase> (%13 : $Builtin.BridgeObject) // user: %15
%15 = struct $_ArrayBuffer<ElementClass> (%14 : $_BridgeStorage<__ContiguousArrayStorageBase>) // user: %16
%16 = struct $Array<ElementClass> (%15 : $_ArrayBuffer<ElementClass>) // user: %20
%17 = ref_tail_addr %3 : $__ContiguousArrayStorageBase, $ElementClass // user: %18
%18 = address_to_pointer %17 : $*ElementClass to $Builtin.RawPointer // user: %19
%19 = struct $UnsafeMutablePointer<ElementClass> (%18 : $Builtin.RawPointer) // user: %20
%20 = tuple (%16 : $Array<ElementClass>, %19 : $UnsafeMutablePointer<ElementClass>) // user: %21
return %20 : $(Array<ElementClass>, UnsafeMutablePointer<ElementClass>) // id: %21
}
// testArrayUsePointsClosure1
sil @testArrayUsePointsClosure1 : $@convention(thin) (@guaranteed { var Optional<VFSStagedContext> }, @guaranteed @callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> ()) -> ()
// testArrayUsePointsClosure2
sil @testArrayUsePointsClosure2 : $@convention(thin) (@guaranteed @callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> (), @guaranteed Optional<VFSStagedContext>, @guaranteed { var Array<ElementClass> }) -> ()
// Make sure both locally allocated array's are globally escaping.
//
// CHECK-LABEL: CG of testArrayEscapeToBox
// CHECK-NEXT: Arg [ref] %0 Esc: A, Succ: (%21)
// CHECK-NEXT: Val [ref] %1 Esc: , Succ: (%21)
// CHECK-NEXT: Val [ref] %4 Esc: , Succ: %0, %1
// CHECK-NEXT: Val [ref] %8 Esc: , Succ: (%21)
// CHECK-NEXT: Val [ref] %12 Esc: G, Succ: (%21)
// CHECK-NEXT: Val [ref] %17 Esc: G, Succ: (%21)
// CHECK-NEXT: Val [ref] %20 Esc: G, Succ: %17
// CHECK-NEXT: Con [int] %21 Esc: G, Succ: (%39)
// CHECK-NEXT: Val [ref] %31 Esc: G, Succ: (%21)
// CHECK-NEXT: Val [ref] %34 Esc: G, Succ: %31
// CHECK-NEXT: Con %39 Esc: G, Succ: (%21), %12, %20, %34
// CHECK-NEXT: Val [ref] %45 Esc: , Succ: %0, %8, %39
// CHECK-NEXT: End
sil private @testArrayEscapeToBox : $@convention(thin) (@guaranteed @callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> ()) -> () {
// %0 // users: %54, %51, %47, %45, %5, %4
bb0(%0 : $@callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> ()):
%1 = alloc_box ${ var Optional<VFSStagedContext> }, var, name "context" // users: %59, %6, %4, %2
%2 = project_box %1 : ${ var Optional<VFSStagedContext> }, 0 // user: %44
// function_ref testArrayUsePointsClosure1
%3 = function_ref @testArrayUsePointsClosure1 : $@convention(thin) (@guaranteed { var Optional<VFSStagedContext> }, @guaranteed @callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> ()) -> () // user: %4
%4 = partial_apply [callee_guaranteed] %3(%1, %0) : $@convention(thin) (@guaranteed { var Optional<VFSStagedContext> }, @guaranteed @callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> ()) -> ()
strong_retain %0 : $@callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> () // id: %5
strong_retain %1 : ${ var Optional<VFSStagedContext> } // id: %6
br bb1 // id: %7
bb1: // Preds: bb0
%8 = alloc_box ${ var Array<ElementClass> }, var, name "intents" // users: %58, %56, %52, %48, %45, %9
%9 = project_box %8 : ${ var Array<ElementClass> }, 0 // users: %41, %36, %27, %22, %13
%10 = metatype $@thin Array<ElementClass>.Type // users: %33, %19, %12
// function_ref specialized Array.init()
%11 = function_ref @$sS2ayxGycfCSo12ElementClassC_Tg5 : $@convention(method) (@thin Array<ElementClass>.Type) -> @owned Array<ElementClass> // user: %12
%12 = apply %11(%10) : $@convention(method) (@thin Array<ElementClass>.Type) -> @owned Array<ElementClass> // user: %13
store %12 to %9 : $*Array<ElementClass> // id: %13
cond_br undef, bb2, bb3 // id: %14
bb2: // Preds: bb1
%15 = integer_literal $Builtin.Int64, 1 // user: %16
%16 = struct $Int (%15 : $Builtin.Int64) // user: %19
%17 = alloc_ref [tail_elems $ElementClass * undef : $Builtin.Word] $_ContiguousArrayStorage<ElementClass> // user: %19
// function_ref specialized static Array._adoptStorage(_:count:)
%18 = function_ref @$sSa13_adoptStorage_5countSayxG_SpyxGts016_ContiguousArrayB0CyxGn_SitFZSo12ElementClassC_Tg5 : $@convention(method) (@owned _ContiguousArrayStorage<ElementClass>, Int, @thin Array<ElementClass>.Type) -> (@owned Array<ElementClass>, UnsafeMutablePointer<ElementClass>) // user: %19
%19 = apply %18(%17, %16, %10) : $@convention(method) (@owned _ContiguousArrayStorage<ElementClass>, Int, @thin Array<ElementClass>.Type) -> (@owned Array<ElementClass>, UnsafeMutablePointer<ElementClass>) // users: %21, %20
%20 = tuple_extract %19 : $(Array<ElementClass>, UnsafeMutablePointer<ElementClass>), 0 // user: %27
%21 = tuple_extract %19 : $(Array<ElementClass>, UnsafeMutablePointer<ElementClass>), 1
%22 = struct_element_addr %9 : $*Array<ElementClass>, #Array._buffer // user: %23
%23 = struct_element_addr %22 : $*_ArrayBuffer<ElementClass>, #_ArrayBuffer._storage // user: %24
%24 = struct_element_addr %23 : $*_BridgeStorage<__ContiguousArrayStorageBase>, #_BridgeStorage.rawValue // user: %25
%25 = load %24 : $*Builtin.BridgeObject // user: %26
strong_release %25 : $Builtin.BridgeObject // id: %26
store %20 to %9 : $*Array<ElementClass> // id: %27
br bb4 // id: %28
bb3: // Preds: bb1
%29 = integer_literal $Builtin.Int64, 1 // user: %30
%30 = struct $Int (%29 : $Builtin.Int64) // user: %33
%31 = alloc_ref [tail_elems $ElementClass * undef : $Builtin.Word] $_ContiguousArrayStorage<ElementClass> // user: %33
// function_ref specialized static Array._adoptStorage(_:count:)
%32 = function_ref @$sSa13_adoptStorage_5countSayxG_SpyxGts016_ContiguousArrayB0CyxGn_SitFZSo12ElementClassC_Tg5 : $@convention(method) (@owned _ContiguousArrayStorage<ElementClass>, Int, @thin Array<ElementClass>.Type) -> (@owned Array<ElementClass>, UnsafeMutablePointer<ElementClass>) // user: %33
%33 = apply %32(%31, %30, %10) : $@convention(method) (@owned _ContiguousArrayStorage<ElementClass>, Int, @thin Array<ElementClass>.Type) -> (@owned Array<ElementClass>, UnsafeMutablePointer<ElementClass>) // users: %35, %34
%34 = tuple_extract %33 : $(Array<ElementClass>, UnsafeMutablePointer<ElementClass>), 0 // user: %41
%35 = tuple_extract %33 : $(Array<ElementClass>, UnsafeMutablePointer<ElementClass>), 1
%36 = struct_element_addr %9 : $*Array<ElementClass>, #Array._buffer // user: %37
%37 = struct_element_addr %36 : $*_ArrayBuffer<ElementClass>, #_ArrayBuffer._storage // user: %38
%38 = struct_element_addr %37 : $*_BridgeStorage<__ContiguousArrayStorageBase>, #_BridgeStorage.rawValue // user: %39
%39 = load %38 : $*Builtin.BridgeObject // user: %40
strong_release %39 : $Builtin.BridgeObject // id: %40
store %34 to %9 : $*Array<ElementClass> // id: %41
br bb4 // id: %42
bb4: // Preds: bb3 bb2
// function_ref testArrayUsePointsClosure2
%43 = function_ref @testArrayUsePointsClosure2 : $@convention(thin) (@guaranteed @callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> (), @guaranteed Optional<VFSStagedContext>, @guaranteed { var Array<ElementClass> }) -> () // user: %45
%44 = load %2 : $*Optional<VFSStagedContext> // users: %55, %53, %49, %45
%45 = partial_apply [callee_guaranteed] %43(%0, %44, %8) : $@convention(thin) (@guaranteed @callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> (), @guaranteed Optional<VFSStagedContext>, @guaranteed { var Array<ElementClass> }) -> () // user: %57
// function_ref specialized Array._getCount()
%46 = function_ref @$sSa9_getCountSiyFSo12ElementClassC_Tg5 : $@convention(method) (@guaranteed Array<ElementClass>) -> Int
strong_retain %0 : $@callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> () // id: %47
strong_retain %8 : ${ var Array<ElementClass> } // id: %48
retain_value %44 : $Optional<VFSStagedContext> // id: %49
br bb5 // id: %50
bb5: // Preds: bb4
strong_retain %0 : $@callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> () // id: %51
strong_retain %8 : ${ var Array<ElementClass> } // id: %52
retain_value %44 : $Optional<VFSStagedContext> // id: %53
strong_release %0 : $@callee_guaranteed (@guaranteed Optional<StagedContext>, @guaranteed Optional<Error>) -> () // id: %54
release_value %44 : $Optional<VFSStagedContext> // id: %55
strong_release %8 : ${ var Array<ElementClass> } // id: %56
strong_release %45 : $@callee_guaranteed () -> () // id: %57
strong_release %8 : ${ var Array<ElementClass> } // id: %58
strong_release %1 : ${ var Optional<VFSStagedContext> } // id: %59
br bb6 // id: %60
bb6: // Preds: bb5
%61 = tuple () // user: %62
return %61 : $() // id: %62
}
// =============================================================================
// Test merging an interior node with a non-interior
// node. Verification can fail in the time between when the properties
// are merged and when the edges are merged.
struct Poly {
@_hasStorage var points: Array<Int64> { get set }
@_hasStorage var length: Int64 { get set }
init(points: Array<Int64>, length: Int64)
}
// CHECK-LABEL: CG of testMergeInteriorPointsTo
// CHECK-NEXT: Arg [ref] %0 Esc: A, Succ: (%6.2)
// CHECK-NEXT: Val %1 Esc: , Succ: (%1.1)
// CHECK-NEXT: Con [ref] %1.1 Esc: , Succ: %0, %12.1
// CHECK-NEXT: Val %6 Esc: , Succ: (%6.1)
// CHECK-NEXT: Con [ref] %6.1 Esc: , Succ: (%6.2)
// CHECK-NEXT: Con [int] %6.2 Esc: G, Succ: (%6.3)
// CHECK-NEXT: Con %6.3 Esc: G, Succ: (%6.4)
// CHECK-NEXT: Con [int] %6.4 Esc: G, Succ: (%6.5)
// CHECK-NEXT: Con %6.5 Esc: G, Succ: (%6.6)
// CHECK-NEXT: Con %6.6 Esc: G, Succ:
// CHECK-NEXT: Val %8 Esc: , Succ: (%8.1)
// CHECK-NEXT: Con [ref] %8.1 Esc: , Succ: %6.1
// CHECK-NEXT: Val %12 Esc: , Succ: (%12.1)
// CHECK-NEXT: Con [ref] %12.1 Esc: , Succ: %6.1
// CHECK-LABEL: End
sil [serialized] @testMergeInteriorPointsTo : $@convention(method) (@owned Array<Int64>) -> () {
bb0(%0 : $Array<Int64>):
%1 = alloc_stack $Poly, var, name "self"
%2 = struct_element_addr %1 : $*Poly, #Poly.points
retain_value %0 : $Array<Int64>
retain_value %0 : $Array<Int64>
store %0 to %2 : $*Array<Int64>
%6 = alloc_stack $Int64, var, name "length"
release_value %0 : $Array<Int64>
%8 = alloc_stack $Int64
copy_addr %6 to [initialization] %8 : $*Int64
destroy_addr %8 : $*Int64
dealloc_stack %8 : $*Int64
%12 = alloc_stack $Int64
copy_addr %6 to [initialization] %12 : $*Int64
%14 = struct_element_addr %1 : $*Poly, #Poly.length
copy_addr [take] %12 to [initialization] %14 : $*Int64
dealloc_stack %12 : $*Int64
destroy_addr %6 : $*Int64
dealloc_stack %6 : $*Int64
dealloc_stack %1 : $*Poly
%20 = tuple ()
return %20 : $()
}
// =============================================================================
// Test merging a callee graph such that when merging pointsTo nodes
// for defer edges in the caller graph, the new pointsTo node has
// already been merged and the deferred node has both a defer edge and
// pointsTo edge to the same node.
public protocol ProceduralOp : AnyObject {}
public class OptypeBase {
@_hasStorage var name : String { get set }
@_hasStorage var id : Int { get set }
}
public class OptypeDependent : OptypeBase {
@_hasStorage var _enable : Bool { get set }
@_hasStorage var _ops : Array<ProceduralOp>
}
public class CombineAnyOp : OptypeDependent {
@_hasStorage var _sources : Array<(ProceduralOp, Bool)>
}
sil_global @_swiftEmptyArrayStorage : $_SwiftEmptyArrayStorage
sil @$sSa28_allocateBufferUninitialized15minimumCapacitys06_ArrayB0VyxGSi_tFZ : $@convention(method) <Ï„_0_0> (Int, @thin Array<Ï„_0_0>.Type) -> @owned _ArrayBuffer<Ï„_0_0>
// specialized static Array._allocateUninitialized(_:)
sil shared [_semantics "array.uninitialized"] @$sSa22_allocateUninitializedySayxG_SpyxGtSiFZ12ProceduralOp_p_Tg5 : $@convention(method) (Int, @thin Array<ProceduralOp>.Type) -> (@owned Array<ProceduralOp>, UnsafeMutablePointer<ProceduralOp>) {
// %0
bb0(%0 : $Int, %1 : $@thin Array<ProceduralOp>.Type):
%2 = global_addr @_swiftEmptyArrayStorage : $*_SwiftEmptyArrayStorage
%3 = address_to_pointer %2 : $*_SwiftEmptyArrayStorage to $Builtin.RawPointer
%4 = raw_pointer_to_ref %3 : $Builtin.RawPointer to $__EmptyArrayStorage
%5 = unchecked_ref_cast %4 : $__EmptyArrayStorage to $Builtin.BridgeObject
%6 = integer_literal $Builtin.Int64, 0
%7 = struct_extract %0 : $Int, #Int._value
%8 = builtin "cmp_slt_Int64"(%6 : $Builtin.Int64, %7 : $Builtin.Int64) : $Builtin.Int1
cond_br %8, bb1, bb2
bb1:
%10 = metatype $@thin Array<ProceduralOp>.Type
// function_ref static Array._allocateBufferUninitialized(minimumCapacity:)
%11 = function_ref @$sSa28_allocateBufferUninitialized15minimumCapacitys06_ArrayB0VyxGSi_tFZ : $@convention(method) <Ï„_0_0> (Int, @thin Array<Ï„_0_0>.Type) -> @owned _ArrayBuffer<Ï„_0_0>
%12 = apply %11<ProceduralOp>(%0, %10) : $@convention(method) <Ï„_0_0> (Int, @thin Array<Ï„_0_0>.Type) -> @owned _ArrayBuffer<Ï„_0_0>
%13 = struct_extract %12 : $_ArrayBuffer<ProceduralOp>, #_ArrayBuffer._storage
%14 = struct_extract %13 : $_BridgeStorage<__ContiguousArrayStorageBase>, #_BridgeStorage.rawValue
%15 = unchecked_ref_cast %14 : $Builtin.BridgeObject to $__ContiguousArrayStorageBase
%16 = ref_element_addr %15 : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity
%17 = struct_element_addr %16 : $*_ArrayBody, #_ArrayBody._storage
%18 = struct_element_addr %17 : $*_SwiftArrayBodyStorage, #_SwiftArrayBodyStorage.count
store %0 to %18 : $*Int
br bb3(%14 : $Builtin.BridgeObject)
bb2:
strong_retain %4 : $__EmptyArrayStorage
br bb3(%5 : $Builtin.BridgeObject)
// %23
bb3(%23 : $Builtin.BridgeObject):
%24 = struct $_BridgeStorage<__ContiguousArrayStorageBase> (%23 : $Builtin.BridgeObject)
%25 = struct $_ArrayBuffer<ProceduralOp> (%24 : $_BridgeStorage<__ContiguousArrayStorageBase>)
%26 = struct $Array<ProceduralOp> (%25 : $_ArrayBuffer<ProceduralOp>)
%27 = unchecked_ref_cast %23 : $Builtin.BridgeObject to $__ContiguousArrayStorageBase
%28 = ref_tail_addr %27 : $__ContiguousArrayStorageBase, $ProceduralOp
%29 = address_to_pointer %28 : $*ProceduralOp to $Builtin.RawPointer
%30 = struct $UnsafeMutablePointer<ProceduralOp> (%29 : $Builtin.RawPointer)
%31 = tuple (%26 : $Array<ProceduralOp>, %30 : $UnsafeMutablePointer<ProceduralOp>)
return %31 : $(Array<ProceduralOp>, UnsafeMutablePointer<ProceduralOp>)
}
sil shared [_semantics "array.uninitialized"] @$sSa22_allocateUninitializedySayxG_SpyxGtSiFZ12ProceduralOp_p_Sbt_Tg5 : $@convention(method) (Int, @thin Array<(ProceduralOp, Bool)>.Type) -> (@owned Array<(ProceduralOp, Bool)>, UnsafeMutablePointer<(ProceduralOp, Bool)>) {
// %0
bb0(%0 : $Int, %1 : $@thin Array<(ProceduralOp, Bool)>.Type):
%2 = global_addr @_swiftEmptyArrayStorage : $*_SwiftEmptyArrayStorage
%3 = address_to_pointer %2 : $*_SwiftEmptyArrayStorage to $Builtin.RawPointer
%4 = raw_pointer_to_ref %3 : $Builtin.RawPointer to $__EmptyArrayStorage
%5 = unchecked_ref_cast %4 : $__EmptyArrayStorage to $Builtin.BridgeObject
%6 = integer_literal $Builtin.Int64, 0
%7 = struct_extract %0 : $Int, #Int._value
%8 = builtin "cmp_slt_Int64"(%6 : $Builtin.Int64, %7 : $Builtin.Int64) : $Builtin.Int1
cond_br %8, bb1, bb2
bb1:
%10 = metatype $@thin Array<(ProceduralOp, Bool)>.Type
// function_ref static Array._allocateBufferUninitialized(minimumCapacity:)
%11 = function_ref @$sSa28_allocateBufferUninitialized15minimumCapacitys06_ArrayB0VyxGSi_tFZ : $@convention(method) <Ï„_0_0> (Int, @thin Array<Ï„_0_0>.Type) -> @owned _ArrayBuffer<Ï„_0_0>
%12 = apply %11<(ProceduralOp, Bool)>(%0, %10) : $@convention(method) <Ï„_0_0> (Int, @thin Array<Ï„_0_0>.Type) -> @owned _ArrayBuffer<Ï„_0_0>
%13 = struct_extract %12 : $_ArrayBuffer<(ProceduralOp, Bool)>, #_ArrayBuffer._storage
%14 = struct_extract %13 : $_BridgeStorage<__ContiguousArrayStorageBase>, #_BridgeStorage.rawValue
%15 = unchecked_ref_cast %14 : $Builtin.BridgeObject to $__ContiguousArrayStorageBase
%16 = ref_element_addr %15 : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity
%17 = struct_element_addr %16 : $*_ArrayBody, #_ArrayBody._storage
%18 = struct_element_addr %17 : $*_SwiftArrayBodyStorage, #_SwiftArrayBodyStorage.count
store %0 to %18 : $*Int
br bb3(%14 : $Builtin.BridgeObject)
bb2:
strong_retain %4 : $__EmptyArrayStorage
br bb3(%5 : $Builtin.BridgeObject)
// %23
bb3(%23 : $Builtin.BridgeObject):
%24 = struct $_BridgeStorage<__ContiguousArrayStorageBase> (%23 : $Builtin.BridgeObject)
%25 = struct $_ArrayBuffer<(ProceduralOp, Bool)> (%24 : $_BridgeStorage<__ContiguousArrayStorageBase>)
%26 = struct $Array<(ProceduralOp, Bool)> (%25 : $_ArrayBuffer<(ProceduralOp, Bool)>)
%27 = unchecked_ref_cast %23 : $Builtin.BridgeObject to $__ContiguousArrayStorageBase
%28 = ref_tail_addr %27 : $__ContiguousArrayStorageBase, $(ProceduralOp, Bool)
%29 = address_to_pointer %28 : $*(ProceduralOp, Bool) to $Builtin.RawPointer
%30 = struct $UnsafeMutablePointer<(ProceduralOp, Bool)> (%29 : $Builtin.RawPointer)
%31 = tuple (%26 : $Array<(ProceduralOp, Bool)>, %30 : $UnsafeMutablePointer<(ProceduralOp, Bool)>)
return %31 : $(Array<(ProceduralOp, Bool)>, UnsafeMutablePointer<(ProceduralOp, Bool)>)
}
sil @testMergePointsTo_OptypeDependent_init : $@convention(method) (@owned String, @owned OptypeDependent) -> @owned OptypeDependent {
bb0(%0 : $String, %1 : $OptypeDependent):
%3 = integer_literal $Builtin.Int64, 0
%4 = struct $Int (%3 : $Builtin.Int64)
%5 = metatype $@thin Array<ProceduralOp>.Type
// function_ref specialized static Array._allocateUninitialized(_:)
%6 = function_ref @$sSa22_allocateUninitializedySayxG_SpyxGtSiFZ12ProceduralOp_p_Tg5 : $@convention(method) (Int, @thin Array<ProceduralOp>.Type) -> (@owned Array<ProceduralOp>, UnsafeMutablePointer<ProceduralOp>)
strong_retain %1 : $OptypeDependent // id: %7
%8 = apply %6(%4, %5) : $@convention(method) (Int, @thin Array<ProceduralOp>.Type) -> (@owned Array<ProceduralOp>, UnsafeMutablePointer<ProceduralOp>)
%9 = tuple_extract %8 : $(Array<ProceduralOp>, UnsafeMutablePointer<ProceduralOp>), 0
%10 = ref_element_addr %1 : $OptypeDependent, #OptypeDependent._ops
store %9 to %10 : $*Array<ProceduralOp>
%12 = integer_literal $Builtin.Int1, -1
%13 = struct $Bool (%12 : $Builtin.Int1)
%14 = ref_element_addr %1 : $OptypeDependent, #OptypeDependent._enable
store %13 to %14 : $*Bool
strong_release %1 : $OptypeDependent
%17 = upcast %1 : $OptypeDependent to $OptypeBase
%19 = ref_element_addr %17 : $OptypeBase, #OptypeBase.name
store %0 to %19 : $*String
return %1 : $OptypeDependent
}
// CHECK-LABEL: CG of testMergePointsTo_CombineAnyOp_init
// CHECK-NEXT: Arg [ref] %0 Esc: A, Succ: (%7.1)
// CHECK-NEXT: Arg [ref] %1 Esc: A, Succ: (%9)
// CHECK-NEXT: Val %7 Esc: A, Succ: (%7.1), %7.1
// CHECK-NEXT: Con [int] %7.1 Esc: G, Succ: (%7.1)
// CHECK-NEXT: Con [int] %9 Esc: A, Succ: (%9.1)
// CHECK-NEXT: Con [ref] %9.1 Esc: A, Succ: %0, %7, %7.1
// CHECK-NEXT: Val [ref] %18 Esc: , Succ: (%9), %1
// CHECK-NEXT: Ret [ref] return Esc: , Succ: %18
// CHECK-LABEL: End
sil @testMergePointsTo_CombineAnyOp_init : $@convention(method) (@owned String, @owned CombineAnyOp) -> @owned CombineAnyOp {
bb0(%0 : $String, %1 : $CombineAnyOp):
strong_retain %1 : $CombineAnyOp
%4 = integer_literal $Builtin.Int64, 0
%5 = struct $Int (%4 : $Builtin.Int64)
%6 = metatype $@thin Array<(ProceduralOp, Bool)>.Type
// function_ref specialized static Array._allocateUninitialized(_:)
%7 = function_ref @$sSa22_allocateUninitializedySayxG_SpyxGtSiFZ12ProceduralOp_p_Sbt_Tg5 : $@convention(method) (Int, @thin Array<(ProceduralOp, Bool)>.Type) -> (@owned Array<(ProceduralOp, Bool)>, UnsafeMutablePointer<(ProceduralOp, Bool)>)
%8 = apply %7(%5, %6) : $@convention(method) (Int, @thin Array<(ProceduralOp, Bool)>.Type) -> (@owned Array<(ProceduralOp, Bool)>, UnsafeMutablePointer<(ProceduralOp, Bool)>)
%9 = tuple_extract %8 : $(Array<(ProceduralOp, Bool)>, UnsafeMutablePointer<(ProceduralOp, Bool)>), 0
%10 = ref_element_addr %1 : $CombineAnyOp, #CombineAnyOp._sources
store %9 to %10 : $*Array<(ProceduralOp, Bool)>
strong_release %1 : $CombineAnyOp
%13 = struct_extract %0 : $String, #String._guts
%14 = struct_extract %13 : $_StringGuts, #_StringGuts._object
%15 = struct_extract %14 : $_StringObject, #_StringObject._object
strong_retain %15 : $Builtin.BridgeObject
%18 = upcast %1 : $CombineAnyOp to $OptypeDependent
%19 = function_ref @testMergePointsTo_OptypeDependent_init : $@convention(method) (@owned String, @owned OptypeDependent) -> @owned OptypeDependent
%20 = apply %19(%0, %18) : $@convention(method) (@owned String, @owned OptypeDependent) -> @owned OptypeDependent
%21 = unchecked_ref_cast %20 : $OptypeDependent to $CombineAnyOp
strong_release %15 : $Builtin.BridgeObject
return %21 : $CombineAnyOp
}
// =============================================================================
// Test calling ConnectionGraph::initializePointsTo from
// mergeAllScheduledNodes when multiple merges are pending. In this
// case, initializePointsTo is called and a node in the
// to-be-initialized defer web already pointsTo a node that has been
// marked for merging.
public protocol ASTNode {}
public struct AssignmentNode : ASTNode {
@_hasStorage public let variable: ASTNode { get }
@_hasStorage public let value: ASTNode { get }
@_hasStorage public let range: Range<Int>? { get }
@_hasStorage public let documentation: String? { get }
public init(variable: ASTNode, value: ASTNode, range: Range<Int>?, documentation: String?) throws
public var childNodes: [ASTNode] { get }
}
public struct VariableNode : ASTNode {
@_hasStorage public let name: String { get }
@_hasStorage public let range: Range<Int>? { get }
public init(name: String, range: Range<Int>?)
public var childNodes: [ASTNode] { get }
public var description: String { get }
public var nodeDescription: String? { get }
}
// CHECK-LABEL: CG of testPendingMergeHelper
// CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.1)
// CHECK-NEXT: Con %0.1 Esc: A, Succ: %3.1
// CHECK-NEXT: Arg %1 Esc: A, Succ: (%1.1)
// CHECK-NEXT: Con %1.1 Esc: A, Succ: (%2.1)
// CHECK-NEXT: Arg [ref] %2 Esc: A, Succ: (%2.1)
// CHECK-NEXT: Con %2.1 Esc: G, Succ:
// CHECK-NEXT: Val %3 Esc: , Succ: (%3.1)
// CHECK-NEXT: Con %3.1 Esc: A, Succ: %1.1, %2
// CHECK-LABEL: End
sil @testPendingMergeHelper : $@convention(method) (@in ASTNode, @owned Optional<String>) -> (@out AssignmentNode, @error Error) {
bb0(%0 : $*AssignmentNode, %1 : $*ASTNode, %4 : $Optional<String>):
%6 = alloc_stack $AssignmentNode, var, name "self"
cond_br undef, bb1, bb2
bb1:
destroy_addr %1 : $*ASTNode
dealloc_stack %6 : $*AssignmentNode
throw undef : $Error
bb2:
%160 = struct_element_addr %6 : $*AssignmentNode, #AssignmentNode.variable
copy_addr [take] %1 to [initialization] %160 : $*ASTNode
%162 = struct_element_addr %6 : $*AssignmentNode, #AssignmentNode.value
%164 = struct_element_addr %6 : $*AssignmentNode, #AssignmentNode.range
%166 = struct_element_addr %6 : $*AssignmentNode, #AssignmentNode.documentation
store %4 to %166 : $*Optional<String>
copy_addr [take] %6 to [initialization] %0 : $*AssignmentNode
dealloc_stack %6 : $*AssignmentNode
%171 = tuple ()
return %171 : $()
}
// CHECK-LABEL: CG of testPendingMerge
// CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.1)
// CHECK-NEXT: Con %0.1 Esc: A, Succ: %1, %4.1
// CHECK-NEXT: Arg [ref] %1 Esc: A, Succ: (%9.1)
// CHECK-NEXT: Val %2 Esc: , Succ: (%9)
// CHECK-NEXT: Val %4 Esc: , Succ: (%4.1)
// CHECK-NEXT: Con %4.1 Esc: A, Succ: (%9.1), %5.1, %9
// CHECK-NEXT: Val %5 Esc: , Succ: (%5.1)
// CHECK-NEXT: Con %5.1 Esc: A, Succ: %1
// CHECK-NEXT: Con [ref] %9 Esc: A, Succ: (%9.1)
// CHECK-NEXT: Con [int] %9.1 Esc: G, Succ: (%9.2)
// CHECK-NEXT: Con %9.2 Esc: G, Succ: (%9.3)
// CHECK-NEXT: Con %9.3 Esc: G, Succ:
// CHECK-LABEL: End
sil private @testPendingMerge : $@convention(thin) (@owned VariableNode) -> (@out ASTNode, @error Error) {
bb0(%0 : $*ASTNode, %1 : $VariableNode):
%9 = alloc_stack $Optional<String>, var, name "documentation"
cond_br undef, bb12, bb14
bb12:
%113 = alloc_stack $AssignmentNode, let, name "assign"
%115 = alloc_stack $ASTNode
retain_value %1 : $VariableNode
%117 = init_existential_addr %115 : $*ASTNode, $VariableNode
store %1 to %117 : $*VariableNode
%122 = load %9 : $*Optional<String>
%123 = function_ref @testPendingMergeHelper : $@convention(method) (@in ASTNode, @owned Optional<String>) -> (@out AssignmentNode, @error Error)
try_apply %123(%113, %115, %122) : $@convention(method) (@in ASTNode, @owned Optional<String>) -> (@out AssignmentNode, @error Error), normal bb13, error bb65
bb13(%125 : $()):
dealloc_stack %115 : $*ASTNode
%128 = init_existential_addr %0 : $*ASTNode, $AssignmentNode
copy_addr %113 to [initialization] %128 : $*AssignmentNode
destroy_addr %113 : $*AssignmentNode
dealloc_stack %113 : $*AssignmentNode
release_value %1 : $VariableNode
dealloc_stack %9 : $*Optional<String>
br bb61
bb14:
destroy_addr %9 : $*Optional<String>
%584 = init_existential_addr %0 : $*ASTNode, $VariableNode
store %1 to %584 : $*VariableNode
dealloc_stack %9 : $*Optional<String>
br bb61
bb61:
%589 = tuple ()
return %589 : $()
bb65(%614 : $Error):
dealloc_stack %115 : $*ASTNode
dealloc_stack %113 : $*AssignmentNode
dealloc_stack %9 : $*Optional<String>
br bb72(undef : $Error)
bb72(%681 : $Error):
throw %681 : $Error
}
//=============================================================================
// Test an "array.uninitialized" with multiple tuple_extract's but no
// other unusual uses. Make sure canOptimizeArrayUninitializedCall
// returns false; otherwise graph verification can fail because only
// one of the tuple_extracts is mapped to a node.
// specialized static Array._adoptStorage(_:count:)
sil [_semantics "array.uninitialized"] @$sSa13_adoptStorage_5countSayxG_SpyxGts016_ContiguousArrayB0CyxGn_SitFZSo5Int64V_Tg5 : $@convention(method) (@owned _ContiguousArrayStorage<Int64>, Int, @thin Array<Int64>.Type) -> (@owned Array<Int64>, UnsafeMutablePointer<Int64>)
// CHECK-LABEL: CG of testArrayUninitResultMapping
// CHECK-NEXT: [ref] %0 Esc: , Succ: (%0.1)
// CHECK-NEXT: Con [int] %0.1 Esc: G, Succ: (%0.2)
// CHECK-NEXT: Con [ref] %0.2 Esc: G, Succ:
// CHECK-NEXT: Val %2 Esc: , Succ: (%2.1)
// CHECK-NEXT: Con %2.1 Esc: G, Succ:
// CHECK-LABEL: End
sil hidden @testArrayUninitResultMapping : $@convention(thin) () -> () {
bb0:
%0 = alloc_ref [tail_elems $Int64 * undef : $Builtin.Word] $_ContiguousArrayStorage<Int64>
// function_ref specialized static Array._adoptStorage(_:count:)
%1 = function_ref @$sSa13_adoptStorage_5countSayxG_SpyxGts016_ContiguousArrayB0CyxGn_SitFZSo5Int64V_Tg5 : $@convention(method) (@owned _ContiguousArrayStorage<Int64>, Int, @thin Array<Int64>.Type) -> (@owned Array<Int64>, UnsafeMutablePointer<Int64>)
%2 = apply %1(%0, undef, undef) : $@convention(method) (@owned _ContiguousArrayStorage<Int64>, Int, @thin Array<Int64>.Type) -> (@owned Array<Int64>, UnsafeMutablePointer<Int64>)
%3 = tuple_extract %2 : $(Array<Int64>, UnsafeMutablePointer<Int64>), 0
%4 = tuple_extract %2 : $(Array<Int64>, UnsafeMutablePointer<Int64>), 1
%5 = tuple_extract %2 : $(Array<Int64>, UnsafeMutablePointer<Int64>), 0
%6 = struct_extract %5 : $Array<Int64>, #Array._buffer
%7 = struct_extract %6 : $_ArrayBuffer<Int64>, #_ArrayBuffer._storage
%8 = struct_extract %7 : $_BridgeStorage<__ContiguousArrayStorageBase>, #_BridgeStorage.rawValue
strong_retain %8 : $Builtin.BridgeObject
%10 = tuple ()
return %10 : $()
}