Files
swift-mirror/test/SILGen/functions.swift
Doug Gregor 793b3326af Implement the new rules for argument label defaults.
The rule changes are as follows:
  * All functions (introduced with the 'func' keyword) have argument
  labels for arguments beyond the first, by default. Methods are no
  longer special in this regard.
  * The presence of a default argument no longer implies an argument
  label.

The actual changes to the parser and printer are fairly simple; the
rest of the noise is updating the standard library, overlays, tests,
etc.

With the standard library, this change is intended to be API neutral:
I've added/removed #'s and _'s as appropriate to keep the user
interface the same. If we want to separately consider using argument
labels for more free functions now that the defaults in the language
have shifted, we can tackle that separately.

Fixes rdar://problem/17218256.

Swift SVN r27704
2015-04-24 19:03:30 +00:00

623 lines
29 KiB
Swift

// RUN: %target-swift-frontend -parse-stdlib -parse-as-library -emit-silgen %s | FileCheck %s
import Swift // just for Optional
typealias Int = Builtin.Int64
typealias Int64 = Builtin.Int64
typealias Bool = Builtin.Int1
var zero = getInt()
func getInt() -> Int { return zero }
func standalone_function(x: Int, _ y: Int) -> Int {
return x
}
func higher_order_function(f: (x: Int, y: Int) -> Int, _ x: Int, _ y: Int) -> Int {
return f(x: x, y: y)
}
func higher_order_function2(f: (Int, Int) -> Int, _ x: Int, _ y: Int) -> Int {
return f(x, y)
}
// -- Entry point BBs correspond to curried arguments in left-to-right order.
// CHECK-LABEL: sil hidden @_TF9functions16curried_function{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
func curried_function(var x: Int)(var y: Int) -> Int {
// CHECK: bb0(%0 : $Builtin.Int64, %1 : $Builtin.Int64):
// CHECK: [[YADDR:%[0-9]+]] = alloc_box $Builtin.Int64
// CHECK: [[XADDR:%[0-9]+]] = alloc_box $Builtin.Int64
return standalone_function(x, y)
// CHECK: [[FUNC:%[0-9]+]] = function_ref @_TF9functions19standalone_function{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
// CHECK: [[X:%[0-9]+]] = load [[XADDR]]
// CHECK: [[Y:%[0-9]+]] = load [[YADDR]]
// CHECK: apply [[FUNC]]([[X]], [[Y]])
// CHECK: return
}
// -- Curried generic function needs to forward archetypes through entry points
func generic_curried_function<T, U>(x: T)(y: U) { }
// -- Curried function that returns a function uncurries to the right "natural" level
// CHECK-LABEL: sil hidden @_TF9functions33curried_function_returns_function{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> @owned @callee_owned (Builtin.Int64) -> Builtin.Int64
func curried_function_returns_function(var x:Int)(var y:Int) -> (z:Int) -> Int {
// CHECK: bb0(%0 : $Builtin.Int64, %1 : $Builtin.Int64):
return { z in standalone_function(standalone_function(x, y), z) }
}
// -- Local function has extra uncurry level with context
// CHECK-LABEL: sil shared @_TFF9functions33curried_function_returns_function{{.*}} : $@convention(thin) (Builtin.Int64, @owned Builtin.NativeObject, @inout Builtin.Int64, @owned Builtin.NativeObject, @inout Builtin.Int64) -> Builtin.Int64
// bb0(%0 : $Builtin.NativeObject, %1 : $*Builtin.Int64, %2 : $Builtin.NativeObject, %3 : $*Builtin.Int64, %4 : $Builtin.Int64):
struct SomeStruct {
// -- Constructors and methods are uncurried in 'self'
// -- Instance methods use 'method' cc
init(x:Int, y:Int) {}
mutating
func method(x: Int) {}
mutating
func curried_method(x: Int)(y: Int) {}
static func static_method(x: Int) {}
static func static_curried_method(x: Int)(y: Int) {}
func generic_method<T>(x: T) {}
}
class SomeClass {
// -- Constructors and methods are uncurried in 'self'
// -- Instance methods use 'method' cc
// CHECK-LABEL: sil hidden @_TFC9functions9SomeClasscfMS0_FT1xBi64_1yBi64__S0_ : $@convention(method) (Builtin.Int64, Builtin.Int64, @owned SomeClass) -> @owned SomeClass
// CHECK: bb0(%0 : $Builtin.Int64, %1 : $Builtin.Int64, %2 : $SomeClass):
// CHECK-LABEL: sil hidden @_TFC9functions9SomeClassCfMS0_FT1xBi64_1yBi64__S0_ : $@convention(thin) (Builtin.Int64, Builtin.Int64, @thick SomeClass.Type) -> @owned SomeClass
// CHECK: bb0(%0 : $Builtin.Int64, %1 : $Builtin.Int64, %2 : $@thick SomeClass.Type):
init(x:Int, y:Int) {}
// CHECK-LABEL: sil hidden @_TFC9functions9SomeClass6method{{.*}} : $@convention(method) (Builtin.Int64, @guaranteed SomeClass) -> ()
// CHECK: bb0(%0 : $Builtin.Int64, %1 : $SomeClass):
func method(x: Int) {}
// CHECK-LABEL: sil hidden @_TFC9functions9SomeClass14curried_method{{.*}} : $@convention(method) (Builtin.Int64, Builtin.Int64, @guaranteed SomeClass) -> ()
// CHECK: bb0(%0 : $Builtin.Int64, %1 : $Builtin.Int64, %2 : $SomeClass):
func curried_method(x: Int)(y: Int) {}
// CHECK-LABEL: sil hidden @_TZFC9functions9SomeClass13static_method{{.*}} : $@convention(thin) (Builtin.Int64, @thick SomeClass.Type) -> ()
// CHECK: bb0(%0 : $Builtin.Int64, %1 : $@thick SomeClass.Type):
class func static_method(x: Int) {}
// CHECK-LABEL: sil hidden @_TZFC9functions9SomeClass21static_curried_method{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64, @thick SomeClass.Type) -> ()
// CHECK: bb0(%0 : $Builtin.Int64, %1 : $Builtin.Int64, %2 : $@thick SomeClass.Type):
class func static_curried_method(x: Int)(y: Int) {}
var someProperty: Int {
get {
return zero
}
set {}
}
subscript(x:Int, y:Int) -> Int {
get {
return zero
}
set {}
}
func generic<T>(x: T) -> T {
return x
}
}
func SomeClassWithBenefits() -> SomeClass.Type {
return SomeClass.self
}
protocol SomeProtocol {
func method(x: Int)
static func static_method(x: Int)
}
struct ConformsToSomeProtocol : SomeProtocol {
func method(x: Int) { }
static func static_method(x: Int) { }
}
class SomeGeneric<T> {
init() { }
func method(x: T) -> T { return x }
func generic<U>(x: U) -> U { return x }
}
// CHECK-LABEL: sil hidden @_TF9functions5calls{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64, Builtin.Int64) -> ()
func calls(var i:Int, var j:Int, var k:Int) {
// CHECK: bb0(%0 : $Builtin.Int64, %1 : $Builtin.Int64, %2 : $Builtin.Int64):
// CHECK: [[IADDR:%[0-9]+]] = alloc_box $Builtin.Int64
// CHECK: [[JADDR:%[0-9]+]] = alloc_box $Builtin.Int64
// CHECK: [[KADDR:%[0-9]+]] = alloc_box $Builtin.Int64
// CHECK: [[FUNC:%[0-9]+]] = function_ref @_TF9functions19standalone_function{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: apply [[FUNC]]([[I]], [[J]])
standalone_function(i, j)
// CHECK: [[FUNC:%[0-9]+]] = function_ref @_TF9functions16curried_function{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: apply [[FUNC]]([[J]], [[I]])
curried_function(i)(y: j)
// -- Paren exprs shouldn't affect the uncurrying optimization.
// CHECK: [[FUNC:%[0-9]+]] = function_ref @_TF9functions16curried_function{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: apply [[FUNC]]([[J]], [[I]])
(curried_function)(i)(y: j)
// -- Coercions and function conversions shouldn't affect the uncurrying
// optimization.
// CHECK: [[FUNC:%[0-9]+]] = function_ref @_TF9functions16curried_function{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: apply [[FUNC]]([[J]], [[I]])
(curried_function)(i)(y: j)
// CHECK: [[FUNC1:%[0-9]+]] = function_ref @_TF9functions33curried_function_returns_function{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> @owned @callee_owned (Builtin.Int64) -> Builtin.Int64
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: [[FUNC2:%[0-9]+]] = apply [[FUNC1]]([[J]], [[I]])
// CHECK: [[K:%[0-9]+]] = load [[KADDR]]
// CHECK: apply [[FUNC2]]([[K]])
curried_function_returns_function(i)(y: j)(z: k)
generic_curried_function(i)(y: j)
// -- Use of curried entry points as values.
// CHECK: [[F1ADDR:%[0-9]+]] = alloc_box $@callee_owned (Builtin.Int64) -> Builtin.Int64
// CHECK: [[FUNC:%[0-9]+]] = function_ref @_TF9functions16curried_function{{.*}} : $@convention(thin) (Builtin.Int64) -> @owned @callee_owned (Builtin.Int64) -> Builtin.Int64
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[FUNC_CURRY:%[0-9]+]] = apply [[FUNC]]([[I]])
// CHECK: store [[FUNC_CURRY]] to [[F1ADDR]]
var f1 = curried_function(i)
// CHECK: [[F1:%[0-9]+]] = load [[F1ADDR]]
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: apply [[F1]]([[J]])
f1(y: j)
// CHECK: [[F2ADDR:%[0-9]+]] = alloc_box $@callee_owned (Builtin.Int64) -> @owned @callee_owned (Builtin.Int64) -> Builtin.Int64
// CHECK: [[FUNC:%[0-9]+]] = function_ref @_TF9functions16curried_function{{.*}} : $@convention(thin) (Builtin.Int64) -> @owned @callee_owned (Builtin.Int64) -> Builtin.Int64
// CHECK: [[FUNC_THICK:%[0-9]+]] = thin_to_thick_function [[FUNC]] : ${{.*}} to $@callee_owned (Builtin.Int64) -> @owned @callee_owned (Builtin.Int64) -> Builtin.Int64
// CHECK: store [[FUNC_THICK]] to [[F2ADDR]]
var f2 = curried_function
// CHECK: [[F2:%[0-9]+]] = load [[F2ADDR]]
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[F2_I:%[0-9]+]] = apply [[F2]]([[I]])
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: apply [[F2_I]]([[J]])
f2(i)(y: j)
var gcf1: Int -> () = generic_curried_function(i)
gcf1(j)
// -- Curry 'self' onto struct method argument lists.
// CHECK: [[ST_ADDR:%.*]] = alloc_box $SomeStruct
// CHECK: [[CTOR:%.*]] = function_ref @_TFV9functions10SomeStructCfMS0_FT1xBi64_1yBi64__S0_ : $@convention(thin) (Builtin.Int64, Builtin.Int64, @thin SomeStruct.Type) -> SomeStruct
// CHECK: [[METATYPE:%.*]] = metatype $@thin SomeStruct.Type
// CHECK: [[I:%.*]] = load [[IADDR]]
// CHECK: [[J:%.*]] = load [[JADDR]]
// CHECK: apply [[CTOR]]([[I]], [[J]], [[METATYPE]]) : $@convention(thin) (Builtin.Int64, Builtin.Int64, @thin SomeStruct.Type) -> SomeStruct
var st = SomeStruct(x: i, y: j)
// -- Use of unapplied struct methods as values.
// CHECK: [[THUNK:%.*]] = function_ref @_TFV9functions10SomeStruct6method{{.*}}
// CHECK: [[THUNK_THICK:%.*]] = thin_to_thick_function [[THUNK]]
var stm1 = SomeStruct.method
stm1(&st)(i)
// CHECK: [[THUNK:%.*]] = function_ref @_TFV9functions10SomeStruct14curried_method{{.*}}
// CHECK: [[THUNK_THICK:%.*]] = thin_to_thick_function [[THUNK]]
var stm2 = SomeStruct.curried_method
stm2(&st)(i)(y: j)
// -- Curry 'self' onto method argument lists dispatched using class_method.
// CHECK: [[CADDR:%[0-9]+]] = alloc_box $SomeClass
// CHECK: [[FUNC:%[0-9]+]] = function_ref @_TFC9functions9SomeClassCfMS0_FT1xBi64_1yBi64__S0_ : $@convention(thin) (Builtin.Int64, Builtin.Int64, @thick SomeClass.Type) -> @owned SomeClass
// CHECK: [[META:%[0-9]+]] = metatype $@thick SomeClass.Type
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: [[C:%[0-9]+]] = apply [[FUNC]]([[I]], [[J]], [[META]])
var c = SomeClass(x: i, y: j)
// CHECK: [[C:%[0-9]+]] = load [[CADDR]]
// CHECK: [[METHOD:%[0-9]+]] = class_method [[C]] : {{.*}}, #SomeClass.method!1
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: apply [[METHOD]]([[I]], [[C]])
c.method(i)
// CHECK: [[C:%[0-9]+]] = load [[CADDR]]
// CHECK: [[METHOD:%[0-9]+]] = class_method [[C]] : {{.*}}, #SomeClass.curried_method!2
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: apply [[METHOD]]([[J]], [[I]], [[C]])
c.curried_method(i)(y: j)
// -- Curry 'self' onto unapplied methods dispatched using class_method.
// CHECK: [[METHOD_CURRY_THUNK:%.*]] = function_ref @_TFC9functions9SomeClass6method{{.*}}
// CHECK: apply [[METHOD_CURRY_THUNK]]
var cm1 = SomeClass.method(c)
cm1(i)
// CHECK: [[C:%[0-9]+]] = load [[CADDR]]
// CHECK: [[METHOD:%[0-9]+]] = class_method [[C]] : {{.*}}, #SomeClass.method!1
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: apply [[METHOD]]([[I]], [[C]])
SomeClass.method(c)(i)
// CHECK: [[C:%[0-9]+]] = load [[CADDR]]
// CHECK: [[METHOD:%[0-9]+]] = class_method [[C]] : {{.*}}, #SomeClass.curried_method!2
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: apply [[METHOD]]([[J]], [[I]], [[C]])
SomeClass.curried_method(c)(i)(y: j)
// -- Curry 'self' onto unapplied methods, after applying side effects from a Type expression.
// CHECK: [[C:%[0-9]+]] = load [[CADDR]]
// CHECK: [[SIDEFUNC:%[0-9]+]] = function_ref @_TF9functions21SomeClassWithBenefitsFT_MCS_9SomeClass : $@convention(thin) () -> @thick SomeClass.Type
// CHECK: apply [[SIDEFUNC]]()
// CHECK: [[METHOD:%[0-9]+]] = class_method [[C]] : {{.*}}, #SomeClass.curried_method!2
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: apply [[METHOD]]([[J]], [[I]], [[C]])
SomeClassWithBenefits().curried_method(c)(i)(y: j)
// -- Curry the Type onto static method argument lists.
// CHECK: [[C:%[0-9]+]] = load [[CADDR]]
// CHECK: [[METHOD:%[0-9]+]] = class_method [[META:%[0-9]+]] : {{.*}}, #SomeClass.static_method!1
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: apply [[METHOD]]([[I]], [[META]])
c.dynamicType.static_method(i)
// CHECK: [[C:%[0-9]+]] = load [[CADDR]]
// CHECK: [[METHOD:%[0-9]+]] = class_method [[META:%[0-9]+]] : {{.*}}, #SomeClass.static_curried_method!2
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: apply [[METHOD]]([[J]], [[I]], [[META]])
c.dynamicType.static_curried_method(i)(y: j)
// FIXME: use of curried method entry points as values
//var m1 = c.curried_method(i)
//m1(j)
//var m2 = c.curried_method
//m2(i)(j)
//var m3 = SomeClass.curried_method
//m3(c)(i)(j)
//var s1 = c.Type.static_curried_method(i)
//s1(j)
//var s2 = c.Type.static_curried_method
//s2(i)(j)
// -- Curry property accesses.
// -- FIXME: class_method-ify class getters.
// CHECK: [[C:%[0-9]+]] = load [[CADDR]]
// CHECK: [[GETTER:%[0-9]+]] = class_method {{.*}} : $SomeClass, #SomeClass.someProperty!getter.1
// CHECK: apply [[GETTER]]([[C]])
i = c.someProperty
// CHECK: [[C:%[0-9]+]] = load [[CADDR]]
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[SETTER:%[0-9]+]] = class_method [[C]] : $SomeClass, #SomeClass.someProperty!setter.1 : SomeClass -> (Builtin.Int64) -> ()
// CHECK: apply [[SETTER]]([[I]], [[C]])
c.someProperty = i
// CHECK: [[C:%[0-9]+]] = load [[CADDR]]
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: [[K:%[0-9]+]] = load [[KADDR]]
// CHECK: [[GETTER:%[0-9]+]] = class_method [[C]] : $SomeClass, #SomeClass.subscript!getter.1 : SomeClass -> (Builtin.Int64, Builtin.Int64) -> Builtin.Int64 , $@convention(method) (Builtin.Int64, Builtin.Int64, @guaranteed SomeClass) -> Builtin.Int64
// CHECK: apply [[GETTER]]([[J]], [[K]], [[C]])
i = c[j, k]
// CHECK: [[C:%[0-9]+]] = load [[CADDR]]
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: [[K:%[0-9]+]] = load [[KADDR]]
// CHECK: [[SETTER:%[0-9]+]] = class_method [[C]] : $SomeClass, #SomeClass.subscript!setter.1 : SomeClass -> (Builtin.Int64, Builtin.Int64, Builtin.Int64) -> () , $@convention(method) (Builtin.Int64, Builtin.Int64, Builtin.Int64, @guaranteed SomeClass) -> ()
// CHECK: apply [[SETTER]]([[K]], [[I]], [[J]], [[C]])
c[i, j] = k
// -- Curry the projected concrete value in an existential (or its Type)
// -- onto protocol type methods dispatched using protocol_method.
// CHECK: [[PADDR:%[0-9]+]] = alloc_box $SomeProtocol
var p : SomeProtocol = ConformsToSomeProtocol()
// CHECK: [[TEMP:%.*]] = alloc_stack $SomeProtocol
// CHECK: copy_addr [[PADDR]]#1 to [initialization] [[TEMP]]#1
// CHECK: [[PVALUE:%[0-9]+]] = open_existential_addr [[TEMP]]#1 : $*SomeProtocol to $*[[OPENED:@opened(.*) SomeProtocol]]
// CHECK: [[PMETHOD:%[0-9]+]] = witness_method $[[OPENED]], #SomeProtocol.method!1
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: apply [[PMETHOD]]<[[OPENED]]>([[I]], [[PVALUE]])
// CHECK: destroy_addr [[PVALUE]]
// CHECK: deinit_existential_addr [[TEMP]]#1
// CHECK: dealloc_stack [[TEMP]]#0
p.method(i)
// CHECK: [[PVALUE:%[0-9]+]] = open_existential_addr [[PADDR:%.*]] : $*SomeProtocol to $*[[OPENED:@opened(.*) SomeProtocol]]
// CHECK: [[PMETHOD:%[0-9]+]] = witness_method $[[OPENED]], #SomeProtocol.method!1
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: apply [[PMETHOD]]<[[OPENED]]>([[I]], [[PVALUE]])
var sp : SomeProtocol = ConformsToSomeProtocol()
sp.method(i)
// FIXME: [[PMETHOD:%[0-9]+]] = witness_method $[[OPENED:@opened(.*) SomeProtocol]], #SomeProtocol.static_method!1
// FIXME: [[I:%[0-9]+]] = load [[IADDR]]
// FIXME: apply [[PMETHOD]]([[I]], [[PMETA]])
// Needs existential metatypes
//p.dynamicType.static_method(i)
// -- Use an apply or partial_apply instruction to bind type parameters of a generic.
// CHECK: [[GADDR:%[0-9]+]] = alloc_box $SomeGeneric<Builtin.Int64>
// CHECK: [[CTOR_GEN:%[0-9]+]] = function_ref @_TFC9functions11SomeGenericCU__fMGS0_Q__FT_GS0_Q__ : $@convention(thin) <τ_0_0> (@thick SomeGeneric<τ_0_0>.Type) -> @owned SomeGeneric<τ_0_0>
// CHECK: [[META:%[0-9]+]] = metatype $@thick SomeGeneric<Builtin.Int64>.Type
// CHECK: apply [[CTOR_GEN]]<Builtin.Int64>([[META]])
var g = SomeGeneric<Builtin.Int64>()
// CHECK: [[G:%[0-9]+]] = load [[GADDR]]
// CHECK: [[METHOD_GEN:%[0-9]+]] = class_method [[G]] : {{.*}}, #SomeGeneric.method!1
// CHECK: [[TMPI:%.*]] = alloc_stack $Builtin.Int64
// CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
// CHECK: apply [[METHOD_GEN]]<{{.*}}>([[TMPR]]#1, [[TMPI]]#1, [[G]])
g.method(i)
// CHECK: [[G:%[0-9]+]] = load [[GADDR]]
// CHECK: [[METHOD_GEN:%[0-9]+]] = class_method [[G]] : {{.*}}, #SomeGeneric.generic!1
// CHECK: [[TMPJ:%.*]] = alloc_stack $Builtin.Int64
// CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
// CHECK: apply [[METHOD_GEN]]<{{.*}}>([[TMPR]]#1, [[TMPJ]]#1, [[G]])
g.generic(j)
// CHECK: [[C:%[0-9]+]] = load [[CADDR]]
// CHECK: [[METHOD_GEN:%[0-9]+]] = class_method [[C]] : {{.*}}, #SomeClass.generic!1
// CHECK: [[TMPK:%.*]] = alloc_stack $Builtin.Int64
// CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
// CHECK: apply [[METHOD_GEN]]<{{.*}}>([[TMPR]]#1, [[TMPK]]#1, [[C]])
c.generic(k)
// FIXME: curried generic entry points
//var gm1 = g.method
//gm1(i)
//var gg1 : (Int) -> Int = g.generic
//gg1(j)
//var cg1 : (Int) -> Int = c.generic
//cg1(k)
// SIL-level "thin" function values need to be able to convert to
// "thick" function values when stored, returned, or passed as arguments.
// CHECK: [[FADDR:%[0-9]+]] = alloc_box $@callee_owned (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
// CHECK: [[FUNC_THIN:%[0-9]+]] = function_ref @_TF9functions19standalone_function{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
// CHECK: [[FUNC_THICK:%[0-9]+]] = thin_to_thick_function [[FUNC_THIN]]
// CHECK: store [[FUNC_THICK]] to [[FADDR]]
var f = standalone_function
// CHECK: [[F:%[0-9]+]] = load [[FADDR]]
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: apply [[F]]([[I]], [[J]])
f(i, j)
// CHECK: [[HOF:%[0-9]+]] = function_ref @_TF9functions21higher_order_function{{.*}} : $@convention(thin) {{.*}}
// CHECK: [[FUNC_THIN:%[0-9]+]] = function_ref @_TF9functions19standalone_function{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
// CHECK: [[FUNC_THICK:%[0-9]+]] = thin_to_thick_function [[FUNC_THIN]]
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: apply [[HOF]]([[FUNC_THICK]], [[I]], [[J]])
higher_order_function(standalone_function, i, j)
// CHECK: [[HOF2:%[0-9]+]] = function_ref @_TF9functions22higher_order_function2{{.*}} : $@convention(thin) {{.*}}
// CHECK: [[FUNC_THIN:%[0-9]+]] = function_ref @_TF9functions19standalone_function{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
// CHECK: [[FUNC_THICK:%.*]] = thin_to_thick_function [[FUNC_THIN]]
// CHECK: [[I:%[0-9]+]] = load [[IADDR]]
// CHECK: [[J:%[0-9]+]] = load [[JADDR]]
// CHECK: apply [[HOF2]]([[FUNC_THICK]], [[I]], [[J]])
higher_order_function2(standalone_function, i, j)
}
// -- Curried entry points
// CHECK-LABEL: sil shared @_TF9functions16curried_function{{.*}} : $@convention(thin) (Builtin.Int64) -> @owned @callee_owned (Builtin.Int64) -> Builtin.Int64
// CHECK: bb0([[X:%[0-9]+]] : $Builtin.Int64):
// CHECK: [[FUNC:%[0-9]+]] = function_ref @_TF9functions16curried_function{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
// CHECK: [[CLOSURE:%[0-9]+]] = partial_apply [[FUNC]]([[X]])
// CHECK: return [[CLOSURE]]
// CHECK-LABEL: sil shared @_TF9functions24generic_curried_function{{.*}} : $@convention(thin) <T, U> (@in T) -> @owned @callee_owned (@in U) -> () {
// CHECK: bb0([[X:%.*]] : $*T):
// CHECK: [[UNCURRIED:%.*]] = function_ref @_TF9functions24generic_curried_function{{.*}}
// CHECK: [[CURRIED:%.*]] = partial_apply [[UNCURRIED]]<T, U>([[X]])
// CHECK: return [[CURRIED]] : $@callee_owned (@in U) -> ()
// CHECK-LABEL: sil shared @_TFV9functions10SomeStruct6method{{.*}} : $@convention(thin) (@inout SomeStruct) -> @owned @callee_owned (Builtin.Int64) -> () {
// CHECK: [[UNCURRIED:%.*]] = function_ref @_TFV9functions10SomeStruct6method{{.*}} : $@convention(method) (Builtin.Int64, @inout SomeStruct) -> () // user: %2
// CHECK: [[CURRIED:%.*]] = partial_apply [[UNCURRIED]]
// CHECK: return [[CURRIED]]
// CHECK-LABEL: sil shared @_TFC9functions9SomeClass6method{{.*}} : $@convention(thin) (@owned SomeClass) -> @owned @callee_owned (Builtin.Int64) -> ()
// CHECK: bb0(%0 : $SomeClass):
// CHECK: class_method %0 : $SomeClass, #SomeClass.method!1 : SomeClass -> (Builtin.Int64) -> ()
// CHECK: %2 = partial_apply %1(%0)
// CHECK: return %2
func return_func() -> (x: Builtin.Int64, y: Builtin.Int64) -> Builtin.Int64 {
// CHECK: [[FUNC_THIN:%[0-9]+]] = function_ref @_TF9functions19standalone_function{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
// CHECK: [[FUNC_THICK:%[0-9]+]] = thin_to_thick_function [[FUNC_THIN]]
// CHECK: return [[FUNC_THICK]]
return standalone_function
}
func standalone_generic<T>(x: T, y: T) -> T { return x }
// CHECK-LABEL: sil hidden @_TF9functions14return_genericFT_FT1xBi64_1yBi64__Bi64_
func return_generic() -> (x:Builtin.Int64, y:Builtin.Int64) -> Builtin.Int64 {
// CHECK: [[GEN:%.*]] = function_ref @_TF9functions18standalone_generic{{.*}} : $@convention(thin) <τ_0_0> (@out τ_0_0, @in τ_0_0, @in τ_0_0) -> ()
// CHECK: [[SPEC:%.*]] = partial_apply [[GEN]]<Builtin.Int64>()
// CHECK: [[THUNK:%.*]] = function_ref @{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64, @owned @callee_owned (@out Builtin.Int64, @in Builtin.Int64, @in Builtin.Int64) -> ()) -> Builtin.Int64
// CHECK: [[T0:%.*]] = partial_apply [[THUNK]]([[SPEC]])
// CHECK: return [[T0]]
return standalone_generic
}
// CHECK-LABEL: sil hidden @_TF9functions20return_generic_tuple{{.*}}
func return_generic_tuple()
-> (x: (Builtin.Int64, Builtin.Int64), y: (Builtin.Int64, Builtin.Int64)) -> (Builtin.Int64, Builtin.Int64) {
// CHECK: [[GEN:%.*]] = function_ref @_TF9functions18standalone_generic{{.*}} : $@convention(thin) <τ_0_0> (@out τ_0_0, @in τ_0_0, @in τ_0_0) -> ()
// CHECK: [[SPEC:%.*]] = partial_apply [[GEN]]<(Builtin.Int64, Builtin.Int64)>()
// CHECK: [[THUNK:%.*]] = function_ref @{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64, Builtin.Int64, Builtin.Int64, @owned @callee_owned (@out (Builtin.Int64, Builtin.Int64), @in (Builtin.Int64, Builtin.Int64), @in (Builtin.Int64, Builtin.Int64)) -> ()) -> (Builtin.Int64, Builtin.Int64)
// CHECK: [[T0:%.*]] = partial_apply [[THUNK]]([[SPEC]])
// CHECK: return [[T0]]
return standalone_generic
}
// CHECK-LABEL: sil hidden @_TF9functions16testNoReturnAttrFT_T_ : $@convention(thin) @noreturn () -> ()
@noreturn func testNoReturnAttr() -> () {}
// CHECK-LABEL: sil hidden @_TF9functions20testNoReturnAttrPoly{{.*}} : $@convention(thin) @noreturn <T> (@in T) -> ()
@noreturn func testNoReturnAttrPoly<T>(x: T) -> () {}
// CHECK-LABEL: sil hidden @_TF9functions21testNoReturnAttrParam{{.*}} : $@convention(thin) (@owned @noreturn @callee_owned () -> ()) -> ()
func testNoReturnAttrParam(fptr: @noreturn ()->()) -> () {}
// CHECK-LABEL: sil hidden [transparent] @_TF9functions15testTransparent{{.*}} : $@convention(thin) (Builtin.Int1) -> Builtin.Int1
@transparent func testTransparent(x: Bool) -> Bool {
return x
}
// CHECK-LABEL: sil hidden @_TF9functions16applyTransparent{{.*}} : $@convention(thin) (Builtin.Int1) -> Builtin.Int1 {
func applyTransparent(x: Bool) -> Bool {
// CHECK: [[FUNC:%[0-9]+]] = function_ref @_TF9functions15testTransparent{{.*}} : $@convention(thin) (Builtin.Int1) -> Builtin.Int1
// CHECK: apply [[FUNC]]({{%[0-9]+}}) : $@convention(thin) (Builtin.Int1) -> Builtin.Int1
return testTransparent(x)
}
// CHECK-LABEL: sil hidden @_TF9functions11funcToBlock{{.*}} : $@convention(thin) (@owned @callee_owned () -> ()) -> @owned @convention(block) () -> ()
// CHECK: [[BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage
// CHECK: [[BLOCK:%.*]] = init_block_storage_header [[BLOCK_STORAGE]]
// CHECK: [[COPY:%.*]] = copy_block [[BLOCK]] : $@convention(block) () -> ()
// CHECK: return [[COPY]]
func funcToBlock(x: () -> ()) -> @convention(block) () -> () {
return x
}
// CHECK-LABEL: sil hidden @_TF9functions11blockToFunc{{.*}} : $@convention(thin) (@owned @convention(block) () -> ()) -> @owned @callee_owned () -> ()
// CHECK: [[COPIED:%.*]] = copy_block %0
// CHECK: [[THUNK:%.*]] = function_ref @_TTRXFdCb__dT__XFo__dT__
// CHECK: [[FUNC:%.*]] = partial_apply [[THUNK]]([[COPIED]])
// CHECK: return [[FUNC]]
func blockToFunc(x: @convention(block) () -> ()) -> () -> () {
return x
}
// CHECK-LABEL: sil hidden [noinline] @_TF9functions15noinline_calleeFT_T_ : $@convention(thin) () -> ()
@inline(never)
func noinline_callee() {}
// CHECK-LABEL: sil hidden [always_inline] @_TF9functions20always_inline_calleeFT_T_ : $@convention(thin) () -> ()
@inline(__always)
func always_inline_callee() {}
protocol AlwaysInline {
func alwaysInlined()
}
// CHECK-LABEL: sil hidden [always_inline] @_TFV9functions19AlwaysInlinedMember13alwaysInlinedfS0_FT_T_ : $@convention(method) (AlwaysInlinedMember) -> () {
// protocol witness for functions.AlwaysInline.alwaysInlined <A : functions.AlwaysInline>(functions.AlwaysInline.Self)() -> () in conformance functions.AlwaysInlinedMember : functions.AlwaysInline in functions
// CHECK-LABEL: sil hidden [transparent] [thunk] [always_inline] @_TTWV9functions19AlwaysInlinedMemberS_12AlwaysInlineS_FS1_13alwaysInlinedUS1___fQPS1_FT_T_ : $@convention(witness_method) (@in_guaranteed AlwaysInlinedMember) -> () {
struct AlwaysInlinedMember : AlwaysInline {
@inline(__always)
func alwaysInlined() {}
}
// CHECK-LABEL: sil hidden [_semantics "foo"] @_TF9functions9semanticsFT_T_ : $@convention(thin) () -> ()
@_semantics("foo")
func semantics() {}
// <rdar://problem/17828355> curried final method on a class crashes in irgen
final class r17828355Class {
func method(x : Int) {
var a : r17828355Class
var fn = a.method // currying a final method.
}
}
// The curry thunk for the method should not include a class_method instruction.
// CHECK-LABEL: sil shared @_TFC9functions14r17828355Class6methodFS0_FBi64_T_
// CHECK-NEXT: bb0(%0 : $r17828355Class):
// CHECK-NEXT: // function_ref functions.r17828355Class.method (functions.r17828355Class)(Builtin.Int64) -> ()
// CHECK-NEXT: %1 = function_ref @_TFC9functions14r17828355Class6methodfS0_FBi64_T_ : $@convention(method) (Builtin.Int64, @guaranteed r17828355Class) -> ()
// CHECK-NEXT: partial_apply %1(%0) : $@convention(method) (Builtin.Int64, @guaranteed r17828355Class) -> ()
// CHECK-NEXT: return
// <rdar://problem/19981118> Swift 1.2 beta 2: Closures nested in @noescape closures copy, rather than reference, captured vars.
func noescapefunc(@noescape f: () -> ()) {}
func escapefunc(f : () -> ()) {}
func testNoescape() {
// "a" must be captured by-box into noescapefunc because the inner closure
// could escape it.
var a = 0
noescapefunc {
escapefunc { a = 42 }
}
println(a)
}
// CHECK-LABEL: functions.testNoescape () -> ()
// CHECK-NEXT: sil hidden @_TF9functions12testNoescapeFT_T_ : $@convention(thin) () -> ()
// CHECK: function_ref functions.(testNoescape () -> ()).(closure #1)
// CHECK-NEXT: function_ref @_TFF9functions12testNoescapeFT_T_U_FT_T_ : $@convention(thin) (@owned Builtin.NativeObject, @inout Int) -> ()
// Despite being a noescape closure, this needs to capture 'a' by-box so it can
// be passed to the capturing closure.closure
// CHECK: functions.(testNoescape () -> ()).(closure #1)
// CHECK-NEXT: sil shared @_TFF9functions12testNoescapeFT_T_U_FT_T_ : $@convention(thin) (@owned Builtin.NativeObject, @inout Int) -> () {
func testNoescape2() {
// "a" must be captured by-box into noescapefunc because the inner closure
// could escape it. This also checks for when the outer closure captures it
// in a way that could be used with escape: the union of the two requirements
// doesn't allow a by-address capture.
var a = 0
noescapefunc {
escapefunc { a = 42 }
println(a)
}
println(a)
}
// CHECK-LABEL: sil hidden @_TF9functions13testNoescape2FT_T_ : $@convention(thin) () -> () {
// CHECK: // functions.(testNoescape2 () -> ()).(closure #1)
// CHECK-NEXT: sil shared @_TFF9functions13testNoescape2FT_T_U_FT_T_ : $@convention(thin) (@owned Builtin.NativeObject, @inout Int) -> () {
// CHECK: // functions.(testNoescape2 () -> ()).(closure #1).(closure #1)
// CHECK-NEXT: sil shared @_TFFF9functions13testNoescape2FT_T_U_FT_T_U_FT_T_ : $@convention(thin) (@owned Builtin.NativeObject, @inout Int) -> () {