Files
swift-mirror/test/SILOptimizer/address_lowering.sil
Erik Eckstein 18063707b5 Optimizer: enable complete OSSA lifetimes throughout the pass pipeline
This new OSSA invariant simplifies many optimizations because they don't have to take care of the corner case of incomplete lifetimes in dead-end blocks.

The implementation basically consists of these changes:
* add the lifetime completion utility
* add a flag in SILFunction which tells optimization that they need to run the lifetime completion utility
* let all optimizations complete lifetimes if necessary
* enable the ownership verifier to check complete lifetimes
2026-01-22 17:41:48 +01:00

3518 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 τ) -> ()
destroy_value [dead_end] %instance
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
}