Files
swift-mirror/test/SILOptimizer/address_lowering.sil
Erik Eckstein 98805c9141 Optimizer: let the InstructionDeleter respect deinit-barriers by default
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.
2025-12-03 15:53:56 +01:00

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
}