Files
swift-mirror/test/SILGen/opaque_values_silgen.swift
Kavon Farvardin a528c5c19c Merge pull request #84734 from kavon/opaque-values/fixes-2
OpaqueValues: support typed throws
2025-10-08 21:17:23 -07:00

950 lines
45 KiB
Swift

// RUN: %target-swift-emit-silgen -Xllvm -sil-print-types -enable-sil-opaque-values -Xllvm -sil-full-demangle -primary-file %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime
// Test SILGen -enable-sil-opaque-values with tests that depend on the stdlib.
// FIXME: "HECK" lines all need to be updated for OSSA.
class C {}
struct MyInt {
var int: Int
}
func genericInout<T>(_: inout T) {}
func hasVarArg(_ args: Any...) {}
@_silgen_name("sink")
func sink<T>(_ t: consuming T) {}
@_silgen_name("source")
func source<T>(_ t: T.Type) -> T
// Test array initialization - we are still (somewhat) using addresses
// ---
// CHECK-LABEL: sil [ossa] @$s20opaque_values_silgen10callVarArgyyF : $@convention(thin) () -> () {
// HECK: %[[APY:.*]] = apply %{{.*}}<Any>(%{{.*}}) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer)
// HECK: %[[BRW:.*]] = begin_borrow %[[APY]]
// HECK: %[[TPL:.*]] = tuple_extract %[[BRW]] : $(Array<Any>, Builtin.RawPointer), 1
// HECK: end_borrow %[[BRW]] : $(Array<Any>, Builtin.RawPointer)
// HECK: destroy_value %[[APY]]
// HECK: %[[PTR:.*]] = pointer_to_address %[[TPL]] : $Builtin.RawPointer to [strict] $*Any
// HECK: [[IOPAQUE:%.*]] = init_existential_value %{{.*}} : $Int, $Int, $Any
// HECK: store [[IOPAQUE]] to [init] %[[PTR]] : $*Any
// HECK: return %{{.*}} : $()
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen10callVarArgyyF'
public func callVarArg() {
hasVarArg(3)
}
// Tests For-each statements
// ---
// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen11forEachStmtyyF : $@convention(thin) () -> () {
// HECK: bb0:
// HECK: [[PROJ_BOX_ARG:%.*]] = project_box %{{.*}} : ${ var IndexingIterator<Range<Int>> }
// HECK: [[APPLY_ARG1:%.*]] = apply
// HECK-NOT: alloc_stack $Int
// HECK-NOT: store [[APPLY_ARG1]] to [trivial]
// HECK-NOT: alloc_stack $Range<Int>
// HECK-NOT: dealloc_stack
// HECK: [[APPLY_ARG2:%.*]] = apply %{{.*}}<Range<Int>>
// HECK: store [[APPLY_ARG2]] to [trivial] [[PROJ_BOX_ARG]]
// HECK: br bb1
// HECK: bb1:
// CHECK-NOT: alloc_stack $Optional<Int>
// HECK: [[APPLY_ARG3:%.*]] = apply %{{.*}}<Range<Int>>
// CHECK-NOT: dealloc_stack
// HECK: switch_enum [[APPLY_ARG3]]
// HECK: bb2:
// HECK: br bb3
// HECK: bb3:
// HECK: return %{{.*}} : $()
// HECK: bb4([[ENUM_ARG:%.*]] : $Int):
// CHECK-NOT: unchecked_enum_data
// HECK: br bb1
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen11forEachStmtyyF'
func forEachStmt() {
for _ in 1..<42 {
}
}
// Tests that existential boxes can contain opaque types
// ---
// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen12openExistBoxySSs5Error_pF : $@convention(thin) (@guaranteed any Error) -> @owned String {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $any Error):
// CHECK: [[OPAQUE_ARG:%.*]] = open_existential_box_value [[ARG]] : $any Error to $@opened({{.*}}, any Error) Self
// CHECK: [[ALLOC_OPEN:%.*]] = alloc_stack $@opened({{.*}}, any Error) Self
// CHECK: [[COPY:%.*]] = copy_value [[OPAQUE_ARG]]
// CHECK: store [[COPY]] to [init] [[ALLOC_OPEN]]
// CHECK: destroy_addr [[ALLOC_OPEN]]
// CHECK: dealloc_stack [[ALLOC_OPEN]]
// CHECK-NOT: destroy_value [[ARG]] : $any Error
// CHECK: return {{.*}} : $String
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen12openExistBoxySSs5Error_pF'
func openExistBox(_ x: Error) -> String {
return x._domain
}
// Tests conditional value casts and correspondingly generated reabstraction thunk
// ---
// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen11condFromAnyyyypF : $@convention(thin) (@in_guaranteed Any) -> () {
// HECK: bb0([[ARG:%.*]] : $Any):
// HECK: [[COPY_ARG:%.*]] = copy_value [[ARG]]
// HECK: checked_cast_br Any in [[COPY_ARG]] : $Any to $@callee_guaranteed (@in_guaranteed (Int, (Int, (Int, Int)), Int)) -> @out (Int, (Int, (Int, Int)), Int), bb2, bb1
// HECK: bb2([[THUNK_PARAM:%.*]] : $@callee_guaranteed (@in_guaranteed (Int, (Int, (Int, Int)), Int)) -> @out (Int, (Int, (Int, Int)), Int)):
// HECK: [[THUNK_REF:%.*]] = function_ref @{{.*}} : $@convention(thin) (Int, Int, Int, Int, Int, @guaranteed @callee_guaranteed (@in_guaranteed (Int, (Int, (Int, Int)), Int)) -> @out (Int, (Int, (Int, Int)), Int)) -> (Int, Int, Int, Int, Int)
// HECK: partial_apply [callee_guaranteed] [[THUNK_REF]]([[THUNK_PARAM]])
// HECK: bb6:
// HECK: return %{{.*}} : $()
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen11condFromAnyyyypF'
func condFromAny(_ x: Any) {
if let f = x as? (Int, (Int, (Int, Int)), Int) -> (Int, (Int, (Int, Int)), Int) {
_ = f(24, (4,(2, 42)), 42)
}
}
// Tests support for if statements for opaque value(s) under new mode
// ---
protocol EmptyP {}
struct AddressOnlyStruct : EmptyP {}
// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen10addrOnlyIf1xAA6EmptyP_pSb_tF : $@convention(thin) (Bool) -> @out any EmptyP {
// HECK: bb0([[ARG:%.*]] : $Bool):
// HECK: [[ALLOC_OF_BOX:%.*]] = alloc_box ${ var any EmptyP }, var
// HECK: [[PROJ_BOX:%.*]] = project_box [[ALLOC_OF_BOX]]
// HECK: [[APPLY_FOR_BOX:%.*]] = apply %{{.*}}(%{{.*}}) : $@convention(method) (@thin AddressOnlyStruct.Type) -> AddressOnlyStruct
// HECK: [[INIT_OPAQUE:%.*]] = init_existential_value [[APPLY_FOR_BOX]] : $AddressOnlyStruct, $AddressOnlyStruct, $any EmptyP
// HECK: store [[INIT_OPAQUE]] to [init] [[PROJ_BOX]] : $*any EmptyP
// HECK: [[APPLY_FOR_BRANCH:%.*]] = apply %{{.*}}([[ARG]]) : $@convention(method) (Bool) -> Builtin.Int1
// HECK: cond_br [[APPLY_FOR_BRANCH]], bb2, bb1
// HECK: bb1:
// HECK: [[READ:%.*]] = begin_access [read] [unknown] [[PROJ_BOX]] : $*EmptyP
// HECK: [[RETVAL1:%.*]] = load [copy] [[READ]] : $*EmptyP
// HECK: br bb3([[RETVAL1]] : $EmptyP)
// HECK: bb2:
// HECK: [[READ:%.*]] = begin_access [read] [unknown] [[PROJ_BOX]] : $*EmptyP
// HECK: [[RETVAL2:%.*]] = load [copy] [[READ]] : $*EmptyP
// HECK: br bb3([[RETVAL2]] : $EmptyP)
// HECK: bb3([[RETVAL:%.*]] : $EmptyP):
// HECK: destroy_value [[ALLOC_OF_BOX]]
// HECK: return [[RETVAL]] : $EmptyP
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen10addrOnlyIf1xAA6EmptyP_pSb_tF'
func addrOnlyIf(x: Bool) -> EmptyP {
var a : EmptyP = AddressOnlyStruct()
genericInout(&a)
return x ? a : a
}
// Tests LValue of error types / existential boxes
// ---
// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen12propOfLValueySSs5Error_pF : $@convention(thin) (@guaranteed any Error) -> @owned String {
// HECK: bb0([[ARG:%.*]] : $any Error):
// HECK: [[ALLOC_OF_BOX:%.*]] = alloc_box ${ var any Error }
// HECK: [[PROJ_BOX:%.*]] = project_box [[ALLOC_OF_BOX]]
// HECK: [[COPY_ARG:%.*]] = copy_value [[ARG]]
// HECK: store [[COPY_ARG]] to [init] [[PROJ_BOX]]
// HECK: [[READ:%.*]] = begin_access [read] [unknown] [[PROJ_BOX]] : $*any Error
// HECK: [[LOAD_BOX:%.*]] = load [copy] [[READ]]
// HECK: [[OPAQUE_ARG:%.*]] = open_existential_box [[LOAD_BOX]] : $any Error to $*@opened({{.*}}, any Error) Self
// HECK: [[LOAD_OPAQUE:%.*]] = load [copy] [[OPAQUE_ARG]]
// HECK: [[ALLOC_OPEN:%.*]] = alloc_stack $@opened({{.*}}, any Error) Self
// HECK: store [[LOAD_OPAQUE]] to [init] [[ALLOC_OPEN]]
// HECK: [[RET_VAL:%.*]] = apply {{.*}}<@opened({{.*}}, any Error) Self>([[ALLOC_OPEN]])
// HECK: return [[RET_VAL]] : $String
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen12propOfLValueySSs5Error_pF'
func propOfLValue(_ x: Error) -> String {
var x = x
genericInout(&x)
return x._domain
}
// Test SILGenBuilder.loadCopy().
// ---
// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen7lastValyxxd_tlF : $@convention(thin) <T> (@guaranteed Array<T>) -> @out T {
// HECK: [[LOAD:%.*]] = load [copy] %{{.*}} : $*T
// HECK: return [[LOAD]] : $T
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen7lastValyxxd_tlF'
func lastVal<T>(_ rest: T...) -> T {
var minValue: T
for value in rest {
minValue = value
}
return minValue
}
// Test SILGenFunction::emitPointerToPointer.
// ---
// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen3foo1pSRyxGSPyxG_tlF : $@convention(thin) <Element> (UnsafePointer<Element>) -> UnsafeBufferPointer<Element> {
// HECK: [[F:%.*]] = function_ref @$sconvertPointerToB8Argumentyq_xB0RzsABR_r0_lF : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : _Pointer, τ_0_1 : _Pointer> (@in_guaranteed τ_0_0) -> @out τ_0_1
// HECK: apply [[F]]<UnsafePointer<Element>, UnsafePointer<Element>>(%0) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : _Pointer, τ_0_1 : _Pointer> (@in_guaranteed τ_0_0) -> @out τ_0_1
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen3foo1pSRyxGSPyxG_tlF'
func foo<Element>(p: UnsafePointer<Element>) -> UnsafeBufferPointer<Element> {
return UnsafeBufferPointer(start: p, count: 1)
}
// Test SILBuilder.createLoadBorrow.
// ---
protocol FooP {
func foo()
}
// CHECK-LABEL: sil private [ossa] @$s20opaque_values_silgen10loadBorrowyyF4FooPL_V3foo3pos7ElementQzSg5IndexQz_tF : $@convention(method) <Elements where Elements : Collection> (@in_guaranteed Elements.Index, @inout FooP<Elements>) -> @out Optional<Elements.Element> {
// CHECK: bb0([[ARG0:%.*]] : @guaranteed $Elements.Index, [[ARG1:%.*]] : $*FooP<Elements>):
// HECK: [[READ:%.*]] = begin_access [read] [unknown] [[ARG1]] : $*FooP<Elements>
// HECK: [[LOAD:%.*]] = load [copy] [[READ]] : $*FooP<Elements>
// HECK: end_access [[READ]] : $*FooP<Elements>
// HECK: [[BORROW_LOAD:%.*]] = begin_borrow [[LOAD]]
// HECK: [[EXTRACT:%.*]] = struct_extract [[BORROW_LOAD]] : $FooP<Elements>, #<abstract function>FooP._elements
// HECK: [[COPYELT:%.*]] = copy_value [[EXTRACT]] : $Elements
// HECK: [[COPYIDX:%.*]] = copy_value [[ARG0]] : $Elements.Index
// HECK: [[WT:%.*]] = witness_method $Elements, #Collection.subscript!getter : <Self where Self : Collection> (Self) -> (Self.Index) -> Self.Element : $@convention(witness_method: Collection) <τ_0_0 where τ_0_0 : Collection> (@in_guaranteed τ_0_0.Index, @in_guaranteed τ_0_0) -> @out τ_0_0.Element
// HECK: [[RESULT:%.*]] = apply [[WT]]<Elements>([[COPYIDX]], [[COPYELT]]) : $@convention(witness_method: Collection) <τ_0_0 where τ_0_0 : Collection> (@in_guaranteed τ_0_0.Index, @in_guaranteed τ_0_0) -> @out τ_0_0.Element
// HECK: destroy_value [[COPYELT]] : $Elements
// HECK: [[ENUM_RESULT:%.*]] = enum $Optional<Elements.Element>, #Optional.some!enumelt, [[RESULT]] : $Elements.Element
// HECK: destroy_value [[LOAD]]
// CHECK-NOT: destroy_value [[ARG0]] : $Elements.Index
// HECK: return [[ENUM_RESULT]] : $Optional<Elements.Element>
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen10loadBorrowyyF4FooPL_V3foo3pos7ElementQzSg5IndexQz_tF'
func loadBorrow() {
struct FooP<Elements : Collection> {
internal let _elements: Elements
public mutating func foo(pos: Elements.Index) -> Elements.Element? {
return _elements[pos]
}
}
var foo = FooP(_elements: [])
_ = foo.foo(pos: 1)
}
// Tests LogicalPathComponent's writeback for opaque value types
// ---
// Dictionary.subscript.getter
// CHECK-LABEL: sil [heuristic_always_inline] [ossa] @$sSD20opaque_values_silgenEyq_Sgq_cig : $@convention(method) <Key, Value where Key : Hashable> (@in_guaranteed Value, @guaranteed Dictionary<Key, Value>) -> @out Optional<Value> {
// HECK: bb0([[ARG0:%.*]] : $Value, [[ARG1:%.*]] : $*Dictionary<Key, Value>):
// HECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[ARG1]] : $*Dictionary<Key, Value>
// HECK: [[OPTIONAL_ALLOC:%.*]] = alloc_stack $Optional<Value>
// HECK: switch_enum_addr [[OPTIONAL_ALLOC]] : $*Optional<Value>, case #Optional.some!enumelt: bb2, case #Optional.none!enumelt: bb1
// HECK: bb2:
// HECK: [[OPTIONAL_LOAD:%.*]] = load [take] [[OPTIONAL_ALLOC]] : $*Optional<Value>
// HECK: apply {{.*}}<Key, Value>([[OPTIONAL_LOAD]], {{.*}}, [[WRITE]]) : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@in Optional<τ_0_1>, @in τ_0_1, @inout Dictionary<τ_0_0, τ_0_1>) -> ()
// HECK: return %{{.*}} : $()
// CHECK-LABEL: } // end sil function '$sSD20opaque_values_silgenEyq_Sgq_cig'
// Tests materializeForSet's createSetterCallback for opaque values
// ---
// Dictionary.subscript.setter
// CHECK-LABEL: sil [ossa] @$sSD20opaque_values_silgenEyq_Sgq_cis : $@convention(method) <Key, Value where Key : Hashable> (@in Optional<Value>, @in Value, @inout Dictionary<Key, Value>) -> () {
// HECK: bb0([[ARG0:%.*]] : $Builtin.RawPointer, [[ARG1:%.*]] : $*Builtin.UnsafeValueBuffer, [[ARG2:%.*]] : $*Dictionary<Key, Value>, [[ARG3:%.*]] : $@thick Dictionary<Key, Value>.Type):
// HECK: [[PROJ_VAL1:%.*]] = project_value_buffer $Value in [[ARG1]] : $*Builtin.UnsafeValueBuffer
// HECK: [[LOAD_VAL1:%.*]] = load [take] [[PROJ_VAL1]] : $*Value
// HECK: [[ADDR_VAL0:%.*]] = pointer_to_address [[ARG0]] : $Builtin.RawPointer to [strict] $*Optional<Value>
// HECK: [[LOAD_VAL0:%.*]] = load [take] [[ADDR_VAL0]] : $*Optional<Value>
// HECK: apply {{.*}}<Key, Value>([[LOAD_VAL0]], [[LOAD_VAL1]], [[ARG2]]) : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@in Optional<τ_0_1>, @in τ_0_1, @inout Dictionary<τ_0_0, τ_0_1>) -> ()
// HECK: return %{{.*}} : $()
// CHECK-LABEL: } // end sil function '$sSD20opaque_values_silgenEyq_Sgq_cis'
extension Dictionary {
public subscript(key: Value) -> Value? {
@inline(__always)
get {
return key
}
set(newValue) {
}
}
public mutating func inoutAccessOfSubscript(key: Value) {
func increment(x: inout Value) { }
increment(x: &self[key]!)
}
}
// Test ownership of multi-case Enum values in the context of to @in thunks.
// ---
// protocol witness for static Swift.Equatable.== infix(A, A) -> Swift.Bool in conformance Swift.FloatingPointSign : Swift.Equatable
// CHECK-LABEL: sil shared [transparent] [serialized] [thunk] [ossa] @$s20opaque_values_silgen17FloatingPointSignOSQAASQ2eeoiySbx_xtFZTW : $@convention(witness_method: Equatable) (@in_guaranteed FloatingPointSign, @in_guaranteed FloatingPointSign, @thick FloatingPointSign.Type) -> Bool {
// HECK: bb0(%0 : $FloatingPointSign, %1 : $FloatingPointSign, %2 : $@thick FloatingPointSign.Type):
// HECK: %3 = metatype $@thin FloatingPointSign.Type // user: %5
// HECK: %4 = function_ref @$ss17FloatingPointSignO21__derived_enum_equalsySbAB_ABtFZ : $@convention(method) (FloatingPointSign, FloatingPointSign, @thin FloatingPointSign.Type) -> Bool // user: %5
// HECK: %5 = apply %4(%0, %1, %3) : $@convention(method) (FloatingPointSign, FloatingPointSign, @thin FloatingPointSign.Type) -> Bool // user: %6
// HECK: return %5 : $Bool
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen17FloatingPointSignOSQAASQ2eeoiySbx_xtFZTW'
public enum FloatingPointSign {
/// The sign for a positive value.
case plus
/// The sign for a negative value.
case minus
}
#if os(macOS)
// Test open_existential_value used in a conversion context.
//
// TODO: Subsequent OSSA optimization should optimize away one of both of these copies.
// ---
// CHECK-OSX-LABEL: sil [ossa] @$s20opaque_values_silgen25unsafeDowncastToAnyObject04fromG0yXlyp_tF : $@convention(thin) (@in_guaranteed Any) -> @owned AnyObject {
// CHECK-OSX: bb0(%0 : @guaranteed $Any):
// CHECK-OSX: [[COPY:%.*]] = copy_value %0 : $Any
// CHECK-OSX: [[BORROW2:%.*]] = begin_borrow [[COPY]] : $Any
// CHECK-OSX: [[VAL:%.*]] = open_existential_value [[BORROW2]] : $Any to $@opened
// CHECK-OSX: [[COPY2:%.*]] = copy_value [[VAL]] : $@opened
// CHECK-OSX: end_borrow [[BORROW2]] : $Any
// CHECK-OSX: [[RESULT:%.*]] = apply %{{.*}}<@opened("{{.*}}", Any) Self>([[COPY2]]) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @owned AnyObject
// CHECK-OSX: destroy_value [[COPY2]] : $@opened
// CHECK-OSX: destroy_value [[COPY]] : $Any
// CHECK-OSX-NOT: destroy_value %0 : $Any
// CHECK-OSX: return [[RESULT]] : $AnyObject
// CHECK-OSX-LABEL: } // end sil function '$s20opaque_values_silgen25unsafeDowncastToAnyObject04fromG0yXlyp_tF'
public func unsafeDowncastToAnyObject(fromAny any: Any) -> AnyObject {
return any as AnyObject
}
#endif
#if os(macOS)
// Test open_existential_box_value in a conversion context.
// ---
// CHECK-OSX-LABEL: sil [ossa] @$s20opaque_values_silgen22testOpenExistentialBox1eys5Error_pSg_tF : $@convention(thin) (@guaranteed Optional<Error>) -> () {
// CHECK-OSX: [[BORROW:%.*]] = begin_borrow [lexical] [var_decl] %{{.*}} : $any Error
// CHECK-OSX: [[VAL:%.*]] = open_existential_box_value [[BORROW]] : $any Error to $@opened
// CHECK-OSX: [[COPY:%.*]] = copy_value [[VAL]] : $@opened
// CHECK-OSX: [[ANY:%.*]] = init_existential_value [[COPY]] : $@opened
// CHECK-OSX: end_borrow [[BORROW]] : $any Error
// CHECK-OSX-LABEL: } // end sil function '$s20opaque_values_silgen22testOpenExistentialBox1eys5Error_pSg_tF'
public func testOpenExistentialBox(e: Error?) {
if let u = e {
let a: Any = u
_ = a
}
}
#endif
// Test passing a +1 RValue to @in_guaranteed.
// ---
public protocol IP {}
public protocol Seq {
associatedtype Iterator : IP
func makeIterator() -> Iterator
}
extension Seq where Self.Iterator == Self {
public func makeIterator() -> Self {
return self
}
}
public struct EnumIter<Base : IP> : IP, Seq {
internal var _base: Base
public typealias Iterator = EnumIter<Base>
}
// CHECK-LABEL: sil [ossa] @$s20opaque_values_silgen7EnumSeqV12makeIteratorAA0D4IterVy0G0QzGyF : $@convention(method) <Base where Base : Seq> (@in_guaranteed EnumSeq<Base>) -> @out EnumIter<Base.Iterator> {
// HECK: bb0(%0 : @guaranteed $EnumSeq<Base>):
// HECK: [[MT:%.*]] = metatype $@thin EnumIter<Base.Iterator>.Type
// HECK: [[FIELD:%.*]] = struct_extract %0 : $EnumSeq<Base>, #EnumSeq._base
// HECK: [[COPY:%.*]] = copy_value [[FIELD]] : $Base
// HECK: [[WT:%.*]] = witness_method $Base, #Seq.makeIterator : <Self where Self : Seq> (Self) -> () -> Self.Iterator : $@convention(witness_method: Seq) <τ_0_0 where τ_0_0 : Seq> (@in_guaranteed τ_0_0) -> @out τ_0_0.Iterator
// HECK: [[ITER:%.*]] = apply [[WT]]<Base>([[COPY]]) : $@convention(witness_method: Seq) <τ_0_0 where τ_0_0 : Seq> (@in_guaranteed τ_0_0) -> @out τ_0_0.Iterator
// HECK: destroy_value [[COPY]] : $Base
// HECK: [[FN:%.*]] = function_ref @$ss8EnumIterV5_baseAByxGx_tcfC : $@convention(method) <τ_0_0 where τ_0_0 : IP> (@in τ_0_0, @thin EnumIter<τ_0_0>.Type) -> @out EnumIter<τ_0_0>
// HECK: [[RET:%.*]] = apply [[FN]]<Base.Iterator>([[ITER]], [[MT]]) : $@convention(method) <τ_0_0 where τ_0_0 : IP> (@in τ_0_0, @thin EnumIter<τ_0_0>.Type) -> @out EnumIter<τ_0_0>
// HECK: return [[RET]] : $EnumIter<Base.Iterator>
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen7EnumSeqV12makeIteratorAA0D4IterVy0G0QzGyF'
public struct EnumSeq<Base : Seq> : Seq {
public typealias Iterator = EnumIter<Base.Iterator>
internal var _base: Base
public func makeIterator() -> Iterator {
return EnumIter(_base: _base.makeIterator())
}
}
extension Collection {
func myMap<T>(_ body: (Element) -> T) -> [T] {
var result = [T]()
for element in self {
result.append(body(element))
}
return result
}
func transformEachElement<U>(_ cl: (Element) -> U) -> [U] {
return myMap(cl)
}
}
extension Array where Element == Int {
// CHECK-LABEL: sil private [ossa] @$sSa20opaque_values_silgenSiRszlE20incrementEachElementSaySiGyFS2iXEfU_ : {{.*}} {
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : $Int):
// CHECK-LABEL: } // end sil function '$sSa20opaque_values_silgenSiRszlE20incrementEachElementSaySiGyFS2iXEfU_'
func incrementEachElement() -> [Int] {
return transformEachElement { element in
return element + 1
}
}
}
// CHECK-LABEL: sil private [ossa] @$s20opaque_values_silgen22anon_read_only_captureyS2iFSiyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> Int {
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen22anon_read_only_captureyS2iFSiyXEfU_'
func anon_read_only_capture(_ x: Int) -> Int {
var x = x
return ({ x })()
}
// CHECK-LABEL: sil private [ossa] @$s20opaque_values_silgen22testEmptyReturnClosureyyFyycyKXEfu_yycfU_ : $@convention(thin) @substituted <τ_0_0> () -> @out τ_0_0 for <()> {
// CHECK-NOT: bb1
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen22testEmptyReturnClosureyyFyycyKXEfu_yycfU_'
func testEmptyReturnClosure() {
func bar() {}
let b = nil ?? { bar() }
}
// Test that PatternMatchEmission::emitIsDispatch can emit a
// class-to-AnyObject cast as a guaranteed scalar cast
// (doesCastPreserveOwnershipForTypes returns true).
//
// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen24testCastClassToAnyObjectyyXlAA1CCF : $@convention(thin) (@guaranteed C) -> @owned AnyObject {
// CHECK: bb0(%0 : @guaranteed $C):
// CHECK: checked_cast_br C in %0 : $C to AnyObject, bb2, bb1
// CHECK: bb1(%{{.*}} : @guaranteed $C):
// CHECK: bb2(%{{.*}} : @guaranteed $AnyObject):
// CHECK-LABEL: } // end sil function
func testCastClassToAnyObject(_ c: C) -> AnyObject {
switch (c) {
case let x as AnyObject:
_ = x
break
}
}
// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen24testCastAnyObjectToClassyAA1CCyXlF : $@convention(thin) (@guaranteed AnyObject) -> @owned C {
// CHECK: bb0(%0 : @guaranteed $AnyObject):
// CHECK: [[CP:%.*]] = copy_value %0 : $AnyObject
// CHECK: checked_cast_br AnyObject in [[CP]] : $AnyObject to C, bb1, bb2
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen24testCastAnyObjectToClassyAA1CCyXlF'
func testCastAnyObjectToClass(_ o: AnyObject) -> C {
switch (o) {
case let x as C:
_ = x
break
default:
break
}
}
// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen024testCastClassArchetypeToF0yAA1CCxRlzClF : $@convention(thin) <T where T : AnyObject> (@guaranteed T) -> @owned C {
// CHECK: bb0(%0 : @guaranteed $T):
// CHECK: [[CP:%.*]] = copy_value %0 : $T
// CHECK: checked_cast_br T in [[CP]] : $T to C, bb1, bb2
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen024testCastClassArchetypeToF0yAA1CCxRlzClF'
func testCastClassArchetypeToClass<T : AnyObject>(_ o: T) -> C {
switch (o) {
case let x as C:
_ = x
break
default:
break
}
}
class TestGeneric<T> {
init() {}
var generic: T
@_borrowed
var borrowedGeneric: T
}
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s20opaque_values_silgen11TestGenericC08borrowedE0xvr :
// 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: [[LD:%.*]] = load_borrow [[ACCESS]] : $*T
// CHECK: yield [[LD]] : $T, resume bb1, unwind bb2
// CHECK: bb1:
// CHECK: end_borrow [[LD]] : $T
// CHECK: end_access [[ACCESS]] : $*T
// CHECK: [[RES:%.*]] = tuple ()
// CHECK: return [[RES]] : $()
// CHECK: bb2:
// CHECK: end_borrow [[LD]] : $T
// CHECK: end_access [[ACCESS]] : $*T
// CHECK: unwind
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen11TestGenericC08borrowedE0xvr'
// CHECK-LABEL: sil hidden [ossa] @$s20opaque_values_silgen8TestEnumO5_codeSivg :
// CHECK: bb0(%0 : @guaranteed $TestEnum<T>):
// CHECK: [[COPY:%.*]] = copy_value %0 : $TestEnum<T>
// CHECK: switch_enum [[COPY]] : $TestEnum<T>, case #TestEnum.invalidValue!enumelt: bb1
// CHECK: bb1([[VAL:%.*]] : @owned $Any):
// CHECK: destroy_value [[VAL]] : $Any
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen8TestEnumO5_codeSivg'
enum TestEnum<T> {
case invalidValue(Any)
var _code: Int {
switch self {
case .invalidValue: return 4866
}
}
}
public enum EnumWithTwoSameAddressOnlyPayloads<T> {
case nope
case yes(T)
case and(T)
// CHECK-LABEL: sil [ossa] @EnumWithTwoSameAddressOnlyPayloads_getPayload : {{.*}} {
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] :
// CHECK: [[RESULT_STORAGE:%[^,]+]] = alloc_stack $T
// CHECK: [[COPY:%[^,]+]] = copy_value [[INSTANCE]]
// CHECK: switch_enum [[COPY]] : $EnumWithTwoSameAddressOnlyPayloads<T>,
// CHECK-SAME: case #EnumWithTwoSameAddressOnlyPayloads.nope!enumelt: {{bb[0-9]+}},
// CHECK-SAME: case #EnumWithTwoSameAddressOnlyPayloads.yes!enumelt: [[YES_BLOCK:bb[0-9]+]],
// CHECK-SAME: case #EnumWithTwoSameAddressOnlyPayloads.and!enumelt: [[AND_BLOCK:bb[0-9]+]]
// CHECK: [[YES_BLOCK]]([[YES_VALUE:%[^,]+]] :
// CHECK: [[YES_LIFETIME:%[^,]+]] = move_value [lexical] [var_decl] [[YES_VALUE]]
// CHECK: [[YES_COPY:%[^,]+]] = copy_value [[YES_LIFETIME]]
// CHECK: store [[YES_COPY]] to [init] [[RESULT_STORAGE]]
// CHECK: [[AND_BLOCK]]([[AND_VALUE:%[^,]+]] :
// CHECK: [[AND_LIFETIME:%[^,]+]] = move_value [lexical] [var_decl] [[AND_VALUE]]
// CHECK: [[AND_COPY:%[^,]+]] = copy_value [[AND_LIFETIME]]
// CHECK: store [[AND_COPY]] to [init] [[RESULT_STORAGE]]
// CHECK-LABEL: } // end sil function 'EnumWithTwoSameAddressOnlyPayloads_getPayload'
public var getPayload: T? {
@_silgen_name("EnumWithTwoSameAddressOnlyPayloads_getPayload")
get {
switch self {
case .nope:
return nil
case .yes(let t), .and(let t):
return t
}
}
}
}
// Verify exit block arguments are ordered correctly.
//
// CHECK-LABEL: sil private [ossa] @$s20opaque_values_silgen19duplicate_with_int49condition5valueSi_S2ix_xttSb_xtlFSi_S2ix_xttyXEfU_ : {{.*}} {
// CHECK: br [[EPILOG:bb[0-9]+]]({{%[^,]+}} : $Int, {{%[^,]+}} : $Int, {{%[^,]+}} : $Int, {{%[^,]+}} : $Value, {{%[^,]+}} : $Value)
// CHECK: br [[EPILOG]]({{%[^,]+}} : $Int, {{%[^,]+}} : $Int, {{%[^,]+}} : $Int, {{%[^,]+}} : $Value, {{%[^,]+}} : $Value)
// CHECK: [[EPILOG]]({{%[^,]+}} : $Int, {{%[^,]+}} : $Int, {{%[^,]+}} : $Int, {{%[^,]+}} : @owned $Value, {{%[^,]+}} : @owned $Value):
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen19duplicate_with_int49condition5valueSi_S2ix_xttSb_xtlFSi_S2ix_xttyXEfU_'
func doit<T>(_ f: () -> T) -> T {
f()
}
@_silgen_name("duplicate_with_int4")
func duplicate_with_int4<Value>(condition: Bool, value: Value) -> (Int, Int, Int, (Value, Value)) {
doit {
if condition {
return (Int(), Int(), Int(), (value, value))
} else {
return (Int(), Int(), Int(), (value, value))
}
}
}
// Verify tuple rebuilding.
// CHECK-LABEL: sil private [ossa] @$s20opaque_values_silgen10duplicate15valuex_xtx_tlFx_xtyXEfU_ : {{.*}} {
// CHECK: [[RETVAL:%[^,]+]] = tuple ({{%[^,]+}} : $Value, {{%[^,]+}} : $Value)
// CHECK: return [[RETVAL]] : $(Value, Value)
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen10duplicate15valuex_xtx_tlFx_xtyXEfU_'
@_silgen_name("duplicate1")
func duplicate1<Value>(value: Value) -> (Value, Value) {
doit {
(value, value)
}
}
// CHECK-LABEL: sil private [ossa] @$s20opaque_values_silgen10duplicate25valuex3one_x3twotx_tlFxAD_xAEtyXEfU_ : {{.*}} {
// CHECK: [[RETVAL:%[^,]+]] = tuple $(one: Value, two: Value) ({{%[^,]+}}, {{%[^,]+}})
// CHECK: return [[RETVAL]] : $(one: Value, two: Value)
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen10duplicate25valuex3one_x3twotx_tlFxAD_xAEtyXEfU_'
@_silgen_name("duplicate2")
func duplicate2<Value>(value: Value) -> (one: Value, two: Value) {
doit {
(one: value, two: value)
}
}
// CHECK-LABEL: sil private [ossa] @$s20opaque_values_silgen19duplicate_with_int15valuex_xSitx_tlFx_xSityXEfU_ : {{.*}} {
// CHECK: [[RETVAL:%[^,]+]] = tuple ({{%[^,]+}} : $Value, {{%[^,]+}} : $Value, {{%[^,]+}} : $Int)
// CHECK: return [[RETVAL]]
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen19duplicate_with_int15valuex_xSitx_tlFx_xSityXEfU_'
@_silgen_name("duplicate_with_int1")
func duplicate_with_int1<Value>(value: Value) -> (Value, Value, Int) {
doit {
(value, value, 42)
}
}
// CHECK-LABEL: sil private [ossa] @$s20opaque_values_silgen19duplicate_with_int25valuex_xt_Sitx_tlFx_xt_SityXEfU_ : {{.*}} {
// CHECK: [[INNER:%[^,]+]] = tuple ({{%[^,]+}} : $Value, {{%[^,]+}} : $Value)
// CHECK: [[RETVAL:%[^,]+]] = tuple ([[INNER]] : $(Value, Value), {{%[^,]+}} : $Int)
// CHECK: return [[RETVAL]]
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen19duplicate_with_int25valuex_xt_Sitx_tlFx_xt_SityXEfU_'
@_silgen_name("duplicate_with_int2")
func duplicate_with_int2<Value>(value: Value) -> ((Value, Value), Int) {
doit {
((value, value), 42)
}
}
// CHECK-LABEL: sil private [ossa] @$s20opaque_values_silgen19duplicate_with_int35valueSi_x_x_x_SitxttSitx_tlFSi_x_x_x_SitxttSityXEfU_ : {{.*}} {
// CHECK: [[INNERMOST:%[^,]+]] = tuple ({{%[^,]+}} : $Value, {{%[^,]+}} : $Int)
// CHECK: [[INNERMIDDLE:%[^,]+]] = tuple ({{%[^,]+}} : $Value, [[INNERMOST]] : $(Value, Int), {{%[^,]+}} : $Value)
// CHECK: [[INNERLEAST:%[^,]+]] = tuple ({{%[^,]+}} : $Value, [[INNERMIDDLE]] : $(Value, (Value, Int), Value))
// CHECK: [[RETVAL:%[^,]+]] = tuple ({{%[^,]+}} : $Int, [[INNERLEAST]] : $(Value, (Value, (Value, Int), Value)), {{%[^,]+}} : $Int)
// CHECK: return [[RETVAL]] : $(Int, (Value, (Value, (Value, Int), Value)), Int)
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen19duplicate_with_int35valueSi_x_x_x_SitxttSitx_tlFSi_x_x_x_SitxttSityXEfU_'
@_silgen_name("duplicate_with_int3")
func duplicate_with_int3<Value>(value: Value) -> (Int, (Value, (Value, (Value, Int), Value)), Int) {
doit {
(42, (value, (value, (value, 43), value)), 44)
}
}
// Keypaths
indirect enum IndirectEnumWithAReadableIntProperty {
// CHECK-LABEL: sil {{.*}}@$s20opaque_values_silgen36IndirectEnumWithAReadableIntPropertyO1iSivpACTK : {{.*}} {
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] :
// TODO: Eliminate this copy.
// CHECK: [[COPY:%[^,]+]] = copy_value [[INSTANCE]]
// CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [[COPY]]
// CHECK: [[FN:%[^,]+]] = function_ref @$s20opaque_values_silgen36IndirectEnumWithAReadableIntPropertyO1iSivg : $@convention(method) (@guaranteed IndirectEnumWithAReadableIntProperty) -> Int
// CHECK: [[RESULT:%[^,]+]] = apply [[FN]]([[LIFETIME]])
// CHECK: end_borrow [[LIFETIME]]
// CHECK: destroy_value [[COPY]]
// CHECK: return [[RESULT]]
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen36IndirectEnumWithAReadableIntPropertyO1iSivpACTK'
var i: Int { 0 }
}
func takeReadableIntKeyPath<T>(_ kp: KeyPath<T, Int>) {
}
func giveReadableIntKeyPathInt() {
takeReadableIntKeyPath(\IndirectEnumWithAReadableIntProperty.i)
}
indirect enum StructWithAReadableStringProperty {
// CHECK-LABEL: sil {{.*}}@$s20opaque_values_silgen33StructWithAReadableStringPropertyO1sSSvpACTK : {{.*}} {
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] :
// CHECK: [[COPY:%[^,]+]] = copy_value [[INSTANCE]]
// CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [[COPY]]
// CHECK: [[FN:%[^,]+]] = function_ref @$s20opaque_values_silgen33StructWithAReadableStringPropertyO1sSSvg : $@convention(method) (@guaranteed StructWithAReadableStringProperty) -> @owned String
// CHECK: [[RESULT:%[^,]+]] = apply [[FN]]([[LIFETIME]])
// CHECK: end_borrow [[LIFETIME]]
// CHECK: destroy_value [[COPY]]
// CHECK: return [[RESULT]]
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen33StructWithAReadableStringPropertyO1sSSvpACTK'
var s: String { "howdy" }
}
func takeKeyPathString<T>(_ kp: KeyPath<T, String>) {
}
func giveKeyPathString() {
takeKeyPathString(\StructWithAReadableStringProperty.s)
}
#if os(macOS)
// CHECK-OSX-LABEL: sil {{.*}}@$s20opaque_values_silgen29backDeployingReturningGenericyxxKlFTwb : {{.*}} <T> {{.*}} {
// Ensure that there aren't any "normal" (in the sense of try_apply) blocks that
// take unbound generic parameters (τ_0_0).
// CHECK-OSX-NOT: {{bb[0-9]+}}({{%[^,]+}} : @owned $τ_0_0):
// CHECK-OSX-LABEL: } // end sil function '$s20opaque_values_silgen29backDeployingReturningGenericyxxKlFTwb'
@available(SwiftStdlib 5.1, *)
@backDeployed(before: SwiftStdlib 5.8)
public func backDeployingReturningGeneric<T>(_ t: T) throws -> T { t }
#endif
// CHECK-LABEL: sil {{.*}}[ossa] @SetIntoContainerAtKeyPath : {{.*}} {
// CHECK: bb0([[CONTAINER_ADDR:%[^,]+]] : {{.*}}, [[KP:%[^,]+]] : {{.*}}, [[VALUE:%[^,]+]] :
// CHECK: [[KP_COPY:%[^,]+]] = copy_value [[KP]] : $WritableKeyPath<Container, Field>
// CHECK: [[VALUE_COPY:%[^,]+]] = copy_value [[VALUE]] : $Field
// CHECK: [[CONTAINER_ACCESS:%[^,]+]] = begin_access [modify] [unknown] [[CONTAINER_ADDR]] : $*Container
// CHECK: [[SETTER:%[^,]+]] = function_ref @swift_setAtWritableKeyPath
// CHECK: apply [[SETTER]]<Container, Field>([[CONTAINER_ACCESS]], [[KP_COPY]], [[VALUE_COPY]])
// CHECK: end_access [[CONTAINER_ACCESS]] : $*Container
// CHECK: destroy_value [[KP_COPY]]
// CHECK-LABEL: } // end sil function 'SetIntoContainerAtKeyPath'
@_silgen_name("SetIntoContainerAtKeyPath")
func set<Container, Field>(into container: inout Container, at keyPath: WritableKeyPath<Container, Field>, _ value: Field) {
container[keyPath: keyPath] = value
}
// CHECK-LABEL: sil {{.*}}[ossa] @$s20opaque_values_silgen16FormClassKeyPathyyF1QL_C1qSivpADTk : {{.*}} {
// CHECK: bb0([[VALUE:%[^,]+]] :
// CHECK-SAME: [[CONTAINER:%[^,]+]] :
// CHECK: [[CONTAINER_COPY:%[^,]+]] = copy_value [[CONTAINER]]
// CHECK: [[SETTER:%[^,]+]] = class_method [[CONTAINER_COPY]]
// CHECK: apply [[SETTER]]([[VALUE]], [[CONTAINER_COPY]])
// CHECK: destroy_value [[CONTAINER_COPY]]
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen16FormClassKeyPathyyF1QL_C1qSivpADTk'
@_silgen_name("FormClassKeyPath")
func FormClassKeyPath() {
class Q {
var q: Int = 0
}
_ = \Q.q
}
// CHECK-LABEL: sil {{.*}}[ossa] @UseGetterOnInout : {{.*}} {
// CHECK: bb0([[CONTAINER_ADDR:%[^,]+]] :
// CHECK: [[KEYPATH:%[^,]+]] = keypath $WritableKeyPath<MyInt, Int>, (root $MyInt; stored_property #MyInt.int : $Int)
// CHECK: [[CONTAINER_ACCESS:%[^,]+]] = begin_access [read] [unknown] [[CONTAINER_ADDR]]
// CHECK: [[KEYPATH_UP:%[^,]+]] = upcast [[KEYPATH]]
// CHECK: [[CONTAINER:%[^,]+]] = load [trivial] [[CONTAINER_ACCESS]]
// CHECK: [[GETTER:%[^,]+]] = function_ref @swift_getAtKeyPath
// CHECK: [[VALUE:%[^,]+]] = apply [[GETTER]]<MyInt, Int>([[CONTAINER]], [[KEYPATH_UP]])
// CHECK: end_access [[CONTAINER_ACCESS]]
// CHECK: destroy_value [[KEYPATH_UP]]
// CHECK: return [[VALUE]] : $Int
// CHECK-LABEL: } // end sil function 'UseGetterOnInout'
@_silgen_name("UseGetterOnInout")
func getInout(_ i: inout MyInt) -> Int {
return i[keyPath: \MyInt.int]
}
protocol IntValuable {
var value: Int { get }
}
// CHECK-LABEL: sil {{.*}}[ossa] @getFromSubscriptOnLValueArray : {{.*}} {
// CHECK: bb0([[ARRAY_ADDR:%[^,]+]] :
// CHECK: [[ARRAY_ACCESS:%[^,]+]] = begin_access [read] [unknown] [[ARRAY_ADDR]]
// CHECK: [[ARRAY:%[^,]+]] = load_borrow [[ARRAY_ACCESS]]
// CHECK: [[SUBSCRIPT:%[^,]+]] = function_ref @$sSayxSicig
// CHECK: [[ELEMENT:%[^,]+]] = apply [[SUBSCRIPT]]<any IntValuable>({{%[^,]+}}, [[ARRAY]])
// CHECK: end_borrow [[ARRAY]]
// CHECK: [[ELEMENT_LIFETIME:%[^,]+]] = begin_borrow [[ELEMENT]]
// CHECK: [[OPEN_ELEMENT:%[^,]+]] = open_existential_value [[ELEMENT_LIFETIME]]
// CHECK: [[OPEN_ELEMENT_COPY:%[^,]+]] = copy_value [[OPEN_ELEMENT]]
// CHECK: end_access [[ARRAY_ACCESS]]
// CHECK: [[OPEN_ELEMENT_LIFETIME:%[^,]+]] = begin_borrow [[OPEN_ELEMENT_COPY]]
// CHECK: [[GETTER:%[^,]+]] = witness_method {{.*}}, #IntValuable.value!getter
// CHECK: apply [[GETTER]]<{{.*}}>([[OPEN_ELEMENT_LIFETIME]])
// CHECK: end_borrow [[OPEN_ELEMENT_LIFETIME]]
// CHECK: destroy_value [[OPEN_ELEMENT_COPY]]
// CHECK: end_borrow [[ELEMENT_LIFETIME]]
// CHECK: destroy_value [[ELEMENT]]
// CHECK-LABEL: } // end sil function 'getFromSubscriptOnLValueArray'
@_silgen_name("getFromSubscriptOnLValueArray")
func getFromSubscriptOnLValueArray(_ array: inout [IntValuable]) {
_ = array[0].value
}
protocol MutatingFooable {
mutating func foo()
}
// CHECK-LABEL: sil {{.*}}@callMutatingFooOnInoutExistential : {{.*}} {
// CHECK: bb0([[EXISTENTIAL_ADDR:%[^,]+]] :
// CHECK: [[EXISTENTIAL_ACCESS:%[^,]+]] = begin_access [modify] [unknown] [[EXISTENTIAL_ADDR]]
// CHECK: [[OPEN_ADDR:%[^,]+]] = open_existential_addr mutable_access [[EXISTENTIAL_ACCESS]]
// CHECK: [[FOO:%[^,]+]] = witness_method {{.*}}#MutatingFooable.foo
// CHECK: apply [[FOO]]<{{.*}}>([[OPEN_ADDR]])
// CHECK: end_access [[EXISTENTIAL_ACCESS]]
// CHECK-LABEL: } // end sil function 'callMutatingFooOnInoutExistential'
@_silgen_name("callMutatingFooOnInoutExistential")
func callMutatingFooOnInoutExistential(_ i: inout any MutatingFooable) {
i.foo()
}
// CHECK-LABEL: sil {{.*}}[ossa] @$s20opaque_values_silgen7WeakBoxV1txSgvg : {{.*}} {
// CHECK: bb0([[INSTANCE:%[^,]+]] :
// CHECK: [[WEAK_OPTIONAL:%[^,]+]] = struct_extract [[INSTANCE]]
// CHECK: [[STRONG_OPTIONAL:%[^,]+]] = strong_copy_weak_value [[WEAK_OPTIONAL]]
// CHECK: return [[STRONG_OPTIONAL]]
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen7WeakBoxV1txSgvg'
// CHECK-LABEL: sil {{.*}}[ossa] @$s20opaque_values_silgen7WeakBoxV1tACyxGxSg_tcfC : {{.*}} {
// CHECK: bb0([[STRONG_OPTIONAL:%[^,]+]] :
// CHECK: [[WEAK_OPTIONAL:%[^,]+]] = weak_copy_value [[STRONG_OPTIONAL]]
// CHECK: destroy_value [[STRONG_OPTIONAL]]
// CHECK: [[INSTANCE:%[^,]+]] = struct $WeakBox<T> ([[WEAK_OPTIONAL]] :
// CHECK: return [[INSTANCE]]
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen7WeakBoxV1tACyxGxSg_tcfC'
struct WeakBox<T : AnyObject> {
weak var t: T?
}
// CHECK-LABEL: sil {{.*}}[ossa] @intIntoAnyHashableVar : {{.*}} {
// CHECK: [[VAR_BOX_ADDR:%[^,]+]] = project_box
// CHECK: [[INT:%[^,]+]] = apply
// CHECK: [[CONVERT:%[^,]+]] = function_ref @$ss21_convertToAnyHashableys0cD0VxSHRzlF
// CHECK: [[INSTANCE:%[^,]+]] = apply [[CONVERT]]<Int>([[INT]])
// CHECK: store [[INSTANCE]] to [init] [[VAR_BOX_ADDR]]
// CHECK-LABEL: } // end sil function 'intIntoAnyHashableVar'
@_silgen_name("intIntoAnyHashableVar")
func intIntoAnyHashableVar() {
var anyHashable: AnyHashable = 0
}
// CHECK-LABEL: sil {{.*}}[ossa] @intIntoAnyHashableLet : {{.*}} {
// CHECK: [[INT:%[^,]+]] = apply
// CHECK: [[CONVERT:%[^,]+]] = function_ref @$ss21_convertToAnyHashableys0cD0VxSHRzlF
// CHECK: [[INSTANCE:%[^,]+]] = apply [[CONVERT]]<Int>([[INT]])
// CHECK-LABEL: } // end sil function 'intIntoAnyHashableLet'
@_silgen_name("intIntoAnyHashableLet")
func intIntoAnyHashableLet() {
let anyHashable: AnyHashable = 0
}
// CHECK-LABEL: sil {{.*}}[ossa] @consumeExprOfOwnedAddrOnlyValue : {{.*}} {
// CHECK: bb0([[T:%[^,]+]] :
// CHECK: [[T_LIFETIME:%[^,]+]] = begin_borrow [[T]]
// CHECK: [[T_COPY:%[^,]+]] = copy_value [[T_LIFETIME]]
// CHECK: [[T_MOVE:%[^,]+]] = move_value [allows_diagnostics] [[T_COPY]]
// CHECK: [[SINK:%[^,]+]] = function_ref @sink
// CHECK: apply [[SINK]]<T>([[T_MOVE]])
// CHECK: end_borrow [[T_LIFETIME]]
// CHECK: destroy_value [[T]]
// CHECK-LABEL: } // end sil function 'consumeExprOfOwnedAddrOnlyValue'
@_silgen_name("consumeExprOfOwnedAddrOnlyValue")
func consumeExprOfOwnedAddrOnlyValue<T>(_ t: __owned T) {
sink(consume t)
}
// CHECK-LABEL: sil {{.*}}[ossa] @consumeExprOfLoadExprOfOwnedAddrOnlyLValue : {{.*}} {
// CHECK: [[VAR:%[^,]+]] = alloc_box $<τ_0_0> { var τ_0_0 } <T>
// CHECK: [[VAR_LIFETIME:%[^,]+]] = begin_borrow [lexical] [var_decl] [[VAR]]
// CHECK: [[VAR_ADDR:%[^,]+]] = project_box [[VAR_LIFETIME]]
// CHECK: store {{%[^,]+}} to [init] [[VAR_ADDR]]
// CHECK: [[VAR_ACCESS:%[^,]+]] = begin_access [modify] [unknown] [[VAR_ADDR]]
// CHECK: [[TEMPORARY_ADDR:%[^,]+]] = alloc_stack $T
// CHECK: mark_unresolved_move_addr [[VAR_ACCESS]] to [[TEMPORARY_ADDR]]
// CHECK: [[TEMPORARY:%[^,]+]] = load [take] [[TEMPORARY_ADDR]]
// CHECK: end_access [[VAR_ACCESS]]
// CHECK: [[SINK:%[^,]+]] = function_ref @sink
// CHECK: apply [[SINK]]<T>([[TEMPORARY]])
// CHECK: dealloc_stack [[TEMPORARY_ADDR]]
// CHECK: destroy_value [[VAR]]
// CHECK-LABEL: } // end sil function 'consumeExprOfLoadExprOfOwnedAddrOnlyLValue'
@_silgen_name("consumeExprOfLoadExprOfOwnedAddrOnlyLValue")
func consumeExprOfLoadExprOfOwnedAddrOnlyLValue<T>(_ ty: T.Type) {
var t = source(ty)
sink(consume t)
}
struct Twople<T> {
var storage: (T, T)
// CHECK-LABEL: sil {{.*}}[ossa] @Twople_init_from_t1_t2 : {{.*}} {
// CHECK: bb0([[T1:%[^,]+]] :
// CHECK-SAME: [[T2:%[^,]+]] :
// CHECK-SAME: ):
// CHECK: [[VAR:%[^,]+]] = alloc_box
// CHECK: [[VAR_UNINIT:%[^,]+]] = mark_uninitialized [rootself] [[VAR]]
// CHECK: [[VAR_LIFETIME:%[^,]+]] = begin_borrow [lexical] [var_decl] [[VAR_UNINIT]]
// CHECK: [[VAR_ADDR:%[^,]+]] = project_box [[VAR_LIFETIME]]
// CHECK: [[T1_BORROW:%[^,]+]] = begin_borrow [[T1]]
// CHECK: [[T1_COPY:%[^,]+]] = copy_value [[T1_BORROW]]
// CHECK: [[T2_BORROW:%[^,]+]] = begin_borrow [[T2]]
// CHECK: [[T2_COPY:%[^,]+]] = copy_value [[T2_BORROW]]
// CHECK: [[VAR_ACCESS:%[^,]+]] = begin_access [modify] [unknown] [[VAR_ADDR]]
// CHECK: [[STORAGE_ACCESS:%[^,]+]] = struct_element_addr [[VAR_ACCESS]]
// In opaque values mode, without regard to the fact that T is
// address-only, a tuple is constructed and assigned into the
// storage.
// CHECK: [[TUPLE:%[^,]+]] = tuple (
// CHECK-SAME: [[T1_COPY]]
// CHECK-SAME: [[T2_COPY]]
// CHECK-SAME: )
// CHECK: assign [[TUPLE]] to [[STORAGE_ACCESS]]
// CHECK: end_access [[VAR_ACCESS]]
// CHECK: end_borrow [[T2_BORROW]]
// CHECK: end_borrow [[T1_BORROW]]
// CHECK: [[RETVAL:%[^,]+]] = load [copy] [[VAR_ADDR]]
// CHECK: destroy_value [[T2]]
// CHECK: destroy_value [[T1]]
// CHECK: end_borrow [[VAR_LIFETIME]]
// CHECK: destroy_value [[VAR_UNINIT]]
// CHECK: return [[RETVAL]]
// CHECK-LABEL: } // end sil function 'Twople_init_from_t1_t2'
@_silgen_name("Twople_init_from_t1_t2")
init(t1: T, t2: T) {
self.storage = (t1, t2)
}
}
// CHECK-LABEL: sil{{.*}} [ossa] @throwTypedValue : {{.*}} -> @error Err {
// CHECK: bb0([[E:%[^,]+]] :
// CHECK: [[SWIFT_WILL_THROW_TYPED:%[^,]+]] = function_ref @swift_willThrowTyped
// CHECK: apply [[SWIFT_WILL_THROW_TYPED]]<Err>([[E]])
// CHECK: throw [[E]]
// CHECK-LABEL: } // end sil function 'throwTypedValue'
@_silgen_name("throwTypedValue")
func throwTypedValue(_ e: Err) throws(Err) { throw e }
// CHECK-LABEL: sil{{.*}} [ossa] @callTypedThrowsFunc : {{.*}} -> @error any Error {
// CHECK: bb0:
// CHECK: [[TYPED_THROW_FN:%[^,]+]] = function_ref @throwTypedValue
// CHECK: try_apply [[TYPED_THROW_FN]]({{%[0-9]+}}) : $@convention(thin) (Err) -> @error Err, normal bb1, error bb2
//
// CHECK: bb1({{%[0-9]+}} : $()):
// CHECK: return
//
// CHECK: bb2([[E:%[^,]+]] : $Err):
// CHECK: [[STACK_ALLOC:%[^,]+]] = alloc_stack $any Error
// CHECK: [[BOX:%[^,]+]] = project_existential_box $Err
// CHECK: store [[E]] to [trivial] [[BOX]]
// CHECK: [[ANY_ERROR:%[^,]+]] = load [take] [[STACK_ALLOC]]
// CHECK: throw [[ANY_ERROR]]
// CHECK-LABEL: } // end sil function 'callTypedThrowsFunc'
@_silgen_name("callTypedThrowsFunc")
func callTypedThrowsFunc() throws {
try throwTypedValue(Err())
}
// CHECK-LABEL: sil{{.*}} [ossa] @throwTypedValueGeneric : {{.*}} <GenErr where GenErr : Error> (@in_guaranteed GenErr) -> @error_indirect GenErr {
// CHECK: bb0([[BORROWED_ERR:%[^,]+]] : @guaranteed $GenErr):
// CHECK: [[E:%[^,]+]] = copy_value [[BORROWED_ERR]]
// CHECK: [[SWIFT_WILL_THROW_TYPED:%[^,]+]] = function_ref @swift_willThrowTyped
// CHECK: apply [[SWIFT_WILL_THROW_TYPED]]<GenErr>([[E]])
// CHECK: throw [[E]]
// CHECK-LABEL: } // end sil function 'throwTypedValueGeneric'
@_silgen_name("throwTypedValueGeneric")
func throwTypedValueGeneric<GenErr: Error>(_ e: GenErr) throws(GenErr) { throw e }
// CHECK-LABEL: sil{{.*}} [ossa] @callTypedThrowsFuncGeneric : {{.*}} -> @error any Error {
// CHECK: bb0:
// CHECK: [[ERR_VAL:%[^,]+]] = apply {{.*}} -> Err
// CHECK: [[GEN_TYPED_THROW_FN:%[^,]+]] = function_ref @throwTypedValueGeneric
// CHECK: try_apply [[GEN_TYPED_THROW_FN]]<Err>([[ERR_VAL]]) : $@convention(thin) <τ_0_0 where τ_0_0 : Error> (@in_guaranteed τ_0_0) -> @error_indirect τ_0_0, normal bb1, error bb2
//
// CHECK: bb1({{%[0-9]+}} : $()):
// CHECK: return
//
// CHECK: bb2([[E:%[^,]+]] : $Err):
// CHECK: [[STACK_ALLOC:%[^,]+]] = alloc_stack $any Error
// CHECK: [[BOX:%[^,]+]] = project_existential_box $Err
// CHECK: store [[E]] to [trivial] [[BOX]]
// CHECK: [[ANY_ERROR:%[^,]+]] = load [take] [[STACK_ALLOC]]
// CHECK: throw [[ANY_ERROR]]
// CHECK-LABEL: } // end sil function 'callTypedThrowsFuncGeneric'
@_silgen_name("callTypedThrowsFuncGeneric")
func callTypedThrowsFuncGeneric() throws {
try throwTypedValueGeneric(Err())
}
struct Err : Error {}
// CHECK-LABEL: sil{{.*}} [ossa] @copy_expr_generic : {{.*}} {
// CHECK: bb0([[E:%[^,]+]] : @guaranteed $T
// CHECK: [[E_COPY:%[^,]+]] = explicit_copy_value [[E]]
// CHECK: apply {{.*}}<T>([[E_COPY]])
// CHECK-LABEL: } // end sil function 'copy_expr_generic'
@_silgen_name("copy_expr_generic")
func copy_expr_generic<T>(_ t: T) {
eat_generic(copy t)
}
func eat_generic<T>(_ t: consuming T) {}