mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
The InstructionDeleter can remove instructions including their destroys and then insert compensating destroys at a new place. This is effectively destroy-hoisting which doesn't respect deinit-barriers. Therefore it's not done for lexical lifetimes. However, since https://github.com/swiftlang/swift/pull/85334, the optimizer should treat _all_ lifetimes as fixed and not only lexical lifetimes. This change adds a `assumeFixedLifetimes` flag to InstructionDeleter which is on by default. Only mandatory passes (like OSLogOptimization) should turn this off.
3517 lines
170 KiB
Plaintext
3517 lines
170 KiB
Plaintext
// RUN: %target-sil-opt -sil-print-types -address-lowering -enable-sil-opaque-values -emit-sorted-sil -module-name Swift -sil-verify-all %s | %FileCheck %s
|
|
//
|
|
// The module name must be Swift so that declarations like Error are parsed as the correct loadable type.
|
|
|
|
import Builtin
|
|
|
|
sil_stage raw
|
|
|
|
typealias AnyObject = Builtin.AnyObject
|
|
typealias Int = Builtin.Int64
|
|
typealias Bool = Builtin.Int1
|
|
|
|
public protocol C : AnyObject {}
|
|
|
|
sil_default_witness_table C {}
|
|
|
|
protocol P {
|
|
func foo()
|
|
}
|
|
|
|
struct S : P {
|
|
func foo()
|
|
}
|
|
|
|
enum Optional<T> {
|
|
case none
|
|
case some(T)
|
|
}
|
|
|
|
protocol Error {}
|
|
|
|
struct Bad: Error {}
|
|
|
|
struct I {}
|
|
|
|
class Klass {}
|
|
|
|
struct LoadableTrivialExtractable {
|
|
var i: I
|
|
}
|
|
|
|
struct LoadableNontrivial {
|
|
var x: Klass
|
|
}
|
|
|
|
struct LoadableNontrivialGeneric<T> {
|
|
var x: Klass
|
|
}
|
|
|
|
struct SI<T> {
|
|
var element: T
|
|
var index: I
|
|
}
|
|
|
|
struct SRef<T> {
|
|
var object: AnyObject
|
|
var element: T
|
|
}
|
|
|
|
struct Pair<T> {
|
|
var x : T
|
|
var y : T
|
|
}
|
|
|
|
struct Box<T> {
|
|
var t: T
|
|
}
|
|
|
|
struct Box2<T, U> {
|
|
var v1: T
|
|
var v2: U
|
|
}
|
|
|
|
enum Mixed<T> {
|
|
case i(Int)
|
|
case t(T)
|
|
case o(AnyObject)
|
|
}
|
|
|
|
indirect enum RE<T> {
|
|
case recursive(RE, T)
|
|
case other(AnyObject)
|
|
}
|
|
|
|
class TestGeneric<T> {
|
|
init()
|
|
@_borrowed @_hasStorage var borrowedGeneric: T { get set }
|
|
}
|
|
|
|
precedencegroup ComparisonPrecedence {
|
|
assignment: true
|
|
associativity: right
|
|
}
|
|
infix operator <: ComparisonPrecedence
|
|
public protocol Comparable {
|
|
static func < (lhs: Self, rhs: Self) -> Bool
|
|
}
|
|
|
|
|
|
sil [ossa] @unknown : $@convention(thin) () -> ()
|
|
sil [ossa] @getT : $@convention(thin) <T> () -> @out T
|
|
sil [ossa] @getKlass : $@convention(thin) () -> (@owned Klass)
|
|
sil [ossa] @borrowKlass : $(@in_guaranteed Klass) -> ()
|
|
sil [ossa] @borrowT : $@convention(thin) <T> (@in_guaranteed T) -> ()
|
|
sil [ossa] @borrowMoveOnlyT : $@convention(thin) <T> (@in_guaranteed @moveOnly T) -> ()
|
|
sil [ossa] @getPair : $@convention(thin) <T> () -> @out Pair<T>
|
|
sil [ossa] @getOwned : $@convention(thin) <T : AnyObject> () -> (@owned T)
|
|
sil [ossa] @takeGuaranteedObject : $@convention(thin) (@guaranteed AnyObject) -> ()
|
|
sil [ossa] @takeIndirectClass : $@convention(thin) (@in_guaranteed C) -> ()
|
|
sil [ossa] @takeTuple : $@convention(thin) <τ_0_0> (@in_guaranteed (τ_0_0, C)) -> ()
|
|
|
|
sil [ossa] @eraseToAny : $@convention(thin) <T> (@in_guaranteed T) -> @out Any
|
|
sil [ossa] @produceInt : $@convention(thin) () -> Int
|
|
sil [ossa] @produceBool : $@convention(thin) () -> Bool
|
|
sil [ossa] @produceBad : $@convention(thin) () -> Bad
|
|
|
|
sil [ossa] @takeIn : $@convention(thin) <T> (@in T) -> ()
|
|
sil [ossa] @takeInGuaranteed : $@convention(thin) <T> (@in_guaranteed T) -> ()
|
|
|
|
sil [ossa] @throwsError : $@convention(thin) <T> (@in T) -> (@out T, @error Error)
|
|
sil [ossa] @returnInt : $@convention(thin) <T> (@in T) -> (Int, @error Error)
|
|
sil [ossa] @returnIntOut : $@convention(thin) <T> (@in T) -> (@out Int, @error Error)
|
|
sil [ossa] @returnTuple : $@convention(thin) <T> (@in T) -> (@out T, Int, @out Int, @out T, @error Error)
|
|
|
|
// CHECK-LABEL: sil [ossa] @f010_addrlower_identity : $@convention(thin) <T> (@in T) -> @out T {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T):
|
|
// CHECK: copy_addr [take] %1 to [init] %0 : $*T
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f010_addrlower_identity'
|
|
sil [ossa] @f010_addrlower_identity : $@convention(thin) <T> (@in T) -> @out T {
|
|
bb0(%0 : @owned $T):
|
|
return %0 : $T
|
|
}
|
|
|
|
// This could happen as a result of either partial specialization from
|
|
// a single type parameter into a generic tuple, or specialization
|
|
// from a single type parameter into a tuple of concrete address-only
|
|
// types.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @f011_identity_tuple : $@convention(thin) <T> (@in (T, T)) -> @out (T, T) {
|
|
// CHECK: bb0(%0 : $*(T, T), %1 : $*(T, T)):
|
|
// CHECK: copy_addr [take] %1 to [init] %0 : $*(T, T)
|
|
// CHECK-LABEL: } // end sil function 'f011_identity_tuple'
|
|
sil [ossa] @f011_identity_tuple : $@convention(thin) <T> (@in (T, T)) -> @out (T, T) {
|
|
bb0(%0 : @owned $(T, T)):
|
|
return %0 : $(T, T)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f012_decompose_tuple_arg : $@convention(thin) <T> (@in (T, T)) -> @out (T, T) {
|
|
// CHECK: bb0(%0 : $*(T, T), %1 : $*(T, T)):
|
|
// CHECK: [[RET0:%.*]] = tuple_element_addr %0 : $*(T, T), 0
|
|
// CHECK: [[ARG0:%.*]] = tuple_element_addr %1 : $*(T, T), 0
|
|
// CHECK: apply %{{.*}}<T>([[RET0]], [[ARG0]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0
|
|
// CHECK: [[RET1:%.*]] = tuple_element_addr %0 : $*(T, T), 1
|
|
// CHECK: [[ARG1:%.*]] = tuple_element_addr %1 : $*(T, T), 1
|
|
// CHECK: copy_addr [take] [[ARG1]] to [init] [[RET1]] : $*T
|
|
// CHECK-LABEL: } // end sil function 'f012_decompose_tuple_arg'
|
|
sil [ossa] @f012_decompose_tuple_arg : $@convention(thin) <T> (@in (T, T)) -> @out (T, T) {
|
|
bb0(%0 : @owned $(T, T)):
|
|
(%arg0, %arg1) = destructure_tuple %0 : $(T, T)
|
|
%f = function_ref @f010_addrlower_identity : $@convention(thin) <T> (@in T) -> @out T
|
|
%call = apply %f<T>(%arg0) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0
|
|
%result = tuple (%call : $T, %arg1 : $T)
|
|
return %result : $(T, T)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f013_pass_tuple_arg : $@convention(thin) <T> (@in T) -> @out T {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T):
|
|
// CHECK: [[IN:%.*]] = alloc_stack $(T, T)
|
|
// CHECK: [[OUT:%.*]] = alloc_stack $(T, T)
|
|
// CHECK: [[IN1:%.*]] = tuple_element_addr [[IN]] : $*(T, T), 1
|
|
// CHECK: copy_addr %1 to [init] [[IN1]] : $*T
|
|
// CHECK: [[IN0:%.*]] = tuple_element_addr %2 : $*(T, T), 0
|
|
// CHECK: copy_addr [take] %1 to [init] [[IN0]] : $*T
|
|
// CHECK: apply %{{.*}}<T>([[OUT]], [[IN]]) : $@convention(thin) <τ_0_0> (@in (τ_0_0, τ_0_0)) -> @out (τ_0_0, τ_0_0)
|
|
// CHECK: [[DEAD:%.*]] = tuple_element_addr [[OUT]] : $*(T, T), 1
|
|
// CHECK: destroy_addr [[DEAD]] : $*T
|
|
// CHECK: [[RET:%.*]] = tuple_element_addr [[OUT]] : $*(T, T), 0
|
|
// CHECK: copy_addr [take] [[RET]] to [init] %0 : $*T
|
|
// CHECK-LABEL: } // end sil function 'f013_pass_tuple_arg'
|
|
sil [ossa] @f013_pass_tuple_arg : $@convention(thin) <T> (@in T) -> @out T {
|
|
bb0(%0 : @owned $T):
|
|
%copy0 = copy_value %0 : $T
|
|
%arg = tuple (%0 : $T, %copy0 : $T)
|
|
%f = function_ref @f011_identity_tuple : $@convention(thin) <T> (@in (T, T)) -> @out (T, T)
|
|
%call = apply %f<T>(%arg) : $@convention(thin) <T> (@in (T, T)) -> @out (T, T)
|
|
(%call0, %call1) = destructure_tuple %call : $(T, T)
|
|
destroy_value %call1 : $T
|
|
return %call0 : $T
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f020_multiResult : $@convention(thin) <T> (@in T) -> (@out T, @out T, @out T) {
|
|
// CHECK: %0 "$return_value"
|
|
// CHECK: %1 "$return_value"
|
|
// CHECK: %2 "$return_value"
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T, %3 : $*T):
|
|
// CHECK: copy_addr %3 to [init] %1 : $*T
|
|
// CHECK: copy_addr %3 to [init] %2 : $*T
|
|
// CHECK: copy_addr [take] %3 to [init] %0 : $*T
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f020_multiResult'
|
|
sil [ossa] @f020_multiResult : $@convention(thin) <T> (@in T) -> (@out T, @out T, @out T) {
|
|
bb0(%0 : @owned $T):
|
|
%1 = copy_value %0 : $T
|
|
%2 = copy_value %0 : $T
|
|
%6 = tuple (%0 : $T, %1 : $T, %2 : $T)
|
|
return %6 : $(T, T, T)
|
|
}
|
|
|
|
// Test returning an opaque tuple of tuples as a concrete tuple.
|
|
// The multiResult call is specialized, but the SIL result convention does not change.
|
|
// ---
|
|
// CHECK-LABEL: sil [ossa] @f021_callMultiResult : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64, Builtin.Int64, Builtin.Int64) {
|
|
// CHECK: bb0(%0 : $Builtin.Int64):
|
|
// CHECK: %[[FN:.*]] = function_ref @f020_multiResult : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0, @out τ_0_0)
|
|
// CHECK: %[[IN:.*]] = alloc_stack $Builtin.Int64
|
|
// CHECK: store %0 to [trivial] %[[IN]] : $*Builtin.Int64
|
|
// CHECK: %[[OUT1:.*]] = alloc_stack $Builtin.Int64
|
|
// CHECK: %[[OUT2:.*]] = alloc_stack $Builtin.Int64
|
|
// CHECK: %[[OUT3:.*]] = alloc_stack $Builtin.Int64
|
|
// CHECK: %{{.*}} = apply %[[FN]]<Builtin.Int64>(%[[OUT1]], %[[OUT2]], %[[OUT3]], %[[IN]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0, @out τ_0_0)
|
|
// CHECK: %[[R3:.*]] = load [trivial] %[[OUT3]] : $*Builtin.Int64
|
|
// CHECK: dealloc_stack %[[OUT3]] : $*Builtin.Int64
|
|
// CHECK: %[[R2:.*]] = load [trivial] %[[OUT2]] : $*Builtin.Int64
|
|
// CHECK: dealloc_stack %[[OUT2]] : $*Builtin.Int64
|
|
// CHECK: %[[R1:.*]] = load [trivial] %[[OUT1]] : $*Builtin.Int64
|
|
// CHECK: dealloc_stack %[[OUT1]] : $*Builtin.Int64
|
|
// CHECK: dealloc_stack %[[IN]] : $*Builtin.Int64
|
|
// CHECK: %[[R:.*]] = tuple (%[[R1]] : $Builtin.Int64, %[[R2]] : $Builtin.Int64, %[[R3]] : $Builtin.Int64)
|
|
// CHECK: return %[[R]] : $(Builtin.Int64, Builtin.Int64, Builtin.Int64)
|
|
// CHECK-LABEL: } // end sil function 'f021_callMultiResult'
|
|
sil [ossa] @f021_callMultiResult : $@convention(thin) (Int) -> (Int, Int, Int) {
|
|
bb0(%0 : $Int):
|
|
%1 = function_ref @f020_multiResult : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0, @out τ_0_0)
|
|
%2 = apply %1<Int>(%0) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0, @out τ_0_0)
|
|
(%3, %4, %5) = destructure_tuple %2 : $(Int, Int, Int)
|
|
%6 = tuple (%3 : $Int, %4 : $Int, %5 : $Int)
|
|
return %6 : $(Int, Int, Int)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f030_returnPair : $@convention(thin) <T> (@in T) -> (@out T, @out T) {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T):
|
|
// CHECK: copy_addr %2 to [init] %1 : $*T
|
|
// CHECK: copy_addr [take] %2 to [init] %0 : $*T
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f030_returnPair'
|
|
sil [ossa] @f030_returnPair : $@convention(thin) <T> (@in T) -> (@out T, @out T) {
|
|
bb0(%0 : @owned $T):
|
|
%1 = copy_value %0 : $T
|
|
%3 = tuple (%0 : $T, %1 : $T)
|
|
return %3 : $(T, T)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f031_unusedIndirect : $@convention(thin) <T> (@in T) -> @out T {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T):
|
|
// CHECK: %[[LOC0:.*]] = alloc_stack $T
|
|
// CHECK: %[[F:.*]] = function_ref @f030_returnPair : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0)
|
|
// CHECK: %[[R0:.*]] = apply %[[F]]<T>(%[[LOC0]], %0, %1) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0)
|
|
// CHECK: destroy_addr %[[LOC0]] : $*T
|
|
// CHECK: dealloc_stack %[[LOC0]] : $*T
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f031_unusedIndirect'
|
|
sil [ossa] @f031_unusedIndirect : $@convention(thin) <T> (@in T) -> @out T {
|
|
bb0(%0 : @owned $T):
|
|
%2 = function_ref @f030_returnPair : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0)
|
|
%4 = apply %2<T>(%0) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0)
|
|
(%5, %6) = destructure_tuple %4 : $(T, T)
|
|
destroy_value %5 : $T
|
|
return %6 : $T
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f040_consumeArg : $@convention(thin) <T> (@in T) -> () {
|
|
// CHECK: destroy_addr %0 : $*T
|
|
// CHECK-LABEL: } // end sil function 'f040_consumeArg'
|
|
sil [ossa] @f040_consumeArg : $@convention(thin) <T> (@in T) -> () {
|
|
bb0(%0 : @owned $T):
|
|
destroy_value %0 : $T
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f041_opaqueArg : $@convention(thin) <T> (@in T) -> () {
|
|
// CHECK: bb0(%0 : $*T):
|
|
// CHECK: %[[LOC:.*]] = alloc_stack $T
|
|
// CHECK: %[[FN:.*]] = function_ref @f040_consumeArg : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
|
|
// CHECK: copy_addr %0 to [init] %[[LOC]] : $*T
|
|
// CHECK: %{{.*}} = apply %[[FN]]<T>(%[[LOC]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
|
|
// CHECK: destroy_addr %0 : $*T
|
|
// CHECK: %[[R:.*]] = tuple ()
|
|
// CHECK: dealloc_stack %[[LOC]] : $*T
|
|
// CHECK: return %[[R]] : $()
|
|
// CHECK-LABEL: } // end sil function 'f041_opaqueArg'
|
|
sil [ossa] @f041_opaqueArg : $@convention(thin) <T> (@in T) -> () {
|
|
bb0(%0 : @owned $T):
|
|
%2 = function_ref @f040_consumeArg : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
|
|
%3 = copy_value %0 : $T
|
|
%4 = apply %2<T>(%3) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
|
|
destroy_value %0 : $T
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// FIXME: Optimize transfers from indirect function args to indirect call args.
|
|
// Verify that a subsequent pass remove the temp allocation.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @f043_indirectGuaranteedArg : $@convention(thin) (@in any C) -> () {
|
|
// CHECK: bb0(%0 : $*any C):
|
|
// CHECK: [[LD:%.*]] = load [take] %0 : $*any C
|
|
// CHECK: [[TMP:%.*]] = alloc_stack $any C
|
|
// CHECK: [[B:%.*]] = begin_borrow [[LD]] : $any C
|
|
// CHECK: [[SB:%.*]] = store_borrow [[B]] to [[TMP]] : $*any C
|
|
// CHECK: apply %{{.*}}([[SB]]) : $@convention(thin) (@in_guaranteed any C) -> ()
|
|
// CHECK: end_borrow [[SB]] : $*any C
|
|
// CHECK: end_borrow [[B]] : $any C
|
|
// CHECK: dealloc_stack [[TMP]] : $*any C
|
|
// CHECK: destroy_value [[LD]] : $any C
|
|
// CHECK-LABEL: } // end sil function 'f043_indirectGuaranteedArg'
|
|
sil [ossa] @f043_indirectGuaranteedArg : $@convention(thin) (@in C) -> () {
|
|
bb0(%0 : @owned $C):
|
|
%1 = function_ref @takeIndirectClass : $@convention(thin) (@in_guaranteed C) -> ()
|
|
%2 = apply %1(%0) : $@convention(thin) (@in_guaranteed C) -> ()
|
|
destroy_value %0 : $C
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
sil [ossa] @f044_indirectGuaranteed : $@convention(thin) <T>(@in_guaranteed T) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @f045_indirectGuaranteedCallArg : $@convention(thin) <T> (@in T) -> () {
|
|
// CHECK: bb0(%0 : $*T):
|
|
// CHECK: apply %{{.*}}<T>(%0) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
|
|
// CHECK: destroy_addr %0 : $*T
|
|
// CHECK-LABEL: } // end sil function 'f045_indirectGuaranteedCallArg'
|
|
sil [ossa] @f045_indirectGuaranteedCallArg : $@convention(thin) <T>(@in T) -> () {
|
|
bb0(%0 : @owned $T):
|
|
%1 = function_ref @f044_indirectGuaranteed : $@convention(thin) <τ_0_0>(@in_guaranteed τ_0_0) -> ()
|
|
%2 = apply %1<T>(%0) : $@convention(thin) <τ_0_0>(@in_guaranteed τ_0_0) -> ()
|
|
destroy_value %0 : $T
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f046_indirectGuaranteedFunctionArg : $@convention(thin) <T> (@in_guaranteed T) -> () {
|
|
// CHECK: bb0(%0 : $*T):
|
|
// CHECK-NOT: load
|
|
// CHECK: apply %{{.*}}<T>(%0) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
|
|
// CHECK-NOT: end_borrow
|
|
// CHECK-LABEL: } // end sil function 'f046_indirectGuaranteedFunctionArg'
|
|
sil [ossa] @f046_indirectGuaranteedFunctionArg : $@convention(thin) <T>(@in_guaranteed T) -> () {
|
|
bb0(%0 : @guaranteed $T):
|
|
%1 = function_ref @f044_indirectGuaranteed : $@convention(thin) <τ_0_0>(@in_guaranteed τ_0_0) -> ()
|
|
%2 = apply %1<T>(%0) : $@convention(thin) <τ_0_0>(@in_guaranteed τ_0_0) -> ()
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f050_storeinout : $@convention(thin) <T> (@inout T, @inout T, @in T) -> () {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T):
|
|
// CHECK: %[[PREV1:.*]] = alloc_stack $T
|
|
// CHECK: %[[PREV2:.*]] = alloc_stack $T
|
|
// CHECK: debug_value %0 : $*T, var, name "t", argno 1
|
|
// CHECK: debug_value %1 : $*T, var, name "u", argno 2
|
|
// CHECK: debug_value %2 : $*T
|
|
// CHECK: copy_addr [take] %0 to [init] %[[PREV1]] : $*T
|
|
// CHECK: copy_addr %2 to [init] %0 : $*T
|
|
// CHECK: destroy_addr %[[PREV1]] : $*T
|
|
// CHECK: copy_addr %1 to [init] %[[PREV2]] : $*T
|
|
// CHECK: copy_addr %2 to %1 : $*T
|
|
// CHECK: destroy_addr %[[PREV2]] : $*T
|
|
// CHECK: destroy_addr %2 : $*T
|
|
// CHECK: dealloc_stack %[[PREV2]] : $*T
|
|
// CHECK: dealloc_stack %[[PREV1]] : $*T
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f050_storeinout'
|
|
sil [ossa] @f050_storeinout : $@convention(thin) <T> (@inout T, @inout T, @in T) -> () {
|
|
bb0(%0 : $*T, %1 : $*T, %2 : @owned $T):
|
|
debug_value %0 : $*T, var, name "t", argno 1, expr op_deref
|
|
debug_value %1 : $*T, var, name "u", argno 2, expr op_deref
|
|
debug_value %2 : $T, let, name "x", argno 3
|
|
%7 = load [take] %0 : $*T
|
|
%6 = copy_value %2 : $T
|
|
store %6 to [init] %0 : $*T
|
|
destroy_value %7 : $T
|
|
%11 = load [copy] %1 : $*T
|
|
%10 = copy_value %2 : $T
|
|
store %10 to [assign] %1 : $*T
|
|
destroy_value %11 : $T
|
|
destroy_value %2 : $T
|
|
%15 = tuple ()
|
|
return %15 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f060_mutate : $@convention(thin) <T> (@inout T, @in T) -> () {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T):
|
|
// CHECK: [[A0:%.*]] = alloc_stack $T
|
|
// CHECK: copy_addr [take] %0 to [init] [[A0]] : $*T
|
|
// CHECK: copy_addr %1 to [init] %0 : $*T
|
|
// CHECK: destroy_addr [[A0]] : $*T
|
|
// CHECK: destroy_addr %1 : $*T
|
|
// CHECK: dealloc_stack [[A0]] : $*T
|
|
// CHECK-LABEL: } // end sil function 'f060_mutate'
|
|
sil [ossa] @f060_mutate : $@convention(thin) <T> (@inout T, @in T) -> () {
|
|
bb0(%0 : $*T, %1 : @owned $T):
|
|
%4 = copy_value %1 : $T
|
|
%5 = load [take] %0 : $*T
|
|
store %4 to [init] %0 : $*T
|
|
destroy_value %5 : $T
|
|
destroy_value %1 : $T
|
|
%9 = tuple ()
|
|
return %9 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f061_callinout : $@convention(thin) <T> (@in T) -> () {
|
|
// CHECK: bb0(%0 : $*T):
|
|
// CHECK: %[[LOC1:.*]] = alloc_stack $T
|
|
// CHECK: %[[INOUT:.*]] = alloc_stack $T, var, name "u"
|
|
// CHECK: copy_addr %0 to [init] %[[INOUT]] : $*T
|
|
// CHECK: %[[FN:.*]] = function_ref @f060_mutate : $@convention(thin) <τ_0_0> (@inout τ_0_0, @in τ_0_0) -> ()
|
|
// CHECK: copy_addr %0 to [init] %[[LOC1]] : $*T
|
|
// CHECK: %{{.*}} = apply %[[FN]]<T>(%[[INOUT]], %[[LOC1]]) : $@convention(thin) <τ_0_0> (@inout τ_0_0, @in τ_0_0) -> ()
|
|
// CHECK: destroy_addr %[[INOUT]] : $*T
|
|
// CHECK: destroy_addr %0 : $*T
|
|
// CHECK: dealloc_stack %[[INOUT]] : $*T
|
|
// CHECK: dealloc_stack %[[LOC1]] : $*T
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f061_callinout'
|
|
sil [ossa] @f061_callinout : $@convention(thin) <T> (@in T) -> () {
|
|
bb0(%0 : @owned $T):
|
|
%1 = alloc_stack $T, var, name "u"
|
|
%3 = copy_value %0 : $T
|
|
store %3 to [init] %1 : $*T
|
|
%5 = function_ref @f060_mutate : $@convention(thin) <τ_0_0> (@inout τ_0_0, @in τ_0_0) -> ()
|
|
%6 = copy_value %0 : $T
|
|
%7 = apply %5<T>(%1, %6) : $@convention(thin) <τ_0_0> (@inout τ_0_0, @in τ_0_0) -> ()
|
|
destroy_addr %1 : $*T
|
|
destroy_value %0 : $T
|
|
%10 = tuple ()
|
|
dealloc_stack %1 : $*T
|
|
return %10 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f070_mixedResult1 : $@convention(thin) <T> (@in T, @owned any C) -> (@out T, @owned any C) {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : @owned $any C):
|
|
// CHECK: copy_addr [take] %1 to [init] %0 : $*T
|
|
// CHECK: return %2 : $any C
|
|
// CHECK-LABEL: } // end sil function 'f070_mixedResult1'
|
|
sil [ossa] @f070_mixedResult1 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @owned C) {
|
|
bb0(%0 : @owned $T, %1 : @owned $C):
|
|
%4 = tuple (%0 : $T, %1 : $C)
|
|
return %4 : $(T, C)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f071_mixedResult2 : $@convention(thin) <T> (@in T, @owned any C) -> (@out T, @out T, @owned any C, @owned any C) {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T, %3 : @owned $any C):
|
|
// CHECK: copy_addr %2 to [init] %0 : $*T
|
|
// CHECK: [[C:%.*]] = copy_value %3 : $any C
|
|
// CHECK: copy_addr [take] %2 to [init] %1 : $*T
|
|
// CHECK: [[T:%.*]] = tuple ([[C]] : $any C, %3 : $any C)
|
|
// CHECK: return [[T]] : $(any C, any C)
|
|
// CHECK-LABEL: } // end sil function 'f071_mixedResult2'
|
|
sil [ossa] @f071_mixedResult2 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @out T, @owned C, @owned C) {
|
|
bb0(%0 : @owned $T, %1 : @owned $C):
|
|
%4 = copy_value %0 : $T
|
|
%5 = copy_value %1 : $C
|
|
%6 = tuple (%4 : $T, %0 : $T, %5 : $C, %1 : $C)
|
|
return %6 : $(T, T, C, C)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f072_callMixedResult1 : $@convention(thin) <T> (@in T, @owned any C) -> (@out T, @owned any C) {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : @owned $any C):
|
|
// CHECK: [[IN:%.*]] = alloc_stack $T
|
|
// CHECK: // function_ref f070_mixedResult1
|
|
// CHECK: [[F:%.*]] = function_ref @f070_mixedResult1 : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned any C) -> (@out τ_0_0, @owned any C)
|
|
// CHECK: copy_addr %1 to [init] [[IN]] : $*T
|
|
// CHECK: [[C:%.*]] = copy_value %2 : $any C
|
|
// CHECK: [[R:%.*]] = apply [[F]]<T>(%0, [[IN]], [[C]]) : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned any C) -> (@out τ_0_0, @owned any C)
|
|
// CHECK: destroy_value %2 : $any C
|
|
// CHECK: destroy_addr %1 : $*T
|
|
// CHECK: dealloc_stack [[IN]] : $*T
|
|
// CHECK: return [[R]] : $any C
|
|
// CHECK-LABEL: } // end sil function 'f072_callMixedResult1'
|
|
sil [ossa] @f072_callMixedResult1 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @owned C) {
|
|
bb0(%0 : @owned $T, %1 : @owned $C):
|
|
%4 = function_ref @f070_mixedResult1 : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @owned C)
|
|
%5 = copy_value %0 : $T
|
|
%6 = copy_value %1 : $C
|
|
%7 = apply %4<T>(%5, %6) : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @owned C)
|
|
(%8, %9) = destructure_tuple %7 : $(T, C)
|
|
destroy_value %1 : $C
|
|
destroy_value %0 : $T
|
|
%15 = tuple (%8 : $T, %9 : $C)
|
|
return %15 : $(T, C)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f073_callMixedResult2 : $@convention(thin) <T> (@in T, @owned any C) -> (@out T, @out T, @owned any C, @owned any C) {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T, %3 : @owned $any C):
|
|
// CHECK: [[IN:%.*]] = alloc_stack $T
|
|
// CHECK: [[F:%.*]] = function_ref @f071_mixedResult2 : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned any C) -> (@out τ_0_0, @out τ_0_0, @owned any C, @owned any C)
|
|
// CHECK: copy_addr %2 to [init] [[IN]] : $*T
|
|
// CHECK: [[C:%.*]] = copy_value %3 : $any C
|
|
// CHECK: [[T:%.*]] = apply [[F]]<T>(%0, %1, [[IN]], [[C]]) : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned any C) -> (@out τ_0_0, @out τ_0_0, @owned any C, @owned any C)
|
|
// CHECK: ([[OUT0:%.*]], [[OUT1:%.*]]) = destructure_tuple [[T]] : $(any C, any C)
|
|
// CHECK: destroy_value %3 : $any C
|
|
// CHECK: destroy_addr %2 : $*T
|
|
// CHECK: [[R:%.*]] = tuple ([[OUT0]] : $any C, [[OUT1]] : $any C)
|
|
// CHECK: dealloc_stack [[IN]] : $*T
|
|
// CHECK: return [[R]] : $(any C, any C)
|
|
// CHECK-LABEL: } // end sil function 'f073_callMixedResult2'
|
|
sil [ossa] @f073_callMixedResult2 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @out T, @owned C, @owned C) {
|
|
bb0(%0 : @owned $T, %1 : @owned $C):
|
|
%4 = function_ref @f071_mixedResult2 : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @out τ_0_0, @owned C, @owned C)
|
|
%5 = copy_value %0 : $T
|
|
%6 = copy_value %1 : $C
|
|
%7 = apply %4<T>(%5, %6) : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @out τ_0_0, @owned C, @owned C)
|
|
(%8, %9, %10, %11) = destructure_tuple %7 : $(T, T, C, C)
|
|
destroy_value %1 : $C
|
|
destroy_value %0 : $T
|
|
%19 = tuple (%8 : $T, %9 : $T, %10 : $C, %11 : $C)
|
|
return %19 : $(T, T, C, C)
|
|
}
|
|
|
|
sil [ossa] @returnMixedResult3 : $@convention(thin) <T> () -> (@out T, @out C, @owned C)
|
|
|
|
// Example directly from the comments in
|
|
// ApplyRewriter::convertApplyWithIndirectResults()
|
|
//
|
|
// FIXME: verify that a subsequent pass remove the temp allocation.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @f074_callMixedResult3 : $@convention(thin) <T> () -> (@out T, @out any C, @owned any C) {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*any C):
|
|
// CHECK: [[OUT1:%.*]] = alloc_stack $any C
|
|
// CHECK: [[OUT2:%.*]] = apply %{{.*}}<T>(%0, [[OUT1]]) : $@convention(thin) <τ_0_0> () -> (@out τ_0_0, @out any C, @owned any C)
|
|
// CHECK: [[LD:%.*]] = load [take] [[OUT1]] : $*any C
|
|
// CHECK: dealloc_stack [[OUT1]] : $*any C
|
|
// CHECK: store [[LD]] to [init] %1 : $*any C
|
|
// CHECK: return [[OUT2]] : $any C
|
|
// CHECK-LABEL: } // end sil function 'f074_callMixedResult3'
|
|
sil [ossa] @f074_callMixedResult3 : $@convention(thin) <T> () -> (@out T, @out C, @owned C) {
|
|
bb0:
|
|
%0 = function_ref @returnMixedResult3 : $@convention(thin) <T> () -> (@out T, @out C, @owned C)
|
|
%1 = apply %0<T>() : $@convention(thin) <T> () -> (@out T, @out C, @owned C)
|
|
(%2, %3, %4) = destructure_tuple %1 : $(T, C, C)
|
|
%5 = tuple (%2 : $T, %3 : $C, %4 : $C)
|
|
return %5 : $(T, C, C)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f075_reusedResult : $@convention(thin) <T> (@in T, @owned any C) -> (@out T, @owned any C) {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : @owned $any C):
|
|
// CHECK: [[TUPLE:%.*]] = alloc_stack $(T, any C)
|
|
// CHECK: [[E1_1:%.*]] = tuple_element_addr [[TUPLE]] : $*(T, any C), 0
|
|
// CHECK: copy_addr [take] %1 to [init] [[E1_1]] : $*T
|
|
// CHECK: [[E2:%.*]] = tuple_element_addr [[TUPLE]] : $*(T, any C), 1
|
|
// CHECK: store %2 to [init] [[E2]] : $*any C
|
|
// CHECK: apply %{{.*}}<T>([[TUPLE]]) : $@convention(thin) <τ_0_0> (@in_guaranteed (τ_0_0, any C)) -> ()
|
|
// CHECK: [[E2:%.*]] = tuple_element_addr [[TUPLE]] : $*(T, any C), 1
|
|
// CHECK: [[LD:%.*]] = load [take] [[E2]] : $*any C
|
|
// CHECK: [[E1_2:%.*]] = tuple_element_addr [[TUPLE]] : $*(T, any C), 0
|
|
// CHECK: copy_addr [take] [[E1_2]] to [init] %0 : $*T
|
|
// CHECK: dealloc_stack [[TUPLE]] : $*(T, any C)
|
|
// CHECK: return [[LD]] : $any C
|
|
// CHECK-LABEL: } // end sil function 'f075_reusedResult'
|
|
sil [ossa] @f075_reusedResult : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @owned C) {
|
|
bb0(%0 : @owned $T, %1 : @owned $C):
|
|
%2 = tuple (%0 : $T, %1 : $C)
|
|
%f = function_ref @takeTuple : $@convention(thin) <τ_0_0> (@in_guaranteed (τ_0_0, C)) -> ()
|
|
%c = apply %f<T>(%2) : $@convention(thin) <τ_0_0> (@in_guaranteed (τ_0_0, C)) -> ()
|
|
return %2 : $(T, C)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f076_opaqueResult : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[S_ADDR:%[^,]+]] : $*S):
|
|
// CHECK: [[GET:%[^,]+]] = function_ref @getT
|
|
// CHECK: [[TEMP:%[^,]+]] = alloc_stack $S
|
|
// CHECK: apply [[GET]]<S>([[TEMP]])
|
|
// CHECK: [[S:%[^,]+]] = load [trivial] [[TEMP]]
|
|
// CHECK: store [[S]] to [trivial] [[S_ADDR]]
|
|
// CHECK: dealloc_stack [[TEMP]]
|
|
// CHECK-LABEL: } // end sil function 'f076_opaqueResult'
|
|
// The following getS definition enables use of the type <<@_opaqueReturnTypeOf("$s5Swift4getSQryF", 0) opaque>>
|
|
@_silgen_name("getS") public func getS() -> some P { return S() }
|
|
sil [ossa] @f076_opaqueResult : $@convention(thin) <T> () -> @out @_opaqueReturnTypeOf("$s5Swift4getSQryF", 0) __<T> {
|
|
%get = function_ref @getT : $@convention(thin) <T> () -> (@out T)
|
|
%s = apply %get<S>() : $@convention(thin) <T> () -> (@out T)
|
|
return %s : $S
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f080_optional : $@convention(thin) <T> (@in T) -> @out Optional<T> {
|
|
// CHECK: bb0(%0 : $*Optional<T>, %1 : $*T):
|
|
// CHECK: [[DATA:%.*]] = init_enum_data_addr %0 : $*Optional<T>, #Optional.some!enumelt
|
|
// CHECK: copy_addr %1 to [init] [[DATA]] : $*T
|
|
// CHECK: inject_enum_addr %0 : $*Optional<T>, #Optional.some!enumelt
|
|
// CHECK: destroy_addr %1 : $*T
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f080_optional'
|
|
sil [ossa] @f080_optional : $@convention(thin) <T> (@in T) -> @out Optional<T> {
|
|
bb0(%0 : @owned $T):
|
|
%cpy = copy_value %0 : $T
|
|
%opt = enum $Optional<T>, #Optional.some!enumelt, %cpy : $T
|
|
destroy_value %0 : $T
|
|
return %opt : $Optional<T>
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f081_unwrap : $@convention(thin) <T> (@in Optional<T>) -> () {
|
|
// CHECK: bb0(%0 : $*Optional<T>):
|
|
// CHECK: [[A:%.*]] = unchecked_take_enum_data_addr %0 : $*Optional<T>, #Optional.some!enumelt
|
|
// CHECK: apply %{{.*}}<T>([[A]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
|
|
// CHECK-LABEL: } // end sil function 'f081_unwrap'
|
|
sil [ossa] @f081_unwrap : $@convention(thin) <T> (@in Optional<T>) -> () {
|
|
bb0(%0 : @owned $Optional<T>):
|
|
%d = unchecked_enum_data %0 : $Optional<T>, #Optional.some!enumelt
|
|
%f = function_ref @takeIn : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
|
|
%call = apply %f<T>(%d) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f090_tupletuple : $@convention(thin) ((Builtin.Int64, Builtin.Int64), Builtin.Int64) -> (@out (Builtin.Int64, Builtin.Int64), @out (Builtin.Int64, Builtin.Int64), Builtin.Int64, Builtin.Int64) {
|
|
// CHECK: bb0(%0 : $*(Builtin.Int64, Builtin.Int64), %1 : $*(Builtin.Int64, Builtin.Int64), %2 : $(Builtin.Int64, Builtin.Int64), %3 : $Builtin.Int64):
|
|
// CHECK: store %2 to [trivial] %0 : $*(Builtin.Int64, Builtin.Int64)
|
|
// CHECK: store %2 to [trivial] %1 : $*(Builtin.Int64, Builtin.Int64)
|
|
// CHECK: %[[T:.*]] = tuple (%3 : $Builtin.Int64, %3 : $Builtin.Int64)
|
|
// CHECK: return %[[T]] : $(Builtin.Int64, Builtin.Int64)
|
|
// CHECK-LABEL: } // end sil function 'f090_tupletuple'
|
|
sil [ossa] @f090_tupletuple : $@convention(thin) ((Int, Int), Int) -> (@out (Int, Int), @out (Int, Int), Int, Int) {
|
|
bb0(%0 : $(Int, Int), %1 : $Int):
|
|
%2 = tuple (%0 : $(Int, Int), %0 : $(Int, Int), %1 : $Int, %1 : $Int)
|
|
return %2 : $((Int, Int), (Int, Int), Int, Int)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f091_callTuple : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64, Builtin.Int64, Builtin.Int64, Builtin.Int64, Builtin.Int64, Builtin.Int64) {
|
|
// CHECK: bb0(%0 : $Builtin.Int64):
|
|
// CHECK: [[T1:%.*]] = tuple (%0 : $Builtin.Int64, %0 : $Builtin.Int64)
|
|
// CHECK: [[F:%.*]] = function_ref @f090_tupletuple : $@convention(thin) ((Builtin.Int64, Builtin.Int64), Builtin.Int64) -> (@out (Builtin.Int64, Builtin.Int64), @out (Builtin.Int64, Builtin.Int64), Builtin.Int64, Builtin.Int64)
|
|
// CHECK: [[O1:%.*]] = alloc_stack $(Builtin.Int64, Builtin.Int64)
|
|
// CHECK: [[O2:%.*]] = alloc_stack $(Builtin.Int64, Builtin.Int64)
|
|
// CHECK: [[R:%.*]] = apply [[F]]([[O1]], [[O2]], %1, %0) : $@convention(thin) ((Builtin.Int64, Builtin.Int64), Builtin.Int64) -> (@out (Builtin.Int64, Builtin.Int64), @out (Builtin.Int64, Builtin.Int64), Builtin.Int64, Builtin.Int64)
|
|
// CHECK: [[L2:%.*]] = load [trivial] [[O2]] : $*(Builtin.Int64, Builtin.Int64)
|
|
// CHECK: dealloc_stack [[O2]] : $*(Builtin.Int64, Builtin.Int64)
|
|
// CHECK: [[L1:%.*]] = load [trivial] [[O1]] : $*(Builtin.Int64, Builtin.Int64)
|
|
// CHECK: dealloc_stack [[O1]] : $*(Builtin.Int64, Builtin.Int64)
|
|
// CHECK: ([[R4:%.*]], [[R5:%.*]]) = destructure_tuple [[R]] : $(Builtin.Int64, Builtin.Int64)
|
|
// CHECK: ([[R0:%.*]], [[R1:%.*]]) = destructure_tuple [[L1]] : $(Builtin.Int64, Builtin.Int64)
|
|
// CHECK: ([[R2:%.*]], [[R3:%.*]]) = destructure_tuple [[L2]] : $(Builtin.Int64, Builtin.Int64)
|
|
// CHECK: [[RET:%.*]] = tuple ([[R0]] : $Builtin.Int64, [[R1]] : $Builtin.Int64, [[R2]] : $Builtin.Int64, [[R3]] : $Builtin.Int64, [[R4]] : $Builtin.Int64, [[R5]] : $Builtin.Int64)
|
|
// CHECK: return [[RET]] : $(Builtin.Int64, Builtin.Int64, Builtin.Int64, Builtin.Int64, Builtin.Int64, Builtin.Int64)
|
|
// CHECK-LABEL: } // end sil function 'f091_callTuple'
|
|
sil [ossa] @f091_callTuple : $@convention(thin) (Int) -> (Int, Int, Int, Int, Int, Int) {
|
|
bb0(%0: $Int):
|
|
%1 = tuple (%0 : $Int, %0 : $Int)
|
|
%2 = function_ref @f090_tupletuple : $@convention(thin) ((Int, Int), Int) -> (@out (Int, Int), @out (Int, Int), Int, Int)
|
|
%3 = apply %2(%1, %0) : $@convention(thin) ((Int, Int), Int) -> (@out (Int, Int), @out (Int, Int), Int, Int)
|
|
(%4, %5, %6, %7) = destructure_tuple %3 : $((Int, Int), (Int, Int), Int, Int)
|
|
(%8, %9) = destructure_tuple %4 : $(Int, Int)
|
|
(%10, %11) = destructure_tuple %5 : $(Int, Int)
|
|
%12 = tuple (%8 : $Int, %9 : $Int, %10 : $Int, %11 : $Int, %6 : $Int, %7 : $Int)
|
|
return %12 : $(Int, Int, Int, Int, Int, Int)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f100_any : $@convention(thin) (@in Any) -> () {
|
|
// CHECK: bb0(%0 : $*Any):
|
|
// CHECK: destroy_addr %0 : $*Any
|
|
// CHECK: %[[T:.*]] = tuple ()
|
|
// CHECK: return %[[T]] : $()
|
|
// CHECK-LABEL: } // end sil function 'f100_any'
|
|
sil [ossa] @f100_any : $@convention(thin) (@in Any) -> () {
|
|
bb0(%0 : @owned $Any):
|
|
debug_value %0 : $Any, let, name "any", argno 1
|
|
destroy_value %0 : $Any
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f101_passAny : $@convention(thin) <T> (@in T) -> () {
|
|
// CHECK: bb0(%0 : $*T):
|
|
// CHECK: %[[A:.*]] = alloc_stack $Any
|
|
// CHECK: %[[F:.*]] = function_ref @f100_any : $@convention(thin) (@in Any) -> ()
|
|
// CHECK: %[[T2:.*]] = init_existential_addr %[[A]] : $*Any, $T
|
|
// CHECK: copy_addr %0 to [init] %[[T2]] : $*T
|
|
// CHECK: %{{.*}} = apply %[[F]](%[[A]]) : $@convention(thin) (@in Any) -> ()
|
|
// CHECK: destroy_addr %0 : $*T
|
|
// CHECK: dealloc_stack %[[A]] : $*Any
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f101_passAny'
|
|
sil [ossa] @f101_passAny : $@convention(thin) <T> (@in T) -> () {
|
|
bb0(%0 : @owned $T):
|
|
%2 = function_ref @f100_any : $@convention(thin) (@in Any) -> ()
|
|
%3 = copy_value %0 : $T
|
|
%4 = init_existential_value %3 : $T, $T, $Any
|
|
%5 = apply %2(%4) : $@convention(thin) (@in Any) -> ()
|
|
destroy_value %0 : $T
|
|
%7 = tuple ()
|
|
return %7 : $()
|
|
}
|
|
|
|
// Test convertIndirectFunctionArgs and init_existential_value on concrete
|
|
// types.
|
|
// CHECK-LABEL: sil [ossa] @f102_passAnyObjectAsAny : $@convention(thin) (@in AnyObject) -> () {
|
|
// CHECK: bb0(%0 : $*AnyObject):
|
|
// CHECK: [[A:%.*]] = alloc_stack $Any
|
|
// CHECK: [[ARG:%.*]] = load [take] %0 : $*AnyObject
|
|
// CHECK: [[F:%.*]] = function_ref @f100_any : $@convention(thin) (@in Any) -> ()
|
|
// CHECK: [[VAL:%.*]] = init_existential_addr [[A]] : $*Any, $AnyObject
|
|
// CHECK: store [[ARG]] to [init] [[VAL]] : $*AnyObject
|
|
// CHECK: %{{.*}} = apply [[F]]([[A]]) : $@convention(thin) (@in Any) -> ()
|
|
// CHECK: [[R:%.*]] = tuple ()
|
|
// CHECK: dealloc_stack [[A]] : $*Any
|
|
// CHECK: return [[R]] : $()
|
|
// CHECK-LABEL: } // end sil function 'f102_passAnyObjectAsAny'
|
|
sil [ossa] @f102_passAnyObjectAsAny : $@convention(thin) (@in AnyObject) -> () {
|
|
bb0(%0 : @owned $AnyObject):
|
|
%2 = function_ref @f100_any : $@convention(thin) (@in Any) -> ()
|
|
%4 = init_existential_value %0 : $AnyObject, $AnyObject, $Any
|
|
%5 = apply %2(%4) : $@convention(thin) (@in Any) -> ()
|
|
%7 = tuple ()
|
|
return %7 : $()
|
|
}
|
|
|
|
// Helper
|
|
sil [ossa] @f110_singleIndirectFunc : $@convention(thin) <τ_0_0> () -> @out τ_0_0
|
|
|
|
// Test convertApplyWithIndirectResults.
|
|
// CHECK-LABEL: sil [ossa] @f111_singleIndirectApply : $@convention(thin) <τ_0_0> () -> @out τ_0_0 {
|
|
// CHECK: bb0(%0 : $*τ_0_0):
|
|
// CHECK: [[F:%.*]] = function_ref @f110_singleIndirectFunc : $@convention(thin) <τ_0_0> () -> @out τ_0_0
|
|
// CHECK: %{{.*}} = apply [[F]]<τ_0_0>(%0) : $@convention(thin) <τ_0_0> () -> @out τ_0_0
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f111_singleIndirectApply'
|
|
sil [ossa] @f111_singleIndirectApply : $@convention(thin) <τ_0_0> () -> @out τ_0_0 {
|
|
bb0:
|
|
%2 = function_ref @f110_singleIndirectFunc : $@convention(thin) <τ_0_0> () -> @out τ_0_0
|
|
%3 = apply %2<τ_0_0>() : $@convention(thin) <τ_0_0> () -> @out τ_0_0
|
|
return %3 : $τ_0_0
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f120_testDestructure : $@convention(method) <Element> (@in SI<Element>) -> (@out Element, @out I) {
|
|
// CHECK: bb0(%0 : $*Element, %1 : $*I, %2 : $*SI<Element>):
|
|
// CHECK: [[IDX_ADR:%.*]] = struct_element_addr %2 : $*SI<Element>, #SI.index
|
|
// CHECK: [[IDX:%.*]] = load [trivial] [[IDX_ADR]] : $*I
|
|
// CHECK: [[ELT_ADR:%.*]] = struct_element_addr %2 : $*SI<Element>, #SI.element
|
|
// CHECK: copy_addr [take] [[ELT_ADR]] to [init] %0 : $*Element // id: %6
|
|
// CHECK: store [[IDX]] to [trivial] %1 : $*I
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f120_testDestructure'
|
|
sil [ossa] @f120_testDestructure : $@convention(method) <Element> (@in SI<Element>) -> (@out Element, @out I) {
|
|
bb0(%0 : @owned $SI<Element>):
|
|
(%element, %index) = destructure_struct %0 : $SI<Element>
|
|
%tuple = tuple(%element : $Element, %index : $I)
|
|
return %tuple : $(Element, I)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f121_testStructExtract : $@convention(method) (@in SI<AnyObject>) -> (@out AnyObject, @out I) {
|
|
// CHECK: bb0(%0 : $*AnyObject, %1 : $*I, %2 : $*SI<AnyObject>):
|
|
// CHECK: [[IN:%.*]] = load [take] %2 : $*SI<AnyObject>
|
|
// CHECK: [[B:%.*]] = begin_borrow [[IN]] : $SI<AnyObject>
|
|
// CHECK: [[E0:%.*]] = struct_extract [[B]] : $SI<AnyObject>, #SI.element
|
|
// CHECK: [[C:%.*]] = copy_value [[E0]] : $AnyObject
|
|
// CHECK: [[E1:%.*]] = struct_extract [[B]] : $SI<AnyObject>, #SI.index
|
|
// CHECK: end_borrow [[B]] : $SI<AnyObject>
|
|
// CHECK: destroy_value [[IN]] : $SI<AnyObject>
|
|
// CHECK: store [[C]] to [init] %0 : $*AnyObject
|
|
// CHECK: store [[E1]] to [trivial] %1 : $*I
|
|
// CHECK-LABEL: } // end sil function 'f121_testStructExtract'
|
|
sil [ossa] @f121_testStructExtract : $@convention(method) (@in SI<AnyObject>) -> (@out AnyObject, @out I) {
|
|
bb0(%0 : @owned $SI<AnyObject>):
|
|
%borrow = begin_borrow %0 : $SI<AnyObject>
|
|
%object = struct_extract %borrow : $SI<AnyObject>, #SI.element
|
|
%copy = copy_value %object : $AnyObject
|
|
%index = struct_extract %borrow : $SI<AnyObject>, #SI.index
|
|
end_borrow %borrow : $SI<AnyObject>
|
|
destroy_value %0 : $SI<AnyObject>
|
|
%tuple = tuple(%copy : $AnyObject, %index : $I)
|
|
return %tuple : $(AnyObject, I)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f122_testStructExtract : $@convention(method) <T> (@in SRef<T>) -> (@out AnyObject, @out T) {
|
|
// CHECK: bb0(%0 : $*AnyObject, %1 : $*T, %2 : $*SRef<T>):
|
|
// CHECK-NOT: alloc_stack
|
|
// CHECK: [[E0:%.*]] = struct_element_addr %2 : $*SRef<T>, #SRef.object
|
|
// CHECK: [[C:%.*]] = load [copy] [[E0]] : $*AnyObject
|
|
// CHECK: [[E1:%.*]] = struct_element_addr %2 : $*SRef<T>, #SRef.element
|
|
// CHECK: copy_addr [[E1]] to [init] %1 : $*T
|
|
// CHECK: destroy_addr %2 : $*SRef<T>
|
|
// CHECK: store [[C]] to [init] %0 : $*AnyObject
|
|
// CHECK-NOT: dealloc_stack
|
|
// CHECK-LABEL: } // end sil function 'f122_testStructExtract'
|
|
sil [ossa] @f122_testStructExtract : $@convention(method) <T>(@in SRef<T>) -> (@out AnyObject, @out T) {
|
|
bb0(%0 : @owned $SRef<T>):
|
|
%borrow = begin_borrow %0 : $SRef<T>
|
|
%object = struct_extract %borrow : $SRef<T>, #SRef.object
|
|
%copy1 = copy_value %object : $AnyObject
|
|
%element = struct_extract %borrow : $SRef<T>, #SRef.element
|
|
%copy2 = copy_value %element : $T
|
|
end_borrow %borrow : $SRef<T>
|
|
destroy_value %0 : $SRef<T>
|
|
%tuple = tuple(%copy1 : $AnyObject, %copy2 : $T)
|
|
return %tuple : $(AnyObject, T)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f123_testStructExtract : $@convention(method) <T> (@in SRef<T>) -> (@out AnyObject, @out T) {
|
|
// CHECK: bb0(%0 : $*AnyObject, %1 : $*T, %2 : $*SRef<T>):
|
|
// CHECK-NOT: alloc_stack
|
|
// CHECK: [[E0:%.*]] = struct_element_addr %2 : $*SRef<T>, #SRef.object
|
|
// CHECK: [[L:%.*]] = load_borrow [[E0]] : $*AnyObject
|
|
// CHECK: apply %{{.*}}([[L]]) : $@convention(thin) (@guaranteed AnyObject) -> ()
|
|
// CHECK: [[C:%.*]] = copy_value [[L]] : $AnyObject
|
|
// CHECK: [[E1:%.*]] = struct_element_addr %2 : $*SRef<T>, #SRef.element
|
|
// CHECK: copy_addr [[E1]] to [init] %1 : $*T
|
|
// CHECK: end_borrow [[L]] : $AnyObject
|
|
// CHECK: destroy_addr %2 : $*SRef<T>
|
|
// CHECK: store [[C]] to [init] %0 : $*AnyObject
|
|
// CHECK-NOT: dealloc_stack
|
|
// CHECK-LABEL: } // end sil function 'f123_testStructExtract'
|
|
sil [ossa] @f123_testStructExtract : $@convention(method) <T>(@in SRef<T>) -> (@out AnyObject, @out T) {
|
|
bb0(%0 : @owned $SRef<T>):
|
|
%borrow = begin_borrow %0 : $SRef<T>
|
|
%object = struct_extract %borrow : $SRef<T>, #SRef.object
|
|
%f = function_ref @takeGuaranteedObject : $@convention(thin) (@guaranteed AnyObject) -> ()
|
|
%call = apply%f(%object) : $@convention(thin) (@guaranteed AnyObject) -> ()
|
|
%copy1 = copy_value %object : $AnyObject
|
|
%element = struct_extract %borrow : $SRef<T>, #SRef.element
|
|
%copy2 = copy_value %element : $T
|
|
end_borrow %borrow : $SRef<T>
|
|
destroy_value %0 : $SRef<T>
|
|
%tuple = tuple(%copy1 : $AnyObject, %copy2 : $T)
|
|
return %tuple : $(AnyObject, T)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f124_testTupleExtract : $@convention(method) <T> (@in (AnyObject, T)) -> (@out AnyObject, @out T) {
|
|
// CHECK: bb0(%0 : $*AnyObject, %1 : $*T, %2 : $*(AnyObject, T)):
|
|
// CHECK-NOT: alloc_stack
|
|
// CHECK: [[E0:%.*]] = tuple_element_addr %2 : $*(AnyObject, T), 0
|
|
// CHECK: [[C:%.*]] = load [copy] [[E0]] : $*AnyObject
|
|
// CHECK: [[E1:%.*]] = tuple_element_addr %2 : $*(AnyObject, T), 1
|
|
// CHECK: copy_addr [[E1]] to [init] %1 : $*T
|
|
// CHECK: destroy_addr %2 : $*(AnyObject, T)
|
|
// CHECK: store [[C]] to [init] %0 : $*AnyObject
|
|
// CHECK-NOT: dealloc_stack
|
|
sil [ossa] @f124_testTupleExtract : $@convention(method) <T>(@in (AnyObject, T)) -> (@out AnyObject, @out T) {
|
|
bb0(%0 : @owned $(AnyObject, T)):
|
|
%borrow = begin_borrow %0 : $(AnyObject, T)
|
|
%object = tuple_extract %borrow : $(AnyObject, T), 0
|
|
%copy1 = copy_value %object : $AnyObject
|
|
%element = tuple_extract %borrow : $(AnyObject, T), 1
|
|
%copy2 = copy_value %element : $T
|
|
end_borrow %borrow : $(AnyObject, T)
|
|
destroy_value %0 : $(AnyObject, T)
|
|
%tuple = tuple(%copy1 : $AnyObject, %copy2 : $T)
|
|
return %tuple : $(AnyObject, T)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f125_testTupleExtract : $@convention(method) <T> (@in (AnyObject, T)) -> (@out AnyObject, @out T) {
|
|
// CHECK: bb0(%0 : $*AnyObject, %1 : $*T, %2 : $*(AnyObject, T)):
|
|
// CHECK-NOT: alloc_stack
|
|
// CHECK: [[E0:%.*]] = tuple_element_addr %2 : $*(AnyObject, T), 0
|
|
// CHECK: [[L:%.*]] = load_borrow [[E0]] : $*AnyObject
|
|
// CHECK: apply %{{.*}}([[L]]) : $@convention(thin) (@guaranteed AnyObject) -> ()
|
|
// CHECK: [[C:%.*]] = copy_value [[L]] : $AnyObject
|
|
// CHECK: [[E1:%.*]] = tuple_element_addr %2 : $*(AnyObject, T), 1
|
|
// CHECK: copy_addr [[E1]] to [init] %1 : $*T
|
|
// CHECK: end_borrow [[L]] : $AnyObject
|
|
// CHECK: destroy_addr %2 : $*(AnyObject, T)
|
|
// CHECK: store [[C]] to [init] %0 : $*AnyObject
|
|
// CHECK-NOT: dealloc_stack
|
|
// CHECK-LABEL: } // end sil function 'f125_testTupleExtract'
|
|
sil [ossa] @f125_testTupleExtract : $@convention(method) <T>(@in (AnyObject, T)) -> (@out AnyObject, @out T) {
|
|
bb0(%0 : @owned $(AnyObject, T)):
|
|
%borrow = begin_borrow %0 : $(AnyObject, T)
|
|
%object = tuple_extract %borrow : $(AnyObject, T), 0
|
|
%f = function_ref @takeGuaranteedObject : $@convention(thin) (@guaranteed AnyObject) -> ()
|
|
%call = apply%f(%object) : $@convention(thin) (@guaranteed AnyObject) -> ()
|
|
%copy1 = copy_value %object : $AnyObject
|
|
%element = tuple_extract %borrow : $(AnyObject, T), 1
|
|
%copy2 = copy_value %element : $T
|
|
end_borrow %borrow : $(AnyObject, T)
|
|
destroy_value %0 : $(AnyObject, T)
|
|
%tuple = tuple(%copy1 : $AnyObject, %copy2 : $T)
|
|
return %tuple : $(AnyObject, T)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f126_testDestructureAndBorrow : $@convention(method) <Element> (@in (SI<Element>, I)) -> (@out Element, @out I) {
|
|
// CHECK: bb0(%0 : $*Element, %1 : $*I, %2 : $*(SI<Element>, I)):
|
|
// CHECK: [[I:%.*]] = tuple_element_addr %2 : $*(SI<Element>, I), 1
|
|
// CHECK: [[LD:%.*]] = load [trivial] [[I]] : $*I
|
|
// CHECK: [[SI:%.*]] = tuple_element_addr %2 : $*(SI<Element>, I), 0
|
|
// CHECK: [[E:%.*]] = struct_element_addr [[SI]] : $*SI<Element>, #SI.element
|
|
// CHECK: copy_addr [[E]] to [init] %0 : $*Element
|
|
// CHECK: destroy_addr [[SI]] : $*SI<Element>
|
|
// CHECK: store [[LD]] to [trivial] %1 : $*I
|
|
// CHECK-LABEL: } // end sil function 'f126_testDestructureAndBorrow'
|
|
sil [ossa] @f126_testDestructureAndBorrow : $@convention(method) <Element> (@in (SI<Element>, I)) -> (@out Element, @out I) {
|
|
bb0(%0 : @owned $(SI<Element>, I)):
|
|
(%si, %i) = destructure_tuple %0 : $(SI<Element>, I)
|
|
%borrow = begin_borrow %si : $SI<Element>
|
|
%element = struct_extract %borrow : $SI<Element>, #SI.element
|
|
%copy = copy_value %element : $Element
|
|
end_borrow %borrow : $SI<Element>
|
|
destroy_value %si : $SI<Element>
|
|
%tuple = tuple(%copy : $Element, %i : $I)
|
|
return %tuple : $(Element, I)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f130_testReleaseValue : $@convention(thin) <T> (@in T) -> () {
|
|
// CHECK: bb0(%0 : $*T):
|
|
// CHECK: destroy_addr %0 : $*T
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f130_testReleaseValue'
|
|
sil [ossa] @f130_testReleaseValue : $@convention(thin) <T> (@in T) -> () {
|
|
bb0(%0 : @owned $T):
|
|
destroy_value %0 : $T
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f140_testTupleProject : $@convention(thin) <T> (@in T) -> () {
|
|
// CHECK: bb0(%0 : $*T):
|
|
// CHECK: [[LOCAL:%.*]] = alloc_stack $((T, T), T)
|
|
// CHECK: [[ELT0:%.*]] = tuple_element_addr [[LOCAL]] : $*((T, T), T), 0
|
|
// CHECK: [[ELT0_0:%.*]] = tuple_element_addr [[ELT0]] : $*(T, T), 0
|
|
// CHECK: copy_addr %0 to [init] [[ELT0_0]] : $*T
|
|
// CHECK: [[ELT1:%.*]] = tuple_element_addr [[LOCAL]] : $*((T, T), T), 1
|
|
// CHECK: copy_addr %0 to [init] [[ELT1]] : $*T
|
|
// CHECK: [[ELT0_1:%.*]] = tuple_element_addr [[ELT0]] : $*(T, T), 1
|
|
// CHECK: copy_addr [take] %0 to [init] [[ELT0_1]] : $*T
|
|
// CHECK: destroy_addr [[LOCAL]] : $*((T, T), T)
|
|
// CHECK: dealloc_stack [[LOCAL]] : $*((T, T), T)
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f140_testTupleProject'
|
|
sil [ossa] @f140_testTupleProject : $@convention(thin) <T> (@in T) -> () {
|
|
bb0(%0 : @owned $T):
|
|
%copy0 = copy_value %0 : $T
|
|
%copy1 = copy_value %0 : $T
|
|
%tuple1 = tuple (%copy0 : $T, %0 : $T)
|
|
%tuple2 = tuple (%tuple1 : $(T, T), %copy1 : $T)
|
|
destroy_value %tuple2 : $((T, T), T)
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f150_testStructProject : $@convention(thin) <T> (@in T) -> () {
|
|
// CHECK: bb0(%0 : $*T):
|
|
// CHECK: [[ALLOC:%.*]] = alloc_stack $Pair<Pair<T>>
|
|
// CHECK: [[ELT_X:%.*]] = struct_element_addr [[ALLOC]] : $*Pair<Pair<T>>, #Pair.x
|
|
// CHECK: [[ELT_XY:%.*]] = struct_element_addr [[ELT_X]] : $*Pair<T>, #Pair.y
|
|
// CHECK: copy_addr %0 to [init] [[ELT_XY]] : $*T
|
|
// CHECK: [[ELT_XX:%.*]] = struct_element_addr [[ELT_X]] : $*Pair<T>, #Pair.x
|
|
// CHECK: copy_addr [take] %0 to [init] [[ELT_XX]] : $*T
|
|
// CHECK: [[ELT_Y:%.*]] = struct_element_addr [[ALLOC]] : $*Pair<Pair<T>>, #Pair.y
|
|
// CHECK: copy_addr [[ELT_X]] to [init] [[ELT_Y]] : $*Pair<T>
|
|
// CHECK: destroy_addr [[ALLOC]] : $*Pair<Pair<T>>
|
|
// CHECK: dealloc_stack [[ALLOC]] : $*Pair<Pair<T>>
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f150_testStructProject'
|
|
sil [ossa] @f150_testStructProject : $@convention(thin) <T> (@in T) -> () {
|
|
bb0(%0 : @owned $T):
|
|
%copy0 = copy_value %0 : $T
|
|
%struct1 = struct $Pair<T> (%0 : $T, %copy0 : $T)
|
|
%struct_copy = copy_value %struct1 : $Pair<T>
|
|
%struct2 = struct $Pair<Pair<T>> (%struct1 : $Pair<T>, %struct_copy : $Pair<T>)
|
|
destroy_value %struct2 : $Pair<Pair<T>>
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f160_testOpenedArchetype : $@convention(thin) (@in any P) -> () {
|
|
// CHECK: bb0(%0 : $*any P):
|
|
// CHECK: [[ALLOC:%.*]] = alloc_stack $any P, var, name "q"
|
|
// CHECK: copy_addr %0 to [init] [[ALLOC]] : $*any P
|
|
// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access %0 : $*any P to $*[[ARCHETYPE:@opened\(.*, any P\) Self]]
|
|
// CHECK: [[CP:%.*]] = alloc_stack $[[ARCHETYPE]] // type-defs: [[OPEN]];
|
|
// CHECK: [[WT:%.*]] = witness_method $[[ARCHETYPE]], #P.foo : <Self where Self : P> (Self) -> () -> (), [[OPEN]] : $*[[ARCHETYPE]] : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> ()
|
|
// CHECK: copy_addr [[OPEN]] to [init] [[CP]] : $*[[ARCHETYPE]]
|
|
// CHECK: %{{.*}} = apply [[WT]]<[[ARCHETYPE]]>([[CP]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> ()
|
|
// CHECK: destroy_addr [[CP]] : $*[[ARCHETYPE]]
|
|
// CHECK: destroy_addr [[ALLOC]] : $*any P
|
|
// CHECK: destroy_addr %0 : $*any P
|
|
// CHECK: %{{.*}} = tuple ()
|
|
// CHECK: dealloc_stack [[CP]] : $*[[ARCHETYPE]]
|
|
// CHECK: dealloc_stack [[ALLOC]] : $*any P
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f160_testOpenedArchetype'
|
|
sil [ossa] @f160_testOpenedArchetype : $@convention(thin) (@in P) -> () {
|
|
bb0(%0 : @owned $P):
|
|
%2 = alloc_stack $P, var, name "q"
|
|
%3 = copy_value %0 : $P
|
|
store %3 to [init] %2 : $*P
|
|
%b = begin_borrow %0 : $P
|
|
%8 = open_existential_value %b : $P to $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self
|
|
%9 = witness_method $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self, #P.foo, %8 : $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> ()
|
|
// Test that we can handle owned value of type opened archetype.
|
|
%10 = copy_value %8 : $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self
|
|
end_borrow %b : $P
|
|
%11 = apply %9<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self>(%10) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> ()
|
|
destroy_value %10 : $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self
|
|
destroy_addr %2 : $*P
|
|
dealloc_stack %2 : $*P
|
|
destroy_value %0 : $P
|
|
%16 = tuple ()
|
|
return %16 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f161_testOpenedArchetype : $@convention(thin) (@in any P) -> () {
|
|
// CHECK: bb0(%0 : $*any P):
|
|
// CHECK: [[ALLOCP:%.*]] = alloc_stack $any P, var, name "q"
|
|
// CHECK: debug_value %0 : $*any P, var, name "q"
|
|
// CHECK: copy_addr %0 to [init] [[ALLOCP]] : $*any P
|
|
// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access %0 : $*any P to $*@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self
|
|
// CHECK: [[OPTIONAL:%.*]] = alloc_stack $Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self>
|
|
// CHECK: witness_method $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self, #P.foo : <Self where Self : P> (Self) -> () -> (), [[OPEN]] : $*@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> ()
|
|
// CHECK: [[INIT:%.*]] = init_enum_data_addr [[OPTIONAL]] : $*Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self>, #Optional.some!enumelt
|
|
// CHECK: copy_addr [[OPEN]] to [init] [[INIT]] : $*@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self
|
|
// CHECK: inject_enum_addr [[OPTIONAL]] : $*Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self>, #Optional.some!enumelt
|
|
// CHECK: [[DATA:%.*]] = unchecked_take_enum_data_addr [[OPTIONAL]] : $*Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self>, #Optional.some!enumelt
|
|
// CHECK: apply %{{.*}}<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self>([[DATA]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> ()
|
|
// CHECK: destroy_addr [[DATA:%[^,]+]] : $*@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self
|
|
// CHECK: destroy_addr [[ALLOCP]] : $*any P
|
|
// CHECK: destroy_addr %0 : $*any P
|
|
// CHECK: dealloc_stack [[OPTIONAL]] : $*Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self>
|
|
// CHECK: dealloc_stack [[ALLOCP]] : $*any P
|
|
// CHECK-LABEL: } // end sil function 'f161_testOpenedArchetype'
|
|
sil [ossa] @f161_testOpenedArchetype : $@convention(thin) (@in P) -> () {
|
|
bb0(%0 : @owned $P):
|
|
%2 = alloc_stack $P, var, name "q"
|
|
%3 = copy_value %0 : $P
|
|
store %3 to [init] %2 : $*P
|
|
%b = begin_borrow %0 : $P
|
|
%8 = open_existential_value %b : $P to $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self
|
|
%9 = witness_method $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self, #P.foo, %8 : $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> ()
|
|
%cpy = copy_value %8 : $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self
|
|
end_borrow %b : $P
|
|
// This optional is an aggregate that contains an opened existential. Make sure it is allocated after open_existential_addr.
|
|
%opt = enum $Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self>, #Optional.some!enumelt, %cpy : $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self
|
|
%some = unchecked_enum_data %opt : $Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self>, #Optional.some!enumelt
|
|
%11 = apply %9<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self>(%some) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> ()
|
|
destroy_value %some : $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self
|
|
destroy_addr %2 : $*P
|
|
dealloc_stack %2 : $*P
|
|
destroy_value %0 : $P
|
|
%16 = tuple ()
|
|
return %16 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f162_testOpenedArchetype :
|
|
// CHECK: [[STK:%.*]] = alloc_stack $Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self>
|
|
// CHECK: bb6:
|
|
// CHECK: dealloc_stack [[STK]] : $*Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", any P) Self>
|
|
// CHECK: br bb7
|
|
// CHECK-LABEL: } // end sil function 'f162_testOpenedArchetype'
|
|
sil [ossa] @f162_testOpenedArchetype : $@convention(thin) (@in P) -> () {
|
|
bb0(%0 : @owned $P):
|
|
cond_br undef, bb1, bb5
|
|
|
|
bb1:
|
|
%2 = alloc_stack $P, var, name "q"
|
|
%3 = copy_value %0 : $P
|
|
store %3 to [init] %2 : $*P
|
|
%5 = begin_borrow %0 : $P
|
|
%6 = open_existential_value %5 : $P to $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self
|
|
%7 = witness_method $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self, #P.foo : <Self where Self : P> (Self) -> () -> (), %6 : $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> ()
|
|
%8 = copy_value %6 : $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self
|
|
end_borrow %5 : $P
|
|
%10 = enum $Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self>, #Optional.some!enumelt, %8 : $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self
|
|
%11 = unchecked_enum_data %10 : $Optional<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self>, #Optional.some!enumelt
|
|
%12 = apply %7<@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self>(%11) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> ()
|
|
destroy_value %11 : $@opened("EF755EF2-B636-11E7-B7B4-A45E60ECC541", P) Self
|
|
destroy_addr %2 : $*P
|
|
dealloc_stack %2 : $*P
|
|
cond_br undef, bb2, bb3
|
|
|
|
bb2:
|
|
br bb4
|
|
|
|
bb3:
|
|
br bb4
|
|
|
|
bb4:
|
|
br bb6
|
|
|
|
bb5:
|
|
br bb7
|
|
|
|
bb6:
|
|
br bb7
|
|
|
|
bb7:
|
|
destroy_value %0 : $P
|
|
%23 = tuple ()
|
|
return %23 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f163_testOpenedArchetype : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] :
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $Optional<Any>
|
|
// CHECK: [[BORROW:%[^,]+]] = begin_borrow [lexical] [[INSTANCE]]
|
|
// CHECK: [[AN_ERROR:%[^,]+]] = open_existential_box [[BORROW]]
|
|
// CHECK: [[ANY_ADDR:%[^,]+]] = init_enum_data_addr [[ADDR]]
|
|
// CHECK: [[OPENED_ADDR:%[^,]+]] = init_existential_addr [[ANY_ADDR]]
|
|
// CHECK: copy_addr [[AN_ERROR]] to [init] [[OPENED_ADDR]]
|
|
// CHECK: inject_enum_addr [[ADDR]] : $*Optional<Any>, #Optional.some!enumelt
|
|
// CHECK: apply undef<Any>([[ADDR]])
|
|
// CHECK-LABEL: } // end sil function 'f163_testOpenedArchetype'
|
|
sil [ossa] @f163_testOpenedArchetype : $@convention(c) (@owned any Error) -> () {
|
|
block(%instance : @owned $any Error):
|
|
%borrow = begin_borrow [lexical] %instance : $any Error
|
|
%an_error = open_existential_box_value %borrow : $any Error to $@opened("55625EBA-9384-11ED-A0B0-32F16C24A34F", any Error) Self
|
|
%an_owned_error = copy_value %an_error : $@opened("55625EBA-9384-11ED-A0B0-32F16C24A34F", any Error) Self
|
|
%any = init_existential_value %an_owned_error : $@opened("55625EBA-9384-11ED-A0B0-32F16C24A34F", any Error) Self, $@opened("55625EBA-9384-11ED-A0B0-32F16C24A34F", any Error) Self, $Any
|
|
%some_any = enum $Optional<Any>, #Optional.some!enumelt, %any : $Any
|
|
apply undef<Any>(%some_any) : $@convention(thin) <T> (@in Optional<T>) -> ()
|
|
end_borrow %borrow : $any Error
|
|
destroy_value %instance : $any Error
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f164_testOpenedArchetype2 : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[ERROR_EXI:%[^,]+]] :
|
|
// CHECK: [[ERROR_CONCR:%[^,]+]] = open_existential_box [[ERROR_EXI]]
|
|
// CHECK: [[STACK:%[^,]+]] = alloc_stack
|
|
// CHECK: copy_addr [[ERROR_CONCR]] to [init] [[STACK]]
|
|
// CHECK: destroy_addr [[STACK]]
|
|
// CHECK: dealloc_stack [[STACK]]
|
|
// CHECK-LABEL: } // end sil function 'f164_testOpenedArchetype2'
|
|
sil [ossa] @f164_testOpenedArchetype2 : $@convention(thin) (@guaranteed any Error) -> () {
|
|
bb0(%error_exi : @guaranteed $any Error):
|
|
%error_concr = open_existential_box_value %error_exi : $any Error to $@opened("F616C4D8-268F-11EE-998B-32F16C24A34D", any Error) Self
|
|
%stack = alloc_stack $@opened("F616C4D8-268F-11EE-998B-32F16C24A34D", any Error) Self
|
|
%error_copy = copy_value %error_concr : $@opened("F616C4D8-268F-11EE-998B-32F16C24A34D", any Error) Self
|
|
store %error_copy to [init] %stack : $*@opened("F616C4D8-268F-11EE-998B-32F16C24A34D", any Error) Self
|
|
destroy_addr %stack : $*@opened("F616C4D8-268F-11EE-998B-32F16C24A34D", any Error) Self
|
|
dealloc_stack %stack : $*@opened("F616C4D8-268F-11EE-998B-32F16C24A34D", any Error) Self
|
|
%tuple = tuple ()
|
|
return %tuple : $()
|
|
}
|
|
|
|
// Test a chain of projections multiple nodes of which feature an opened
|
|
// archetype AND the archetype-defining instruction for the first projection
|
|
// whose type has an opened archetype dominates all blocks but the
|
|
// archetype-defining instruction for the SECOND projection does not.
|
|
//
|
|
// This test case demonstrates why getDominandsForUseProjection returns
|
|
// multiple values all of which must dominate each incoming value.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @f165_testOpenedArchetypsDominance : {{.*}} {
|
|
// CHECK: alloc_stack $(T, T)
|
|
// CHECK-LABEL: } // end sil function 'f165_testOpenedArchetypsDominance'
|
|
sil [ossa] @f165_testOpenedArchetypsDominance : $@convention(thin) <T> () -> () {
|
|
%borrow = function_ref @takeInGuaranteed : $@convention(thin) <T> (@in_guaranteed T) -> ()
|
|
%take = function_ref @takeIn : $@convention(thin) <T> (@in T) -> ()
|
|
%get = function_ref @getT : $@convention(thin) <T> () -> (@out T)
|
|
%getOwned = function_ref @getOwned : $@convention(thin) <T : AnyObject> () -> (@owned T)
|
|
|
|
|
|
%exi = apply %getOwned<any P & C>() : $@convention(thin) <T : AnyObject> () -> (@owned T)
|
|
%exi2 = apply %getOwned<any P & C>() : $@convention(thin) <T : AnyObject> () -> (@owned T)
|
|
%O_1 = apply %get<T>() : $@convention(thin) <T> () -> (@out T)
|
|
%O_2 = apply %get<T>() : $@convention(thin) <T> () -> (@out T)
|
|
%O = tuple (%O_1 : $T, %O_2 : $T)
|
|
%ope = open_existential_ref %exi : $P & C to $@opened("00000000-0000-0000-0000-000000000000", P & C) Self
|
|
cond_br undef, left, right
|
|
|
|
left:
|
|
%ope2 = open_existential_ref %exi2 : $P & C to $@opened("00000000-0000-0000-0000-000000000001", P & C) Self
|
|
%U = struct $Box2<(T, T), @opened("00000000-0000-0000-0000-000000000000", P & C) Self> (%O : $(T, T), %ope : $@opened("00000000-0000-0000-0000-000000000000", P & C) Self)
|
|
%U2 = struct $Box2<Box2<(T, T), @opened("00000000-0000-0000-0000-000000000000", P & C) Self>, @opened("00000000-0000-0000-0000-000000000001", P & C) Self> (%U : $Box2<(T, T), @opened("00000000-0000-0000-0000-000000000000", P & C) Self> , %ope2 : $@opened("00000000-0000-0000-0000-000000000001", P & C) Self)
|
|
destroy_value %U2 : $Box2<Box2<(T, T), @opened("00000000-0000-0000-0000-000000000000", P & C) Self>, @opened("00000000-0000-0000-0000-000000000001", P & C) Self>
|
|
br exit
|
|
right:
|
|
destroy_value %exi2 : $any P & C
|
|
destroy_value %ope : $@opened("00000000-0000-0000-0000-000000000000", P & C) Self
|
|
destroy_value %O : $(T, T)
|
|
br exit
|
|
exit:
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f170_compare : $@convention(thin) <T where T : Comparable> (@in_guaranteed T, @in_guaranteed T) -> @out T {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T):
|
|
// CHECK: [[WT:%.*]] = witness_method $T, #Comparable."<" : <Self where Self : Comparable> (Self.Type) -> (Self, Self) -> Builtin.Int1 : $@convention(witness_method: Comparable) <τ_0_0 where τ_0_0 : Comparable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Builtin.Int1
|
|
// CHECK: [[MT:%.*]] = metatype $@thick T.Type
|
|
// CHECK: [[COND:%.*]] = apply [[WT]]<T>(%1, %2, [[MT]]) : $@convention(witness_method: Comparable) <τ_0_0 where τ_0_0 : Comparable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Builtin.Int1
|
|
// CHECK: cond_br [[COND]], bb2, bb1
|
|
// CHECK: bb1:
|
|
// CHECK: copy_addr %1 to [init] %0 : $*T
|
|
// CHECK: br bb3
|
|
// CHECK: bb2:
|
|
// CHECK: copy_addr %2 to [init] %0 : $*T
|
|
// CHECK: br bb3
|
|
// CHECK-LABEL: } // end sil function 'f170_compare'
|
|
sil [ossa] @f170_compare : $@convention(thin) <T where T : Comparable> (@in_guaranteed T, @in_guaranteed T) -> @out T {
|
|
bb0(%0 : @guaranteed $T, %1 : @guaranteed $T):
|
|
%2 = witness_method $T, #Comparable."<" : <Self where Self : Comparable> (Self.Type) -> (Self, Self) -> Bool : $@convention(witness_method: Comparable) <τ_0_0 where τ_0_0 : Comparable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool
|
|
%3 = metatype $@thick T.Type
|
|
%4 = apply %2<T>(%0, %1, %3) : $@convention(witness_method: Comparable) <τ_0_0 where τ_0_0 : Comparable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool
|
|
cond_br %4, bb1, bb2
|
|
|
|
bb1:
|
|
%6 = copy_value %1 : $T
|
|
br bb3(%6 : $T)
|
|
|
|
bb2:
|
|
%8 = copy_value %0 : $T
|
|
br bb3(%8 : $T)
|
|
|
|
bb3(%15 : @owned $T):
|
|
return %15 : $T
|
|
}
|
|
|
|
// Verify that trivial arguments are loaded trivially and for which no
|
|
// end_borrows were created.
|
|
// CHECK-LABEL: sil [ossa] @f171_subtract_overflow : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[RETVAL:%[^,]+]] : $*Builtin.Int64, [[LHS_ADDR:%[^,]+]] : $*Builtin.Int64, [[RHS_ADDR:%[^,]+]] :
|
|
// CHECK: [[LHS:%[^,]+]] = load [trivial] [[LHS_ADDR]]
|
|
// CHECK: [[RHS:%[^,]+]] = load [trivial] [[RHS_ADDR]]
|
|
// CHECK: [[SUM_AND:%[^,]+]] = apply {{%[^,]+}}([[LHS]], [[RHS]])
|
|
// CHECK-NOT: end_borrow
|
|
// CHECK: ([[SUM:%[^,]+]], [[OVERFLOWED:%[^,]+]]) = destructure_tuple [[SUM_AND]]
|
|
// CHECK: store [[SUM]] to [trivial] [[RETVAL]]
|
|
// CHECK: return [[OVERFLOWED]]
|
|
// CHECK-LABEL: } // end sil function 'f171_subtract_overflow'
|
|
sil [ossa] @f171_subtract_overflow : $@convention(thin) (@in_guaranteed Int, @in_guaranteed Int) -> (@out Int, Bool) {
|
|
bb0(%0 : $Int, %1 : $Int):
|
|
%2 = function_ref @f171_subtract_overflow_callee : $@convention(method) (Int, Int) -> (Int, Bool)
|
|
%3 = apply %2(%0, %1) : $@convention(method) (Int, Int) -> (Int, Bool)
|
|
(%4, %5) = destructure_tuple %3 : $(Int, Bool)
|
|
%6 = tuple (%4 : $Int, %5 : $Bool)
|
|
return %6 : $(Int, Bool)
|
|
}
|
|
sil [ossa] @f171_subtract_overflow_callee : $@convention(method) (Int, Int) -> (Int, Bool)
|
|
|
|
// Test switching on a single opaque value.
|
|
// CHECK-LABEL: sil [ossa] @f210_testSwitchEnum : $@convention(method) <T> (@in Optional<T>, @inout T) -> () {
|
|
// CHECK: bb0(%0 : $*Optional<T>, %1 : $*T):
|
|
// CHECK: switch_enum_addr %0 : $*Optional<T>, case #Optional.some!enumelt: [[SOMEBB:bb[0-9]+]], case #Optional.none!enumelt: [[NONEBB:bb[0-9]+]]
|
|
// CHECK: [[NONEBB]]:
|
|
// CHECK: br [[RETBB:bb[0-9]+]]
|
|
// CHECK: [[SOMEBB]]:
|
|
// CHECK: [[CAST:%.*]] = unchecked_take_enum_data_addr %0 : $*Optional<T>, #Optional.some!enumelt
|
|
// CHECK: copy_addr [take] [[CAST]] to [init] %1 : $*T
|
|
// CHECK: br [[RETBB]]
|
|
// CHECK: [[RETBB]]:
|
|
// CHECK-LABEL: } // end sil function 'f210_testSwitchEnum'
|
|
sil [ossa] @f210_testSwitchEnum : $@convention(method) <T> (@in Optional<T>, @inout T) -> () {
|
|
bb0(%0 : @owned $Optional<T>, %1 : $*T):
|
|
switch_enum %0 : $Optional<T>, case #Optional.some: bb2, case #Optional.none: bb1
|
|
|
|
bb1:
|
|
br bb3
|
|
|
|
bb2(%some : @owned $T):
|
|
destroy_addr %1 : $*T
|
|
store %some to [init] %1 : $*T
|
|
br bb3
|
|
|
|
bb3:
|
|
%31 = tuple ()
|
|
return %31 : $()
|
|
}
|
|
|
|
// f220_testSwitchMixed
|
|
// CHECK-LABEL: sil [ossa] @f220_testSwitchMixed : $@convention(method) <T> (@in Mixed<T>, @inout Builtin.Int64, @inout T) -> () {
|
|
// CHECK: bb0(%0 : $*Mixed<T>, %1 : $*Builtin.Int64, %2 : $*T):
|
|
// CHECK: switch_enum_addr %0 : $*Mixed<T>, case #Mixed.i!enumelt: [[IBB:bb[0-9]+]], case #Mixed.t!enumelt: [[TBB:bb[0-9]+]], default [[DBB:bb[0-9]+]]
|
|
// CHECK: [[DBB]]:
|
|
// CHECK: [[OBJADDR:%.*]] = unchecked_take_enum_data_addr %0 : $*Mixed<T>, #Mixed.o!enumelt
|
|
// CHECK: [[LD:%.*]] = load [take] [[OBJADDR]] : $*AnyObject
|
|
// CHECK: destroy_value [[LD]] : $AnyObject
|
|
// CHECK: br [[RBB:bb[0-9]+]]
|
|
// CHECK: [[TBB]]:
|
|
// CHECK: [[CAST:%.*]] = unchecked_take_enum_data_addr %0 : $*Mixed<T>, #Mixed.t!enumelt
|
|
// CHECK: destroy_addr %2 : $*T
|
|
// CHECK: copy_addr [take] [[CAST]] to [init] %2 : $*T
|
|
// CHECK: br [[RBB]]
|
|
// CHECK: [[IBB]]:
|
|
// CHECK: [[CAST:%.*]] = unchecked_take_enum_data_addr %0 : $*Mixed<T>, #Mixed.i!enumelt
|
|
// CHECK: [[VAL:%.*]] = load [trivial] [[CAST]] : $*Builtin.Int64
|
|
// CHECK: store [[VAL]] to [trivial] %1 : $*Builtin.Int64
|
|
// CHECK: br [[RBB]]
|
|
// CHECK: [[RBB]]:
|
|
// CHECK-LABEL: } // end sil function 'f220_testSwitchMixed'
|
|
sil [ossa] @f220_testSwitchMixed : $@convention(method) <T> (@in Mixed<T>, @inout Int, @inout T) -> () {
|
|
bb0(%0 : @owned $Mixed<T>, %1 : $*Int, %2 : $*T):
|
|
switch_enum %0 : $Mixed<T>, case #Mixed.i: bb1, case #Mixed.t: bb2, default bb3
|
|
|
|
bb1(%13 : $Int):
|
|
store %13 to [trivial] %1 : $*Int
|
|
br bb4
|
|
|
|
bb2(%14 : @owned $T):
|
|
destroy_addr %2 : $*T
|
|
store %14 to [init] %2 : $*T
|
|
br bb4
|
|
|
|
bb3(%18: @owned $AnyObject):
|
|
destroy_value %18 : $AnyObject
|
|
br bb4
|
|
|
|
bb4:
|
|
%31 = tuple ()
|
|
return %31 : $()
|
|
}
|
|
|
|
// Verify the handling of non-unique default case blocks when there is more
|
|
// than one case handled by default.
|
|
// CHECK-LABEL: sil [ossa] @f221_testSwitchDefault : $@convention(thin) <T> (@in Optional<T>) -> () {
|
|
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : $*Optional<T>):
|
|
// CHECK: switch_enum_addr [[INSTANCE]] : $*Optional<T>, default [[EXIT:bb[0-9]+]]
|
|
// CHECK: [[EXIT]]:
|
|
// CHECK: destroy_addr [[INSTANCE]] : $*Optional<T>
|
|
// CHECK-LABEL: } // end sil function 'f221_testSwitchDefault'
|
|
sil [ossa] @f221_testSwitchDefault : $@convention(thin) <T> (@in Optional<T>) -> () {
|
|
entry(%instance : @owned $Optional<T>):
|
|
switch_enum %instance : $Optional<T>, default exit
|
|
|
|
exit(%instance_2 : @owned $Optional<T>):
|
|
destroy_value %instance_2 : $Optional<T>
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f230_testTryApply : $@convention(thin) <T> (@in T) -> (@out T, @error any Error) {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T):
|
|
// CHECK: [[F:%.*]] = function_ref @throwsError : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error any Error)
|
|
// CHECK: try_apply [[F]]<T>(%0, %1) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error any Error), normal bb2, error bb1
|
|
// CHECK: bb1([[E:%.*]] : $any Error):
|
|
// CHECK: throw [[E]] : $any Error
|
|
// CHECK: bb2([[NONE:%.*]] : $()):
|
|
// CHECK: %{{.*}} = tuple ()
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f230_testTryApply'
|
|
sil [ossa] @f230_testTryApply : $@convention(thin) <T> (@in T) -> (@out T, @error Error) {
|
|
bb0(%0 : @owned $T):
|
|
%3 = function_ref @throwsError : $@convention(thin) <T> (@in T) -> (@out T, @error Error)
|
|
try_apply %3<T>(%0) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%5 : @owned $T):
|
|
return %5 : $T
|
|
|
|
bb2(%7 : $Error):
|
|
throw %7 : $Error
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f240_testTryApplyDirect : $@convention(thin) <T> (@in T) -> (Builtin.Int64, @error any Error) {
|
|
// CHECK: bb0(%0 : $*T):
|
|
// CHECK: [[F:%.*]] = function_ref @returnInt : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (Builtin.Int64, @error any Error)
|
|
// CHECK: try_apply [[F]]<T>(%0) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (Builtin.Int64, @error any Error), normal bb2, error bb1
|
|
// CHECK: bb1([[E:%.*]] : $any Error):
|
|
// CHECK: throw [[E]] : $any Error
|
|
// CHECK: bb2([[V:%.*]] : $Builtin.Int64):
|
|
// CHECK: return [[V]] : $Builtin.Int64
|
|
// CHECK-LABEL: } // end sil function 'f240_testTryApplyDirect'
|
|
sil [ossa] @f240_testTryApplyDirect : $@convention(thin) <T> (@in T) -> (Int, @error Error) {
|
|
bb0(%0 : @owned $T):
|
|
%3 = function_ref @returnInt : $@convention(thin) <T> (@in T) -> (Int, @error Error)
|
|
try_apply %3<T>(%0) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (Int, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%5 : $Int):
|
|
return %5 : $Int
|
|
|
|
bb2(%7 : $Error):
|
|
throw %7 : $Error
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f250_testTryApplyIndirect : $@convention(thin) <T> (@in T) -> (Builtin.Int64, @error any Error) {
|
|
// CHECK: bb0(%0 : $*T):
|
|
// CHECK: [[F:%.*]] = function_ref @returnIntOut : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out Builtin.Int64, @error any Error)
|
|
// CHECK: [[OUT_I:%.*]] = alloc_stack $Builtin.Int64
|
|
// CHECK: try_apply %1<T>([[OUT_I]], %0) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out Builtin.Int64, @error any Error), normal bb2, error bb1
|
|
// CHECK: bb1([[E:%.*]] : $any Error):
|
|
// CHECK: dealloc_stack [[OUT_I]] : $*Builtin.Int64
|
|
// CHECK: throw [[E]] : $any Error
|
|
// CHECK: bb2(%{{.*}} : $()):
|
|
// CHECK: [[V:%.*]] = load [trivial] [[OUT_I]] : $*Builtin.Int64
|
|
// CHECK: dealloc_stack [[OUT_I]] : $*Builtin.Int64
|
|
// CHECK: return [[V]] : $Builtin.Int64
|
|
// CHECK-LABEL: } // end sil function 'f250_testTryApplyIndirect'
|
|
sil [ossa] @f250_testTryApplyIndirect : $@convention(thin) <T> (@in T) -> (Int, @error Error) {
|
|
bb0(%0 : @owned $T):
|
|
%3 = function_ref @returnIntOut : $@convention(thin) <T> (@in T) -> (@out Int, @error Error)
|
|
try_apply %3<T>(%0) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out Int, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%5 : $Int):
|
|
return %5 : $Int
|
|
|
|
bb2(%7 : $Error):
|
|
throw %7 : $Error
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f260_testTryApplyTuple : $@convention(thin) <T> (@in T) -> (@out T, @error any Error) {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T):
|
|
// CHECK: [[OUT_T:%.*]] = alloc_stack $T
|
|
// CHECK: [[F:%.*]] = function_ref @returnTuple : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, Builtin.Int64, @out Builtin.Int64, @out τ_0_0, @error any Error)
|
|
// CHECK: [[OUT_I:%.*]] = alloc_stack $Builtin.Int64
|
|
// CHECK: try_apply [[F]]<T>([[OUT_T]], [[OUT_I]], %0, %1) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, Builtin.Int64, @out Builtin.Int64, @out τ_0_0, @error any Error), normal bb2, error bb1
|
|
// CHECK: bb1([[E:%.*]] : $any Error):
|
|
// CHECK: dealloc_stack [[OUT_I]] : $*Builtin.Int64
|
|
// CHECK: dealloc_stack [[OUT_T]] : $*T
|
|
// CHECK: throw [[E]] : $any Error
|
|
// CHECK: bb2([[RESULT:%.*]] : $Builtin.Int64):
|
|
// CHECK: dealloc_stack [[OUT_I]] : $*Builtin.Int64
|
|
// CHECK: destroy_addr [[OUT_T]] : $*T
|
|
// CHECK: %{{.*}} = tuple ()
|
|
// CHECK: dealloc_stack [[OUT_T]] : $*T
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f260_testTryApplyTuple'
|
|
sil [ossa] @f260_testTryApplyTuple : $@convention(thin) <T> (@in T) -> (@out T, @error Error) {
|
|
bb0(%0 : @owned $T):
|
|
%1 = function_ref @returnTuple : $@convention(thin) <T> (@in T) -> (@out T, Int, @out Int, @out T, @error Error)
|
|
try_apply %1<T>(%0) : $@convention(thin) <T> (@in T) -> (@out T, Int, @out Int, @out T, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%3 : @owned $(T, Int, Int, T)):
|
|
(%4, %5, %6, %7) = destructure_tuple %3 : $(T, Int, Int, T)
|
|
destroy_value %4 : $T
|
|
return %7 : $T
|
|
|
|
bb2(%9 : $Error):
|
|
throw %9 : $Error
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f261_testTryApplyIntoEnum : $@convention(thin) <T> () -> (@out Optional<T>, @error any Error) {
|
|
// CHECK: {{bb[0-9]+}}([[OUT_ADDR:%[^,]+]] : $*Optional<T>):
|
|
// CHECK: [[SOME_ADDR:%[^,]+]] = init_enum_data_addr %0 : $*Optional<T>, #Optional.some!enumelt
|
|
// CHECK: try_apply undef<T>([[SOME_ADDR]]) {{.*}}, normal [[NORMAL:bb[0-9]+]], error {{bb[0-9]+}}
|
|
// CHECK: [[NORMAL]]
|
|
// CHECK: inject_enum_addr [[OUT_ADDR]] : $*Optional<T>, #Optional.some!enumelt
|
|
// CHECK-LABEL: } // end sil function 'f261_testTryApplyIntoEnum'
|
|
sil [ossa] @f261_testTryApplyIntoEnum : $@convention(thin) <T> () -> (@out Optional<T>, @error any Error) {
|
|
entry:
|
|
try_apply undef<T>() : $@convention(thin) <T> () -> (@out T, @error any Error), normal okay, error nopers
|
|
|
|
okay(%instance : @owned $T):
|
|
%some = enum $Optional<T>, #Optional.some!enumelt, %instance : $T
|
|
return %some : $Optional<T>
|
|
|
|
nopers(%error : @owned $any Error):
|
|
throw %error : $any Error
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f262_testTryApplyIntoPhi : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[ADDR:%[^,]+]] :
|
|
// CHECK: try_apply undef<R>([[ADDR]]) {{.*}}, normal [[NORMAL:bb[0-9]+]]
|
|
// CHECK: [[NORMAL]]({{%[^,]+}} : $()):
|
|
// CHECK: br [[EXIT:bb[0-9]+]]
|
|
// CHECK: [[EXIT]]:
|
|
// CHECK: return {{%[^,]+}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f262_testTryApplyIntoPhi'
|
|
sil [ossa] @f262_testTryApplyIntoPhi : $@convention(thin) <R> () -> (@out R, @error any Error) {
|
|
entry:
|
|
try_apply undef<R>() : $@convention(thin) <U> () -> (@out U, @error any Error), normal good, error bad
|
|
|
|
good(%instance : @owned $R):
|
|
br exit(%instance : $R)
|
|
|
|
exit(%instance_2 : @owned $R):
|
|
return %instance_2 : $R
|
|
|
|
bad(%41 : @owned $any Error):
|
|
throw %41 : $any Error
|
|
}
|
|
|
|
// While an '@error Error' turns into an '@error any Error', an '@error' of a concrete type remains as-is.
|
|
// --------
|
|
// CHECK-LABEL: sil [ossa] @f270_typedThrows_throwConcrete : $@convention(thin) (Bad) -> (Bad, @error Bad) {
|
|
// CHECK: bb0(%0 : $Bad):
|
|
// CHECK: return %0 : $Bad
|
|
// CHECK: throw %0 : $Bad
|
|
// CHECK-LABEL: } // end sil function 'f270_typedThrows_throwConcrete'
|
|
sil [ossa] @f270_typedThrows_throwConcrete : $@convention(thin) (Bad) -> (Bad, @error Bad) {
|
|
bb0(%0 : $Bad):
|
|
%fn = function_ref @produceBool : $@convention(thin) () -> Bool
|
|
%cond = apply %fn() : $@convention(thin) () -> Bool
|
|
cond_br %cond, doThrow, doReturn
|
|
|
|
doThrow:
|
|
throw %0
|
|
|
|
doReturn:
|
|
return %0
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f271_typedThrows_callConcrete : $@convention(thin) () -> () {
|
|
// CHECK: try_apply {{.*}} : $@convention(thin) (Bad) -> (Bad, @error Bad), normal bb2, error bb1
|
|
// CHECK: bb1({{.*}} : $Bad)
|
|
// CHECK: bb2({{.*}} : $Bad)
|
|
// CHECK-LABEL: } // end sil function 'f271_typedThrows_callConcrete'
|
|
sil [ossa] @f271_typedThrows_callConcrete : $@convention(thin) () -> () {
|
|
bb0:
|
|
%fn = function_ref @produceBad : $@convention(thin) () -> Bad
|
|
%arg = apply %fn() : $@convention(thin) () -> Bad
|
|
%callee = function_ref @f270_typedThrows_throwConcrete : $@convention(thin) (Bad) -> (Bad, @error Bad)
|
|
try_apply %callee(%arg) : $@convention(thin) (Bad) -> (Bad, @error Bad), normal normalBB, error errorBB
|
|
|
|
normalBB(%r : $Bad):
|
|
ignored_use %r
|
|
br exitBB
|
|
|
|
errorBB(%e : $Bad):
|
|
ignored_use %e
|
|
br exitBB
|
|
|
|
exitBB:
|
|
%t = tuple ()
|
|
return %t
|
|
}
|
|
|
|
// Handle throwing a generic type conforming to Error via @error_indirect
|
|
// --------
|
|
// CHECK-LABEL: sil [ossa] @f272_typedThrows_throwGeneric : $@convention(thin) <GenBad, Result where GenBad : Error> (@in_guaranteed GenBad, @in_guaranteed Result) -> (@out Result, @error_indirect GenBad) {
|
|
// CHECK: bb0(%0 : $*Result, %1 : $*GenBad, %2 : $*GenBad, %3 : $*Result):
|
|
// CHECK: cond_br {{.*}}, bb2, bb1
|
|
//
|
|
// CHECK: bb1:
|
|
// CHECK: copy_addr %3 to [init] %0 : $*Result
|
|
// CHECK: return {{.*}} : $()
|
|
//
|
|
// CHECK: bb2:
|
|
// CHECK: [[STACK:%[^,]+]] = alloc_stack $GenBad
|
|
// CHECK: copy_addr %2 to [init] [[STACK]] : $*GenBad
|
|
// CHECK: copy_addr [take] [[STACK]] to [init] %1 : $*GenBad
|
|
// CHECK: dealloc_stack [[STACK]] : $*GenBad
|
|
// CHECK: throw_addr
|
|
// CHECK-LABEL: } // end sil function 'f272_typedThrows_throwGeneric'
|
|
sil [ossa] @f272_typedThrows_throwGeneric : $@convention(thin) <GenBad, Result where GenBad : Error> (@in_guaranteed GenBad, @in_guaranteed Result) -> (@out Result, @error_indirect GenBad) {
|
|
bb0(%e : @guaranteed $GenBad, %r : @guaranteed $Result):
|
|
%fn = function_ref @produceBool : $@convention(thin) () -> Bool
|
|
%cond = apply %fn() : $@convention(thin) () -> Bool
|
|
cond_br %cond, doThrow, doReturn
|
|
|
|
doReturn:
|
|
%rCopy = copy_value %r
|
|
return %rCopy
|
|
|
|
doThrow:
|
|
%eCopy = copy_value %e
|
|
throw %eCopy
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @f273_typedThrows_callGeneric : $@convention(thin) () -> () {
|
|
// CHECK: bb0:
|
|
// CHECK: // function_ref produceBad
|
|
// CHECK: [[PROD:%[^,]+]] = function_ref @produceBad : $@convention(thin) () -> Bad
|
|
// CHECK: [[ARG1:%[^,]+]] = apply [[PROD]]() : $@convention(thin) () -> Bad
|
|
// CHECK: [[ARG2:%[^,]+]] = apply [[PROD]]() : $@convention(thin) () -> Bad
|
|
// CHECK: [[ARG1_IN:%[^,]+]] = alloc_stack $Bad
|
|
// CHECK: store [[ARG1]] to [trivial] [[ARG1_IN]] : $*Bad
|
|
// CHECK: [[ARG2_IN:%[^,]+]] = alloc_stack $Bad
|
|
// CHECK: store [[ARG2]] to [trivial] [[ARG2_IN]] : $*Bad
|
|
// CHECK: [[RESULT_OUT:%[^,]+]] = alloc_stack $Bad
|
|
// CHECK: [[ERR_OUT:%[^,]+]] = alloc_stack $Bad
|
|
// CHECK: try_apply {{.*}}<Bad, Bad>([[RESULT_OUT]], [[ERR_OUT]], [[ARG1_IN]], [[ARG2_IN]]) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Error> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (@out τ_0_1, @error_indirect τ_0_0), normal bb2, error bb1
|
|
|
|
// CHECK: bb1:
|
|
// CHECK: [[ERR:%[^,]+]] = load [trivial] [[ERR_OUT]] : $*Bad
|
|
// CHECK: dealloc_stack [[ERR_OUT]] : $*Bad
|
|
// CHECK: dealloc_stack [[RESULT_OUT]] : $*Bad
|
|
// CHECK: dealloc_stack [[ARG2_IN]] : $*Bad
|
|
// CHECK: dealloc_stack [[ARG1_IN]] : $*Bad
|
|
// CHECK: ignored_use [[ERR]] : $Bad
|
|
// CHECK: ignored_use [[ERR]] : $Bad
|
|
// CHECK: br bb3
|
|
|
|
// CHECK: bb2(%11 : $()):
|
|
// CHECK: dealloc_stack [[ERR_OUT]] : $*Bad
|
|
// CHECK: [[RESULT:%[^,]+]] = load [trivial] [[RESULT_OUT]] : $*Bad
|
|
// CHECK: dealloc_stack [[RESULT_OUT]] : $*Bad
|
|
// CHECK: dealloc_stack [[ARG2_IN]] : $*Bad
|
|
// CHECK: dealloc_stack [[ARG1_IN]] : $*Bad
|
|
// CHECK: ignored_use [[RESULT]] : $Bad
|
|
// CHECK: br bb3
|
|
|
|
// CHECK: bb3:
|
|
// CHECK: return {{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'f273_typedThrows_callGeneric'
|
|
sil [ossa] @f273_typedThrows_callGeneric : $@convention(thin) () -> () {
|
|
bb0:
|
|
%fn = function_ref @produceBad : $@convention(thin) () -> Bad
|
|
%arg1 = apply %fn() : $@convention(thin) () -> Bad
|
|
%arg2 = apply %fn() : $@convention(thin) () -> Bad
|
|
%callee = function_ref @f272_typedThrows_throwGeneric : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Error> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (@out τ_0_1, @error_indirect τ_0_0)
|
|
try_apply %callee<Bad, Bad>(%arg1, %arg2) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Error> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (@out τ_0_1, @error_indirect τ_0_0), normal normalBB, error errorBB
|
|
|
|
normalBB(%r : $Bad):
|
|
ignored_use %r
|
|
br exitBB
|
|
|
|
errorBB(%e : $Bad):
|
|
ignored_use %e
|
|
ignored_use %e
|
|
br exitBB
|
|
|
|
exitBB:
|
|
%t = tuple ()
|
|
return %t
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: sil [ossa] @fixeeLifetime : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[ADDR:%[^,]+]] : $*T):
|
|
// CHECK: fix_lifetime [[ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'fixeeLifetime'
|
|
sil [ossa] @fixeeLifetime : $@convention(thin) <T> (@in T) -> () {
|
|
bb0(%instance : @owned $T):
|
|
fix_lifetime %instance : $T
|
|
destroy_value %instance : $T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @lexical_borrow_struct_extract {{.*}} {
|
|
// CHECK: [[PAIR_ADDR:%[^,]+]] = alloc_stack [lexical]
|
|
// CHECK: [[X_ADDR:%[^,]+]] = struct_element_addr [[PAIR_ADDR]]
|
|
// CHECK: apply {{%[^,]+}}<T>([[X_ADDR]])
|
|
// CHECK: destroy_addr [[PAIR_ADDR]]
|
|
// CHECK: dealloc_stack [[PAIR_ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'lexical_borrow_struct_extract'
|
|
sil [ossa] @lexical_borrow_struct_extract : $@convention(thin) <T> () -> () {
|
|
%getPair = function_ref @getPair : $@convention(thin) <Tee> () -> @out Pair<Tee>
|
|
%instance = apply %getPair<T>() : $@convention(thin) <Tee> () -> @out Pair<Tee>
|
|
%scope = begin_borrow %instance : $Pair<T>
|
|
%x = struct_extract %scope : $Pair<T>, #Pair.x
|
|
%lifetime = begin_borrow [lexical] %x : $T
|
|
%takeInGuaranteed = function_ref @takeInGuaranteed : $@convention(thin) <Tee> (@in_guaranteed Tee) -> ()
|
|
apply %takeInGuaranteed<T>(%lifetime) : $@convention(thin) <Tee> (@in_guaranteed Tee) -> ()
|
|
%unknown = function_ref @unknown : $@convention(thin) () -> ()
|
|
apply %unknown() : $@convention(thin) () -> ()
|
|
end_borrow %lifetime : $T
|
|
end_borrow %scope : $Pair<T>
|
|
destroy_value %instance : $Pair<T>
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @lexical_borrow_struct_extract_arg {{.*}} {
|
|
// CHECK: [[X_ADDR:%[^,]+]] = struct_element_addr [[PAIR_ADDR:%[^,]+]]
|
|
// CHECK: apply {{%[^,]+}}<T>([[X_ADDR]])
|
|
// CHECK: destroy_addr [[PAIR_ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'lexical_borrow_struct_extract_arg'
|
|
sil [ossa] @lexical_borrow_struct_extract_arg : $@convention(thin) <T> (@in Pair<T>) -> () {
|
|
entry(%instance : @owned $Pair<T>):
|
|
%scope = begin_borrow %instance : $Pair<T>
|
|
%x = struct_extract %scope : $Pair<T>, #Pair.x
|
|
%lifetime = begin_borrow [lexical] %x : $T
|
|
%takeInGuaranteed = function_ref @takeInGuaranteed : $@convention(thin) <Tee> (@in_guaranteed Tee) -> ()
|
|
apply %takeInGuaranteed<T>(%lifetime) : $@convention(thin) <Tee> (@in_guaranteed Tee) -> ()
|
|
%unknown = function_ref @unknown : $@convention(thin) () -> ()
|
|
apply %unknown() : $@convention(thin) () -> ()
|
|
end_borrow %lifetime : $T
|
|
end_borrow %scope : $Pair<T>
|
|
destroy_value %instance : $Pair<T>
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
/// Verify that alloc_stacks for which there is already a dealloc stack can be
|
|
/// deleted.
|
|
// CHECK-LABEL: sil [ossa] @partition : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[INDEX_OUT:%[^,]+]] : $*Self.Index, [[SELF:%[^,]+]] : $*Self):
|
|
// CHECK: [[MAYBE_INDEX_ADDR:%[^,]+]] = alloc_stack $Optional<Builtin.Int64>
|
|
// CHECK: try_apply {{%[^,]+}}<Self, Builtin.Int64>([[MAYBE_INDEX_ADDR]], [[SELF]]) : $@convention(thin) <τ_0_0 where τ_0_0 : MyCollection><τ_1_0> (@inout τ_0_0) -> (@out Optional<τ_1_0>, @error any Error), normal [[YES_BLOCK:bb[0-9]+]], error [[NO_BLOCK:bb[0-9]+]]
|
|
// CHECK: [[NO_BLOCK]]([[ERROR:%[^,]+]] : @owned $any Error):
|
|
// CHECK: dealloc_stack [[MAYBE_INDEX_ADDR]]
|
|
// CHECK: br [[EXIT_ERROR:bb[0-9]+]]([[ERROR]] : $any Error)
|
|
// CHECK: [[EXIT_ERROR]]([[ERROR_TO_THROW:%[^,]+]] : @owned $any Error):
|
|
// CHECK: throw [[ERROR_TO_THROW]]
|
|
// CHECK: [[YES_BLOCK]]
|
|
// CHECK: [[MAYBE_INDEX:%[^,]+]] = load [trivial] [[MAYBE_INDEX_ADDR]]
|
|
// CHECK: dealloc_stack [[MAYBE_INDEX_ADDR]]
|
|
// CHECK: switch_enum [[MAYBE_INDEX]] : $Optional<Builtin.Int64>, case #Optional.some!enumelt: [[SOME_BLOCK:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BLOCK:bb[0-9]+]]
|
|
// CHECK: [[NONE_BLOCK]]:
|
|
// CHECK: apply {{%[^,]+}}<Self>([[INDEX_OUT]], [[SELF]])
|
|
// CHECK: [[SOME_BLOCK]]([[SOME_INDEX:%[^,]+]] : $Builtin.Int64):
|
|
// CHECK: apply {{%[^,]+}}<Self>([[INDEX_OUT]], [[SOME_INDEX]])
|
|
// CHECK-LABEL: } // end sil function 'partition'
|
|
protocol MyCollection {
|
|
associatedtype Index
|
|
}
|
|
sil [ossa] @impl : $@convention(method) <τ_0_0 where τ_0_0 : MyCollection> (@inout τ_0_0) -> @out τ_0_0.Index
|
|
sil [ossa] @one : $@convention(thin) <τ_0_0 where τ_0_0 : MyCollection><τ_1_0> (@inout τ_0_0) -> (@out Optional<τ_1_0>, @error any Error)
|
|
sil [ossa] @startIndex : $@convention(thin) <τ_0_0 where τ_0_0 : MyCollection> (@in_guaranteed τ_0_0) -> @out τ_0_0.Index
|
|
sil [ossa] @index : $@convention(thin) <τ_0_0 where τ_0_0 : MyCollection> (Int) -> @out τ_0_0.Index
|
|
sil [ossa] @partition : $@convention(method) <Self where Self : MyCollection> (@inout Self) -> (@out Self.Index, @error any Error) {
|
|
bb0(%1 : $*Self):
|
|
%11 = function_ref @one : $@convention(thin) <τ_0_0 where τ_0_0 : MyCollection><τ_1_0> (@inout τ_0_0) -> (@out Optional<τ_1_0>, @error any Error)
|
|
try_apply %11<Self, Int>(%1) : $@convention(thin) <τ_0_0 where τ_0_0 : MyCollection><τ_1_0> (@inout τ_0_0) -> (@out Optional<τ_1_0>, @error any Error), normal bb1, error bb6
|
|
|
|
bb1(%13 : $Optional<Int>):
|
|
switch_enum %13 : $Optional<Int>, case #Optional.some!enumelt: bb2, case #Optional.none!enumelt: bb3
|
|
|
|
bb2(%17 : $Int):
|
|
%28 = function_ref @index : $@convention(thin) <τ_0_0 where τ_0_0 : MyCollection> (Int) -> @out τ_0_0.Index
|
|
%29 = apply %28<Self>(%17) : $@convention(thin) <τ_0_0 where τ_0_0 : MyCollection> (Int) -> @out τ_0_0.Index
|
|
br exit_normal(%29 : $Self.Index)
|
|
|
|
bb3:
|
|
%34 = function_ref @impl : $@convention(method) <τ_0_0 where τ_0_0 : MyCollection> (@inout τ_0_0) -> @out τ_0_0.Index
|
|
%36 = apply %34<Self>(%1) : $@convention(method) <τ_0_0 where τ_0_0 : MyCollection> (@inout τ_0_0) -> @out τ_0_0.Index
|
|
br exit_normal(%36 : $Self.Index)
|
|
|
|
bb6(%41 : @owned $any Error):
|
|
br exit_error(%41 : $any Error)
|
|
|
|
exit_normal(%39 : @owned $Self.Index):
|
|
return %39 : $Self.Index
|
|
|
|
exit_error(%47 : @owned $any Error):
|
|
throw %47 : $any Error
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @selecteroo : $@convention(thin) <T> () -> () {
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $Optional<T>
|
|
// CHECK: apply undef<T>([[ADDR]]) : $@convention(thin) <τ_0_0> () -> @out Optional<τ_0_0>
|
|
// CHECK: select_enum_addr [[ADDR]] : $*Optional<T>, case #Optional.some!enumelt: {{%[^,]+}}, default {{%[^,]+}} : $Builtin.Int1
|
|
// CHECK: dealloc_stack [[ADDR]] : $*Optional<T>
|
|
// CHECK-LABEL: } // end sil function 'selecteroo'
|
|
sil [ossa] @selecteroo : $@convention(thin) <T> () -> () {
|
|
bb0:
|
|
%11 = apply undef<T>() : $@convention(thin) <τ_0_0> () -> @out Optional<τ_0_0>
|
|
%12 = integer_literal $Builtin.Int1, -1
|
|
%13 = integer_literal $Builtin.Int1, 0
|
|
%14 = select_enum %11 : $Optional<T>, case #Optional.some!enumelt: %12, default %13 : $Builtin.Int1
|
|
destroy_value %11 : $Optional<T>
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
} // end sil function '$ss17FixedWidthIntegerPsEyxSgSScfC'
|
|
|
|
sil hidden [ossa] @testBeginApply1DeadYield : $@convention(thin) <T> (@guaranteed TestGeneric<T>) -> () {
|
|
bb0(%0 : @guaranteed $TestGeneric<T>):
|
|
%2 = class_method %0 : $TestGeneric<T>, #TestGeneric.borrowedGeneric!read : <T> (TestGeneric<T>) -> () -> (), $@yield_once @convention(method) <τ_0_0> (@guaranteed TestGeneric<τ_0_0>) -> @yields @in_guaranteed τ_0_0
|
|
(%3, %4) = begin_apply %2<T>(%0) : $@yield_once @convention(method) <τ_0_0> (@guaranteed TestGeneric<τ_0_0>) -> @yields @in_guaranteed τ_0_0
|
|
end_apply %4 as $()
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @testBeginApply2LoadableYieldWithIndirectConv :
|
|
// CHECK: bb0(%0 : @guaranteed $TestGeneric<Klass>):
|
|
// CHECK: [[STK:%.*]] = alloc_stack $Klass
|
|
// CHECK: [[METH:%.*]] = class_method %0 : $TestGeneric<Klass>, #TestGeneric.borrowedGeneric!read : <T> (TestGeneric<T>) -> () -> (), $@yield_once @convention(method) <τ_0_0> (@guaranteed TestGeneric<τ_0_0>) -> @yields @in_guaranteed τ_0_0
|
|
// CHECK: ([[Y:%.*]], [[TOK:%.*]]) = begin_apply [[METH]]<Klass>(%0) : $@yield_once @convention(method) <τ_0_0> (@guaranteed TestGeneric<τ_0_0>) -> @yields @in_guaranteed τ_0_0
|
|
// CHECK: copy_addr [[Y]] to [init] [[STK]] : $*Klass
|
|
// CHECK: end_apply [[TOK]] as $()
|
|
// CHECK: destroy_addr [[STK]] : $*Klass
|
|
// CHECK-LABEL: }
|
|
sil hidden [ossa] @testBeginApply2LoadableYieldWithIndirectConv : $@convention(thin) <Klass> (@guaranteed TestGeneric<Klass>) -> () {
|
|
bb0(%0 : @guaranteed $TestGeneric<Klass>):
|
|
%2 = class_method %0 : $TestGeneric<Klass>, #TestGeneric.borrowedGeneric!read : <Klass> (TestGeneric<Klass>) -> () -> (), $@yield_once @convention(method) <τ_0_0> (@guaranteed TestGeneric<τ_0_0>) -> @yields @in_guaranteed τ_0_0
|
|
(%3, %4) = begin_apply %2<Klass>(%0) : $@yield_once @convention(method) <τ_0_0> (@guaranteed TestGeneric<τ_0_0>) -> @yields @in_guaranteed τ_0_0
|
|
%5 = copy_value %3 : $Klass
|
|
end_apply %4 as $()
|
|
destroy_value %5 : $Klass
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @testBeginApply3OpaqueYield :
|
|
// CHECK: bb0(%0 : @guaranteed $TestGeneric<T>):
|
|
// CHECK: [[STK:%.*]] = alloc_stack $T
|
|
// CHECK: [[M:%.*]] = class_method %0 : $TestGeneric<T>, #TestGeneric.borrowedGeneric!read : <T> (TestGeneric<T>) -> () -> (), $@yield_once @convention(method) <τ_0_0> (@guaranteed TestGeneric<τ_0_0>) -> @yields @in_guaranteed τ_0_0
|
|
// CHECK: ([[Y:%.*]], [[TOK:%.*]]) = begin_apply %2<T>(%0) : $@yield_once @convention(method) <τ_0_0> (@guaranteed TestGeneric<τ_0_0>) -> @yields @in_guaranteed τ_0_0
|
|
// CHECK: copy_addr [[Y]] to [init] [[STK]] : $*T
|
|
// CHECK: end_apply [[TOK]] as $()
|
|
// CHECK: destroy_addr [[STK]] : $*T
|
|
// CHECK-LABEL: } // end sil function 'testBeginApply3OpaqueYield'
|
|
sil hidden [ossa] @testBeginApply3OpaqueYield : $@convention(thin) <T> (@guaranteed TestGeneric<T>) -> () {
|
|
bb0(%0 : @guaranteed $TestGeneric<T>):
|
|
%2 = class_method %0 : $TestGeneric<T>, #TestGeneric.borrowedGeneric!read : <T> (TestGeneric<T>) -> () -> (), $@yield_once @convention(method) <τ_0_0> (@guaranteed TestGeneric<τ_0_0>) -> @yields @in_guaranteed τ_0_0
|
|
(%3, %4) = begin_apply %2<T>(%0) : $@yield_once @convention(method) <τ_0_0> (@guaranteed TestGeneric<τ_0_0>) -> @yields @in_guaranteed τ_0_0
|
|
%5 = copy_value %3 : $T
|
|
end_apply %4 as $()
|
|
destroy_value %5 : $T
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testBeginApply4YieldLoadableTrivial : {{.*}} {
|
|
// CHECK: ([[ADDR:%[^,]+]], {{%[^,]+}}) = begin_apply
|
|
// CHECK: [[INSTANCE:%[^,]+]] = load [trivial] [[ADDR]]
|
|
// CHECK: struct_extract [[INSTANCE]]
|
|
// CHECK-LABEL: } // end sil function 'testBeginApply4YieldLoadableTrivial'
|
|
sil [ossa] @testBeginApply4YieldLoadableTrivial : $@convention(thin) () -> I {
|
|
entry:
|
|
(%instance, %token) = begin_apply undef<LoadableTrivialExtractable>() : $@yield_once @convention(thin) <U> () -> @yields @in_guaranteed U
|
|
%extract = struct_extract %instance : $LoadableTrivialExtractable, #LoadableTrivialExtractable.i
|
|
end_apply %token as $()
|
|
return %extract : $I
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testBeginApply5Yield2LoadableTrivial : {{.*}} {
|
|
// CHECK: ([[ADDR_1:%[^,]+]], [[ADDR_2:%[^,]+]], {{%[^,]+}}) = begin_apply
|
|
// CHECK: [[INSTANCE_1:%[^,]+]] = load [trivial] [[ADDR_1]]
|
|
// CHECK: [[INSTANCE_2:%[^,]+]] = load [trivial] [[ADDR_2]]
|
|
// CHECK: struct_extract [[INSTANCE_1]]
|
|
// CHECK: struct_extract [[INSTANCE_2]]
|
|
// CHECK-LABEL: } // end sil function 'testBeginApply5Yield2LoadableTrivial'
|
|
sil [ossa] @testBeginApply5Yield2LoadableTrivial : $@convention(thin) () -> (I, I) {
|
|
entry:
|
|
(%instance_1, %instance_2, %token) = begin_apply undef<LoadableTrivialExtractable>() : $@yield_once @convention(thin) <U> () -> (@yields @in_guaranteed U, @yields @in_guaranteed U)
|
|
%i_1 = struct_extract %instance_1 : $LoadableTrivialExtractable, #LoadableTrivialExtractable.i
|
|
%i_2 = struct_extract %instance_2 : $LoadableTrivialExtractable, #LoadableTrivialExtractable.i
|
|
end_apply %token as $()
|
|
%tuple = tuple (%i_1 : $I, %i_2 : $I)
|
|
return %tuple : $(I, I)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testBeginApply6Yield1LoadableTrivial1OpaqueGuaranteed : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[TRIV_OUT:%[^,]+]] : $*I, [[OPAQUE_OUT:%[^,]+]] : $*T):
|
|
// CHECK: ([[ADDR_1:%[^,]+]], [[ADDR_2:%[^,]+]], {{%[^,]+}}) = begin_apply
|
|
// CHECK: [[INSTANCE_1:%[^,]+]] = load [trivial] [[ADDR_1]]
|
|
// CHECK: copy_addr [[ADDR_2]] to [init] [[OPAQUE_OUT]]
|
|
// CHECK: [[EXTRACT:%[^,]+]] = struct_extract [[INSTANCE_1]]
|
|
// CHECK: store [[EXTRACT]] to [trivial] [[TRIV_OUT]]
|
|
// CHECK-LABEL: } // end sil function 'testBeginApply6Yield1LoadableTrivial1OpaqueGuaranteed'
|
|
sil [ossa] @testBeginApply6Yield1LoadableTrivial1OpaqueGuaranteed : $@convention(thin) <T> () -> (@out I, @out T) {
|
|
entry:
|
|
(%instance_1, %instance_2, %token) = begin_apply undef<LoadableTrivialExtractable, T>() : $@yield_once @convention(thin) <U, T> () -> (@yields @in_guaranteed U, @yields @in_guaranteed T)
|
|
%copy = copy_value %instance_2 : $T
|
|
%i = struct_extract %instance_1 : $LoadableTrivialExtractable, #LoadableTrivialExtractable.i
|
|
end_apply %token as $()
|
|
%tuple = tuple (%i : $I, %copy : $T)
|
|
return %tuple : $(I, T)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testBeginApply7YieldLoadableNontrivialGuaranteed : {{.*}} {
|
|
// CHECK: ([[ADDR:%[^,]+]], {{%[^,]+}}) = begin_apply
|
|
// CHECK: [[BORROW:%[^,]+]] = load_borrow [[ADDR]]
|
|
// CHECK: end_borrow [[BORROW]]
|
|
// CHECK-LABEL: } // end sil function 'testBeginApply7YieldLoadableNontrivialGuaranteed'
|
|
sil [ossa] @testBeginApply7YieldLoadableNontrivialGuaranteed : $@convention(thin) () -> @owned Klass {
|
|
entry:
|
|
(%instance, %token) = begin_apply undef<LoadableNontrivial>() : $@yield_once @convention(thin) <U> () -> @yields @in_guaranteed U
|
|
%extract = struct_extract %instance : $LoadableNontrivial, #LoadableNontrivial.x
|
|
%retval = copy_value %extract : $Klass
|
|
end_apply %token as $()
|
|
return %retval : $Klass
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testBeginApply8Yield2LoadableNontrivialGuaranteed : {{.*}} {
|
|
// CHECK: ([[ADDR_1:%[^,]+]], [[ADDR_2:%[^,]+]], {{%[^,]+}}) = begin_apply
|
|
// CHECK: [[INSTANCE_1:%[^,]+]] = load_borrow [[ADDR_1]]
|
|
// CHECK: [[INSTANCE_2:%[^,]+]] = load_borrow [[ADDR_2]]
|
|
// CHECK: struct_extract [[INSTANCE_1]]
|
|
// CHECK: struct_extract [[INSTANCE_2]]
|
|
// CHECK: end_borrow [[INSTANCE_1]]
|
|
// CHECK: end_borrow [[INSTANCE_2]]
|
|
// CHECK-LABEL: } // end sil function 'testBeginApply8Yield2LoadableNontrivialGuaranteed'
|
|
sil [ossa] @testBeginApply8Yield2LoadableNontrivialGuaranteed : $@convention(thin) () -> @owned (Klass, Klass) {
|
|
entry:
|
|
(%instance_1, %instance_2, %token) = begin_apply undef<LoadableNontrivial>() : $@yield_once @convention(thin) <U> () -> (@yields @in_guaranteed U, @yields @in_guaranteed U)
|
|
%extract_1 = struct_extract %instance_1 : $LoadableNontrivial, #LoadableNontrivial.x
|
|
%extract_2 = struct_extract %instance_2 : $LoadableNontrivial, #LoadableNontrivial.x
|
|
%copy_1 = copy_value %extract_1 : $Klass
|
|
%copy_2 = copy_value %extract_2 : $Klass
|
|
end_apply %token as $()
|
|
%retval = tuple (%copy_1 : $Klass, %copy_2 : $Klass)
|
|
return %retval : $(Klass, Klass)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testBeginApply9Yield1LoadableNontrivialGuaranteed1OpaqueGuaranteed : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : $*Klass, [[OPAQUE_OUT:%[^,]+]] : $*T):
|
|
// CHECK: ([[ADDR_1:%[^,]+]], [[ADDR_2:%[^,]+]], {{%[^,]+}}) = begin_apply
|
|
// CHECK: [[BORROW_1:%[^,]+]] = load_borrow [[ADDR_1]] : $*LoadableNontrivial
|
|
// CHECK: struct_extract [[BORROW_1]] : $LoadableNontrivial, #LoadableNontrivial.x
|
|
// CHECK: copy_addr [[ADDR_2]] to [init] [[OPAQUE_OUT]] : $*T
|
|
// CHECK: end_borrow [[BORROW_1]] : $LoadableNontrivial
|
|
// CHECK-LABEL: } // end sil function 'testBeginApply9Yield1LoadableNontrivialGuaranteed1OpaqueGuaranteed'
|
|
sil [ossa] @testBeginApply9Yield1LoadableNontrivialGuaranteed1OpaqueGuaranteed : $@convention(thin) <T> () -> (@out Klass, @out T) {
|
|
entry:
|
|
(%instance_1, %instance_2, %token) = begin_apply undef<LoadableNontrivial, T>() : $@yield_once @convention(thin) <U, T> () -> (@yields @in_guaranteed U, @yields @in_guaranteed T)
|
|
%extract_1 = struct_extract %instance_1 : $LoadableNontrivial, #LoadableNontrivial.x
|
|
%copy_1 = copy_value %extract_1 : $Klass
|
|
%copy_2 = copy_value %instance_2 : $T
|
|
end_apply %token as $()
|
|
%retval = tuple (%copy_1 : $Klass, %copy_2 : $T)
|
|
return %retval : $(Klass, T)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testBeginApplyAYieldLoadableNontrivialOwned : {{.*}} {
|
|
// CHECK: ([[ADDR:%[^,]+]], {{%[^,]+}}) = begin_apply
|
|
// CHECK: [[INSTANCE:%[^,]+]] = load [take] [[ADDR]] : $*LoadableNontrivial
|
|
// CHECK: [[BORROW:%[^,]+]] = begin_borrow [[INSTANCE]] : $LoadableNontrivial
|
|
// CHECK: struct_extract [[BORROW]] : $LoadableNontrivial, #LoadableNontrivial.x
|
|
// CHECK: end_borrow [[BORROW]] : $LoadableNontrivial
|
|
// CHECK-LABEL: } // end sil function 'testBeginApplyAYieldLoadableNontrivialOwned'
|
|
sil [ossa] @testBeginApplyAYieldLoadableNontrivialOwned : $@convention(thin) () -> @owned Klass {
|
|
entry:
|
|
(%instance, %token) = begin_apply undef<LoadableNontrivial>() : $@yield_once @convention(thin) <U> () -> @yields @in U
|
|
end_apply %token as $()
|
|
%borrow = begin_borrow %instance : $LoadableNontrivial
|
|
%extract = struct_extract %borrow : $LoadableNontrivial, #LoadableNontrivial.x
|
|
%retval = copy_value %extract : $Klass
|
|
end_borrow %borrow : $LoadableNontrivial
|
|
destroy_value %instance : $LoadableNontrivial
|
|
return %retval : $Klass
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testBeginApplyBYield2LoadableNontrivialOwned : {{.*}} {
|
|
// CHECK: ([[ADDR_1:%[^,]+]], [[ADDR_2:%[^,]+]], {{%[^,]+}}) = begin_apply
|
|
// CHECK: [[INSTANCE_1:%[^,]+]] = load [take] [[ADDR_1]]
|
|
// CHECK: [[INSTANCE_2:%[^,]+]] = load [take] [[ADDR_2]]
|
|
// CHECK: begin_borrow [[INSTANCE_1]]
|
|
// CHECK: begin_borrow [[INSTANCE_2]]
|
|
// CHECK-LABEL: } // end sil function 'testBeginApplyBYield2LoadableNontrivialOwned'
|
|
sil [ossa] @testBeginApplyBYield2LoadableNontrivialOwned : $@convention(thin) () -> @owned (Klass, Klass) {
|
|
entry:
|
|
(%instance_1, %instance_2, %token) = begin_apply undef<LoadableNontrivial>() : $@yield_once @convention(thin) <U> () -> (@yields @in U, @yields @in U)
|
|
end_apply %token as $()
|
|
%borrow_1 = begin_borrow %instance_1 : $LoadableNontrivial
|
|
%extract_1 = struct_extract %borrow_1 : $LoadableNontrivial, #LoadableNontrivial.x
|
|
%copy_1 = copy_value %extract_1 : $Klass
|
|
end_borrow %borrow_1 : $LoadableNontrivial
|
|
destroy_value %instance_1 : $LoadableNontrivial
|
|
%borrow_2 = begin_borrow %instance_2 : $LoadableNontrivial
|
|
%extract_2 = struct_extract %borrow_2 : $LoadableNontrivial, #LoadableNontrivial.x
|
|
%copy_2 = copy_value %extract_2 : $Klass
|
|
end_borrow %borrow_2 : $LoadableNontrivial
|
|
destroy_value %instance_2 : $LoadableNontrivial
|
|
%retval = tuple (%copy_1 : $Klass, %copy_2 : $Klass)
|
|
return %retval : $(Klass, Klass)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testBeginApplyCYield1LoadableNontrivialOwned1OpaqueOwned : $@convention(thin) <T> () -> (@out Klass, @out T) {
|
|
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : $*Klass, [[OPAQUE_OUT:%[^,]+]] : $*T):
|
|
// CHECK: ([[ADDR_1:%[^,]+]], [[ADDR_2:%[^,]+]], {{%[^,]+}}) = begin_apply
|
|
// CHECK: [[INSTANCE_1:%[^,]+]] = load [take] [[ADDR_1]]
|
|
// CHECK: copy_addr [take] [[ADDR_2]] to [init] [[OPAQUE_OUT]]
|
|
// CHECK: begin_borrow [[INSTANCE_1]]
|
|
// CHECK-LABEL: } // end sil function 'testBeginApplyCYield1LoadableNontrivialOwned1OpaqueOwned'
|
|
sil [ossa] @testBeginApplyCYield1LoadableNontrivialOwned1OpaqueOwned : $@convention(thin) <T> () -> (@out Klass, @out T) {
|
|
entry:
|
|
(%instance_1, %instance_2, %token) = begin_apply undef<LoadableNontrivial, T>() : $@yield_once @convention(thin) <U, T> () -> (@yields @in U, @yields @in T)
|
|
%borrow_1 = begin_borrow %instance_1 : $LoadableNontrivial
|
|
%extract_1 = struct_extract %borrow_1 : $LoadableNontrivial, #LoadableNontrivial.x
|
|
%copy_1 = copy_value %extract_1 : $Klass
|
|
end_borrow %borrow_1 : $LoadableNontrivial
|
|
destroy_value %instance_1 : $LoadableNontrivial
|
|
end_apply %token as $()
|
|
%retval = tuple (%copy_1 : $Klass, %instance_2 : $T)
|
|
return %retval : $(Klass, T)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testBeginApplyDYieldOpaqueInout : {{.*}} {
|
|
// CHECK: begin_apply undef<T>() : $@yield_once @convention(method) <τ_0_0> () -> @yields @inout τ_0_0
|
|
// CHECK-LABEL: } // end sil function 'testBeginApplyDYieldOpaqueInout'
|
|
sil [ossa] @testBeginApplyDYieldOpaqueInout : $@yield_once @convention(thin) <T> () -> () {
|
|
entry:
|
|
(%addr, %token) = begin_apply undef<T>() : $@yield_once @convention(method) <U> () -> @yields @inout U
|
|
end_apply %token as $()
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testBeginApplyEYieldOpaqueInoutAndYield : {{.*}}{
|
|
// CHECK: ([[ADDR:%[^,]+]], {{%[^,]+}}) = begin_apply
|
|
// CHECK: yield [[ADDR]] : $*T
|
|
// CHECK-LABEL: } // end sil function 'testBeginApplyEYieldOpaqueInoutAndYield'
|
|
sil [ossa] @testBeginApplyEYieldOpaqueInoutAndYield : $@yield_once @convention(thin) <T> () -> @yields @inout T {
|
|
entry:
|
|
(%addr, %token) = begin_apply undef<T>() : $@yield_once @convention(method) <U> () -> @yields @inout U
|
|
yield %addr : $*T, resume bb1, unwind bb2
|
|
|
|
bb1:
|
|
end_apply %token as $()
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
|
|
bb2:
|
|
abort_apply %token
|
|
unwind
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testBeginApplyFYieldDirectOwnedAndAddressOnlyGuaranteed : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[OUT_ADDR:%[^,]+]] :
|
|
// CHECK: ([[OWNED_INSTANCE:%[^,]+]], [[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply
|
|
// CHECK: destroy_value [[OWNED_INSTANCE]]
|
|
// CHECK: copy_addr [[ADDR]] to [init] [[OUT_ADDR]]
|
|
// CHECK: end_apply [[TOKEN]] as $()
|
|
// CHECK-LABEL: } // end sil function 'testBeginApplyFYieldDirectOwnedAndAddressOnlyGuaranteed'
|
|
sil [ossa] @testBeginApplyFYieldDirectOwnedAndAddressOnlyGuaranteed : $@convention(thin) <T> () -> @out T {
|
|
entry:
|
|
(%klass, %instance, %token) = begin_apply undef<T>() : $@yield_once @convention(thin) <T> () -> (@yields @owned Klass, @yields @in_guaranteed T)
|
|
destroy_value %klass : $Klass
|
|
%retval = copy_value %instance : $T
|
|
end_apply %token as $()
|
|
return %retval : $T
|
|
}
|
|
|
|
// Verify that a copy_value of a @in_guaranteed yield generates storage.
|
|
// CHECK-LABEL: sil [ossa] @testBeginApplyGCopyConsumeInGuaranteedValue : {{.*}} {
|
|
// CHECK: bb0:
|
|
// CHECK: [[COPY_STORAGE:%[^,]+]] = alloc_stack $T
|
|
// CHECK: ([[YIELD_STORAGE:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply
|
|
// CHECK: copy_addr [[YIELD_STORAGE]] to [init] [[COPY_STORAGE]]
|
|
// CHECK: end_apply [[TOKEN]] as $()
|
|
// CHECK: apply undef<T>([[COPY_STORAGE]])
|
|
// CHECK: dealloc_stack [[COPY_STORAGE]]
|
|
// CHECK-LABEL: } // end sil function 'testBeginApplyGCopyConsumeInGuaranteedValue'
|
|
sil [ossa] @testBeginApplyGCopyConsumeInGuaranteedValue : $@convention(thin) <T> () -> () {
|
|
entry:
|
|
(%yield, %token) = begin_apply undef<T>() : $@yield_once @convention(thin) <τ_0_0> () -> @yields @in_guaranteed τ_0_0
|
|
%copy = copy_value %yield : $T
|
|
end_apply %token as $()
|
|
apply undef<T>(%copy) : $@convention(thin) <T> (@in T) -> ()
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// Verify that a copy_value that is a "copy-store" whose source is an
|
|
// @in_guaranteed storage generates storage.
|
|
// CHECK-LABEL: sil [ossa] @testBeginApplyH1CopyStoreInGuaranteedValue : {{.*}} {
|
|
// CHECK: [[COPY_STORAGE:%[^,]+]] = alloc_stack $T
|
|
// CHECK: ([[YIELD_STORAGE:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply
|
|
// CHECK: copy_addr [[YIELD_STORAGE]] to [init] [[COPY_STORAGE]]
|
|
// CHECK: end_apply [[TOKEN]] as $()
|
|
// CHECK: [[PTR:%[^,]+]] = apply undef
|
|
// CHECK: [[ADDR:%[^,]+]] = pointer_to_address [[PTR:%[^,]+]]
|
|
// CHECK: copy_addr [take] [[COPY_STORAGE]] to [[ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'testBeginApplyH1CopyStoreInGuaranteedValue'
|
|
sil [ossa] @testBeginApplyH1CopyStoreInGuaranteedValue : $@convention(thin) <T> () -> () {
|
|
entry:
|
|
(%yield, %token) = begin_apply undef<T>() : $@yield_once @convention(thin) <τ_0_0> () -> @yields @in_guaranteed τ_0_0
|
|
%copy = copy_value %yield : $T
|
|
end_apply %token as $()
|
|
%ptr = apply undef<T>() : $@convention(method) <τ_0_0> () -> Builtin.RawPointer
|
|
%addr = pointer_to_address %ptr : $Builtin.RawPointer to [strict] $*T
|
|
store %copy to [assign] %addr : $*T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// Verify that a copy_value that is a "copy-store" whose source is a borrow of an
|
|
// @in_guaranteed yield generates storage.
|
|
// testBeginApplyH2CopyStoreBorrowedInGuaranteedValue
|
|
// CHECK-LABEL: sil [ossa] @testBeginApplyH2CopyStoreBorrowedInGuaranteedValue : {{.*}} {
|
|
// CHECK: [[COPY_STORAGE:%[^,]+]] = alloc_stack $T
|
|
// CHECK: ([[YIELD_STORAGE:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply undef
|
|
// CHECK: copy_addr [[YIELD_STORAGE]] to [init] [[COPY_STORAGE]] : $*T
|
|
// CHECK: end_apply [[TOKEN]] as $()
|
|
// CHECK: [[PTR:%[^,]+]] = apply undef
|
|
// CHECK: [[ADDR:%[^,]+]] = pointer_to_address [[PTR]]
|
|
// CHECK: copy_addr [take] [[COPY_STORAGE]] to [[ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'testBeginApplyH2CopyStoreBorrowedInGuaranteedValue'
|
|
sil [ossa] @testBeginApplyH2CopyStoreBorrowedInGuaranteedValue : $@convention(thin) <T> () -> () {
|
|
entry:
|
|
(%yield, %token) = begin_apply undef<T>() : $@yield_once @convention(thin) <τ_0_0> () -> @yields @in_guaranteed τ_0_0
|
|
%borrow = begin_borrow %yield : $T
|
|
apply undef<T>(%borrow) : $@convention(thin) <τ> (@in_guaranteed τ) -> ()
|
|
%copy = copy_value %borrow : $T
|
|
end_borrow %borrow : $T
|
|
end_apply %token as $()
|
|
%ptr = apply undef<T>() : $@convention(method) <τ_0_0> () -> Builtin.RawPointer
|
|
%addr = pointer_to_address %ptr : $Builtin.RawPointer to [strict] $*T
|
|
store %copy to [assign] %addr : $*T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// sil [ossa] @testBeginApplyIConsumeInValue : {{.*}} {
|
|
// bb0:
|
|
// [[IN_STORAGE:%[^,]+]] = alloc_stack $T
|
|
// ([[YIELD_STORAGE:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply undef<T>()
|
|
// copy_addr [take] [[YIELD_STORAGE]] to [init] [[IN_STORAGE]]
|
|
// end_apply [[TOKEN]] as $()
|
|
// apply undef<T>([[IN_STORAGE]])
|
|
// } // end sil function 'testBeginApplyIConsumeInValue'
|
|
sil [ossa] @testBeginApplyIConsumeInValue : $@convention(thin) <T> () -> () {
|
|
entry:
|
|
(%yield, %token) = begin_apply undef<T>() : $@yield_once @convention(thin) <τ_0_0> () -> @yields @in τ_0_0
|
|
end_apply %token as $()
|
|
apply undef<T>(%yield) : $@convention(thin) <T> (@in T) -> ()
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// sil [ossa] @testBeginApplyJStoreInValue : {{.*}} {
|
|
// [[IN_STORAGE:%[^,]+]] = alloc_stack $T
|
|
// ([[YIELD_STORAGE:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply
|
|
// copy_addr [take] [[YIELD_STORAGE]] to [init] [[IN_STORAGE]]
|
|
// end_apply [[TOKEN]] as $()
|
|
// [[PTR:%[^,]+]] = apply
|
|
// [[ADDR:%[^,]+]] = pointer_to_address [[PTR:%[^,]+]]
|
|
// copy_addr [take] [[IN_STORAGE]] to [[ADDR]]
|
|
// } // end sil function 'testBeginApplyJStoreInValue'
|
|
sil [ossa] @testBeginApplyJStoreInValue : $@convention(thin) <T> () -> () {
|
|
entry:
|
|
(%yield, %token) = begin_apply undef<T>() : $@yield_once @convention(thin) <τ_0_0> () -> @yields @in τ_0_0
|
|
end_apply %token as $()
|
|
%ptr = apply undef<T>() : $@convention(method) <τ_0_0> () -> Builtin.RawPointer
|
|
%addr = pointer_to_address %ptr : $Builtin.RawPointer to [strict] $*T
|
|
store %yield to [assign] %addr : $*T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// sil [ossa] @testBeginApplyKConsumeInConstantValue : {{.*}} {
|
|
// bb0:
|
|
// [[IN_CONSTANT_STORAGE:%[^,]+]] = alloc_stack $T
|
|
// ([[YIELD_STORAGE:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply undef<T>()
|
|
// copy_addr [take] [[YIELD_STORAGE]] to [init] [[IN_CONSTANT_STORAGE]]
|
|
// end_apply [[TOKEN]] as $()
|
|
// apply undef<T>([[IN_CONSTANT_STORAGE]])
|
|
// } // end sil function 'testBeginApplyKConsumeInConstantValue'
|
|
sil [ossa] @testBeginApplyKConsumeInConstantValue : $@convention(thin) <T> () -> () {
|
|
entry:
|
|
(%yield, %token) = begin_apply undef<T>() : $@yield_once @convention(thin) <τ_0_0> () -> @yields @in_constant τ_0_0
|
|
end_apply %token as $()
|
|
apply undef<T>(%yield) : $@convention(thin) <T> (@in_constant T) -> ()
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// sil [ossa] @testBeginApplyLStoreInConstantValue : {{.*}} {
|
|
// [[IN_CONSTANT_STORAGE:%[^,]+]] = alloc_stack $T
|
|
// ([[YIELD_STORAGE:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply
|
|
// copy_addr [take] [[YIELD_STORAGE]] to [init] [[IN_CONSTANT_STORAGE]]
|
|
// end_apply [[TOKEN]] as $()
|
|
// [[PTR:%[^,]+]] = apply
|
|
// [[ADDR:%[^,]+]] = pointer_to_address [[PTR:%[^,]+]]
|
|
// copy_addr [take] [[IN_CONSTANT_STORAGE]] to [[ADDR]]
|
|
// } // end sil function 'testBeginApplyLStoreInConstantValue'
|
|
sil [ossa] @testBeginApplyLStoreInConstantValue : $@convention(thin) <T> () -> () {
|
|
entry:
|
|
(%yield, %token) = begin_apply undef<T>() : $@yield_once @convention(thin) <τ_0_0> () -> @yields @in_constant τ_0_0
|
|
end_apply %token as $()
|
|
%ptr = apply undef<T>() : $@convention(method) <τ_0_0> () -> Builtin.RawPointer
|
|
%addr = pointer_to_address %ptr : $Builtin.RawPointer to [strict] $*T
|
|
store %yield to [assign] %addr : $*T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testCopyValue1StoreExtractAfterDestroyAggregate : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[ADDR:%[^,]+]] :
|
|
// CHECK: [[COPY_ADDR:%[^,]+]] = alloc_stack $T
|
|
// CHECK: [[INSTANCE_ADDR:%[^,]+]] = alloc_stack $Pair<T>
|
|
// CHECK: apply undef<T>([[INSTANCE_ADDR]])
|
|
// CHECK: [[X_ADDR:%[^,]+]] = struct_element_addr [[INSTANCE_ADDR]]{{.*}}, #Pair.x
|
|
// CHECK: copy_addr [[X_ADDR]] to [init] [[COPY_ADDR]]
|
|
// CHECK: destroy_addr [[INSTANCE_ADDR]]
|
|
// CHECK: copy_addr [take] [[COPY_ADDR]] to [[ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'testCopyValue1StoreExtractAfterDestroyAggregate'
|
|
sil [ossa] @testCopyValue1StoreExtractAfterDestroyAggregate : $@convention(thin) <T> (@inout T) -> () {
|
|
entry(%addr : $*T):
|
|
%instance = apply undef<T>() : $@convention(thin) <Tee> () -> @out Pair<Tee>
|
|
%lifetime = begin_borrow %instance : $Pair<T>
|
|
%x = struct_extract %lifetime : $Pair<T>, #Pair.x
|
|
%copy = copy_value %x : $T
|
|
end_borrow %lifetime : $Pair<T>
|
|
destroy_value %instance : $Pair<T>
|
|
store %copy to [assign] %addr : $*T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testCopyValue2StoreCopyAfterDestroy : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[ADDR:%[^,]+]] :
|
|
// CHECK: [[INSTANCE_ADDR:%[^,]+]] = alloc_stack $T
|
|
// CHECK: [[COPY_ADDR:%[^,]+]] = alloc_stack $T
|
|
// CHECK: apply undef<T>([[INSTANCE_ADDR]])
|
|
// CHECK: copy_addr [[INSTANCE_ADDR]] to [init] [[COPY_ADDR]]
|
|
// CHECK: destroy_addr [[INSTANCE_ADDR]]
|
|
// CHECK: copy_addr [take] [[COPY_ADDR]] to [[ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'testCopyValue2StoreCopyAfterDestroy'
|
|
sil [ossa] @testCopyValue2StoreCopyAfterDestroy : $@convention(thin) <T> (@inout T) -> () {
|
|
entry(%addr : $*T):
|
|
%instance = apply undef<T>() : $@convention(thin) <Tee> () -> @out Tee
|
|
%copy = copy_value %instance : $T
|
|
destroy_value %instance : $T
|
|
store %copy to [assign] %addr : $*T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testCopyValue3StoreTupleDestructureFieldAfterDestroy : $@convention(thin) <T> (@inout T) -> () {
|
|
// CHECK: {{bb[0-9]+}}([[ADDR:%[^,]+]] :
|
|
// CHECK: [[INSTANCE_ADDR:%[^,]+]] = alloc_stack $(T, T)
|
|
// CHECK: [[COPY_ADDR:%[^,]+]] = alloc_stack $T
|
|
// CHECK: apply undef<T>([[INSTANCE_ADDR]]) : $@convention(thin) <τ_0_0> () -> @out (τ_0_0, τ_0_0)
|
|
// CHECK: [[ONE_ADDR:%[^,]+]] = tuple_element_addr [[INSTANCE_ADDR]]{{.*}}, 0
|
|
// CHECK: copy_addr [[ONE_ADDR]] to [init] [[COPY_ADDR]]
|
|
// CHECK: destroy_addr [[ONE_ADDR]]
|
|
// CHECK: [[TWO_ADDR:%[^,]+]] = tuple_element_addr [[INSTANCE_ADDR]]{{.*}}, 1
|
|
// CHECK: destroy_addr [[TWO_ADDR]]
|
|
// CHECK: copy_addr [take] [[COPY_ADDR]] to [[ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'testCopyValue3StoreTupleDestructureFieldAfterDestroy'
|
|
sil [ossa] @testCopyValue3StoreTupleDestructureFieldAfterDestroy : $@convention(thin) <T> (@inout T) -> () {
|
|
entry(%addr : $*T):
|
|
%instance = apply undef<T>() : $@convention(thin) <Tee> () -> @out (Tee, Tee)
|
|
(%one, %two) = destructure_tuple %instance : $(T, T)
|
|
%copy = copy_value %one : $T
|
|
destroy_value %one : $T
|
|
destroy_value %two : $T
|
|
store %copy to [assign] %addr : $*T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// The move_value is lexical so the corresponding alloc_stack must be marked
|
|
// lexical too.
|
|
// CHECK-LABEL: sil [ossa] @testMoveValueLexical : {{.*}} {
|
|
// CHECK: alloc_stack [lexical]
|
|
// CHECK-LABEL: } // end sil function 'testMoveValueLexical'
|
|
sil [ossa] @testMoveValueLexical : $@convention(thin) <T> () -> () {
|
|
%getT = function_ref @getT : $@convention(thin) <T> () -> @out T
|
|
%instance = apply %getT<T>() : $@convention(thin) <T> () -> @out T
|
|
%moved = move_value [lexical] %instance : $T
|
|
destroy_value %moved : $T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// Verify that the temporary storage is lexical and moved out of
|
|
// (copy_addr [take]).
|
|
// CHECK-LABEL: sil [ossa] @testMoveValueLexicalAndReturn : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[RETVAL:%[^,]+]] :
|
|
// CHECK: [[STACK:%[^,]+]] = alloc_stack [lexical]
|
|
// CHECK: copy_addr [take] [[STACK]] to [init] [[RETVAL]]
|
|
// CHECK-LABEL: } // end sil function 'testMoveValueLexicalAndReturn'
|
|
sil [ossa] @testMoveValueLexicalAndReturn : $@convention(thin) <T> () -> @out T {
|
|
%getT = function_ref @getT : $@convention(thin) <T> () -> @out T
|
|
%instance = apply %getT<T>() : $@convention(thin) <T> () -> @out T
|
|
%moved = move_value [lexical] %instance : $T
|
|
return %moved : $T
|
|
}
|
|
|
|
// Verify that a move_value gets no stack storage if it's from an argument.
|
|
// CHECK-LABEL: sil [ossa] @testMoveValueLexicalArgument : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] :
|
|
// CHECK: destroy_addr [[INSTANCE]]
|
|
// CHECK-LABEL: } // end sil function 'testMoveValueLexicalArgument'
|
|
sil [ossa] @testMoveValueLexicalArgument : $@convention(thin) <T> (@in T) -> () {
|
|
entry(%instance : @owned $T):
|
|
%moved = move_value [lexical] %instance : $T
|
|
destroy_value %moved : $T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// Only lexical move_values should mark the alloc_stack lexical.
|
|
// CHECK-LABEL: sil [ossa] @testMoveValueNonlexical : {{.*}} {
|
|
// CHECK-NOT: alloc_stack [lexical]
|
|
// CHECK-LABEL: } // end sil function 'testMoveValueNonlexical'
|
|
sil [ossa] @testMoveValueNonlexical : $@convention(thin) <T> () -> () {
|
|
%getT = function_ref @getT : $@convention(thin) <T> () -> @out T
|
|
%instance = apply %getT<T>() : $@convention(thin) <T> () -> @out T
|
|
%moved = move_value %instance : $T
|
|
destroy_value %moved : $T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @testOpaqueYield :
|
|
// CHECK: bb0(%0 : @guaranteed $TestGeneric<T>):
|
|
// CHECK: [[REF:%.*]] = ref_element_addr %0 : $TestGeneric<T>, #TestGeneric.borrowedGeneric
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[REF]] : $*T
|
|
// CHECK: yield [[ACCESS]] : $*T, resume bb2, unwind bb1
|
|
// CHECK: bb1:
|
|
// CHECK: end_access [[ACCESS]] : $*T
|
|
// CHECK: unwind
|
|
// CHECK: bb2:
|
|
// CHECK: end_access [[ACCESS]] : $*T
|
|
// CHECK-LABEL: } // end sil function 'testOpaqueYield'
|
|
sil hidden [ossa] @testOpaqueYield : $@yield_once @convention(method) <T> (@guaranteed TestGeneric<T>) -> @yields @in_guaranteed T {
|
|
bb0(%0 : @guaranteed $TestGeneric<T>):
|
|
%2 = ref_element_addr %0 : $TestGeneric<T>, #TestGeneric.borrowedGeneric
|
|
%3 = begin_access [read] [dynamic] %2 : $*T
|
|
%4 = load_borrow %3 : $*T
|
|
yield %4 : $T, resume bb1, unwind bb2
|
|
|
|
bb1:
|
|
end_borrow %4 : $T
|
|
end_access %3 : $*T
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
|
|
bb2:
|
|
end_borrow %4 : $T
|
|
end_access %3 : $*T
|
|
unwind
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testUnreachable1NoDestroy : {{.*}} {
|
|
// CHECK: [[STORAGE:%[^,]+]] = alloc_stack $T
|
|
// CHECK: apply undef<T>([[STORAGE]])
|
|
// CHECK: apply undef<T>([[STORAGE]])
|
|
// CHECK: unreachable
|
|
// CHECK-LABEL: } // end sil function 'testUnreachable1NoDestroy'
|
|
sil [ossa] @testUnreachable1NoDestroy : $@convention(thin) <T> () -> () {
|
|
bb0:
|
|
%instance = apply undef<T>() : $@convention(thin) <τ> () -> @out τ
|
|
apply undef<T>(%instance) : $@convention(thin) <τ> (@in_guaranteed τ) -> ()
|
|
unreachable
|
|
}
|
|
|
|
sil [ossa] @use_T : $@convention(thin) <T> (@in T) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_checked_cast_br1 : $@convention(method) <T> (@in Any) -> () {
|
|
// CHECK: bb0(%0 : $*Any):
|
|
// CHECK: [[SUCCESS_DST:%.*]] = alloc_stack $T
|
|
// CHECK: checked_cast_addr_br take_on_success Any in %0 : $*Any to T in [[SUCCESS_DST]] : $*T, bb2, bb1
|
|
// CHECK: bb1:
|
|
// CHECK: destroy_addr %0 : $*Any
|
|
// CHECK: br bb3
|
|
// CHECK: bb2:
|
|
// CHECK: [[FUNC:%.*]] = function_ref @use_T : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
|
|
// CHECK: apply [[FUNC]]<T>([[SUCCESS_DST]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
|
|
// CHECK: br bb3
|
|
// CHECK: bb3:
|
|
// CHECK: [[RES:%.*]] = tuple ()
|
|
// CHECK: dealloc_stack [[SUCCESS_DST]] : $*T
|
|
// CHECK: return [[RES]] : $()
|
|
// CHECK-LABEL: } // end sil function 'test_checked_cast_br1'
|
|
sil [ossa] @test_checked_cast_br1 : $@convention(method) <T> (@in Any) -> () {
|
|
bb0(%0 : @owned $Any):
|
|
checked_cast_br Any in %0 : $Any to T, bb1, bb2
|
|
|
|
bb1(%3 : @owned $T):
|
|
%f = function_ref @use_T : $@convention(thin) <T> (@in T) -> ()
|
|
%call = apply %f<T>(%3) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
|
|
br bb3
|
|
|
|
bb2(%4 : @owned $Any):
|
|
destroy_value %4 : $Any
|
|
br bb3
|
|
|
|
bb3:
|
|
%31 = tuple ()
|
|
return %31 : $()
|
|
}
|
|
|
|
sil [ossa] @use_C : $@convention(thin) (@owned C) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_checked_cast_br2 : $@convention(method) (@in Any) -> () {
|
|
// CHECK: bb0(%0 : $*Any):
|
|
// CHECK: [[SUCCESS_DST:%.*]] = alloc_stack $any C
|
|
// CHECK: checked_cast_addr_br take_on_success Any in %0 : $*Any to any C in [[SUCCESS_DST]] : $*any C, bb2, bb1
|
|
// CHECK: bb1:
|
|
// CHECK: dealloc_stack [[SUCCESS_DST]] : $*any C
|
|
// CHECK: destroy_addr %0 : $*Any
|
|
// CHECK: br bb3
|
|
// CHECK: bb2:
|
|
// CHECK: [[LD:%.*]] = load [take] [[SUCCESS_DST]] : $*any C
|
|
// CHECK: dealloc_stack [[SUCCESS_DST]] : $*any C
|
|
// CHECK: [[FUNC:%.*]] = function_ref @use_C : $@convention(thin) (@owned any C) -> ()
|
|
// CHECK: apply [[FUNC]]([[LD]]) : $@convention(thin) (@owned any C) -> ()
|
|
// CHECK: br bb3
|
|
// CHECK: bb3:
|
|
// CHECK: [[RES:%.*]] = tuple ()
|
|
// CHECK: return [[RES]] : $()
|
|
// CHECK-LABEL: }
|
|
sil [ossa] @test_checked_cast_br2 : $@convention(method) (@in Any) -> () {
|
|
bb0(%0 : @owned $Any):
|
|
checked_cast_br Any in %0 : $Any to C, bb1, bb2
|
|
|
|
bb1(%3 : @owned $C):
|
|
%f = function_ref @use_C : $@convention(thin) (@owned C) -> ()
|
|
%call = apply %f(%3) : $@convention(thin) (@owned C) -> ()
|
|
br bb3
|
|
|
|
bb2(%4 : @owned $Any):
|
|
destroy_value %4 : $Any
|
|
br bb3
|
|
|
|
bb3:
|
|
%31 = tuple ()
|
|
return %31 : $()
|
|
}
|
|
|
|
sil @use_Any : $@convention(thin) (@in Any) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_checked_cast_br3 : $@convention(method) (@owned any C) -> () {
|
|
// CHECK: bb0(%0 : @owned $any C):
|
|
// CHECK: [[DST:%.*]] = alloc_stack $Any
|
|
// CHECK: [[SRC_TMP:%.*]] = alloc_stack $any C
|
|
// CHECK: store %0 to [init] [[SRC_TMP]] : $*any C
|
|
// CHECK: checked_cast_addr_br take_on_success any C in [[SRC_TMP]] : $*any C to Any in [[DST]] : $*Any, bb2, bb1
|
|
// CHECK: bb1:
|
|
// CHECK: [[LD:%.*]] = load [take] [[SRC_TMP]] : $*any C
|
|
// CHECK: dealloc_stack [[SRC_TMP]] : $*any C
|
|
// CHECK: destroy_value [[LD]] : $any C
|
|
// CHECK: br bb3
|
|
// CHECK: bb2:
|
|
// CHECK: dealloc_stack [[SRC_TMP]] : $*any C
|
|
// CHECK: [[FUNC:%.*]] = function_ref @use_Any : $@convention(thin) (@in Any) -> ()
|
|
// CHECK: apply [[FUNC]]([[DST]]) : $@convention(thin) (@in Any) -> ()
|
|
// CHECK: br bb3
|
|
// CHECK: bb3:
|
|
// CHECK: [[RES:%.*]] = tuple ()
|
|
// CHECK: dealloc_stack [[DST]] : $*Any
|
|
// CHECK: return [[RES]] : $()
|
|
// CHECK: }
|
|
sil [ossa] @test_checked_cast_br3 : $@convention(method) (@owned C) -> () {
|
|
bb0(%0 : @owned $C):
|
|
checked_cast_br C in %0 : $C to Any, bb1, bb2
|
|
|
|
bb1(%3 : @owned $Any):
|
|
%f = function_ref @use_Any : $@convention(thin) (@in Any) -> ()
|
|
%call = apply %f(%3) : $@convention(thin) (@in Any) -> ()
|
|
br bb3
|
|
|
|
bb2(%4 : @owned $C):
|
|
destroy_value %4 : $C
|
|
br bb3
|
|
|
|
bb3:
|
|
%31 = tuple ()
|
|
return %31 : $()
|
|
}
|
|
|
|
// Test the result being stored into an @out enum.
|
|
// CHECK-LABEL: sil [ossa] @test_checked_cast_br4 : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[OUT_ADDR:%[^,]+]] : $*Optional<T>, [[INSTANCE:%[^,]+]] : @owned $TestGeneric<Element>):
|
|
// CHECK: [[CAST_SOURCE_ADDR:%[^,]+]] = alloc_stack $TestGeneric<Element>
|
|
// CHECK: store [[INSTANCE]] to [init] [[CAST_SOURCE_ADDR]]
|
|
// CHECK: [[CAST_DEST_ADDR:%[^,]+]] = init_enum_data_addr [[OUT_ADDR]] : $*Optional<T>, #Optional.some!enumelt
|
|
// CHECK: checked_cast_addr_br take_on_success TestGeneric<Element> in [[CAST_SOURCE_ADDR]] : $*TestGeneric<Element> to T in [[CAST_DEST_ADDR]] : $*T, [[SUCCESS:bb[0-9]+]]
|
|
// CHECK: [[SUCCESS]]:
|
|
// CHECK: dealloc_stack [[CAST_SOURCE_ADDR]]
|
|
// CHECK: inject_enum_addr [[OUT_ADDR]] : $*Optional<T>, #Optional.some!enumelt
|
|
// CHECK-LABEL: } // end sil function 'test_checked_cast_br4'
|
|
sil [ossa] @test_checked_cast_br4 : $@convention(method) <Element><T> (@owned TestGeneric<Element>) -> @out Optional<T> {
|
|
bb0(%3 : @owned $TestGeneric<Element>):
|
|
checked_cast_br TestGeneric<Element> in %3 : $TestGeneric<Element> to T, bb1, bb2
|
|
|
|
bb1(%5 : @owned $T):
|
|
%6 = enum $Optional<T>, #Optional.some!enumelt, %5 : $T
|
|
br bb3(%6 : $Optional<T>)
|
|
|
|
bb2(%8 : @owned $TestGeneric<Element>):
|
|
destroy_value %8 : $TestGeneric<Element>
|
|
%10 = enum $Optional<T>, #Optional.none!enumelt
|
|
br bb3(%10 : $Optional<T>)
|
|
|
|
bb3(%12 : @owned $Optional<T>):
|
|
return %12 : $Optional<T>
|
|
}
|
|
|
|
// Verify that checked_cast_br neither from nor to an address-only value but
|
|
// whose operands require rewriting to checked_cast_addr_br gets rewritten.
|
|
// CHECK-LABEL: sil [ossa] @test_checked_cast_br5 : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[SRC:%[^,]+]] :
|
|
// CHECK: [[SRC_ADDR:%[^,]+]] = alloc_stack $AnyObject
|
|
// CHECK: store [[SRC]] to [init] [[SRC_ADDR]]
|
|
// CHECK: [[DEST_ADDR:%[^,]+]] = alloc_stack $@thick any AnyObject.Type
|
|
// CHECK: checked_cast_addr_br take_on_success AnyObject in [[SRC_ADDR]] {{.*}} to any AnyObject.Type in [[DEST_ADDR]] {{.*}}, [[SUCCESS:bb[0-9]+]], [[FAILURE:bb[0-9]+]]
|
|
// CHECK: [[FAILURE]]:
|
|
// CHECK: load [take] [[SRC_ADDR]] : $*AnyObject
|
|
// CHECK: [[SUCCESS]]:
|
|
// CHECK: load [trivial] [[DEST_ADDR]] : $*@thick any AnyObject.Type
|
|
// CHECK-LABEL: } // end sil function 'test_checked_cast_br5'
|
|
sil [ossa] @test_checked_cast_br5 : $@convention(thin) (@owned AnyObject) -> () {
|
|
entry(%instance : @owned $AnyObject):
|
|
checked_cast_br AnyObject in %instance : $AnyObject to any AnyObject.Type, success, failure
|
|
|
|
success(%metatype : $@thick any AnyObject.Type):
|
|
br exit
|
|
|
|
failure(%original : @owned $AnyObject):
|
|
destroy_value %original : $AnyObject
|
|
br exit
|
|
|
|
exit:
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// Verify that checked_cast_br which both has an address-only value and also
|
|
// produces a value whose type would anyway require rewriting but is not
|
|
// address-only gets lowered properly.
|
|
// CHECK-LABEL: sil [ossa] @test_checked_cast_br6 : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[SRC:%[^,]+]] :
|
|
// CHECK: [[DEST_ADDR:%[^,]+]] = alloc_stack $@thick any AnyObject.Type
|
|
// CHECK: checked_cast_addr_br take_on_success T in [[SRC]] {{.*}} to any AnyObject.Type in [[DEST_ADDR]] {{.*}}, [[SUCCESS]], [[FAILURE]]
|
|
// CHECK: [[FAILURE]]:
|
|
// CHECK: destroy_addr [[SRC]] : $*T
|
|
// CHECK: [[SUCCESS]]:
|
|
// CHECK: load [trivial] [[DEST_ADDR]] : $*@thick any AnyObject.Type
|
|
// CHECK-LABEL: } // end sil function 'test_checked_cast_br6'
|
|
sil [ossa] @test_checked_cast_br6 : $@convention(thin) <T> (@in T) -> () {
|
|
entry(%instance : @owned $T):
|
|
checked_cast_br T in %instance : $T to any AnyObject.Type, success, failure
|
|
success(%metatype : $@thick any AnyObject.Type):
|
|
br exit
|
|
failure(%original : @owned $T):
|
|
destroy_value %original : $T
|
|
br exit
|
|
exit:
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_copyable_to_moveonlywrapper_1_owned : {{.*}} {
|
|
// CHECK: bb0([[TMO:%[^,]+]] :
|
|
// CHECK: [[T:%[^,]+]] = copyable_to_moveonlywrapper_addr [[TMO]]
|
|
// CHECK: destroy_addr [[T]]
|
|
// CHECK-LABEL: } // end sil function 'test_copyable_to_moveonlywrapper_1_owned'
|
|
sil [ossa] @test_copyable_to_moveonlywrapper_1_owned : $@convention(thin) <T> (@in T) -> () {
|
|
entry(%t : @owned $T):
|
|
%tmo = copyable_to_moveonlywrapper [owned] %t : $T
|
|
destroy_value %tmo : $@moveOnly T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_copyable_to_moveonlywrapper_2_guaranteed : {{.*}} {
|
|
// CHECK: bb0([[TMO:%[^,]+]] :
|
|
// CHECK: [[T:%[^,]+]] = copyable_to_moveonlywrapper_addr [[TMO]]
|
|
// CHECK: [[BORROW_T:%[^,]+]] = function_ref @borrowMoveOnlyT
|
|
// CHECK: apply [[BORROW_T]]<T>([[T]])
|
|
// CHECK-LABEL: } // end sil function 'test_copyable_to_moveonlywrapper_2_guaranteed'
|
|
sil [ossa] @test_copyable_to_moveonlywrapper_2_guaranteed : $@convention(thin) <T> (@in_guaranteed T) -> () {
|
|
entry(%t : @guaranteed $T):
|
|
%tmo = copyable_to_moveonlywrapper [guaranteed] %t : $T
|
|
%borrowT = function_ref @borrowMoveOnlyT : $@convention(thin) <T> (@in_guaranteed @moveOnly T) -> ()
|
|
apply %borrowT<T>(%tmo) : $@convention(thin) <T> (@in_guaranteed @moveOnly T) -> ()
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
enum PairEnum<T> {
|
|
case it(T, T)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_destructure_tuple_1_guaranteed : {{.*}} {
|
|
// CHECK: [[INSTANCE:%[^,]+]] = unchecked_take_enum_data_addr
|
|
// CHECK: [[KLASS_ADDR:%[^,]+]] = tuple_element_addr [[INSTANCE]] {{.*}}, 0
|
|
// CHECK: [[KLASS:%[^,]+]] = load_borrow [[KLASS_ADDR]]
|
|
// CHECK: [[ANY_ADDR:%[^,]+]] = tuple_element_addr [[INSTANCE]] {{.*}}, 1
|
|
// CHECK: apply undef<Any>([[ANY_ADDR]])
|
|
// CHECK: end_borrow [[KLASS]]
|
|
// CHECK: destroy_addr [[INSTANCE]]
|
|
// CHECK-LABEL: } // end sil function 'test_destructure_tuple_1_guaranteed'
|
|
sil [ossa] @test_destructure_tuple_1_guaranteed : $@convention(thin) () -> () {
|
|
bb0:
|
|
%maybe = apply undef<(Klass?, Any)>() : $@convention(method) <τ_0_0> () -> @out Optional<τ_0_0>
|
|
switch_enum %maybe : $Optional<(Optional<Klass>, Any)>, case #Optional.some!enumelt: success, case #Optional.none!enumelt: failure
|
|
success(%instance : @owned $(Optional<Klass>, Any)):
|
|
%borrow = begin_borrow [lexical] %instance : $(Optional<Klass>, Any)
|
|
(%klass, %any) = destructure_tuple %borrow : $(Optional<Klass>, Any)
|
|
apply undef<Any>(%any) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
|
|
end_borrow %borrow : $(Optional<Klass>, Any)
|
|
destroy_value %instance : $(Optional<Klass>, Any)
|
|
br exit
|
|
|
|
failure:
|
|
br exit
|
|
|
|
exit:
|
|
%505 = tuple ()
|
|
return %505 : $()
|
|
}
|
|
|
|
// Verify that projections from the unchecked_take_enum_data_addr are dominated
|
|
// by it.
|
|
// CHECK-LABEL: sil [ossa] @test_destructure_tuple_2_from_enum : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[INOUT_ADDR:%[^,]+]] :
|
|
// CHECK: [[ORIGINAL_ADDR:%[^,]+]] = alloc_stack $PairEnum<T>
|
|
// CHECK: [[NEW_ADDR:%[^,]+]] = alloc_stack $PairEnum<T>
|
|
// CHECK: copy_addr [[INOUT_ADDR]] to [init] [[ORIGINAL_ADDR]] : $*PairEnum<T>
|
|
// CHECK: switch_enum_addr [[ORIGINAL_ADDR]] : $*PairEnum<T>
|
|
// CHECK: bb1:
|
|
// CHECK: [[ORIGINAL_PAYLOAD_ADDR:%[^,]+]] = unchecked_take_enum_data_addr [[ORIGINAL_ADDR]]
|
|
// CHECK: [[NEW_PAYLOAD_ADDR:%[^,]+]] = init_enum_data_addr [[NEW_ADDR]]
|
|
// CHECK: [[NEW_FIRST_ADDR:%[^,]+]] = tuple_element_addr [[NEW_PAYLOAD_ADDR]] {{.*}}, 0
|
|
// CHECK: [[ORIGINAL_FIRST_ADDR:%[^,]+]] = tuple_element_addr [[ORIGINAL_PAYLOAD_ADDR]] {{.*}}, 0
|
|
// CHECK: apply undef<T>([[NEW_FIRST_ADDR]], [[ORIGINAL_FIRST_ADDR]])
|
|
// CHECK: [[NEW_SECOND_ADDR:%[^,]+]] = tuple_element_addr [[NEW_PAYLOAD_ADDR]] {{.*}}, 1
|
|
// CHECK: [[ORIGINAL_SECOND_ADDR:%[^,]+]] = tuple_element_addr [[ORIGINAL_PAYLOAD_ADDR]] {{.*}}, 1
|
|
// CHECK: copy_addr [[ORIGINAL_SECOND_ADDR]] to [init] [[NEW_SECOND_ADDR]] : $*T
|
|
// CHECK: inject_enum_addr [[NEW_ADDR]]
|
|
// CHECK: destroy_addr [[NEW_ADDR]]
|
|
// CHECK: destroy_addr [[ORIGINAL_SECOND_ADDR]]
|
|
// CHECK: destroy_addr [[ORIGINAL_FIRST_ADDR]]
|
|
// CHECK: dealloc_stack [[NEW_ADDR]]
|
|
// CHECK: dealloc_stack [[ORIGINAL_ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'test_destructure_tuple_2_from_enum'
|
|
sil [ossa] @test_destructure_tuple_2_from_enum : $@convention(thin) <T> (@inout PairEnum<T>) -> () {
|
|
entry(%inout_addr : $*PairEnum<T>):
|
|
%original = load [copy] %inout_addr : $*PairEnum<T>
|
|
switch_enum %original : $PairEnum<T>, case #PairEnum.it!enumelt: it_block
|
|
|
|
it_block(%original_payload : @owned $(T, T)):
|
|
(%original_first, %original_second) = destructure_tuple %original_payload : $(T, T)
|
|
%new_first = apply undef<T>(%original_first) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0
|
|
%new_second = copy_value %original_second : $T
|
|
%new_payload = tuple (%new_first : $T, %new_second : $T)
|
|
%new = enum $PairEnum<T>, #PairEnum.it!enumelt, %new_payload : $(T, T)
|
|
destroy_value %new : $PairEnum<T>
|
|
destroy_value %original_second : $T
|
|
destroy_value %original_first : $T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// Check that the end_borrows created on behalf of the destructure_tuple end
|
|
// after the use of the load_borrow of the projection of the terminator result
|
|
// of the switch_enum that is guaranteed by that load_borrow.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @test_destructure_tuple_load_borrow_projected_box : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[OUTER:%[^,]+]] :
|
|
// CHECK: switch_enum [[OUTER]] : $RE<T>, case #RE.recursive!enumelt: [[OUTER_RECURSIVE:bb[0-9]+]], case #RE.other!enumelt: [[OUTER_OTHER:bb[0-9]+]]
|
|
// CHECK: [[OUTER_OTHER]]({{%[^,]+}} :
|
|
// CHECK: br [[EXIT:bb[0-9]+]]
|
|
// CHECK: [[OUTER_RECURSIVE]]([[TUPLE_BOX:%[^,]+]] :
|
|
// CHECK-NEXT: [[TUPLE_ADDR:%[^,]+]] = project_box [[TUPLE_BOX]]
|
|
// CHECK: [[INNER_ADDR:%[^,]+]] = tuple_element_addr [[TUPLE_ADDR]]
|
|
// CHECK: [[INNER:%[^,]+]] = load_borrow [[INNER_ADDR]]
|
|
// CHECK: switch_enum [[INNER]] : $RE<T>, case #RE.recursive!enumelt: [[INNER_RECURSIVE:bb[0-9]+]], case #RE.other!enumelt: [[INNER_OTHER:bb[0-9]+]]
|
|
// CHECK: [[INNER_OTHER]]([[OTHER_BOX:%[^,]+]] :
|
|
// CHECK: [[OTHER_ADDR:%[^,]+]] = project_box [[OTHER_BOX]]
|
|
// CHECK: [[OTHER:%[^,]+]] = load_borrow [[OTHER_ADDR]]
|
|
// CHECK: [[OTHER_COPY:%[^,]+]] = copy_value [[OTHER]]
|
|
// CHECK: end_borrow [[OTHER]]
|
|
// CHECK: end_borrow [[INNER]]
|
|
// CHECK: destroy_value [[OTHER_COPY]]
|
|
// CHECK: br [[EXIT]]
|
|
// CHECK: [[INNER_RECURSIVE]]
|
|
// CHECK: end_borrow [[INNER]]
|
|
// CHECK: br [[EXIT]]
|
|
// CHECK-LABEL: } // end sil function 'test_destructure_tuple_load_borrow_projected_box'
|
|
sil [ossa] @test_destructure_tuple_load_borrow_projected_box : $@convention(thin) <T> (@guaranteed RE<T>) -> () {
|
|
entry(%o : @guaranteed $RE<T>):
|
|
switch_enum %o : $RE<T>, case #RE.recursive!enumelt: outer_recursive, case #RE.other!enumelt: outer_other
|
|
|
|
outer_other(%other : @guaranteed $<τ_0_0> { var AnyObject } <T>):
|
|
br exit
|
|
|
|
outer_recursive(%tuple_box : @guaranteed $<Tau> { var (RE<Tau>, Tau) } <T>):
|
|
%tuple_addr = project_box %tuple_box : $<Tau> { var (RE<Tau>, Tau) } <T>, 0
|
|
%tuple = load_borrow %tuple_addr : $*(RE<T>, T)
|
|
(%i, %c) = destructure_tuple %tuple : $(RE<T>, T)
|
|
switch_enum %i : $RE<T>, case #RE.recursive!enumelt: inner_recursive, case #RE.other!enumelt: inner_other
|
|
|
|
inner_recursive(%in_tuple_box : @guaranteed $<Tau> { var (RE<Tau>, Tau) } <T>):
|
|
end_borrow %tuple : $(RE<T>, T)
|
|
br exit
|
|
|
|
inner_other(%s_box : @guaranteed $<Tau> { var AnyObject } <T>):
|
|
%s_addr = project_box %s_box : $<Tau> { var AnyObject } <T>, 0
|
|
%s = load_borrow %s_addr : $*AnyObject
|
|
%sc = copy_value %s : $AnyObject
|
|
end_borrow %s : $AnyObject
|
|
end_borrow %tuple : $(RE<T>, T)
|
|
destroy_value %sc : $AnyObject
|
|
br exit
|
|
|
|
exit:
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// Verify that the init_enum_data_addr instruction is created before its first
|
|
// use. Although the opaque values are visited in forward order, their
|
|
// uses are visited at the same time. At that point, addresses are
|
|
// materialized, and, in this case, an init_enum_data_addr is created.
|
|
//
|
|
// In this test, because %second_in is the first opaque value (i.e. in forward
|
|
// order), its copy_value use is visited before %first_out is defined. If the
|
|
// init_enum_data_addr were created at that point and reused from then on, it
|
|
// would be reused when rewriting the def of %first_out:
|
|
//
|
|
// %second_in_addr = alloc_stack $T
|
|
// %out_addr = alloc_stack $PairEnum<T>
|
|
// apply undef<T>(%second_in_addr)
|
|
// %first_out_addr = tuple_element_addr %enum_data_addr, 0
|
|
// ^^^^^^^^^^^^^^^ USE BEFORE DEF
|
|
// apply undef<T>(%first_out_addr)
|
|
// %enum_data_addr = init_enum_data_addr %out_addr
|
|
// %second_out_addr = tuple_element_addr %enum_data_addr, 1
|
|
// copy_addr %second_in_addr to [init] %second_out_addr
|
|
//
|
|
// We would end up with a use of %enum_data_addr (in the definition of
|
|
// %first_out_addr) that is not dominated by %enum_data_addr's def.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @test_enum_1_tuple_projection_dominance : {{.*}} {
|
|
// CHECK: [[SECOND_IN_ADDR:%[^,]+]] = alloc_stack $T
|
|
// CHECK: [[OUT_ADDR:%[^,]+]] = alloc_stack $PairEnum<T>
|
|
// CHECK: apply undef<T>([[SECOND_IN_ADDR]])
|
|
// CHECK: [[ENUM_DATA_ADDR:%[^,]+]] = init_enum_data_addr [[OUT_ADDR]]
|
|
// CHECK: [[FIRST_OUT_ADDR:%[^,]+]] = tuple_element_addr [[ENUM_DATA_ADDR]]{{.*}}, 0
|
|
// CHECK: apply undef<T>([[FIRST_OUT_ADDR]])
|
|
// CHECK: [[SECOND_OUT_ADDR:%[^,]+]] = tuple_element_addr [[ENUM_DATA_ADDR]]{{.*}}, 1
|
|
// CHECK: copy_addr [[SECOND_IN_ADDR]] to [init] [[SECOND_OUT_ADDR]]
|
|
// CHECK: inject_enum_addr [[OUT_ADDR]]
|
|
// CHECK: destroy_addr [[OUT_ADDR]]
|
|
// CHECK: destroy_addr [[SECOND_IN_ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'test_enum_1_tuple_projection_dominance'
|
|
sil [ossa] @test_enum_1_tuple_projection_dominance : $@convention(thin) <T> () -> () {
|
|
bb0:
|
|
%second_in = apply undef<T>() : $@convention(thin) <Tee> () -> @out Tee
|
|
%first_out = apply undef<T>() : $@convention(thin) <Tee> () -> @out Tee
|
|
%second_out = copy_value %second_in : $T
|
|
%pair_out = tuple (%first_out : $T, %second_out : $T)
|
|
%out = enum $PairEnum<T>, #PairEnum.it!enumelt, %pair_out : $(T, T)
|
|
destroy_value %out : $PairEnum<T>
|
|
destroy_value %second_in : $T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// Verify that ignored_use of an address-only type gets lowered correctly.
|
|
// CHECK-LABEL: sil [ossa] @test_ignored_use : $@convention(thin) () -> () {
|
|
// CHECK: [[RETVAL_ADDR:%[^,]+]] = alloc_stack $Any
|
|
// CHECK: [[MAKE_INT:%[^,]+]] = function_ref @produceInt : $@convention(thin) () -> Builtin.Int64
|
|
// CHECK: [[INT:%[^,]+]] = apply [[MAKE_INT]]()
|
|
// CHECK: [[ERASE_FN:%[^,]+]] = function_ref @eraseToAny : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out Any
|
|
// CHECK: [[ARG_ADDR:%[^,]+]] = alloc_stack $Builtin.Int64
|
|
// CHECK: store [[INT]] to [trivial] [[ARG_ADDR]] : $*Builtin.Int64
|
|
// CHECK: = apply [[ERASE_FN]]<Builtin.Int64>([[RETVAL_ADDR]], [[ARG_ADDR]]) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out Any
|
|
// CHECK: dealloc_stack [[ARG_ADDR]] : $*Builtin.Int64
|
|
// CHECK: ignored_use [[RETVAL_ADDR]] : $*Any
|
|
// CHECK: destroy_addr [[RETVAL_ADDR]] : $*Any
|
|
// CHECK: dealloc_stack [[RETVAL_ADDR]] : $*Any
|
|
// CHECK: } // end sil function 'test_ignored_use'
|
|
sil [ossa] @test_ignored_use : $@convention(thin) () -> () {
|
|
bb0:
|
|
%1 = function_ref @produceInt : $@convention(thin) () -> Int
|
|
%2 = apply %1() : $@convention(thin) () -> Int
|
|
%3 = function_ref @eraseToAny : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out Any
|
|
%4 = apply %3<Int>(%2) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out Any
|
|
ignored_use %4
|
|
destroy_value %4
|
|
%5 = tuple ()
|
|
return %5
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_mark_unresolved_non_copyable_value_1_consumable_and_assignable : {{.*}} {
|
|
// CHECK: bb0([[T:%[^,]+]] :
|
|
// CHECK: [[TP:%[^,]+]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[T]]
|
|
// CHECK: destroy_addr [[TP]]
|
|
// CHECK-LABEL: } // end sil function 'test_mark_unresolved_non_copyable_value_1_consumable_and_assignable'
|
|
sil [ossa] @test_mark_unresolved_non_copyable_value_1_consumable_and_assignable : $@convention(thin) <T> (@in @moveOnly T) -> () {
|
|
entry(%t : @owned $@moveOnly T):
|
|
%tp = mark_unresolved_non_copyable_value [consumable_and_assignable] %t : $@moveOnly T
|
|
destroy_value %tp : $@moveOnly T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_mark_unresolved_non_copyable_value_2_no_consume_or_assign : {{.*}} {
|
|
// CHECK: bb0([[T:%[^,]+]] :
|
|
// CHECK: [[TP:%[^,]+]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[T]]
|
|
// CHECK: destroy_addr [[TP]]
|
|
// CHECK-LABEL: } // end sil function 'test_mark_unresolved_non_copyable_value_2_no_consume_or_assign'
|
|
sil [ossa] @test_mark_unresolved_non_copyable_value_2_no_consume_or_assign : $@convention(thin) <T> (@in @moveOnly T) -> () {
|
|
entry(%t : @owned $@moveOnly T):
|
|
%tp = mark_unresolved_non_copyable_value [no_consume_or_assign] %t : $@moveOnly T
|
|
destroy_value %tp : $@moveOnly T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_moveonlywrapper_to_copyable_1_owned : {{.*}} {
|
|
// CHECK: bb0([[TMO:%[^,]+]] :
|
|
// CHECK: [[T:%[^,]+]] = moveonlywrapper_to_copyable_addr [[TMO]]
|
|
// CHECK: destroy_addr [[T]]
|
|
// CHECK-LABEL: } // end sil function 'test_moveonlywrapper_to_copyable_1_owned'
|
|
sil [ossa] @test_moveonlywrapper_to_copyable_1_owned : $@convention(thin) <T> (@in @moveOnly T) -> () {
|
|
entry(%tmo : @owned $@moveOnly T):
|
|
%t = moveonlywrapper_to_copyable [owned] %tmo : $@moveOnly T
|
|
destroy_value %t : $T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_moveonlywrapper_to_copyable_2_guaranteed : {{.*}} {
|
|
// CHECK: bb0([[TMO:%[^,]+]] :
|
|
// CHECK: [[T:%[^,]+]] = moveonlywrapper_to_copyable_addr [[TMO]]
|
|
// CHECK: [[BORROW_T:%[^,]+]] = function_ref @borrowT
|
|
// CHECK: apply [[BORROW_T]]<T>([[T]])
|
|
// CHECK-LABEL: } // end sil function 'test_moveonlywrapper_to_copyable_2_guaranteed'
|
|
sil [ossa] @test_moveonlywrapper_to_copyable_2_guaranteed : $@convention(thin) <T> (@in_guaranteed @moveOnly T) -> () {
|
|
entry(%tmo : @guaranteed $@moveOnly T):
|
|
%t = moveonlywrapper_to_copyable [guaranteed] %tmo : $@moveOnly T
|
|
%borrowT = function_ref @borrowT : $@convention(thin) <T> (@in_guaranteed T) -> ()
|
|
apply %borrowT<T>(%t) : $@convention(thin) <T> (@in_guaranteed T) -> ()
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_open_pack_element_dominance : $@convention(thin) <each T> (@pack_guaranteed Pack{repeat each T}, Builtin.Word) -> () {
|
|
// CHECK: bb0([[PACK:%[^,]+]] :
|
|
// CHECK-SAME: [[RAW_INDEX:%[^,]+]] :
|
|
// CHECK: [[INDEX:%[^,]+]] = dynamic_pack_index [[RAW_INDEX]]
|
|
// CHECK: open_pack_element [[INDEX]] {{.*}}, uuid "00000000-0000-0000-0000-000000000003"
|
|
// CHECK: [[STACK:%[^,]+]] = alloc_stack $@pack_element("00000000-0000-0000-0000-000000000003")
|
|
// CHECK: [[ELEMENT_ADDR:%[^,]+]] = pack_element_get [[INDEX]] of [[PACK]]
|
|
// CHECK: copy_addr [[ELEMENT_ADDR]] to [init] [[STACK]]
|
|
// CHECK: destroy_addr [[STACK]]
|
|
// CHECK: dealloc_stack [[STACK]]
|
|
// CHECK-LABEL: } // end sil function 'test_open_pack_element_dominance'
|
|
sil [ossa] @test_open_pack_element_dominance : $@convention(thin) <each T> (@pack_guaranteed Pack{repeat each T}, Builtin.Word) -> () {
|
|
bb0(%pack : $*Pack{repeat each T}, %raw_index : $Builtin.Word):
|
|
%index = dynamic_pack_index %raw_index of $Pack{repeat each T}
|
|
open_pack_element %index of <each T> at <Pack{repeat each T}>, shape $each T, uuid "00000000-0000-0000-0000-000000000003"
|
|
%element_addr = pack_element_get %index of %pack : $*Pack{repeat each T} as $*@pack_element("00000000-0000-0000-0000-000000000003") each T
|
|
%element = load [copy] %element_addr : $*@pack_element("00000000-0000-0000-0000-000000000003") each T
|
|
destroy_value %element : $@pack_element("00000000-0000-0000-0000-000000000003") each T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_partial_apply_1_addronly_heap : {{.*}} {
|
|
// CHECK: [[STACK:%[^,]+]] = alloc_stack $T
|
|
// CHECK: [[GET:%[^,]+]] = function_ref @getT
|
|
// CHECK: apply [[GET]]<T>([[STACK]])
|
|
// CHECK: [[BORROW:%[^,]+]] = function_ref @borrowT
|
|
// CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [[BORROW]]<T>([[STACK]])
|
|
// CHECK: apply [[CLOSURE]]()
|
|
// CHECK: destroy_value [[CLOSURE]]
|
|
// CHECK: dealloc_stack [[STACK]]
|
|
// CHECK-LABEL: } // end sil function 'test_partial_apply_1_addronly_heap'
|
|
sil [ossa] @test_partial_apply_1_addronly_heap : $<T> () -> () {
|
|
%get = function_ref @getT : $@convention(thin) <T> () -> (@out T)
|
|
%instance = apply %get<T>() : $@convention(thin) <T> () -> (@out T)
|
|
%callee = function_ref @borrowT : $@convention(thin) <T> (@in_guaranteed T) -> ()
|
|
%closure = partial_apply [callee_guaranteed] %callee<T>(%instance) : $@convention(thin) <T> (@in_guaranteed T) -> ()
|
|
apply %closure() : $@callee_guaranteed () -> ()
|
|
destroy_value %closure : $@callee_guaranteed () -> ()
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_partial_apply_2_addronly_stack : {{.*}} {
|
|
// CHECK: [[STACK:%[^,]+]] = alloc_stack $T
|
|
// CHECK: [[GET:%[^,]+]] = function_ref @getT
|
|
// CHECK: apply [[GET]]<T>([[STACK]])
|
|
// CHECK: [[BORROW:%[^,]+]] = function_ref @borrowT
|
|
// CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [on_stack] [[BORROW]]<T>([[STACK]])
|
|
// CHECK: apply [[CLOSURE]]()
|
|
// CHECK: destroy_value [[CLOSURE]]
|
|
// CHECK: destroy_addr [[STACK]]
|
|
// CHECK: dealloc_stack [[STACK]]
|
|
// CHECK-LABEL: } // end sil function 'test_partial_apply_2_addronly_stack'
|
|
sil [ossa] @test_partial_apply_2_addronly_stack : $<T> () -> () {
|
|
%get = function_ref @getT : $@convention(thin) <T> () -> (@out T)
|
|
%instance = apply %get<T>() : $@convention(thin) <T> () -> (@out T)
|
|
%callee = function_ref @borrowT : $@convention(thin) <T> (@in_guaranteed T) -> ()
|
|
%closure = partial_apply [on_stack] [callee_guaranteed] %callee<T>(%instance) : $@convention(thin) <T> (@in_guaranteed T) -> ()
|
|
apply %closure() : $@noescape @callee_guaranteed () -> ()
|
|
destroy_value %closure : $@noescape @callee_guaranteed () -> ()
|
|
destroy_value %instance : $T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_partial_apply_3_loadable_heap : {{.*}} {
|
|
// CHECK: [[GET:%[^,]+]] = function_ref @getKlass
|
|
// CHECK: [[INSTANCE:%[^,]+]] = apply [[GET]]()
|
|
// CHECK: [[BORROW:%[^,]+]] = function_ref @borrowKlass
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $Klass
|
|
// CHECK: store [[INSTANCE]] to [init] [[ADDR]]
|
|
// CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [[BORROW]]([[ADDR]])
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK: apply [[CLOSURE]]()
|
|
// CHECK: destroy_value [[CLOSURE]]
|
|
// CHECK-LABEL: } // end sil function 'test_partial_apply_3_loadable_heap'
|
|
sil [ossa] @test_partial_apply_3_loadable_heap : $() -> () {
|
|
%get = function_ref @getKlass : $@convention(thin) () -> (@owned Klass)
|
|
%instance = apply %get() : $@convention(thin) () -> (@owned Klass)
|
|
%callee = function_ref @borrowKlass : $@convention(thin) (@in_guaranteed Klass) -> ()
|
|
%closure = partial_apply [callee_guaranteed] %callee(%instance) : $@convention(thin) (@in_guaranteed Klass) -> ()
|
|
apply %closure() : $@callee_guaranteed () -> ()
|
|
destroy_value %closure : $@callee_guaranteed () -> ()
|
|
// destroy_value %instance : $Klass
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_partial_apply_4_loadable_stack : {{.*}} {
|
|
// CHECK: [[GET:%[^,]+]] = function_ref @getKlass
|
|
// CHECK: [[INSTANCE:%[^,]+]] = apply [[GET]]()
|
|
// CHECK: [[BORROW:%[^,]+]] = function_ref @borrowKlass
|
|
// CHECK: [[STACK:%[^,]+]] = alloc_stack $Klass
|
|
// CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [[INSTANCE]]
|
|
// CHECK: [[STORAGE_LIFETIME:%[^,]+]] = store_borrow [[LIFETIME]] to [[STACK]]
|
|
// CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [on_stack] [[BORROW]]([[STORAGE_LIFETIME]])
|
|
// FIXME: These end_borrows must be _after_ the apply of the closure!
|
|
// CHECK: end_borrow [[STORAGE_LIFETIME]]
|
|
// CHECK: end_borrow [[LIFETIME]]
|
|
// CHECK: dealloc_stack [[STACK]]
|
|
// CHECK: apply [[CLOSURE]]() : $@noescape @callee_guaranteed () -> ()
|
|
// CHECK: destroy_value [[CLOSURE]] : $@noescape @callee_guaranteed () -> ()
|
|
// CHECK: destroy_value [[INSTANCE]]
|
|
// CHECK-LABEL: } // end sil function 'test_partial_apply_4_loadable_stack'
|
|
sil [ossa] @test_partial_apply_4_loadable_stack : $() -> () {
|
|
%get = function_ref @getKlass : $@convention(thin) () -> (@owned Klass)
|
|
%instance = apply %get() : $@convention(thin) () -> (@owned Klass)
|
|
%callee = function_ref @borrowKlass : $@convention(thin) (@in_guaranteed Klass) -> ()
|
|
%closure = partial_apply [on_stack] [callee_guaranteed] %callee(%instance) : $@convention(thin) (@in_guaranteed Klass) -> ()
|
|
apply %closure() : $@noescape @callee_guaranteed () -> ()
|
|
destroy_value %closure : $@noescape @callee_guaranteed () -> ()
|
|
destroy_value %instance : $Klass
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_partial_apply_5_indexing : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[C:%[^,]+]] :
|
|
// CHECK: [[CALLEE:%[^,]+]] = function_ref @test_partial_apply_5_indexing_callee
|
|
// CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [[CALLEE]]([[C]])
|
|
// CHECK: destroy_value [[CLOSURE]]
|
|
// CHECK-LABEL: } // end sil function 'test_partial_apply_5_indexing'
|
|
sil @test_partial_apply_5_indexing_callee : $@convention(thin) (@inout Int, @guaranteed Klass) -> (@out Int)
|
|
sil [ossa] @test_partial_apply_5_indexing : $@convention(thin) (@owned Klass) -> () {
|
|
bb0(%c : @owned $Klass):
|
|
%callee = function_ref @test_partial_apply_5_indexing_callee : $@convention(thin) (@inout Int, @guaranteed Klass) -> (@out Int)
|
|
%closure = partial_apply [callee_guaranteed] %callee(%c) : $@convention(thin) (@inout Int, @guaranteed Klass) -> (@out Int)
|
|
destroy_value %closure : $@callee_guaranteed (@inout Int) -> (@out Int)
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @test_store_1 : {{.*}} {
|
|
// CHECK: [[MAYBE_ADDR:%[^,]+]] = alloc_stack $Optional<Self>
|
|
// CHECK: [[LOAD_ADDR:%[^,]+]] = alloc_stack $Self
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $Self, var, name "self"
|
|
// CHECK: [[INSTANCE_ADDR:%[^,]+]] = unchecked_take_enum_data_addr [[MAYBE_ADDR]] : $*Optional<Self>, #Optional.some!enumelt
|
|
// CHECK: debug_value [[INSTANCE_ADDR]] : $*Self, var, name "self", expr op_deref
|
|
// CHECK: copy_addr [take] [[INSTANCE_ADDR]] to [init] [[ADDR]]
|
|
// CHECK: copy_addr [[ADDR]] to [init] [[LOAD_ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'test_store_1'
|
|
sil hidden [ossa] @test_store_1 : $@convention(thin) <Self> () -> () {
|
|
bb0:
|
|
%addr = alloc_stack $Self, var, name "self"
|
|
%maybe = apply undef<Self>() : $@convention(thin) <τ_0_0> () -> @out Optional<τ_0_0>
|
|
%instance = unchecked_enum_data %maybe : $Optional<Self>, #Optional.some!enumelt
|
|
store %instance to [init] %addr : $*Self
|
|
%load = load [copy] %addr : $*Self
|
|
destroy_addr %addr : $*Self
|
|
dealloc_stack %addr : $*Self
|
|
destroy_value %load : $Self
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_store_borrow_1_copy_addr : {{.*}} {
|
|
// CHECK: alloc_stack
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack
|
|
// CHECK: apply undef<T>([[ADDR]])
|
|
// CHECK: [[COPY:%[^,]+]] = alloc_stack
|
|
// CHECK: copy_addr [[ADDR]] to [init] [[COPY]]
|
|
// CHECK: apply undef<T>([[COPY]])
|
|
// CHECK: destroy_addr [[COPY]]
|
|
// CHECK: dealloc_stack [[COPY]]
|
|
// CHECK-NOT: end_borrow [[ADDR]]
|
|
// CHECK: destroy_addr [[ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'test_store_borrow_1_copy_addr'
|
|
sil [ossa] @test_store_borrow_1_copy_addr : $@convention(thin) <T> () -> () {
|
|
entry:
|
|
%addr = alloc_stack $T
|
|
%instance = apply undef<T>() : $@convention(thin) <τ> () -> (@out τ)
|
|
%lifetime = begin_borrow %instance : $T
|
|
%borrow = store_borrow %lifetime to %addr : $*T
|
|
%copy = alloc_stack $T
|
|
copy_addr %borrow to [init] %copy : $*T
|
|
apply undef<T>(%copy) : $@convention(thin) <τ> (@inout τ) -> ()
|
|
destroy_addr %copy : $*T
|
|
dealloc_stack %copy : $*T
|
|
end_borrow %borrow : $*T
|
|
end_borrow %lifetime : $T
|
|
dealloc_stack %addr : $*T
|
|
destroy_value %instance : $T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_struct_1_two_use_projections : {{.*}} {
|
|
// CHECK: [[S_ADDR:%[^,]+]] = alloc_stack $Box<T>
|
|
// CHECK: [[S2_ADDR:%[^,]+]] = alloc_stack $Box<T>
|
|
// CHECK: [[S_FIELD_ADDR:%[^,]+]] = struct_element_addr [[S_ADDR]] : $*Box<T>, #Box.t
|
|
// CHECK: apply undef<T>([[S_FIELD_ADDR]])
|
|
// CHECK: cond_br undef, [[LEFT:bb[0-9]+]], [[RIGHT:bb[0-9]+]]
|
|
// CHECK: [[RIGHT]]:
|
|
// CHECK: destroy_addr [[S_ADDR]] : $*Box<T>
|
|
// CHECK: br [[EXIT:bb[0-9]+]]
|
|
// CHECK: [[LEFT]]:
|
|
// CHECK: [[S2_FIELD_ADDR:%[^,]+]] = struct_element_addr [[S2_ADDR]] : $*Box<T>, #Box.t
|
|
// CHECK: copy_addr [take] [[S_FIELD_ADDR]] to [init] [[S2_FIELD_ADDR]]
|
|
// CHECK: destroy_addr [[S2_ADDR]] : $*Box<T>
|
|
// CHECK: br [[EXIT]]
|
|
// CHECK: [[EXIT]]:
|
|
// CHECK: dealloc_stack [[S2_ADDR]] : $*Box<T>
|
|
// CHECK: dealloc_stack [[S_ADDR]] : $*Box<T>
|
|
// CHECK-LABEL: } // end sil function 'test_struct_1_two_use_projections'
|
|
sil [ossa] @test_struct_1_two_use_projections : $@convention(thin) <T> () -> () {
|
|
entry:
|
|
%box = apply undef<T>() : $@convention(thin) <T> () -> (@out T)
|
|
cond_br undef, left, right
|
|
|
|
left:
|
|
%s2 = struct $Box<T>(%box : $T)
|
|
destroy_value %s2 : $Box<T>
|
|
br exit
|
|
|
|
right:
|
|
%s = struct $Box<T>(%box : $T)
|
|
destroy_value %s : $Box<T>
|
|
br exit
|
|
|
|
exit:
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_tuple_pack_extract : {{.*}} {
|
|
// CHECK: bb0([[TUPLE_PACK_ADDR:%[^,]+]] :
|
|
// CHECK: [[INDEX:%[^,]+]] = dynamic_pack_index
|
|
// CHECK: open_pack_element [[INDEX]] of <each U_1> at <Pack{repeat each T}>, shape $each U_1, uuid [[UUID:".*"]]
|
|
// CHECK: [[BORROW:%[^,]+]] = function_ref @borrowT
|
|
// CHECK: [[ELEMENT_ADDR:%[^,]+]] = tuple_pack_element_addr [[INDEX]] of [[TUPLE_PACK_ADDR]] : {{.*}} as $*@pack_element([[UUID]]) each U_1
|
|
// CHECK: apply [[BORROW]]<@pack_element([[UUID]]) each U_1>([[ELEMENT_ADDR]])
|
|
// CHECK-LABEL: } // end sil function 'test_tuple_pack_extract'
|
|
sil [ossa] @test_tuple_pack_extract : $@convention(thin) <each T> (@in_guaranteed (repeat each T)) -> () {
|
|
entry(%tuple_addr : $*(repeat each T)):
|
|
%tuple = load_borrow %tuple_addr : $*(repeat each T)
|
|
%zero = integer_literal $Builtin.Word, 0
|
|
%index = dynamic_pack_index %zero of $Pack{repeat each T}
|
|
%opened = open_pack_element %index of <each U_1> at <Pack{repeat each T}>, shape $U_1, uuid "00000000-0000-0000-0000-000000000002"
|
|
%elt = tuple_pack_extract %index of %tuple : $(repeat each T) as $@pack_element("00000000-0000-0000-0000-000000000002") U_1
|
|
%borrow = function_ref @borrowT : $@convention(thin) <T> (@in_guaranteed T) -> ()
|
|
apply %borrow<@pack_element("00000000-0000-0000-0000-000000000002") U_1>(%elt) : $@convention(thin) <T> (@in_guaranteed T) -> ()
|
|
end_borrow %tuple : $(repeat each T)
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @test_unchecked_bitwise_cast :
|
|
// CHECK: bb0(%0 : $*U, %1 : $*T, %2 : $@thick U.Type):
|
|
// CHECK: [[STK:%.*]] = alloc_stack $T
|
|
// CHECK: copy_addr %1 to [init] [[STK]] : $*T
|
|
// CHECK: [[CAST:%.*]] = unchecked_addr_cast [[STK]] : $*T to $*U
|
|
// CHECK: copy_addr [[CAST]] to [init] %0 : $*U
|
|
// CHECK: destroy_addr [[STK]] : $*T
|
|
// CHECK: dealloc_stack [[STK]] : $*T
|
|
// CHECK-LABEL: } // end sil function 'test_unchecked_bitwise_cast'
|
|
sil hidden [ossa] @test_unchecked_bitwise_cast : $@convention(thin) <T, U> (@in_guaranteed T, @thick U.Type) -> @out U {
|
|
bb0(%0 : @guaranteed $T, %1 : $@thick U.Type):
|
|
%4 = copy_value %0 : $T
|
|
%5 = unchecked_bitwise_cast %4 : $T to $U
|
|
%6 = copy_value %5 : $U
|
|
destroy_value %4 : $T
|
|
return %6 : $U
|
|
}
|
|
|
|
// There's only one use and it's a copy, just rewrite it as a load [copy].
|
|
// CHECK-LABEL: sil hidden [ossa] @test_unchecked_bitwise_cast_to_loadable :
|
|
// CHECK: {{bb[0-9]+}}([[ADDR_IN:%[^,]+]] : $*T):
|
|
// CHECK: [[STACK:%[^,]+]] = alloc_stack $T
|
|
// CHECK: copy_addr [[ADDR_IN]] to [init] [[STACK]]
|
|
// CHECK: [[STACK_AS_CLASS:%[^,]+]] = unchecked_addr_cast [[STACK]] : $*T to $*Klass
|
|
// CHECK: [[KLASS:%[^,]+]] = load [copy] [[STACK_AS_CLASS]]
|
|
// CHECK: destroy_addr [[STACK]]
|
|
// CHECK: dealloc_stack [[STACK]]
|
|
// CHECK: return [[KLASS]]
|
|
// CHECK-LABEL: } // end sil function 'test_unchecked_bitwise_cast_to_loadable'
|
|
sil hidden [ossa] @test_unchecked_bitwise_cast_to_loadable : $@convention(thin) <T> (@in_guaranteed T) -> @owned Klass {
|
|
bb0(%instance : @guaranteed $T):
|
|
%copy = copy_value %instance : $T
|
|
%unowned_klass = unchecked_bitwise_cast %copy : $T to $Klass
|
|
%klass = copy_value %unowned_klass : $Klass
|
|
destroy_value %copy : $T
|
|
return %klass : $Klass
|
|
}
|
|
|
|
// There is more than one use of the unchecked_addr_cast. The value should be
|
|
// load_borrow'd and uses of the original should be uses of that load.
|
|
// CHECK-LABEL: sil hidden [ossa] @test_unchecked_bitwise_cast_to_loadable_multiuse : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : $*T):
|
|
// CHECK: [[STACK:%[^,]+]] = alloc_stack $T
|
|
// CHECK: copy_addr [[INSTANCE]] to [init] [[STACK]]
|
|
// CHECK: [[STACK_AS_CLASS:%[^,]+]] = unchecked_addr_cast [[STACK]] : $*T to $*Klass
|
|
// CHECK: [[BORROWED_KLASS:%[^,]+]] = load_borrow [[STACK_AS_CLASS]]
|
|
// CHECK: [[KLASS_TO_RETURN:%[^,]+]] = copy_value [[BORROWED_KLASS]]
|
|
// CHECK: [[KLASS_TO_DESTROY:%[^,]+]] = copy_value [[BORROWED_KLASS]]
|
|
// CHECK: end_borrow [[BORROWED_KLASS]]
|
|
// CHECK: destroy_value [[KLASS_TO_DESTROY]]
|
|
// CHECK: destroy_addr [[STACK]]
|
|
// CHECK: dealloc_stack [[STACK]]
|
|
// CHECK: return [[KLASS_TO_RETURN]]
|
|
// CHECK-LABEL: } // end sil function 'test_unchecked_bitwise_cast_to_loadable_multiuse'
|
|
sil hidden [ossa] @test_unchecked_bitwise_cast_to_loadable_multiuse : $@convention(thin) <T> (@in_guaranteed T) -> @owned Klass {
|
|
bb0(%instance : @guaranteed $T):
|
|
%copy = copy_value %instance : $T
|
|
%unowned_klass = unchecked_bitwise_cast %copy : $T to $Klass
|
|
%klass = copy_value %unowned_klass : $Klass
|
|
%klass2 = copy_value %unowned_klass : $Klass
|
|
destroy_value %klass2 : $Klass
|
|
destroy_value %copy : $T
|
|
return %klass : $Klass
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @test_unconditional_checked_cast1 : $@convention(thin) <T> (Builtin.Int64) -> @out T {
|
|
// CHECK: bb0(%0 : $*T, %1 : $Builtin.Int64):
|
|
// CHECK: [[INT:%.*]] = alloc_stack $Builtin.Int64
|
|
// CHECK: store %1 to [trivial] [[INT]] : $*Builtin.Int64
|
|
// CHECK: unconditional_checked_cast_addr Builtin.Int64 in [[INT]] : $*Builtin.Int64 to T in %0 : $*T
|
|
// CHECK: %5 = tuple ()
|
|
// CHECK: dealloc_stack %2 : $*Builtin.Int64
|
|
// CHECK: return %5 : $()
|
|
// CHECK: } // end sil function 'test_unconditional_checked_cast1'
|
|
sil hidden [ossa] @test_unconditional_checked_cast1 : $@convention(thin) <T> (Int) -> @out T {
|
|
bb0(%0 : $Int):
|
|
%2 = unconditional_checked_cast %0 : $Int to T
|
|
return %2 : $T
|
|
}
|
|
|
|
// CHECK: sil hidden [ossa] @test_unconditional_checked_cast2 : $@convention(thin) <T> (@in_guaranteed T) -> Builtin.Int64 {
|
|
// CHECK: bb0(%0 : $*T):
|
|
// CHECK: [[SRC:%.*]] = alloc_stack $T
|
|
// CHECK: copy_addr %0 to [init] [[SRC]] : $*T
|
|
// CHECK: [[INT:%.*]] = alloc_stack $Builtin.Int64
|
|
// CHECK: unconditional_checked_cast_addr T in [[SRC]] : $*T to Builtin.Int64 in [[INT]] : $*Builtin.Int64
|
|
// CHECK: [[RES:%.*]] = load [trivial] [[INT]] : $*Builtin.Int64
|
|
// CHECK: return [[RES]] : $Builtin.Int64
|
|
// CHECK: } // end sil function 'test_unconditional_checked_cast2'
|
|
sil hidden [ossa] @test_unconditional_checked_cast2 : $@convention(thin) <T> (@in_guaranteed T) -> Int {
|
|
bb0(%0 : @guaranteed $T):
|
|
%2 = copy_value %0 : $T
|
|
%3 = unconditional_checked_cast %2 : $T to Int
|
|
return %3 : $Int
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @test_unconditional_checked_cast3 : $@convention(thin) <T, U> (@in_guaranteed T) -> @out U {
|
|
// CHECK: bb0(%0 : $*U, %1 : $*T):
|
|
// CHECK: [[TTMP:%.*]] = alloc_stack $T
|
|
// CHECK: copy_addr %1 to [init] [[TTMP]] : $*T
|
|
// CHECK: [[UTMP:%.*]] = alloc_stack [lexical] $U
|
|
// CHECK: unconditional_checked_cast_addr T in [[TTMP]] : $*T to U in [[UTMP]] : $*U
|
|
// CHECK: copy_addr [[UTMP]] to [init] %0 : $*U
|
|
// CHECK: destroy_addr [[UTMP]] : $*U
|
|
// CHECK: %8 = tuple ()
|
|
// CHECK: dealloc_stack [[UTMP]] : $*U
|
|
// CHECK: dealloc_stack [[TTMP]] : $*T
|
|
// CHECK: return %8 : $()
|
|
// CHECK-LABEL: } // end sil function 'test_unconditional_checked_cast3'
|
|
sil hidden [ossa] @test_unconditional_checked_cast3 : $@convention(thin) <T, U> (@in_guaranteed T) -> @out U {
|
|
bb0(%0 : @guaranteed $T):
|
|
%2 = copy_value %0 : $T
|
|
%3 = unconditional_checked_cast %2 : $T to U
|
|
%4 = begin_borrow [lexical] %3 : $U
|
|
%6 = copy_value %4 : $U
|
|
end_borrow %4 : $U
|
|
destroy_value %3 : $U
|
|
return %6 : $U
|
|
}
|
|
|
|
// Verify lowering of unconditional_checked_cast not involving address-only
|
|
// values.
|
|
// CHECK-LABEL: sil hidden [ossa] @test_unconditional_checked_cast4 : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[SRC:%[^,]+]] :
|
|
// CHECK: [[SRC_ADDR:%[^,]+]] = alloc_stack $AnyObject
|
|
// CHECK: store [[SRC]] to [init] [[SRC_ADDR]] : $*AnyObject
|
|
// CHECK: [[DEST_ADDR:%[^,]+]] = alloc_stack $@thick any AnyObject.Type
|
|
// CHECK: unconditional_checked_cast_addr AnyObject in [[SRC_ADDR]] {{.*}} to @thick any AnyObject.Type in [[DEST_ADDR]]
|
|
// CHECK: load [trivial] [[DEST_ADDR]] : $*@thick any AnyObject.Type
|
|
// CHECK-LABEL: } // end sil function 'test_unconditional_checked_cast4'
|
|
sil hidden [ossa] @test_unconditional_checked_cast4 : $@convention(thin) (@owned AnyObject) -> () {
|
|
entry(%instance : @owned $AnyObject):
|
|
%casted = unconditional_checked_cast %instance : $AnyObject to any AnyObject.Type
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// Verify lowering of unconditional_checked_cast that involves address-only
|
|
// values and also non-address-only values which on its own requires lowering
|
|
// to unconditional_checked_cast_addr.
|
|
// CHECK-LABEL: sil [ossa] @test_unconditional_checked_cast5 : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[SRC_ADDR:%[^,]+]] :
|
|
// CHECK: [[DEST_ADDR:%[^,]+]] = alloc_stack $@thick any AnyObject.Type
|
|
// CHECK: unconditional_checked_cast_addr T in [[SRC_ADDR]] {{.*}} to @thick any AnyObject.Type in [[DEST_ADDR]]
|
|
// CHECK: load [trivial] [[DEST_ADDR]] : $*@thick any AnyObject.Type
|
|
// CHECK-LABEL: } // end sil function 'test_unconditional_checked_cast5'
|
|
sil [ossa] @test_unconditional_checked_cast5 : $@convention(thin) <T> (@in T) -> () {
|
|
entry(%instance : @owned $T):
|
|
%casted = unconditional_checked_cast %instance : $T to any AnyObject.Type
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_unconditional_checked_cast6 : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] :
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $Klass
|
|
// CHECK: unconditional_checked_cast_addr T in [[INSTANCE]]
|
|
// CHECK: [[KLASS:%[^,]+]] = load [take] [[ADDR]]
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'test_unconditional_checked_cast6'
|
|
sil [ossa] @test_unconditional_checked_cast6 : $@convention(method) <T> (@in T) -> () {
|
|
bb0(%instance : @owned $T):
|
|
%klass = unconditional_checked_cast %instance : $T to Klass
|
|
destroy_value %klass : $Klass
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_yield_1_two_values : {{.*}} {
|
|
// CHECK: tuple_element_addr
|
|
// CHECK: tuple_element_addr
|
|
// CHECK: [[VALUE:%[^,]+]] = tuple_element_addr {{%[^,]+}} : $*(key: Key, value: Value), 1
|
|
// CHECK: [[KEY:%[^,]+]] = tuple_element_addr {{%[^,]+}} : $*(key: Key, value: Value), 0
|
|
// CHECK: yield ([[KEY]] : $*Key, [[VALUE]] : $*Value)
|
|
// CHECK-LABEL: } // end sil function 'test_yield_1_two_values'
|
|
sil [ossa] @test_yield_1_two_values : $@yield_once @convention(method) <Key, Value> (@in_guaranteed Key, @in_guaranteed Value) -> (@yields @in_guaranteed Key, @yields @in_guaranteed Value) {
|
|
bb0(%0 : @guaranteed $Key, %1 : @guaranteed $Value):
|
|
%7 = copy_value %0 : $Key
|
|
%8 = copy_value %1 : $Value
|
|
%9 = tuple $(key: Key, value: Value) (%7, %8)
|
|
%10 = begin_borrow %9 : $(key: Key, value: Value)
|
|
%11 = tuple_extract %10 : $(key: Key, value: Value), 0
|
|
%12 = tuple_extract %10 : $(key: Key, value: Value), 1
|
|
yield (%11 : $Key, %12 : $Value), resume bb1, unwind bb2
|
|
|
|
bb1:
|
|
end_borrow %10 : $(key: Key, value: Value)
|
|
destroy_value %9 : $(key: Key, value: Value)
|
|
%17 = tuple ()
|
|
return %17 : $()
|
|
|
|
bb2:
|
|
end_borrow %10 : $(key: Key, value: Value)
|
|
destroy_value %9 : $(key: Key, value: Value)
|
|
unwind
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_yield_2_1loadable_nontrivial_guaranteed_as_inguaranteed : {{.*}} {
|
|
// CHECK: ([[INSTANCE:%[^,]+]], {{%[^,]+}}) = begin_apply
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $AnyObject
|
|
// CHECK: [[STORE_BORROW:%[^,]+]] = store_borrow [[INSTANCE]] to [[ADDR]]
|
|
// CHECK: yield [[STORE_BORROW]] {{.*}}, resume [[RESUME:bb[0-9]+]], unwind [[UNWIND:bb[0-9]+]]
|
|
// CHECK: [[UNWIND]]:
|
|
// CHECK: end_borrow [[STORE_BORROW]]
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK: [[RESUME]]:
|
|
// CHECK: end_borrow [[STORE_BORROW]]
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK-LABEL: }
|
|
sil [ossa] @test_yield_2_1loadable_nontrivial_guaranteed_as_inguaranteed : $@yield_once @convention(thin) () -> @yields @in_guaranteed AnyObject {
|
|
entry:
|
|
(%instance, %token) = begin_apply undef() : $@yield_once @convention(thin) () -> @yields @guaranteed AnyObject
|
|
yield %instance : $AnyObject, resume resumebb, unwind unwindbb
|
|
|
|
resumebb:
|
|
end_apply %token as $()
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
|
|
unwindbb:
|
|
abort_apply %token
|
|
unwind
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_yield_3_1loadable_nontrivial_owned_as_inguaranteed : $@yield_once @convention(thin) () -> @yields @in_guaranteed AnyObject {
|
|
// CHECK: [[INSTANCE:%[^,]+]] = apply
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $AnyObject
|
|
// CHECK: [[BORROW:%[^,]+]] = begin_borrow [[INSTANCE]]
|
|
// CHECK: [[STORE_BORROW:%[^,]+]] = store_borrow [[BORROW]] to [[ADDR]]
|
|
// CHECK: yield [[STORE_BORROW]] {{.*}}, resume [[RESUME:bb[0-9]+]], unwind [[UNWIND:bb[0-9]+]]
|
|
// CHECK: [[UNWIND]]:
|
|
// CHECK: end_borrow [[STORE_BORROW]]
|
|
// CHECK: end_borrow [[BORROW]]
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK: [[RESUME]]:
|
|
// CHECK: end_borrow [[STORE_BORROW]]
|
|
// CHECK: end_borrow [[BORROW]]
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'test_yield_3_1loadable_nontrivial_owned_as_inguaranteed'
|
|
sil [ossa] @test_yield_3_1loadable_nontrivial_owned_as_inguaranteed : $@yield_once @convention(thin) () -> @yields @in_guaranteed AnyObject {
|
|
entry:
|
|
%instance = apply undef() : $@convention(thin) () -> @owned AnyObject
|
|
yield %instance : $AnyObject, resume resumebb, unwind unwindbb
|
|
|
|
resumebb:
|
|
destroy_value %instance : $AnyObject
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
|
|
unwindbb:
|
|
destroy_value %instance : $AnyObject
|
|
unwind
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_yield_3_1trivial_as_inguaranteed {{.*}} {
|
|
// CHECK: [[INSTANCE:%[^,]+]] = apply
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $I
|
|
// CHECK: store [[INSTANCE]] to [trivial] [[ADDR]]
|
|
// CHECK: yield [[ADDR]] {{.*}}, resume [[RESUME:bb[0-9]+]], unwind [[UNWIND:bb[0-9]+]]
|
|
// CHECK: [[UNWIND]]:
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK: [[RESUME]]:
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'test_yield_3_1trivial_as_inguaranteed'
|
|
sil [ossa] @test_yield_3_1trivial_as_inguaranteed : $@yield_once @convention(thin) @substituted <T> () -> @yields @in_guaranteed T for <I> {
|
|
entry:
|
|
%instance = apply undef() : $@convention(thin) () -> I
|
|
yield %instance : $I, resume resumebb, unwind unwindbb
|
|
|
|
resumebb:
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
|
|
unwindbb:
|
|
unwind
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_yield_4_1addressonly_owned_as_inguaranteed : {{.*}} {
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $T
|
|
// CHECK: apply undef<T>([[ADDR]])
|
|
// CHECK: yield [[ADDR]] {{.*}}, resume bb2, unwind bb1
|
|
// CHECK: bb1:
|
|
// CHECK: destroy_addr [[ADDR]]
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK: bb2:
|
|
// CHECK: destroy_addr [[ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'test_yield_4_1addressonly_owned_as_inguaranteed'
|
|
sil [ossa] @test_yield_4_1addressonly_owned_as_inguaranteed : $@yield_once @convention(thin) <T> () -> @yields @in_guaranteed T {
|
|
entry:
|
|
%instance = apply undef<T>() : $@convention(thin) <T> () -> @out T
|
|
yield %instance : $T, resume resumebb, unwind unwindbb
|
|
|
|
resumebb:
|
|
destroy_value %instance : $T
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
|
|
unwindbb:
|
|
destroy_value %instance : $T
|
|
unwind
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_yield_5_1loadable_nontrivial_owned_as_in : {{.*}} {
|
|
// CHECK: [[INSTANCE:%[^,]+]] = apply
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $AnyObject
|
|
// CHECK: store [[INSTANCE]] to [init] [[ADDR]]
|
|
// CHECK: yield [[ADDR]] {{.*}}, resume [[RESUME:bb[0-9]+]], unwind [[UNWIND:bb[0-9]+]]
|
|
// CHECK: [[UNWIND]]:
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK: [[RESUME]]:
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'test_yield_5_1loadable_nontrivial_owned_as_in'
|
|
sil [ossa] @test_yield_5_1loadable_nontrivial_owned_as_in : $@yield_once @convention(thin) () -> @yields @in AnyObject {
|
|
entry:
|
|
%instance = apply undef() : $@convention(thin) () -> @owned AnyObject
|
|
yield %instance : $AnyObject, resume resumebb, unwind unwindbb
|
|
|
|
resumebb:
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
|
|
unwindbb:
|
|
unwind
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_yield_6_1trivial_as_in : {{.*}} {
|
|
// CHECK: [[INSTANCE:%[^,]+]] = apply
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $I
|
|
// CHECK: store [[INSTANCE]] to [trivial] [[ADDR]]
|
|
// CHECK: yield [[ADDR]] {{.*}}, resume [[RESUME:bb[0-9]+]], unwind [[UNWIND:bb[0-9]+]]
|
|
// CHECK: [[UNWIND]]:
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK: [[RESUME]]:
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'test_yield_6_1trivial_as_in'
|
|
sil [ossa] @test_yield_6_1trivial_as_in : $@yield_once @convention(thin) @substituted <T> () -> @yields @in T for <I> {
|
|
entry:
|
|
%instance = apply undef() : $@convention(thin) () -> I
|
|
yield %instance : $I, resume resumebb, unwind unwindbb
|
|
|
|
resumebb:
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
|
|
unwindbb:
|
|
unwind
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_yield_7_1addressonly_owned_as_in : {{.*}} {
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $T
|
|
// CHECK: apply undef<T>([[ADDR]])
|
|
// CHECK: yield [[ADDR]] {{.*}}, resume [[RESUME:bb[0-9]+]], unwind [[UNWIND:bb[0-9]+]]
|
|
// CHECK: [[UNWIND]]:
|
|
// CHECK: dealloc_stack [[ADDR]] : $*T
|
|
// CHECK: [[RESUME]]:
|
|
// CHECK: dealloc_stack [[ADDR]] : $*T
|
|
// CHECK-LABEL: } // end sil function 'test_yield_7_1addressonly_owned_as_in'
|
|
sil [ossa] @test_yield_7_1addressonly_owned_as_in : $@yield_once @convention(thin) <T> () -> @yields @in T {
|
|
entry:
|
|
%instance = apply undef<T>() : $@convention(thin) <T> () -> @out T
|
|
yield %instance : $T, resume resumebb, unwind unwindbb
|
|
|
|
resumebb:
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
|
|
unwindbb:
|
|
unwind
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_yield_8_1loadable_nontrivial_owned_as_inconstant : {{.*}} {
|
|
// CHECK: [[INSTANCE:%[^,]+]] = apply
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $AnyObject
|
|
// CHECK: store [[INSTANCE]] to [init] [[ADDR]] : $*AnyObject
|
|
// CHECK: yield [[ADDR]] {{.*}}, resume [[RESUME:bb[0-9]+]], unwind [[UNWIND:bb[0-9]+]]
|
|
// CHECK: [[UNWIND]]:
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK: [[RESUME]]:
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'test_yield_8_1loadable_nontrivial_owned_as_inconstant'
|
|
sil [ossa] @test_yield_8_1loadable_nontrivial_owned_as_inconstant : $@yield_once @convention(thin) () -> @yields @in_constant AnyObject {
|
|
entry:
|
|
%instance = apply undef() : $@convention(thin) () -> @owned AnyObject
|
|
yield %instance : $AnyObject, resume resumebb, unwind unwindbb
|
|
|
|
resumebb:
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
|
|
unwindbb:
|
|
unwind
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_yield_9_1trivial_as_inconstant : {{.*}} {
|
|
// CHECK: [[INSTANCE:%[^,]+]] = apply
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $I
|
|
// CHECK: store [[INSTANCE]] to [trivial] [[ADDR]]
|
|
// CHECK: yield [[ADDR]] {{.*}}, resume [[RESUME:bb[0-9]+]], unwind [[UNWIND:bb[0-9]+]]
|
|
// CHECK: [[UNWIND]]:
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK: [[RESUME]]:
|
|
// CHECK: dealloc_stack [[ADDR]]
|
|
// CHECK-LABEL: } // end sil function 'test_yield_9_1trivial_as_inconstant'
|
|
sil [ossa] @test_yield_9_1trivial_as_inconstant : $@yield_once @convention(thin) @substituted <T> () -> @yields @in_constant T for <I> {
|
|
entry:
|
|
%instance = apply undef() : $@convention(thin) () -> I
|
|
yield %instance : $I, resume resumebb, unwind unwindbb
|
|
|
|
resumebb:
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
|
|
unwindbb:
|
|
unwind
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_yield_A_1addressonly_owned_as_inconstant : {{.*}} {
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $T
|
|
// CHECK: apply undef<T>([[ADDR]])
|
|
// CHECK: yield [[ADDR]] {{.*}}, resume [[RESUME:bb[0-9]+]], unwind [[UNWIND:bb[0-9]+]]
|
|
// CHECK: [[UNWIND]]:
|
|
// CHECK: dealloc_stack [[ADDR]] : $*T
|
|
// CHECK: [[RESUME]]:
|
|
// CHECK: dealloc_stack [[ADDR]] : $*T
|
|
// CHECK-LABEL: } // end sil function 'test_yield_A_1addressonly_owned_as_inconstant'
|
|
sil [ossa] @test_yield_A_1addressonly_owned_as_inconstant : $@yield_once @convention(thin) <T> () -> @yields @in_constant T {
|
|
entry:
|
|
%instance = apply undef<T>() : $@convention(thin) <T> () -> @out T
|
|
yield %instance : $T, resume resumebb, unwind unwindbb
|
|
|
|
resumebb:
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
|
|
unwindbb:
|
|
unwind
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_yield_C_1loadable_nontrivial_guaranteed_as_inguaranteed_1address_only_owned_as_inguaranteed : {{.*}} {
|
|
// CHECK: ([[INSTANCE_1:%[^,]+]], [[INSTANCE_2:%[^,]+]], {{%[^,]+}}) = begin_apply
|
|
// CHECK: [[ADDR:%[^,]+]] = alloc_stack $AnyObject
|
|
// CHECK: [[BORROW:%[^,]+]] = store_borrow [[INSTANCE_1]] to [[ADDR]] : $*AnyObject
|
|
// CHECK: yield ([[BORROW]] : $*AnyObject, [[INSTANCE_2]] : $*T), resume [[RESUME:bb[0-9]+]], unwind [[UNWIND:bb[0-9]+]]
|
|
// CHECK: [[UNWIND]]:
|
|
// CHECK: end_borrow [[BORROW]] : $*AnyObject
|
|
// CHECK: dealloc_stack [[ADDR]] : $*AnyObject
|
|
// CHECK: [[RESUME]]:
|
|
// CHECK: end_borrow [[BORROW]] : $*AnyObject
|
|
// CHECK: dealloc_stack [[ADDR]] : $*AnyObject
|
|
// CHECK-LABEL: } // end sil function 'test_yield_C_1loadable_nontrivial_guaranteed_as_inguaranteed_1address_only_owned_as_inguaranteed'
|
|
sil [ossa] @test_yield_C_1loadable_nontrivial_guaranteed_as_inguaranteed_1address_only_owned_as_inguaranteed : $@yield_once @convention(thin) <T> () -> (@yields @in_guaranteed AnyObject, @yields @in_guaranteed T) {
|
|
entry:
|
|
(%instance_1, %instance_2, %token) = begin_apply undef() : $@yield_once @convention(thin) () -> (@yields @guaranteed AnyObject, @yields @in_guaranteed T)
|
|
yield (%instance_1 : $AnyObject, %instance_2 : $T), resume resumebb, unwind unwindbb
|
|
|
|
resumebb:
|
|
end_apply %token as $()
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
|
|
unwindbb:
|
|
abort_apply %token
|
|
unwind
|
|
}
|
|
|
|
// Verify that the type of the alloc_stack is appropriately mapped into the
|
|
// function's context.
|
|
// CHECK-LABEL: sil [ossa] @test_yield_D_loadable_generic_as_inguaranteed : {{.*}} <T> {{.*}} {
|
|
// CHECK: ([[INSTANCE_ADDR:%[^,]+]], {{%[^,]+}}) = begin_apply undef<T>()
|
|
// CHECK: [[INSTANCE:%[^,]+]] = load_borrow [[INSTANCE_ADDR:%[^,]+]]
|
|
// CHECK: [[STACK_ADDR:%[^,]+]] = alloc_stack $LoadableNontrivialGeneric<T>
|
|
// ^^^ Verify that T and not τ_0_0 appears
|
|
// CHECK: [[YIELDABLE_INSTANCE:%[^,]+]] = store_borrow [[INSTANCE:%[^,]+]] to [[STACK_ADDR:%[^,]+]]
|
|
// CHECK: yield [[YIELDABLE_INSTANCE]]
|
|
// CHECK-LABEL: } // end sil function 'test_yield_D_loadable_generic_as_inguaranteed'
|
|
sil [ossa] @test_yield_D_loadable_generic_as_inguaranteed : $@yield_once @convention(thin) <T> () -> @yields @in_guaranteed LoadableNontrivialGeneric<T> {
|
|
bb0:
|
|
(%3, %4) = begin_apply undef<T>() : $@yield_once @convention(method) <Tee> () -> @yields @in_guaranteed LoadableNontrivialGeneric<Tee>
|
|
yield %3 : $LoadableNontrivialGeneric<T>, resume bb1, unwind bb2
|
|
|
|
bb1:
|
|
end_apply %4 as $()
|
|
%7 = tuple ()
|
|
return %7 : $()
|
|
|
|
bb2:
|
|
abort_apply %4
|
|
unwind
|
|
}
|
|
|