mirror of
https://github.com/apple/swift.git
synced 2026-06-20 15:42:51 +02:00
097b0d3400
We cannot use spare bits or other overlapping storage layout tricks with fundamentally address-only enums, and we can take advantage of this to do borrowing switches or other in-place projections without copying the value. However, for resilient enums, the implementation may use spare bit packing, but the type must be handled address-only outside of its defining module, and we didn't have a way to express that with borrowing switch. Optimization passes have also been running into problems with the complexity that we were using `unchecked_take_enum_data_addr` sometimes as a pure operation. This patch splits the instruction into three: - `unchecked_inplace_enum_data_addr` represents a nondestructive in-place enum projection. It is only allowed for enums whose projection operation is nondestructive. - `unchecked_take_enum_data_addr` represents a destructive enum projection, invalidating the enum and leaving the payload to be further consumed. This matches the current instruction's semantics. - `unchecked_borrow_enum_data_addr` represents a borrowing enum projection. The instruction takes a second operand for "scratch" space, which the enum representation may be copied into in order to avoid invalidating the enum value, so the result is dependent on the lifetime of both the original enum and the scratch buffer. This allows for borrowing switches over resilient enums. `unchecked_borrow_enum_data_addr` is implemented by taking advantage of the "address-only enums can't do spare bit optimization" property at runtime. We inspect the operand type's bitwise-borrowability from its metadata. If the type is bitwise-borrowable, then we are allowed to bitwise-copy the enum to the scratch space and apply the projection to the scratch space, preserving the original value. If the type is not bitwise-borrowable, then we cannot use spare bit optimization in its layout, so we apply the projection in-place. Fixes rdar://174952822.
1926 lines
75 KiB
Plaintext
1926 lines
75 KiB
Plaintext
// RUN: %target-sil-opt -sil-print-types -enable-objc-interop -enable-sil-verify-all=true %s | %target-sil-opt -sil-print-types -enable-objc-interop -enable-sil-verify-all=true | %FileCheck %s
|
|
|
|
sil_stage raw // CHECK: sil_stage raw
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
// CHECK: sil_global private @globalinit_token0 : $Builtin.Word
|
|
sil_global private @globalinit_token0 : $Builtin.Word
|
|
|
|
class TestArrayStorage {
|
|
@_hasStorage var count: Int32
|
|
init()
|
|
}
|
|
|
|
struct TestArray {
|
|
var storage : TestArrayStorage
|
|
}
|
|
|
|
struct TestArray2 {
|
|
var storage : TestArrayStorage
|
|
var someValue : Int32
|
|
var storage2 : TestArrayStorage
|
|
}
|
|
|
|
// CHECK-LABEL: sil_global @static_array : $TestArrayStorage = {
|
|
// CHECK: %initval = object $TestArrayStorage (%3 : $Int32, [tail_elems] %4 : $Int64, %5 : $Int64)
|
|
// CHECK-NEXT: }
|
|
sil_global @static_array : $TestArrayStorage = {
|
|
%0 = integer_literal $Builtin.Int32, 2
|
|
%1 = integer_literal $Builtin.Int64, 10
|
|
%2 = integer_literal $Builtin.Int64, 20
|
|
%3 = struct $Int32 (%0 : $Builtin.Int32)
|
|
%4 = struct $Int64 (%1 : $Builtin.Int64)
|
|
%5 = struct $Int64 (%2 : $Builtin.Int64)
|
|
%initval = object $TestArrayStorage (%3 : $Int32, [tail_elems] %4 : $Int64, %5 : $Int64)
|
|
}
|
|
|
|
// CHECK-LABEL: sil_global @static_global_vector : $Int32 = {
|
|
// CHECK: %initval = vector (%1 : $Int32, %3 : $Int32)
|
|
// CHECK-NEXT: }
|
|
sil_global @static_global_vector : $Int32 = {
|
|
%0 = integer_literal $Builtin.Int32, 0
|
|
%1 = struct $Int32 (%0 : $Builtin.Int32)
|
|
%2 = integer_literal $Builtin.Int32, 1
|
|
%3 = struct $Int32 (%2 : $Builtin.Int32)
|
|
%initval = vector (%1 : $Int32, %3 : $Int32)
|
|
}
|
|
|
|
// Type references
|
|
|
|
// Some cyclic type references between SIL function bodies.
|
|
class Class1 {
|
|
var a : Class2
|
|
init()
|
|
}
|
|
class Class2 {
|
|
var b : Class1
|
|
init()
|
|
}
|
|
|
|
struct MoveOnlyStruct: ~Copyable {
|
|
@_hasStorage var i: Int
|
|
deinit
|
|
}
|
|
|
|
|
|
sil @type_ref1 : $(Class1, Int) -> () // CHECK-LABEL: sil @type_ref1 : $@convention(thin) (Class1, Int)
|
|
|
|
// Instructions
|
|
|
|
sil @test1 : $() -> () { // CHECK-LABEL: sil @test1 : $@convention(thin) () -> ()
|
|
bb0: // CHECK: bb0:
|
|
%0 = tuple () // CHECK: %0 = tuple ()
|
|
br bb1 // CHECK: br bb1
|
|
bb1:
|
|
%b = alloc_box $<τ_0_0> { var τ_0_0 } <Int> // CHECK: %2 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
|
|
%c = integer_literal $Builtin.Word, 1
|
|
// CHECK: integer_literal $Builtin.Word, -1
|
|
%e = integer_literal $Builtin.Word, -1
|
|
return %0 : $() // CHECK: return %0 : $()
|
|
}
|
|
|
|
// Forward referenced values.
|
|
sil @test2 : $(Int) -> () { // CHECK-LABEL: sil @test2 : $@convention(thin) (Int) -> ()
|
|
bb0(%0 : $Int):
|
|
br bb2
|
|
bb1:
|
|
// Forward reference MRVs.
|
|
store %0 to %7 : $*Int // CHECK: store %0 to %7
|
|
strong_release %6 : $<τ_0_0> { var τ_0_0 } <Int> // CHECK: strong_release %6
|
|
|
|
return %5 : $() // CHECK: return %5 : $()
|
|
bb2:
|
|
%5 = tuple () // CHECK: %5 = tuple ()
|
|
%6 = alloc_box $<τ_0_0> { var τ_0_0 } <Int> // CHECK: %6 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
|
|
%7 = project_box %6 : $<τ_0_0> { var τ_0_0 } <Int>, 0 // CHECK: %7 = project_box %6 : $<τ_0_0> { var τ_0_0 } <Int>
|
|
|
|
br bb1 // CHECK: br bb1
|
|
}
|
|
|
|
sil @named_tuple : $() -> (Builtin.Word, Builtin.Word) {
|
|
%0 = integer_literal $Builtin.Word, 42 // CHECK: integer_literal $Builtin.Word, 42
|
|
%9 = tuple $(Builtin.Word, Builtin.Word) (%0, %0)
|
|
return %9 : $(Builtin.Word, Builtin.Word)
|
|
}
|
|
|
|
sil @return_int : $@convention(thin) (Int) -> Int { // CHECK: $@convention(thin) (Int) -> Int {
|
|
bb0(%0 : $Int): // CHECK: bb0(%0 : $Int):
|
|
%1 = alloc_stack $Int // CHECK: alloc_stack $Int
|
|
store %0 to %1 : $*Int // CHECK: store %0 to %1 : $*Int
|
|
%3 = load %1 : $*Int // CHECK: load {{.*}} : $*Int
|
|
dealloc_stack %1 : $*Int // CHECK: dealloc_stack {{.*}} : $*Int
|
|
return %3 : $Int // CHECK: return {{.*}} : $Int
|
|
}
|
|
|
|
sil @call_fn_pointer : $@convention(thin) (() -> Int) -> Int {
|
|
bb0(%0 : $() -> Int):
|
|
%1 = alloc_stack $() -> Int // CHECK: alloc_stack $() -> Int
|
|
store %0 to %1 : $*() -> Int // CHECK: store %0 to %1 : $*() -> Int
|
|
%3 = load %1 : $*() -> Int // CHECK: load %1 : $*() -> Int
|
|
strong_retain %3 : $() -> Int // CHECK: strong_retain %3 : $() -> Int
|
|
%5 = apply %3() : $() -> Int // CHECK: apply %3() : $() -> Int
|
|
%6 = load %1 : $*() -> Int // CHECK: load %1 : $*() -> Int
|
|
strong_release %3 : $() -> Int // CHECK: release {{.*}} : $() -> Int
|
|
dealloc_stack %1 : $*() -> Int // CHECK: dealloc_stack %1 : $*() -> Int
|
|
return %5 : $Int // CHECK: return %5 : $Int
|
|
}
|
|
|
|
sil @return_constant : $@convention(thin) () -> Int { // CHECK-LABEL: @return_constant
|
|
bb0: // CHECK: bb0:
|
|
// CHECK: function_ref @_TSi25convertFromIntegerLiteralfMSiFT3valBi64__Si : $@convention(thin) (Builtin.Word, @thin Int.Type) -> Int
|
|
%1 = function_ref @_TSi25convertFromIntegerLiteralfMSiFT3valBi64__Si : $@convention(thin) (Builtin.Word, @thin Int.Type) -> Int
|
|
|
|
// CHECK: metatype $@thin Int.Type
|
|
%2 = metatype $@thin Int.Type
|
|
|
|
// CHECK: integer_literal $Builtin.Word, 1
|
|
%3 = integer_literal $Builtin.Word, 1
|
|
|
|
// CHECK: apply
|
|
%4 = apply %1(%3, %2) : $@convention(thin) (Builtin.Word, @thin Int.Type) -> Int
|
|
// CHECK: return
|
|
return %4 : $Int
|
|
}
|
|
|
|
sil @_TSi25convertFromIntegerLiteralfMSiFT3valBi64__Si : $@convention(thin) (Builtin.Word, @thin Int.Type) -> Int
|
|
|
|
// Parse SIL generated from the following swift program:
|
|
// func x(a : Bool) -> Int { if a { return 4 } else {return 5} }
|
|
sil @_TSb13getLogicValuefRSbFT_Bi1_ : $@convention(method) (@inout Bool) -> Builtin.Int1
|
|
sil @_TSi33_convertFromBuiltinIntegerLiteralfMSiFT3valBi128__Si : $@convention(thin) (Builtin.Int128, @thin Int.Type) -> Int
|
|
|
|
// CHECK-LABEL: @_T4test1xFT1aSb_Si
|
|
sil @_T4test1xFT1aSb_Si : $@convention(thin) (Bool) -> Int {
|
|
// CHECK: bb0(%0 : $Bool):
|
|
bb0(%0 : $Bool):
|
|
// CHECK: alloc_stack $Bool
|
|
%1 = alloc_stack $Bool
|
|
// CHECK: store
|
|
store %0 to %1 : $*Bool
|
|
// CHECK: function_ref @_TSb13getLogicValuefRSbFT_Bi1_ : $@convention(method) (@inout Bool) -> Builtin.Int1
|
|
%3 = function_ref @_TSb13getLogicValuefRSbFT_Bi1_ : $@convention(method) (@inout Bool) -> Builtin.Int1
|
|
// CHECK: apply
|
|
%4 = apply %3(%1) : $@convention(method) (@inout Bool) -> Builtin.Int1
|
|
// CHECK: cond_br
|
|
cond_br %4, bb1, bb2
|
|
|
|
// CHECK: bb1:
|
|
bb1:
|
|
// CHECK: function_ref @_TSi33_convertFromBuiltinIntegerLiteralfMSiFT3valBi128__Si : $@convention(thin) (Builtin.Int128, @thin Int.Type) -> Int
|
|
%6 = function_ref @_TSi33_convertFromBuiltinIntegerLiteralfMSiFT3valBi128__Si : $@convention(thin) (Builtin.Int128, @thin Int.Type) -> Int
|
|
// CHECK: metatype $@thin Int.Type
|
|
%7 = metatype $@thin Int.Type
|
|
// CHECK: integer_literal $Builtin.Int128, 4
|
|
%8 = integer_literal $Builtin.Int128, 4
|
|
// CHECK: apply
|
|
%9 = apply %6(%8, %7) : $@convention(thin) (Builtin.Int128, @thin Int.Type) -> Int
|
|
// CHECK: dealloc_stack
|
|
dealloc_stack %1 : $*Bool
|
|
// CHECK: br
|
|
br bb3(%9 : $Int)
|
|
|
|
// CHECK: bb2:
|
|
bb2:
|
|
// CHECK: function_ref @_TSi33_convertFromBuiltinIntegerLiteralfMSiFT3valBi128__Si : $@convention(thin) (Builtin.Int128, @thin Int.Type) -> Int
|
|
%12 = function_ref @_TSi33_convertFromBuiltinIntegerLiteralfMSiFT3valBi128__Si : $@convention(thin) (Builtin.Int128, @thin Int.Type) -> Int
|
|
// CHECK: metatype $@thin Int.Type
|
|
%13 = metatype $@thin Int.Type
|
|
// CHECK: integer_literal $Builtin.Int128, 5
|
|
%14 = integer_literal $Builtin.Int128, 5
|
|
// CHECK: apply
|
|
%15 = apply %12(%14, %13) : $@convention(thin) (Builtin.Int128, @thin Int.Type) -> Int
|
|
// CHECK: dealloc_stack
|
|
dealloc_stack %1 : $*Bool
|
|
// CHECK: br
|
|
br bb3(%15 : $Int)
|
|
|
|
bb3(%17 : $Int):
|
|
// CHECK: return
|
|
return %17 : $Int
|
|
}
|
|
|
|
|
|
protocol P {
|
|
func doIt()
|
|
}
|
|
|
|
sil @existentials : $@convention(thin) (@in P) -> () {
|
|
bb0(%0 : $*P):
|
|
// CHECK: open_existential_addr mutable_access %0
|
|
%1 = open_existential_addr mutable_access %0 : $*P to $*@opened("01234567-89ab-cdef-0123-000000000000", P) Self
|
|
|
|
// CHECK: witness_method ${{.*}}, #P.doIt
|
|
%2 = witness_method $@opened("01234567-89ab-cdef-0123-000000000000", P) Self, #P.doIt, %1 : $*@opened("01234567-89ab-cdef-0123-000000000000", P) Self : $@convention(witness_method: P) <T: P> (@inout T) -> ()
|
|
// Make sure we have the correct scope for generic parameters.
|
|
// CHECK: witness_method $@opened("{{.*}}", any P) Self, #P.doIt
|
|
%7 = witness_method $@opened("01234567-89ab-cdef-0123-000000000000", P) Self, #P.doIt, %1 : $*@opened("01234567-89ab-cdef-0123-000000000000", P) Self : $@convention(witness_method: P) <T: P> (@inout T) -> ()
|
|
// CHECK: apply
|
|
%3 = apply %2<@opened("01234567-89ab-cdef-0123-000000000000", P) Self>(%1) : $@convention(witness_method: P) <T: P> (@inout T) -> ()
|
|
%4 = tuple () // CHECK: tuple ()
|
|
|
|
// CHECK: open_existential_addr immutable_access
|
|
%5 = open_existential_addr immutable_access %0 : $*P to $*@opened("01234567-89ab-cdef-0123-000000000001", P) Self
|
|
%6 = witness_method $@opened("01234567-89ab-cdef-0123-000000000001", P) Self, #P.doIt, %5 : $*@opened("01234567-89ab-cdef-0123-000000000001", P) Self : $@convention(witness_method: P) <T: P> (@in_guaranteed T) -> ()
|
|
%8 = apply %6<@opened("01234567-89ab-cdef-0123-000000000001", P) Self>(%5) : $@convention(witness_method: P) <T: P> (@in_guaranteed T) -> ()
|
|
|
|
destroy_addr %0 : $*P // CHECK: destroy_addr %0 : $*any P
|
|
return %4 : $() // CHECK: return
|
|
}
|
|
|
|
|
|
class C {
|
|
func doIt() {}
|
|
}
|
|
|
|
class D : C {
|
|
override func doIt() {
|
|
super.doIt()
|
|
}
|
|
}
|
|
|
|
|
|
sil @classes : $@convention(thin) () -> () {
|
|
bb0:
|
|
// CHECK: %0 = alloc_ref $C
|
|
%C = alloc_ref $C
|
|
// CHECK: unchecked_ref_cast %0 : $C to $Builtin.NativeObject
|
|
%1 = unchecked_ref_cast %C : $C to $Builtin.NativeObject
|
|
// CHECK: unchecked_ref_cast %0 : $C to $AnyObject
|
|
%O = unchecked_ref_cast %C : $C to $Builtin.AnyObject
|
|
|
|
// CHECK: class_method {{.*}} : $C, #C.doIt
|
|
%2 = class_method %C : $C, #C.doIt : (C) -> () -> (), $@convention(method) (@guaranteed C) -> ()
|
|
|
|
// CHECK: alloc_ref $D
|
|
%D = alloc_ref $D
|
|
|
|
// CHECK: upcast {{.*}} : $D to $C
|
|
%a = upcast %D : $D to $C
|
|
|
|
|
|
%5 = unconditional_checked_cast %C : $C to D // CHECK: unconditional_checked_cast
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_alloc_ref_non_nested : $@convention(thin) () -> () {
|
|
sil @test_alloc_ref_non_nested : $@convention(thin) () -> () {
|
|
bb0:
|
|
// CHECK: %0 = alloc_ref [stack] [non_nested] $C
|
|
%0 = alloc_ref [stack] [non_nested] $C
|
|
dealloc_stack_ref %0
|
|
|
|
%2 = metatype $@thick C.Type
|
|
|
|
// CHECK: %3 = alloc_ref_dynamic [stack] [non_nested] %2 : $@thick C.Type, $C
|
|
%3 = alloc_ref_dynamic [stack] [non_nested] %2 : $@thick C.Type, $C
|
|
dealloc_stack_ref %3
|
|
|
|
%result = tuple ()
|
|
return %result
|
|
}
|
|
|
|
sil @optional_upcasts : $@convention(thin) (Optional<D>) -> () {
|
|
bb0(%0: $Optional<D>):
|
|
// CHECK: upcast {{.*}} : $Optional<D> to $Optional<C>
|
|
%1 = upcast %0 : $Optional<D> to $Optional<C>
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
|
|
// Generated from:
|
|
// func archetype_member_ref<T:Runcible>(x:T) {
|
|
// x.free_method()
|
|
// T.static_method()
|
|
// }
|
|
|
|
protocol Runcible {
|
|
var free:Int { get }
|
|
|
|
func free_method() -> Int
|
|
static func static_method()
|
|
}
|
|
|
|
// CHECK: $@convention(thin) <T where T : Runcible> (@in T) -> ()
|
|
sil @_T4arch20archetype_member_refUS_8Runcible___FT1xQ__T_ : $@convention(thin) <T : Runcible> (@in T) -> () {
|
|
bb0(%0 : $*T):
|
|
// CHECK: witness_method $T, #Runcible.free_method
|
|
%1 = witness_method $T, #Runcible.free_method : $@convention(witness_method: Runcible) <Self : Runcible> (@in Self) -> Int
|
|
%2 = apply %1<T>(%0) : $@convention(witness_method: Runcible) <Self : Runcible> (@in Self) -> Int
|
|
%3 = metatype $@thick T.Type
|
|
// CHECK: witness_method $T, #Runcible.static_method
|
|
%4 = witness_method $T, #Runcible.static_method : $@convention(witness_method: Runcible) <Self : Runcible> (@thick Self.Type) -> ()
|
|
%5 = apply %4<T>(%3) : $@convention(witness_method: Runcible) <Self : Runcible> (@thick Self.Type) -> ()
|
|
%6 = tuple ()
|
|
destroy_addr %0 : $*T
|
|
return %6 : $()
|
|
}
|
|
|
|
protocol Bendable { }
|
|
|
|
// CHECK: $@convention(thin) (@in any Bendable & Runcible) -> @out any Runcible
|
|
sil @_T4todo18erasure_from_protoFT1xPS_8RuncibleS_8Bendable__PS0__ : $@convention(thin) (@in Bendable & Runcible) -> @out Runcible {
|
|
bb0(%0 : $*Runcible, %1 : $*Bendable & Runcible):
|
|
// CHECK: alloc_box
|
|
%2 = alloc_box $<τ_0_0> { var τ_0_0 } <Bendable & Runcible>
|
|
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <Bendable & Runcible>, 0
|
|
// CHECK: copy_addr [take] {{.*}} to [init] {{.*}} : $*any Bendable & Runcible
|
|
copy_addr [take] %1 to [init] %2a : $*Bendable & Runcible
|
|
// CHECK: alloc_stack
|
|
%4 = alloc_stack $Bendable & Runcible
|
|
// CHECK: copy_addr {{.*}} to [init] {{.*}} : $*any Bendable & Runcible
|
|
copy_addr %2a to [init] %4 : $*Bendable & Runcible
|
|
%7 = tuple ()
|
|
// CHECK: destroy_addr
|
|
destroy_addr %4 : $*Bendable & Runcible
|
|
// CHECK: dealloc_stack
|
|
dealloc_stack %4 : $*Bendable & Runcible
|
|
// CHECK: release
|
|
strong_release %2 : $<τ_0_0> { var τ_0_0 } <Bendable & Runcible>
|
|
// CHECK: return
|
|
return %7 : $()
|
|
}
|
|
|
|
protocol ClassBound : AnyObject {
|
|
func classBoundMethod()
|
|
}
|
|
|
|
// CHECK: $@convention(thin) (any ClassBound) -> ()
|
|
sil @_T4todo18class_bound_methodFT1xPS_10ClassBound__T_ : $@convention(thin) (ClassBound) -> () {
|
|
bb0(%0 : $ClassBound):
|
|
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <ClassBound> // CHECK: alloc_box
|
|
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <ClassBound>, 0
|
|
store %0 to %1a : $*ClassBound // CHECK: store
|
|
%3 = load %1a : $*ClassBound // CHECK: load
|
|
strong_retain %3 : $ClassBound // CHECK: strong_retain
|
|
// CHECK: open_existential_ref {{%.*}} : $any ClassBound to $@opened({{.*}}, any ClassBound) Self
|
|
%5 = open_existential_ref %3 : $ClassBound to $@opened("01234567-89ab-cdef-0123-111111111111", ClassBound) Self
|
|
// CHECK: witness_method
|
|
%6 = witness_method $@opened("01234567-89ab-cdef-0123-111111111111", ClassBound) Self, #ClassBound.classBoundMethod, %5 : $@opened("01234567-89ab-cdef-0123-111111111111", ClassBound) Self : $@convention(witness_method: ClassBound) <T: ClassBound> (T) -> ()
|
|
%7 = apply %6<@opened("01234567-89ab-cdef-0123-111111111111", ClassBound) Self>(%5) : $@convention(witness_method: ClassBound) <T: ClassBound> (T) -> ()
|
|
%8 = tuple ()
|
|
strong_release %1 : $<τ_0_0> { var τ_0_0 } <ClassBound>
|
|
return %8 : $()
|
|
}
|
|
|
|
struct Val {
|
|
}
|
|
|
|
// CHECK: $@convention(thin) (@thin Val.Type) -> Val
|
|
sil @_TV4todo3ValCfMS0_FT_S0_ : $@convention(thin) (@thin Val.Type) -> Val {
|
|
bb0(%0 : $@thin Val.Type):
|
|
%1 = alloc_stack $Val // CHECK: alloc_stack
|
|
%3 = load %1 : $*Val
|
|
dealloc_stack %1 : $*Val
|
|
return %3 : $Val
|
|
}
|
|
|
|
class Ref {
|
|
}
|
|
struct Aleph {
|
|
var a:Ref
|
|
var b:Val
|
|
}
|
|
|
|
// CHECK: $@convention(thin) (Ref, Val, @thin Aleph.Type) -> Aleph
|
|
sil @_TV6struct5AlephCfMS0_FT1aCS_3Ref1bVS_3Val_S0_ : $@convention(thin) (Ref, Val, @thin Aleph.Type) -> Aleph {
|
|
bb0(%0 : $Ref, %1 : $Val, %2 : $@thin Aleph.Type):
|
|
// CHECK: struct $Aleph ({{%.*}} : $Ref, {{%.*}} : $Val)
|
|
%3 = struct $Aleph (%0 : $Ref, %1 : $Val)
|
|
return %3 : $Aleph // CHECK: return
|
|
}
|
|
|
|
// CHECK: $@convention(thin) (@thin Aleph.Type) -> Aleph
|
|
sil @_TV6struct5AlephCfMS0_FT_S0_ : $@convention(thin) (@thin Aleph.Type) -> Aleph {
|
|
bb0(%0 : $@thin Aleph.Type):
|
|
%1 = tuple ()
|
|
%2 = alloc_box $<τ_0_0> { var τ_0_0 } <Aleph> // CHECK: alloc_box
|
|
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <Aleph>, 0
|
|
// CHECK: struct_element_addr {{.*}} : $*Aleph, #Aleph.a
|
|
%5 = struct_element_addr %2a : $*Aleph, #Aleph.a
|
|
%6 = load %5 : $*Ref
|
|
strong_release %6 : $Ref
|
|
%14 = load %2a : $*Aleph
|
|
// CHECK: struct_extract {{%.*}} : $Aleph, #Aleph.a
|
|
%15 = struct_extract %14 : $Aleph, #Aleph.a
|
|
strong_retain %15 : $Ref
|
|
strong_release %2 : $<τ_0_0> { var τ_0_0 } <Aleph>
|
|
return %14 : $Aleph
|
|
}
|
|
|
|
enum Beth {
|
|
case EmptyCase
|
|
case DataCase(Int)
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_union_empty_case : $@convention(thin) () -> Beth {
|
|
sil @test_union_empty_case : $() -> Beth {
|
|
bb0:
|
|
// CHECK: %0 = enum $Beth, #Beth.EmptyCase!enumelt
|
|
%0 = enum $Beth, #Beth.EmptyCase!enumelt
|
|
return %0 : $Beth
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_union_data_case : $@convention(thin) (Int) -> Beth {
|
|
sil @test_union_data_case : $(Int) -> Beth {
|
|
bb0(%0 : $Int):
|
|
// CHECK: %1 = enum $Beth, #Beth.DataCase!enumelt, %0 : $Int
|
|
%1 = enum $Beth, #Beth.DataCase!enumelt, %0 : $Int
|
|
return %1 : $Beth
|
|
}
|
|
|
|
protocol Q {}
|
|
|
|
enum Gimel {
|
|
case EmptyCase
|
|
case DataCase(Q)
|
|
}
|
|
|
|
sil @test_union_addr_empty_case : $() -> @out Gimel {
|
|
bb0(%0 : $*Gimel):
|
|
// CHECK: inject_enum_addr {{%.*}} : $*Gimel, #Gimel.EmptyCase!enumelt
|
|
inject_enum_addr %0 : $*Gimel, #Gimel.EmptyCase!enumelt
|
|
%t = tuple ()
|
|
return %t : $()
|
|
}
|
|
|
|
sil @test_union_addr_data_case : $(@in Q) -> (@out Gimel) {
|
|
bb0(%0 : $*Gimel, %1 : $*Q):
|
|
// CHECK: {{%.*}} = init_enum_data_addr {{%.*}} : $*Gimel, #Gimel.DataCase!enumelt
|
|
%p = init_enum_data_addr %0 : $*Gimel, #Gimel.DataCase!enumelt
|
|
copy_addr [take] %1 to [init] %p : $*Q
|
|
inject_enum_addr %0 : $*Gimel, #Gimel.DataCase!enumelt
|
|
%t = tuple ()
|
|
return %t : $()
|
|
}
|
|
|
|
sil @_T5tuple5floatFT1xSf_T_ : $@convention(thin) (Float32) -> ()
|
|
sil @_T5tuple5tupleFT_TSiSf_ : $@convention(thin) () -> (Int, Float32)
|
|
|
|
// CHECK: $@convention(thin) (Int, Float) -> ()
|
|
sil @_T5tuple13tuple_elementFT1xTSiSf__T_ : $@convention(thin) (Int, Float) -> () {
|
|
bb0(%0 : $Int, %1 : $Float):
|
|
%2 = alloc_box $<τ_0_0> { var τ_0_0 } <(Int, Float)>
|
|
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <(Int, Float)>, 0
|
|
// CHECK: tuple ({{%.*}} : $Int, {{%.*}} : $Float)
|
|
%3 = tuple (%0 : $Int, %1 : $Float)
|
|
store %3 to %2a : $*(Int, Float)
|
|
// CHECK: tuple_element_addr {{%.*}} : $*(Int, Float), 0
|
|
%6 = tuple_element_addr %2a : $*(Int, Float), 0
|
|
// CHECK: load
|
|
%7 = load %6 : $*Int
|
|
// CHECK: tuple_element_addr {{%.*}} : $*(Int, Float), 1
|
|
%10 = tuple_element_addr %2a : $*(Int, Float), 1
|
|
// CHECK: load
|
|
%11 = load %10 : $*Float
|
|
// CHECK: function_ref
|
|
%14 = function_ref @_T5tuple5tupleFT_TSiSf_ : $@convention(thin) () -> (Int, Float)
|
|
// CHECK: apply
|
|
%15 = apply %14() : $@convention(thin) () -> (Int, Float)
|
|
// CHECK: function_ref
|
|
%19 = function_ref @_T5tuple5floatFT1xSf_T_ : $@convention(thin) (Float) -> ()
|
|
// CHECK: tuple_extract {{%.*}} : $(Int, Float), 1
|
|
%17 = tuple_extract %15 : $(Int, Float), 1
|
|
// CHECK: apply
|
|
%24 = apply %19(%17) : $@convention(thin) (Float) -> ()
|
|
%25 = tuple ()
|
|
strong_release %2 : $<τ_0_0> { var τ_0_0 } <(Int, Float)>
|
|
return %25 : $()
|
|
}
|
|
|
|
class M {
|
|
var member: Int
|
|
init()
|
|
}
|
|
|
|
// CHECK: $@convention(method) (Int, M) -> ()
|
|
sil @_TC3ref1C3foofS0_FT1xSi_T_ : $@convention(method) (Int, M) -> () {
|
|
bb0(%0 : $Int, %1 : $M):
|
|
%2 = alloc_box $<τ_0_0> { var τ_0_0 } <Int> // CHECK: alloc_box $<τ_0_0> { var τ_0_0 } <Int>
|
|
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <Int>, 0
|
|
store %0 to %2a : $*Int
|
|
%4 = alloc_box $<τ_0_0> { var τ_0_0 } <M> // CHECK: alloc_box $<τ_0_0> { var τ_0_0 } <M>
|
|
%4a = project_box %4 : $<τ_0_0> { var τ_0_0 } <M>, 0
|
|
store %1 to %4a : $*M
|
|
%6 = load %2a : $*Int // CHECK: load {{.*}} : $*Int
|
|
%7 = load %4a : $*M // CHECK: load {{.*}} : $*M
|
|
strong_retain %7 : $M
|
|
// CHECK: ref_element_addr {{%.*}} : $M, #M.member
|
|
%9 = ref_element_addr %7 : $M, #M.member
|
|
store %6 to %9 : $*Int
|
|
strong_release %7 : $M
|
|
%12 = tuple ()
|
|
strong_release %4 : $<τ_0_0> { var τ_0_0 } <M>
|
|
strong_release %2 : $<τ_0_0> { var τ_0_0 } <Int>
|
|
return %12 : $()
|
|
}
|
|
|
|
class GenericClass<Q> {
|
|
var member: Q
|
|
init()
|
|
}
|
|
|
|
// CHECK: sil @bound_generic_class_ref_element_addr : $@convention(thin) (GenericClass<Int>) -> Int {
|
|
sil @bound_generic_class_ref_element_addr : $@convention(thin) (GenericClass<Int>) -> Int {
|
|
entry(%0 : $GenericClass<Int>):
|
|
// CHECK: %1 = ref_element_addr %0 : $GenericClass<Int>, #GenericClass.member
|
|
%1 = ref_element_addr %0 : $GenericClass<Int>, #GenericClass.member
|
|
// CHECK: %2 = load %1 : $*Int
|
|
%2 = load %1 : $*Int
|
|
return %2 : $Int
|
|
}
|
|
|
|
class B { }
|
|
class E : B { }
|
|
|
|
// CHECK: $@convention(thin) (B) -> Builtin.Int1
|
|
sil @_T4null3isaFT1bCS_1B_Sb : $@convention(thin) (B) -> Builtin.Int1 {
|
|
bb0(%0 : $B):
|
|
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <B> // CHECK: alloc_box
|
|
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <B>, 0
|
|
store %0 to %1a : $*B
|
|
%3 = load %1a : $*B // CHECK: load
|
|
strong_retain %3 : $B
|
|
checked_cast_br B in %3 : $B to E, yes, no // CHECK: checked_cast_br
|
|
yes(%5 : $E):
|
|
%y = integer_literal $Builtin.Int1, 1
|
|
br isa(%y : $Builtin.Int1)
|
|
no:
|
|
%n = integer_literal $Builtin.Int1, 0
|
|
br isa(%n : $Builtin.Int1)
|
|
isa(%6 : $Builtin.Int1):
|
|
strong_release %3 : $B
|
|
strong_release %1 : $<τ_0_0> { var τ_0_0 } <B>
|
|
return %6 : $Builtin.Int1
|
|
}
|
|
|
|
sil @_TSd31_convertFromBuiltinFloatLiteralfMSdFT5valueBf64__Sd : $@convention(thin) (Builtin.FPIEEE64, @thin Float64.Type) -> Float64
|
|
sil @_TSS32_convertFromBuiltinStringLiteralfMSSFT5valueBp17utf8CodeUnitCountBi64_7isASCIIBi1__SS : $@convention(thin) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> String
|
|
|
|
|
|
sil @_T5index5gep64FT1pBp1iBi64__Bp : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Builtin.RawPointer {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
|
|
%2 = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.RawPointer> // CHECK: alloc_box
|
|
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <Builtin.RawPointer>, 0
|
|
%3 = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.Word> // CHECK: alloc_box
|
|
%3a = project_box %3 : $<τ_0_0> { var τ_0_0 } <Builtin.Word>, 0
|
|
store %0 to %2a : $*Builtin.RawPointer
|
|
store %1 to %3a : $*Builtin.Word
|
|
%7 = load %2a : $*Builtin.RawPointer // CHECK: load
|
|
%8 = load %3a : $*Builtin.Word // CHECK: load
|
|
// CHECK: index_raw_pointer {{%.*}} : $Builtin.RawPointer, {{%.*}} : $Builtin.Word
|
|
%9 = index_raw_pointer %7 : $Builtin.RawPointer, %8 : $Builtin.Word
|
|
strong_release %3 : $<τ_0_0> { var τ_0_0 } <Builtin.Word>
|
|
strong_release %2 : $<τ_0_0> { var τ_0_0 } <Builtin.RawPointer>
|
|
return %9 : $Builtin.RawPointer
|
|
}
|
|
|
|
sil_global @x : $Int
|
|
sil @global_callee : $@convention(thin) (Builtin.Int128, @thin Int.Type) -> Int
|
|
|
|
// CHECK-LABEL: sil @return_static_array
|
|
sil @return_static_array : $@convention(thin) () -> TestArray {
|
|
bb0:
|
|
// CHECK: %0 = global_value @static_array : $TestArrayStorage
|
|
%0 = global_value @static_array : $TestArrayStorage
|
|
%1 = struct $TestArray (%0 : $TestArrayStorage)
|
|
return %1 : $TestArray
|
|
}
|
|
|
|
// CHECK-LABEL: @global_code : $@convention(thin) () -> ()
|
|
sil private @global_code : $() -> () {
|
|
bb0:
|
|
// CHECK: alloc_global @x
|
|
alloc_global @x
|
|
// CHECK: global_addr @x : $*Int
|
|
%0 = global_addr @x : $*Int
|
|
%1 = function_ref @global_callee : $@convention(thin) (Builtin.Int128, @thin Int.Type) -> Int
|
|
%2 = metatype $@thin Int.Type
|
|
%3 = integer_literal $Builtin.Int128, 0 // CHECK: integer_literal $Builtin.Int128, 0
|
|
%4 = apply %1(%3, %2) : $@convention(thin) (Builtin.Int128, @thin Int.Type) -> Int
|
|
store %4 to %0 : $*Int
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @base_addr : $@convention(thin) () -> ()
|
|
sil private @base_addr : $() -> () {
|
|
bb0:
|
|
// CHECK: base_addr_for_offset $*Int
|
|
%0 = base_addr_for_offset $*Int
|
|
%1 = tuple ()
|
|
return %1 : $()
|
|
}
|
|
|
|
protocol SomeProtocol {
|
|
}
|
|
class SomeClass : SomeProtocol {
|
|
}
|
|
class SomeSubclass : SomeClass {}
|
|
|
|
sil @test_class_metatype : $@convention(thin) (SomeClass, SomeSubclass) -> (@thick SomeClass.Type, @thick SomeClass.Type) {
|
|
bb0(%0 : $SomeClass, %1 : $SomeSubclass):
|
|
%2 = alloc_box $<τ_0_0> { var τ_0_0 } <SomeClass> // CHECK: alloc_box
|
|
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <SomeClass>, 0
|
|
%3 = alloc_box $<τ_0_0> { var τ_0_0 } <SomeSubclass> // CHECK: alloc_box
|
|
%3a = project_box %3 : $<τ_0_0> { var τ_0_0 } <SomeSubclass>, 0
|
|
store %0 to %2a : $*SomeClass
|
|
store %1 to %3a : $*SomeSubclass
|
|
%7 = load %2a : $*SomeClass // CHECK: load
|
|
strong_retain %7 : $SomeClass
|
|
// CHECK: value_metatype $@thick SomeClass.Type, {{%.*}} : $SomeClass
|
|
%9 = value_metatype $@thick SomeClass.Type, %7 : $SomeClass
|
|
%11 = load %3a : $*SomeSubclass // CHECK: load
|
|
strong_retain %11 : $SomeSubclass
|
|
// CHECK: value_metatype $@thick SomeSubclass.Type, {{%.*}} : $SomeSubclass
|
|
%13 = value_metatype $@thick SomeSubclass.Type, %11 : $SomeSubclass
|
|
%14 = upcast %13 : $@thick SomeSubclass.Type to $@thick SomeClass.Type // CHECK: upcast
|
|
%15 = tuple (%9 : $@thick SomeClass.Type, %14 : $@thick SomeClass.Type) // CHECK: tuple
|
|
strong_release %11 : $SomeSubclass
|
|
strong_release %7 : $SomeClass
|
|
strong_release %3 : $<τ_0_0> { var τ_0_0 } <SomeSubclass>
|
|
strong_release %2 : $<τ_0_0> { var τ_0_0 } <SomeClass>
|
|
return %15 : $(@thick SomeClass.Type, @thick SomeClass.Type)
|
|
}
|
|
|
|
sil @test_value_metatype : $@convention(thin) <T> (@in T) -> (@thick T.Type, @thick T.Type) {
|
|
bb0(%0 : $*T):
|
|
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <T> // CHECK: alloc_box
|
|
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <T>, 0
|
|
copy_addr [take] %0 to [init] %1a : $*T
|
|
%3 = metatype $@thick T.Type // CHECK: metatype
|
|
%5 = alloc_stack $T // CHECK: alloc_stack
|
|
copy_addr %1a to [init] %5 : $*T
|
|
// CHECK: value_metatype $@thick T.Type, {{%.*}} : $*T
|
|
%7 = value_metatype $@thick T.Type, %5 : $*T
|
|
%8 = tuple (%3 : $@thick T.Type, %7 : $@thick T.Type) // CHECK: tuple
|
|
destroy_addr %5 : $*T
|
|
dealloc_stack %5 : $*T
|
|
strong_release %1 : $<τ_0_0> { var τ_0_0 } <T>
|
|
return %8 : $(@thick T.Type, @thick T.Type)
|
|
}
|
|
|
|
sil @test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type {
|
|
bb0(%0 : $*SomeProtocol):
|
|
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <SomeProtocol> // CHECK: alloc_box
|
|
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <SomeProtocol>, 0
|
|
copy_addr [take] %0 to [init] %1a : $*SomeProtocol
|
|
%4 = alloc_stack $SomeProtocol // CHECK: alloc_stack
|
|
copy_addr %1a to [init] %4 : $*SomeProtocol
|
|
// CHECK: existential_metatype $@thick any SomeProtocol.Type, {{%.*}} : $*any SomeProtocol
|
|
%6 = existential_metatype $@thick SomeProtocol.Type, %4 : $*SomeProtocol
|
|
destroy_addr %4 : $*SomeProtocol
|
|
dealloc_stack %4 : $*SomeProtocol
|
|
strong_release %1 : $<τ_0_0> { var τ_0_0 } <SomeProtocol>
|
|
return %6 : $@thick SomeProtocol.Type
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_unreachable
|
|
sil @test_unreachable : $() -> () {
|
|
bb0:
|
|
unreachable
|
|
// CHECK: unreachable
|
|
}
|
|
|
|
sil @test_unowned_retain : $@convention(thin) (SomeClass) -> () {
|
|
bb0(%0 : $SomeClass):
|
|
%1 = ref_to_unowned %0 : $SomeClass to $@sil_unowned SomeClass
|
|
// CHECK: ref_to_unowned %0 : $SomeClass to $@sil_unowned SomeClass
|
|
unowned_retain %1 : $@sil_unowned SomeClass
|
|
// CHECK: unowned_retain %1 : $@sil_unowned SomeClass
|
|
unowned_release %1 : $@sil_unowned SomeClass
|
|
// CHECK: unowned_release %1 : $@sil_unowned SomeClass
|
|
%4 = unowned_to_ref %1 : $@sil_unowned SomeClass to $SomeClass
|
|
// CHECK: unowned_to_ref %1 : $@sil_unowned SomeClass to $SomeClass
|
|
%5 = tuple ()
|
|
return %5 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_basic_block_arguments
|
|
sil @test_basic_block_arguments : $@convention(thin) (Builtin.Int1) -> Builtin.Word {
|
|
bb0(%0 : $Builtin.Int1):
|
|
cond_br %0, bb1, bb2
|
|
bb1:
|
|
%2 = integer_literal $Builtin.Word, 5
|
|
br bb3(%2 : $Builtin.Word)
|
|
//CHECK: br bb3(%2 : $Builtin.Word)
|
|
bb2:
|
|
%4 = integer_literal $Builtin.Word, 6
|
|
br bb3(%4 : $Builtin.Word)
|
|
//CHECK: br bb3(%4 : $Builtin.Word)
|
|
bb3(%6 : $Builtin.Word):
|
|
//CHECK: bb3(%6 : $Builtin.Word)
|
|
return %6 : $Builtin.Word
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_cond_branch_basic_block_args
|
|
sil @test_cond_branch_basic_block_args : $@convention(thin) (Int, Builtin.Int1) -> Int {
|
|
bb0(%0 : $Int, %1 : $Builtin.Int1):
|
|
cond_br %1, bb1(%0 : $Int), bb2(%0 : $Int)
|
|
// CHECK: cond_br %1, bb1(%0 : $Int), bb2(%0 : $Int)
|
|
bb1(%3 : $Int):
|
|
br bb3 (%3 : $Int)
|
|
bb2(%2 : $Int):
|
|
br bb3(%2 : $Int)
|
|
bb3(%4 : $Int):
|
|
return %4 : $Int
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_builtin
|
|
sil @test_builtin : $@convention(thin) (Builtin.Int1, Builtin.Int1) -> Builtin.Int1 {
|
|
bb0(%0 : $Builtin.Int1, %1 : $Builtin.Int1):
|
|
%2 = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.Int1>
|
|
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <Builtin.Int1>, 0
|
|
%3 = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.Int1>
|
|
%3a = project_box %3 : $<τ_0_0> { var τ_0_0 } <Builtin.Int1>, 0
|
|
store %0 to %2a : $*Builtin.Int1
|
|
store %1 to %3a : $*Builtin.Int1
|
|
%8 = load %2a : $*Builtin.Int1
|
|
%9 = load %3a : $*Builtin.Int1
|
|
// CHECK: builtin "cmp_eq_Int1"({{%.*}} : $Builtin.Int1, {{%.*}} : $Builtin.Int1) : $Builtin.Int1
|
|
%10 = builtin "cmp_eq_Int1"(%8 : $Builtin.Int1, %9 : $Builtin.Int1) : $Builtin.Int1
|
|
strong_release %3 : $<τ_0_0> { var τ_0_0 } <Builtin.Int1>
|
|
strong_release %2 : $<τ_0_0> { var τ_0_0 } <Builtin.Int1>
|
|
return %10 : $Builtin.Int1
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_dealloc_ref
|
|
sil @test_dealloc_ref : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = alloc_ref $Class1
|
|
dealloc_ref %0 : $Class1
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_dealloc_partial_ref
|
|
sil @test_dealloc_partial_ref : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = alloc_ref $Class1
|
|
%1 = metatype $@thick Class1.Type
|
|
dealloc_partial_ref %0 : $Class1, %1 : $@thick Class1.Type
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_dealloc_box
|
|
sil @test_dealloc_box : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = alloc_box $<τ_0_0> { var τ_0_0 } <Class1>
|
|
dealloc_box %0 : $<τ_0_0> { var τ_0_0 } <Class1>
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_stack_flag
|
|
sil @test_stack_flag : $@convention(thin) () -> () {
|
|
bb0:
|
|
// CHECK: alloc_ref [stack] $Class1
|
|
%0 = alloc_ref [stack] $Class1
|
|
// CHECK: dealloc_stack_ref %0 : $Class1
|
|
dealloc_stack_ref %0 : $Class1
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_bare_flags
|
|
sil @test_bare_flags : $@convention(thin) () -> () {
|
|
bb0:
|
|
// CHECK: alloc_ref [bare] $Class1
|
|
%0 = alloc_ref [bare] $Class1
|
|
// CHECK: global_value [bare] @static_array : $TestArrayStorage
|
|
%1 = global_value [bare] @static_array : $TestArrayStorage
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_stack_protection_flags
|
|
sil @test_stack_protection_flags : $@convention(thin) (@inout Builtin.Word) -> () {
|
|
bb0(%0 : $*Builtin.Word):
|
|
// CHECK: address_to_pointer [stack_protection] %0
|
|
%1 = address_to_pointer [stack_protection] %0 : $*Builtin.Word to $Builtin.RawPointer
|
|
// CHECK: address_to_pointer %0
|
|
%2 = address_to_pointer %0 : $*Builtin.Word to $Builtin.RawPointer
|
|
%3 = integer_literal $Builtin.Word, 0
|
|
// CHECK: index_addr [stack_protection] %0
|
|
%4 = index_addr [stack_protection] %0 : $*Builtin.Word, %3 : $Builtin.Word
|
|
// CHECK: index_addr %0
|
|
%5 = index_addr %0 : $*Builtin.Word, %3 : $Builtin.Word
|
|
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_tail_elems
|
|
sil @test_tail_elems : $@convention(thin) (Builtin.Word, Builtin.Word) -> () {
|
|
bb0(%0 : $Builtin.Word, %1 : $Builtin.Word):
|
|
// CHECK: alloc_ref [tail_elems $Val * %0 : $Builtin.Word] [tail_elems $Aleph * %1 : $Builtin.Word] $Class1
|
|
%2 = alloc_ref [tail_elems $Val * %0 : $Builtin.Word] [tail_elems $Aleph * %1 : $Builtin.Word] $Class1
|
|
// CHECK: dealloc_ref %2 : $Class1
|
|
dealloc_ref %2 : $Class1
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_tail_elems_dynamic
|
|
sil @test_tail_elems_dynamic : $@convention(thin) (Builtin.Word, Builtin.Word, @thick Class1.Type) -> () {
|
|
bb0(%0 : $Builtin.Word, %1 : $Builtin.Word, %2 : $@thick Class1.Type):
|
|
// CHECK: alloc_ref_dynamic [tail_elems $Val * %0 : $Builtin.Word] [tail_elems $Aleph * %1 : $Builtin.Word] %2 : $@thick Class1
|
|
%3 = alloc_ref_dynamic [tail_elems $Val * %0 : $Builtin.Word] [tail_elems $Aleph * %1 : $Builtin.Word] %2 : $@thick Class1.Type, $Class1
|
|
// CHECK: dealloc_ref %3 : $Class1
|
|
dealloc_ref %3 : $Class1
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_tail_addr
|
|
sil @test_tail_addr : $@convention(thin) (@owned Class1, Builtin.Word) -> @owned Class1 {
|
|
bb0(%0 : $Class1, %1 : $Builtin.Word):
|
|
// CHECK: [[T:%[0-9]+]] = ref_tail_addr %0 : $Class1, $Val
|
|
%2 = ref_tail_addr %0 : $Class1, $Val
|
|
// CHECK: tail_addr [[T]] : $*Val, %1 : $Builtin.Word, $Aleph
|
|
%3 = tail_addr %2 : $*Val, %1 : $Builtin.Word, $Aleph
|
|
return %0 : $Class1
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_cow_mutation
|
|
sil @test_cow_mutation : $@convention(thin) (@owned Class1) -> @owned Class1 {
|
|
bb0(%0 : $Class1):
|
|
// CHECK: (%1, %2) = begin_cow_mutation %0 : $Class1
|
|
(%1, %2) = begin_cow_mutation %0 : $Class1
|
|
// CHECK: %3 = end_cow_mutation [keep_unique] %2 : $Class1
|
|
%3 = end_cow_mutation [keep_unique] %2 : $Class1
|
|
// CHECK: (%4, %5) = begin_cow_mutation [native] %0 : $Class1
|
|
(%4, %5) = begin_cow_mutation [native] %0 : $Class1
|
|
// CHECK: %6 = end_cow_mutation %5 : $Class1
|
|
%6 = end_cow_mutation %5 : $Class1
|
|
// CHECK: [[T:%[0-9]+]] = ref_tail_addr [immutable] %3 : $Class1, $Val
|
|
%7 = ref_tail_addr [immutable] %3 : $Class1, $Val
|
|
// CHECK: ref_element_addr [immutable] %3 : $Class1, #Class1.a
|
|
%8 = ref_element_addr [immutable] %3 : $Class1, #Class1.a
|
|
return %0 : $Class1
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: closure_test
|
|
sil @takes_closure : $@convention(thin) (@callee_owned () -> ()) -> ()
|
|
sil @closure0 : $@convention(thin) (<τ_0_0> { var τ_0_0 } <Int>, @inout Int) -> ()
|
|
|
|
sil @closure_test : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = alloc_box $<τ_0_0> { var τ_0_0 } <Int> // users: %10, %8, %8, %7, %4
|
|
%0a = project_box %0 : $<τ_0_0> { var τ_0_0 } <Int>, 0
|
|
|
|
%5 = function_ref @takes_closure : $@convention(thin) (@callee_owned () -> ()) -> ()
|
|
%6 = function_ref @closure0 : $@convention(thin) (<τ_0_0> { var τ_0_0 } <Int>, @inout Int) -> ()
|
|
strong_retain %0 : $<τ_0_0> { var τ_0_0 } <Int>
|
|
%8 = partial_apply %6(%0, %0a) : $@convention(thin) (<τ_0_0> { var τ_0_0 } <Int>, @inout Int) -> ()
|
|
%9 = apply %5(%8) : $@convention(thin) (@callee_owned () -> ()) -> ()
|
|
strong_release %0 : $<τ_0_0> { var τ_0_0 } <Int>
|
|
|
|
%11 = tuple ()
|
|
return %11 : $()
|
|
}
|
|
|
|
sil @test_super_to_archetype_ref : $@convention(thin) <T : Class1> (Class1) -> T {
|
|
bb0(%c : $Class1):
|
|
%0 = unconditional_checked_cast %c : $Class1 to T
|
|
return %0 : $T
|
|
}
|
|
|
|
sil @test_downcast_archetype_ref : $@convention(thin) <T:Class1, U:Class1> (T) -> () {
|
|
bb0(%t : $T):
|
|
%0 = unconditional_checked_cast %t : $T to U
|
|
%1 = tuple ()
|
|
return %1 : $()
|
|
}
|
|
|
|
protocol ClassP : AnyObject {}
|
|
|
|
enum MaybePair {
|
|
case Neither
|
|
case Left(Int)
|
|
}
|
|
|
|
sil @_T6switch1aFT_T_ : $@convention(thin) () -> ()
|
|
sil @_T6switch1bFT_T_ : $@convention(thin) () -> ()
|
|
sil @_T6switch1cFT_T_ : $@convention(thin) () -> ()
|
|
|
|
// CHECK-LABEL: sil @test_switch_union : $@convention(thin) (MaybePair) -> ()
|
|
sil @test_switch_union : $@convention(thin) (MaybePair) -> () {
|
|
bb0(%0 : $MaybePair):
|
|
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <MaybePair>
|
|
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <MaybePair>, 0
|
|
store %0 to %1a : $*MaybePair
|
|
%3 = load %1a : $*MaybePair
|
|
%4 = tuple ()
|
|
// CHECK: switch_enum %{{.*}} : $MaybePair, case #MaybePair.Neither!enumelt: bb{{.*}}, case #MaybePair.Left!enumelt: bb
|
|
switch_enum %3 : $MaybePair, case #MaybePair.Neither!enumelt: bb1, case #MaybePair.Left!enumelt: bb3
|
|
|
|
bb1:
|
|
br bb2
|
|
|
|
bb2:
|
|
%7 = function_ref @_T6switch1aFT_T_ : $@convention(thin) () -> () // CHECK: function_ref
|
|
%8 = apply %7() : $@convention(thin) () -> ()
|
|
br bb5 // CHECK: br
|
|
|
|
bb3(%10 : $Int):
|
|
// CHECK: unchecked_enum_data {{%.*}} : $MaybePair, #MaybePair.Left!enumelt
|
|
%x = unchecked_enum_data %3 : $MaybePair, #MaybePair.Left!enumelt
|
|
br bb4(%x : $Int)
|
|
|
|
bb4(%y : $Int):
|
|
%12 = function_ref @_T6switch1bFT_T_ : $@convention(thin) () -> () // CHECK: function_ref
|
|
%13 = apply %12() : $@convention(thin) () -> ()
|
|
br bb5 // CHECK: br
|
|
|
|
bb5:
|
|
%15 = function_ref @_T6switch1cFT_T_ : $@convention(thin) () -> () // CHECK: function_ref
|
|
%16 = apply %15() : $@convention(thin) () -> ()
|
|
strong_release %1 : $<τ_0_0> { var τ_0_0 } <MaybePair>
|
|
%18 = tuple ()
|
|
return %18 : $() // CHECK: return
|
|
}
|
|
|
|
enum MaybeAddressOnlyPair {
|
|
case Neither
|
|
case Left(Q)
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_switch_enum_addr : $@convention(thin) (@in MaybeAddressOnlyPair) -> ()
|
|
sil @test_switch_enum_addr : $@convention(thin) (@in MaybeAddressOnlyPair) -> () {
|
|
bb0(%0 : $*MaybeAddressOnlyPair):
|
|
// CHECK: switch_enum_addr [[ENUM:%.*]] : $*MaybeAddressOnlyPair, case #MaybeAddressOnlyPair.Neither!enumelt: bb{{.*}}, case #MaybeAddressOnlyPair.Left!enumelt: bb
|
|
switch_enum_addr %0 : $*MaybeAddressOnlyPair, case #MaybeAddressOnlyPair.Neither!enumelt: bb1, case #MaybeAddressOnlyPair.Left!enumelt: bb2
|
|
|
|
bb1:
|
|
br bb3
|
|
|
|
bb2:
|
|
// CHECK: unchecked_take_enum_data_addr [[ENUM]] : $*MaybeAddressOnlyPair, #MaybeAddressOnlyPair.Left!enumelt
|
|
%q = unchecked_take_enum_data_addr %0 : $*MaybeAddressOnlyPair, #MaybeAddressOnlyPair.Left!enumelt
|
|
br bb3
|
|
|
|
bb3:
|
|
%t = tuple ()
|
|
return %t : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_switch_enum_addr_inplace : $@convention(thin) (@in MaybeAddressOnlyPair) -> ()
|
|
sil @test_switch_enum_addr_inplace : $@convention(thin) (@in MaybeAddressOnlyPair) -> () {
|
|
bb0(%0 : $*MaybeAddressOnlyPair):
|
|
// CHECK: switch_enum_addr [[ENUM:%.*]] : $*MaybeAddressOnlyPair, case #MaybeAddressOnlyPair.Neither!enumelt: bb{{.*}}, case #MaybeAddressOnlyPair.Left!enumelt: bb
|
|
switch_enum_addr %0 : $*MaybeAddressOnlyPair, case #MaybeAddressOnlyPair.Neither!enumelt: bb1, case #MaybeAddressOnlyPair.Left!enumelt: bb2
|
|
|
|
bb1:
|
|
br bb3
|
|
|
|
bb2:
|
|
// CHECK: unchecked_inplace_enum_data_addr [[ENUM]] : $*MaybeAddressOnlyPair, #MaybeAddressOnlyPair.Left!enumelt
|
|
%q = unchecked_inplace_enum_data_addr %0 : $*MaybeAddressOnlyPair, #MaybeAddressOnlyPair.Left!enumelt
|
|
br bb3
|
|
|
|
bb3:
|
|
%t = tuple ()
|
|
return %t : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_switch_enum_addr_borrow : $@convention(thin) (@in MaybeAddressOnlyPair) -> ()
|
|
sil @test_switch_enum_addr_borrow : $@convention(thin) (@in MaybeAddressOnlyPair) -> () {
|
|
bb0(%0 : $*MaybeAddressOnlyPair):
|
|
// CHECK: switch_enum_addr [[ENUM:%.*]] : $*MaybeAddressOnlyPair, case #MaybeAddressOnlyPair.Neither!enumelt: bb{{.*}}, case #MaybeAddressOnlyPair.Left!enumelt: bb
|
|
switch_enum_addr %0 : $*MaybeAddressOnlyPair, case #MaybeAddressOnlyPair.Neither!enumelt: bb1, case #MaybeAddressOnlyPair.Left!enumelt: bb2
|
|
|
|
bb1:
|
|
br bb3
|
|
|
|
bb2:
|
|
// CHECK: [[SCRATCH:%.*]] = alloc_stack $MaybeAddressOnlyPair
|
|
%s = alloc_stack $MaybeAddressOnlyPair
|
|
// CHECK: unchecked_borrow_enum_data_addr [[ENUM]] : $*MaybeAddressOnlyPair, #MaybeAddressOnlyPair.Left!enumelt in [[SCRATCH]]
|
|
%q = unchecked_borrow_enum_data_addr %0 : $*MaybeAddressOnlyPair, #MaybeAddressOnlyPair.Left!enumelt in %s
|
|
dealloc_stack %s
|
|
br bb3
|
|
|
|
bb3:
|
|
%t = tuple ()
|
|
return %t : $()
|
|
}
|
|
|
|
class ConcreteClass : ClassP {
|
|
}
|
|
struct Spoon : Bendable {
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_init_existential : $@convention(thin) (Spoon) -> @out any Bendable
|
|
sil @test_init_existential : $@convention(thin) (Spoon) -> @out Bendable {
|
|
bb0(%0 : $*Bendable, %1 : $Spoon):
|
|
%2 = alloc_box $<τ_0_0> { var τ_0_0 } <Spoon>
|
|
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <Spoon>, 0
|
|
store %1 to %2a : $*Spoon
|
|
// CHECK: init_existential_addr %{{.*}} : $*any Bendable, $Spoon
|
|
%4 = init_existential_addr %0 : $*Bendable, $Spoon
|
|
// CHECK: deinit_existential_addr %{{.*}} : $*any Bendable
|
|
deinit_existential_addr %0 : $*Bendable
|
|
%5 = load %2a : $*Spoon
|
|
store %5 to %4 : $*Spoon
|
|
strong_release %2 : $<τ_0_0> { var τ_0_0 } <Spoon>
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_existential_ref : $@convention(thin) (ConcreteClass) -> any ClassP
|
|
sil @test_existential_ref : $@convention(thin) (ConcreteClass) -> ClassP {
|
|
bb0(%0 : $ConcreteClass):
|
|
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <ConcreteClass>
|
|
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <ConcreteClass>, 0
|
|
store %0 to %1a : $*ConcreteClass
|
|
%3 = load %1a : $*ConcreteClass
|
|
strong_retain %3 : $ConcreteClass
|
|
// CHECK: init_existential_ref %{{.*}} : $ConcreteClass : $ConcreteClass, $any ClassP
|
|
%5 = init_existential_ref %3 : $ConcreteClass : $ConcreteClass, $ClassP
|
|
strong_release %1 : $<τ_0_0> { var τ_0_0 } <ConcreteClass>
|
|
return %5 : $ClassP
|
|
}
|
|
|
|
sil @test_assign : $(Int, @inout Int) -> () { // CHECK-LABEL: sil @test_assign
|
|
bb0(%0 : $Int, %1 : $*Int):
|
|
assign %0 to %1 : $*Int // CHECK: assign %0 to %1
|
|
assign %0 to [init] %1 : $*Int // CHECK: assign %0 to [init] %1
|
|
assign %0 to [reinit] %1 : $*Int // CHECK: assign %0 to [reinit] %1
|
|
assign %0 to [reassign] %1 : $*Int // CHECK: assign %0 to [reassign] %1
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_transparent : $@convention(thin) () -> () {
|
|
sil @test_transparent : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @classes : $@convention(thin) () -> ()
|
|
// CHECK: apply %{{.*}}() : $@convention(thin) () -> ()
|
|
%1 = apply %0() : $@convention(thin) () -> ()
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [thunk] @test_thunk : $@convention(thin) () -> () {
|
|
sil [thunk] @test_thunk : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = tuple ()
|
|
return %0 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @takes_unnamed_closure : $@convention(thin) (@callee_owned () -> Int) -> () -> () -> Int
|
|
sil @takes_unnamed_closure : $@convention(thin) (@callee_owned () -> Int) -> () -> () -> Int
|
|
|
|
sil @takes_int64_float32 : $@convention(thin) (Int, Float32) -> ()
|
|
|
|
// CHECK-LABEL: sil @test_partial_apply : $@convention(thin) (Float) -> @callee_owned (Int) -> () {
|
|
sil @test_partial_apply : $@convention(thin) (Float) -> @callee_owned (Int) -> () {
|
|
bb0(%0 : $Float):
|
|
%1 = function_ref @takes_int64_float32 : $@convention(thin) (Int, Float) -> ()
|
|
// CHECK: partial_apply %{{.*}}(%{{.*}}) : $@convention(thin) (Int, Float) -> ()
|
|
%2 = partial_apply %1(%0) : $@convention(thin) (Int, Float) -> ()
|
|
return %2 : $@callee_owned (Int) -> ()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_partial_apply_non_nested : $@convention(thin) (Float) -> () {
|
|
sil @test_partial_apply_non_nested : $@convention(thin) (Float) -> () {
|
|
bb0(%0 : $Float):
|
|
%1 = function_ref @takes_int64_float32 : $@convention(thin) (Int, Float) -> ()
|
|
// CHECK: partial_apply [on_stack] [non_nested] %{{.*}}(%{{.*}}) : $@convention(thin) (Int, Float) -> ()
|
|
%2 = partial_apply [on_stack] [non_nested] %1(%0) : $@convention(thin) (Int, Float) -> ()
|
|
dealloc_stack %2
|
|
%3 = tuple ()
|
|
return %3
|
|
}
|
|
|
|
class X {
|
|
@objc func f() { }
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_dynamic_lookup_br : $@convention(thin) (AnyObject) -> ()
|
|
sil @test_dynamic_lookup_br : $@convention(thin) (AnyObject) -> () {
|
|
bb0(%0 : $AnyObject):
|
|
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <AnyObject>
|
|
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <AnyObject>, 0
|
|
store %0 to %1a : $*AnyObject
|
|
%3 = alloc_box $<τ_0_0> { var τ_0_0 } <Optional<() -> ()>>
|
|
%4 = load %1a : $*AnyObject
|
|
strong_retain %4 : $AnyObject
|
|
%6 = open_existential_ref %4 : $AnyObject to $@opened("01234567-89ab-cdef-0123-222222222222", AnyObject) Self
|
|
dynamic_method_br %6 : $@opened("01234567-89ab-cdef-0123-222222222222", AnyObject) Self, #X.f!foreign, bb1, bb2
|
|
bb1(%z : $@convention(objc_method) (@opened("01234567-89ab-cdef-0123-222222222222", AnyObject) Self) -> ()):
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
%28 = tuple ()
|
|
return %28 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_mark_fn_escape
|
|
sil @test_mark_fn_escape : $() -> () {
|
|
%b = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
|
|
%ba = project_box %b : $<τ_0_0> { var τ_0_0 } <Int>, 0
|
|
%c = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
|
|
%ca = project_box %c : $<τ_0_0> { var τ_0_0 } <Int>, 0
|
|
|
|
// CHECK: mark_function_escape {{.*}} : $*Int
|
|
mark_function_escape %ba : $*Int
|
|
// CHECK: mark_function_escape {{.*}} : $*Int, {{.*}} : $*Int
|
|
mark_function_escape %ba : $*Int, %ca : $*Int
|
|
|
|
%28 = tuple ()
|
|
return %28 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_copy_release_value
|
|
sil @test_copy_release_value : $(Val) -> (Val) {
|
|
bb0(%0 : $Val):
|
|
retain_value %0 : $Val
|
|
release_value %0 : $Val
|
|
return %0 : $Val
|
|
// CHECK: retain_value [[T0:%.*]] : $Val
|
|
// CHECK-NEXT: release_value [[T0]] : $Val
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_autorelease_value
|
|
sil @test_autorelease_value : $(X) -> X {
|
|
bb0(%0 : $X):
|
|
autorelease_value %0 : $X
|
|
return %0 : $X
|
|
// CHECK: autorelease_value [[T0]] : $X
|
|
// CHECK-NEXT: return [[T0]] : $X
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_begin_dealloc_ref
|
|
sil @test_begin_dealloc_ref : $() -> X {
|
|
bb0:
|
|
%0 = alloc_ref $X
|
|
%1 = begin_dealloc_ref %0 : $X of %0 : $X
|
|
return %1 : $X
|
|
// CHECK: %1 = begin_dealloc_ref %0 : $X of %0 : $X
|
|
// CHECK-NEXT: return %1 : $X
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_end_init_let_ref
|
|
sil @test_end_init_let_ref : $(X) -> X {
|
|
bb0(%0 : $X):
|
|
%1 = end_init_let_ref %0 : $X
|
|
return %1 : $X
|
|
// CHECK: %1 = end_init_let_ref %0 : $X
|
|
// CHECK-NEXT: return %1 : $X
|
|
}
|
|
|
|
struct GenericStruct<T> {
|
|
var x : T
|
|
}
|
|
|
|
// CHECK-LABEL: sil @extract_generic_struct
|
|
sil @extract_generic_struct : $(GenericStruct<Int>) -> Int {
|
|
entry(%0 : $GenericStruct<Int>):
|
|
// CHECK: %1 = struct_extract %0 : $GenericStruct<Int>, #GenericStruct.x
|
|
%1 = struct_extract %0 : $GenericStruct<Int>, #GenericStruct.x
|
|
// CHECK: return %1 : $Int
|
|
return %1 : $Int
|
|
}
|
|
|
|
class Foo {
|
|
subscript (x: Int32, y: Int32) -> Int32 { get set }
|
|
var x: Int32
|
|
var y: Int32
|
|
init()
|
|
}
|
|
|
|
sil @Foo_subscript_getter : $@convention(method) (Int32, Int32, @guaranteed Foo) -> Int32 {
|
|
bb0(%0 : $Int32, %1 : $Int32, %2 : $Foo):
|
|
%3 = tuple ()
|
|
%4 = alloc_stack $Int32 // var x // users: %17, %6
|
|
%5 = alloc_stack $Int32 // var y // users: %16, %7
|
|
store %0 to %4 : $*Int32
|
|
store %1 to %5 : $*Int32
|
|
%8 = alloc_stack $Foo // var self // users: %15, %14, %9
|
|
store %2 to %8 : $*Foo
|
|
%10 = metatype $@thin Int32.Type
|
|
%12 = integer_literal $Builtin.Int32, 0 // user: %13
|
|
%13 = struct $Int32 (%12 : $Builtin.Int32) // user: %18
|
|
dealloc_stack %8 : $*Foo
|
|
dealloc_stack %5 : $*Int32
|
|
dealloc_stack %4 : $*Int32
|
|
return %13 : $Int32
|
|
}
|
|
|
|
sil @Foo_subscript_setter : $@convention(method) (Int32, Int32, Int32, @guaranteed Foo) -> () {
|
|
bb0(%0 : $Int32, %1 : $Int32, %2 : $Int32, %3 : $Foo):
|
|
%4 = alloc_stack $Int32 // var value // users: %16, %5
|
|
store %0 to %4 : $*Int32
|
|
%6 = alloc_stack $Int32 // var x // users: %15, %8
|
|
%7 = alloc_stack $Int32 // var y // users: %14, %9
|
|
store %1 to %6 : $*Int32
|
|
store %2 to %7 : $*Int32
|
|
%10 = alloc_stack $Foo // var self // users: %13, %12, %11
|
|
store %3 to %10 : $*Foo
|
|
dealloc_stack %10 : $*Foo
|
|
dealloc_stack %7 : $*Int32
|
|
dealloc_stack %6 : $*Int32
|
|
dealloc_stack %4 : $*Int32
|
|
%17 = tuple () // user: %18
|
|
return %17 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @cond_fail_test : $@convention(thin) (Builtin.Int1) -> () {
|
|
sil @cond_fail_test : $(Builtin.Int1) -> () {
|
|
entry(%0 : $Builtin.Int1):
|
|
// CHECK: cond_fail %0 : $Builtin.Int1, ""
|
|
cond_fail %0 : $Builtin.Int1
|
|
// CHECK: cond_fail %0 : $Builtin.Int1, "message"
|
|
cond_fail %0 : $Builtin.Int1, "message"
|
|
%1 = tuple ()
|
|
return %1 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_dynamic_lifetime_flag : $@convention(thin) () -> ()
|
|
sil @test_dynamic_lifetime_flag : $() -> () {
|
|
bb0:
|
|
// CHECK: alloc_box [dynamic_lifetime] $<τ_0_0> { var τ_0_0 } <AnyObject>
|
|
%0 = alloc_box [dynamic_lifetime] $<τ_0_0> { var τ_0_0 } <AnyObject>
|
|
// CHECK: alloc_stack [dynamic_lifetime] $AnyObject
|
|
%1 = alloc_stack [dynamic_lifetime] $AnyObject
|
|
dealloc_stack %1 : $*AnyObject
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @alloc_stack_test
|
|
sil @alloc_stack_test : $() -> () {
|
|
// CHECK: alloc_stack $Builtin.NativeObject
|
|
%instance = alloc_stack $Builtin.NativeObject
|
|
dealloc_stack %instance : $*Builtin.NativeObject
|
|
// CHECK: alloc_stack [dynamic_lifetime]
|
|
%instance2 = alloc_stack [dynamic_lifetime] $Builtin.NativeObject
|
|
dealloc_stack %instance2 : $*Builtin.NativeObject
|
|
// CHECK: alloc_stack [lexical]
|
|
%instance3 = alloc_stack [lexical] $Builtin.NativeObject
|
|
dealloc_stack %instance3 : $*Builtin.NativeObject
|
|
// CHECK: alloc_stack [var_decl]
|
|
%instance5 = alloc_stack [var_decl] $Builtin.NativeObject
|
|
dealloc_stack %instance5 : $*Builtin.NativeObject
|
|
// CHECK: alloc_stack [dynamic_lifetime] [lexical]
|
|
%instance4 = alloc_stack [lexical] [dynamic_lifetime] $Builtin.NativeObject
|
|
dealloc_stack %instance4 : $*Builtin.NativeObject
|
|
// CHECK: alloc_stack [dynamic_lifetime] [var_decl]
|
|
%instance6 = alloc_stack [dynamic_lifetime] [var_decl] $Builtin.NativeObject
|
|
dealloc_stack %instance6 : $*Builtin.NativeObject
|
|
// CHECK: alloc_stack [lexical] [var_decl]
|
|
%instance7 = alloc_stack [lexical] [var_decl] $Builtin.NativeObject
|
|
dealloc_stack %instance7 : $*Builtin.NativeObject
|
|
// CHECK: alloc_stack [dynamic_lifetime] [lexical] [var_decl]
|
|
%instance8 = alloc_stack [lexical] [var_decl] [dynamic_lifetime] $Builtin.NativeObject
|
|
dealloc_stack %instance8 : $*Builtin.NativeObject
|
|
%res = tuple ()
|
|
return %res : $()
|
|
// CHECK: } // end sil function 'alloc_stack_test'
|
|
}
|
|
|
|
// CHECK-LABEL: sil @vector_base_addr :
|
|
// CHECK: %1 = vector_base_addr %0 : $*Builtin.FixedArray<10, Int>
|
|
// CHECK-LABEL: } // end sil function 'vector_base_addr'
|
|
sil @vector_base_addr : $@convention(thin) (@inout Builtin.FixedArray<10, Int>) -> Int {
|
|
bb0(%0 : $*Builtin.FixedArray<10, Int>):
|
|
%1 = vector_base_addr %0
|
|
%2 = load %1
|
|
return %2
|
|
}
|
|
|
|
sil_global @staticProp: $Int
|
|
|
|
// CHECK-LABEL: sil private @globalinit_func0 : $@convention(thin) () -> () {
|
|
sil private @globalinit_func0 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = global_addr @staticProp : $*Int
|
|
%1 = mark_uninitialized [var] %0 : $*Int
|
|
%7 = tuple ()
|
|
return %7 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @_TV18lazy_global_access4Type10staticPropSia : $@convention(thin) () -> Builtin.RawPointer {
|
|
sil @_TV18lazy_global_access4Type10staticPropSia : $@convention(thin) () -> Builtin.RawPointer {
|
|
bb0:
|
|
// CHECK: global_addr @globalinit_token0 : $*Builtin.Word
|
|
%1 = global_addr @globalinit_token0 : $*Builtin.Word
|
|
// CHECK: unchecked_addr_cast {{%.*}} : $*Builtin.Word to $*Builtin.RawPointer
|
|
%a = unchecked_addr_cast %1 : $*Builtin.Word to $*Builtin.RawPointer
|
|
%2 = address_to_pointer %a : $*Builtin.RawPointer to $Builtin.RawPointer
|
|
%3 = function_ref @globalinit_func0 : $@convention(thin) () -> ()
|
|
// CHECK: [[O:%.*]] = builtin "once"({{%.*}} : $Builtin.RawPointer, {{%.*}} : $@convention(thin) () -> ()) : $Builtin.SILToken
|
|
%5 = builtin "once"(%2 : $Builtin.RawPointer, %3 : $@convention(thin) () -> ()) : $Builtin.SILToken
|
|
// CHECK: global_addr @staticProp : $*Int depends_on [[O]]
|
|
%6 = global_addr @staticProp : $*Int depends_on %5
|
|
%7 = address_to_pointer %6 : $*Int to $Builtin.RawPointer
|
|
return %7 : $Builtin.RawPointer
|
|
}
|
|
|
|
// CHECK-LABEL: sil @thin_metatype : $@convention(thin) (@thin Int.Type) -> @thick Int.Type
|
|
sil @thin_metatype : $@convention(thin) (@thin Int.Type) -> @thick Int.Type
|
|
|
|
sil @undef_value : $() -> () {
|
|
bb0:
|
|
store undef to undef : $*Builtin.Int1
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil @debug_value
|
|
sil @debug_value : $@convention(thin) (Int, @in P, AnyObject) -> () {
|
|
bb0(%0 : $Int, %1 : $*P, %2 : $AnyObject):
|
|
debug_value %0 : $Int // CHECK: debug_value %0 : $Int
|
|
debug_value [poison] %2 : $AnyObject // CHECK: debug_value [poison] %2 : $AnyObject
|
|
debug_value [trace] %2 : $AnyObject // CHECK: debug_value [trace] %2 : $AnyObject
|
|
debug_value %1 : $*P, expr op_deref // CHECK: debug_value %1 : $*any P, expr op_deref
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil @debug_step
|
|
// CHECK: bb0:
|
|
// CHECK-NEXT: debug_step
|
|
// CHECK-NEXT: unreachable
|
|
sil @debug_step : $@convention(thin) () -> () {
|
|
bb0:
|
|
debug_step
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil @block_storage_type
|
|
sil @block_storage_type : $@convention(thin) (Int) -> @convention(block) () -> () {
|
|
entry(%0 : $Int):
|
|
// CHECK: [[STORAGE:%.*]] = alloc_stack $@block_storage Int
|
|
%s = alloc_stack $@block_storage Int
|
|
// CHECK: [[PROJECT:%.*]] = project_block_storage [[STORAGE]] : $*@block_storage Int
|
|
%c = project_block_storage %s : $*@block_storage Int
|
|
// CHECK: store %0 to [[PROJECT]]
|
|
store %0 to %c : $*Int
|
|
// CHECK: [[FUNC:%.*]] = function_ref
|
|
%f = function_ref @block_invoke : $@convention(c) (@inout_aliasable @block_storage Int) -> ()
|
|
// CHECK: [[BLOCK:%.*]] = init_block_storage_header [[STORAGE]] : $*@block_storage Int, invoke [[FUNC]] : $@convention(c) (@inout_aliasable @block_storage Int) -> (), type $@convention(block) () -> ()
|
|
%b = init_block_storage_header %s : $*@block_storage Int, invoke %f : $@convention(c) (@inout_aliasable @block_storage Int) -> (), type $@convention(block) () -> ()
|
|
// CHECK: dealloc_stack [[STORAGE]] : $*@block_storage Int
|
|
dealloc_stack %s : $*@block_storage Int
|
|
// CHECK: return [[BLOCK]] : $@convention(block) () -> ()
|
|
return %b : $@convention(block) () -> ()
|
|
}
|
|
|
|
sil @block_invoke : $@convention(c) (@inout_aliasable @block_storage Int) -> () {
|
|
entry(%0 : $*@block_storage Int):
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @bitcasts : $@convention(thin) (@owned Class1) -> @owned (Class2, Int) {
|
|
// CHECK: bb0(%0 : $Class1):
|
|
// CHECK-NEXT: %1 = unchecked_ref_cast %0 : $Class1 to $Class2
|
|
// CHECK-NEXT: %2 = unchecked_trivial_bit_cast %0 : $Class1 to $Int
|
|
// CHECK-NEXT: %3 = tuple (%1 : $Class2, %2 : $Int)
|
|
// CHECK-NEXT: return %3 : $(Class2, Int)
|
|
sil @bitcasts : $@convention(thin) (@owned Class1) -> @owned (Class2, Int) {
|
|
entry(%0 : $Class1):
|
|
%1 = unchecked_ref_cast %0 : $Class1 to $Class2
|
|
%2 = unchecked_trivial_bit_cast %0 : $Class1 to $Int
|
|
%3 = tuple (%1 : $Class2, %2 : $Int)
|
|
return %3 : $(Class2, Int)
|
|
}
|
|
|
|
// CHECK-LABEL: sil @bridge_object : $@convention(thin) (@owned Class1, Builtin.Word) -> () {
|
|
// CHECK: bb0([[X:%.*]] : $Class1, [[W:%.*]] : $Builtin.Word):
|
|
// CHECK-NEXT: [[A:%.*]] = ref_to_bridge_object [[X]] : $Class1, [[W]] : $Builtin.Word
|
|
// CHECK-NEXT: [[B:%.*]] = bridge_object_to_ref [[A]] : $Builtin.BridgeObject to $Class1
|
|
// CHECK-NEXT: [[C:%.*]] = bridge_object_to_word [[A]] : $Builtin.BridgeObject to $Builtin.Word
|
|
// CHECK-NEXT: return undef : $()
|
|
sil @bridge_object : $@convention(thin) (@owned Class1, Builtin.Word) -> () {
|
|
entry(%x : $Class1, %w : $Builtin.Word):
|
|
%a = ref_to_bridge_object %x : $Class1, %w : $Builtin.Word
|
|
%b = bridge_object_to_ref %a : $Builtin.BridgeObject to $Class1
|
|
%c = bridge_object_to_word %a : $Builtin.BridgeObject to $Builtin.Word
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [_semantics "foo"] @test_semantics : $@convention(thin) () -> () {
|
|
sil [_semantics "foo"] @test_semantics : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = tuple ()
|
|
return %0 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @select_enum : $@convention(thin) (@in Beth) -> () {
|
|
sil @select_enum : $@convention(thin) (@in Beth) -> () {
|
|
bb0(%0 : $*Beth):
|
|
%1 = load %0 : $*Beth
|
|
%2 = integer_literal $Builtin.Int32, 2
|
|
%3 = integer_literal $Builtin.Int32, 3
|
|
// CHECK: %4 = select_enum %1 : $Beth, case #Beth.EmptyCase!enumelt: %2, case #Beth.DataCase!enumelt: %3 : $Builtin.Int32
|
|
%4 = select_enum %1 : $Beth, case #Beth.EmptyCase!enumelt: %2, case #Beth.DataCase!enumelt: %3 : $Builtin.Int32
|
|
// CHECK: %5 = select_enum_addr %0 : $*Beth, case #Beth.EmptyCase!enumelt: %2, case #Beth.DataCase!enumelt: %3 : $Builtin.Int32
|
|
%5 = select_enum_addr %0 : $*Beth, case #Beth.EmptyCase!enumelt: %2, case #Beth.DataCase!enumelt: %3 : $Builtin.Int32
|
|
// CHECK: %6 = select_enum %1 : $Beth, case #Beth.EmptyCase!enumelt: %2, default %3 : $Builtin.Int32
|
|
%6 = select_enum %1 : $Beth, case #Beth.EmptyCase!enumelt: %2, default %3 : $Builtin.Int32
|
|
// CHECK: %7 = select_enum_addr %0 : $*Beth, case #Beth.EmptyCase!enumelt: %2, default %3 : $Builtin.Int32
|
|
%7 = select_enum_addr %0 : $*Beth, case #Beth.EmptyCase!enumelt: %2, default %3 : $Builtin.Int32
|
|
return undef : $()
|
|
}
|
|
|
|
struct SomeError: Error {
|
|
var _domain: String { get }
|
|
var _code: Int { get }
|
|
}
|
|
|
|
// CHECK-LABEL: sil @existential_box : $@convention(thin) (SomeError) -> () {
|
|
sil @existential_box : $@convention(thin) (SomeError) -> () {
|
|
bb0(%0 : $SomeError):
|
|
// CHECK: %1 = alloc_existential_box $any Error, $SomeError
|
|
%1 = alloc_existential_box $Error, $SomeError
|
|
// CHECK: %2 = project_existential_box $SomeError in %1 : $any Error
|
|
%2 = project_existential_box $SomeError in %1 : $Error
|
|
// CHECK: store %0 to %2 : $*SomeError
|
|
store %0 to %2 : $*SomeError
|
|
// CHECK: %4 = open_existential_box %1 : $any Error to $*@opened("01234567-89AB-CDEF-0123-333333333333", any Error) Self
|
|
%4 = open_existential_box %1 : $Error to $*@opened("01234567-89AB-CDEF-0123-333333333333", Error) Self
|
|
// CHECK: destroy_addr %4 : $*@opened("01234567-89AB-CDEF-0123-333333333333", any Error) Self
|
|
destroy_addr %4 : $*@opened("01234567-89AB-CDEF-0123-333333333333", Error) Self
|
|
// CHECK: dealloc_existential_box %1 : $any Error, $SomeError
|
|
dealloc_existential_box %1 : $Error, $SomeError
|
|
return undef : $()
|
|
}
|
|
|
|
sil @convert_function : $@convention(thin) (@convention(thin) (AnyObject) -> Optional<AnyObject>) -> (@convention(thin) (Optional<AnyObject>) -> AnyObject) {
|
|
entry(%0 : $@convention(thin) (AnyObject) -> Optional<AnyObject>):
|
|
%1 = convert_function %0 : $@convention(thin) (AnyObject) -> Optional<AnyObject> to $@convention(thin) (Optional<AnyObject>) -> AnyObject
|
|
return %1 : $@convention(thin) (Optional<AnyObject>) -> AnyObject
|
|
}
|
|
// CHECK-LABEL: sil @convert_function_trivial
|
|
// CHECK: %1 = convert_escape_to_noescape %0 : $@callee_guaranteed (AnyObject) -> Optional<AnyObject> to $@noescape @callee_guaranteed (Optional<AnyObject>) -> AnyObject
|
|
// CHECK: %2 = convert_escape_to_noescape [not_guaranteed] %0 : $@callee_guaranteed (AnyObject) -> Optional<AnyObject> to $@noescape @callee_guaranteed (Optional<AnyObject>) -> AnyObject
|
|
// CHECK: return
|
|
sil @convert_function_trivial : $@convention(thin) (@owned @callee_guaranteed (AnyObject) -> Optional<AnyObject>) -> () {
|
|
entry(%0 : $@callee_guaranteed (AnyObject) -> Optional<AnyObject>):
|
|
%1 = convert_escape_to_noescape %0 : $@callee_guaranteed (AnyObject) -> Optional<AnyObject> to $@noescape @callee_guaranteed (Optional<AnyObject>) -> AnyObject
|
|
%2 = convert_escape_to_noescape [not_guaranteed] %0 : $@callee_guaranteed (AnyObject) -> Optional<AnyObject> to $@noescape @callee_guaranteed (Optional<AnyObject>) -> AnyObject
|
|
return undef : $()
|
|
}
|
|
|
|
sil @meta_metatype : $@convention(thin) () -> @thick Beth.Type.Type {
|
|
entry:
|
|
%m = metatype $@thick Beth.Type.Type
|
|
return %m : $@thick Beth.Type.Type
|
|
}
|
|
|
|
sil @concrete_meta_existential_metatype : $@convention(thin) () -> @thick P.Type.Protocol {
|
|
entry:
|
|
%m = metatype $@thick P.Type.Protocol
|
|
return %m : $@thick P.Type.Protocol
|
|
}
|
|
|
|
sil @concrete_meta_existential_meta_existential_metatype
|
|
: $@convention(thin) () -> @thick P.Type.Type.Protocol {
|
|
entry:
|
|
%m = metatype $@thick P.Type.Type.Protocol
|
|
return %m : $@thick P.Type.Type.Protocol
|
|
}
|
|
|
|
sil @function_metatype : $@convention(thin) () -> @thick (() -> ()).Type {
|
|
entry:
|
|
%m = metatype $@thick (() -> ()).Type
|
|
return %m : $@thick (() -> ()).Type
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: sil @error_result : $@convention(thin) () -> @error any Error
|
|
sil @error_result : $@convention(thin) () -> @error Error {
|
|
entry:
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil @error_result2 : $@convention(thin) () -> (Int, @error any Error)
|
|
sil @error_result2 : $@convention(thin) () -> (Int, @error Error) {
|
|
entry:
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil @error_result3 : $@convention(thin) () -> (@owned Class1, @error any Error)
|
|
sil @error_result3 : $@convention(thin) () -> (@owned Class1, @error Error) {
|
|
entry:
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil @error_result4 : $@convention(thin) (@owned Class1) -> (@owned Class1, @error any Error)
|
|
sil @error_result4 : $@convention(thin) (@owned Class1) -> (@owned Class1, @error Error) {
|
|
entry(%0 : $Class1):
|
|
return %0 : $Class1
|
|
}
|
|
|
|
// CHECK-LABEL: sil @try_apply : $@convention(thin) (@owned Class1) -> ()
|
|
sil @try_apply : $@convention(thin) (@owned Class1) -> () {
|
|
entry(%0 : $Class1):
|
|
%1 = function_ref @error_result4 : $@convention(thin) (@owned Class1) -> (@owned Class1, @error Error)
|
|
// CHECK: try_apply %1(%0) : $@convention(thin) (@owned Class1) -> (@owned Class1, @error any Error), normal bb1, error bb2
|
|
try_apply %1(%0) : $@convention(thin) (@owned Class1) -> (@owned Class1, @error Error),
|
|
normal bb1, error bb2
|
|
bb1(%2 : $Class1):
|
|
strong_release %2 : $Class1
|
|
br bb3
|
|
bb2(%3 : $Error):
|
|
release_value %3 : $Error
|
|
br bb3
|
|
bb3:
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @apply_nothrow : $@convention(thin) (@owned Class1) -> ()
|
|
sil @apply_nothrow : $@convention(thin) (@owned Class1) -> () {
|
|
entry(%0 : $Class1):
|
|
%1 = function_ref @error_result4 : $@convention(thin) (@owned Class1) -> (@owned Class1, @error Error)
|
|
// CHECK: apply [nothrow] %1(%0) : $@convention(thin) (@owned Class1) -> (@owned Class1, @error any Error)
|
|
%2 = apply [nothrow] %1(%0) : $@convention(thin) (@owned Class1) -> (@owned Class1, @error Error)
|
|
strong_release %2 : $Class1
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
struct Fork : Bendable {}
|
|
|
|
sil @thin_convention : $@convention(thin) () -> ()
|
|
sil @c_convention : $@convention(c) () -> ()
|
|
sil @method_convention : $@convention(method) (Int) -> ()
|
|
sil @objc_method_convention : $@convention(objc_method) (Int) -> ()
|
|
sil @witness_method_convention : $@convention(witness_method: Bendable) (Fork) -> ()
|
|
|
|
// CHECK-LABEL: sil @conventions : $@convention(thin) (() -> (), @convention(thin) () -> (), @convention(c) () -> (), @convention(block) () -> (), @convention(method) () -> (), @convention(objc_method) () -> (), @convention(witness_method: Bendable) (Fork) -> ()) -> () {
|
|
sil @conventions : $@convention(thin) (@convention(thick) () -> (),
|
|
@convention(thin) () -> (),
|
|
@convention(c) () -> (),
|
|
@convention(block) () -> (),
|
|
@convention(method) () -> (),
|
|
@convention(objc_method) () -> (),
|
|
@convention(witness_method: Bendable) (Fork) -> ()) -> () {
|
|
entry(%0 : $@convention(thick) () -> (),
|
|
%1 : $@convention(thin) () -> (),
|
|
%2 : $@convention(c) () -> (),
|
|
%3 : $@convention(block) () -> (),
|
|
%4 : $@convention(method) () -> (),
|
|
%5 : $@convention(objc_method) () -> (),
|
|
%6 : $@convention(witness_method: Bendable) (Fork) -> ()):
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @is_unique : $@convention(thin) (@inout Builtin.NativeObject)
|
|
sil @is_unique : $@convention(thin) (@inout Builtin.NativeObject) -> Builtin.Int1 {
|
|
bb0(%0 : $*Builtin.NativeObject):
|
|
// CHECK: %1 = is_unique %0 : $*Builtin.NativeObject
|
|
%1 = is_unique %0 : $*Builtin.NativeObject
|
|
return %1 : $Builtin.Int1
|
|
}
|
|
|
|
// CHECK-LABEL: sil @destroy_not_escaped_closure
|
|
sil @destroy_not_escaped_closure : $@convention(thin)(@guaranteed @callee_guaranteed () -> ()) -> Builtin.Int1 {
|
|
bb0(%0 : $@callee_guaranteed () -> ()):
|
|
// CHECK: %1 = destroy_not_escaped_closure %0 : $@callee_guaranteed () -> ()
|
|
// CHECK: %2 = destroy_not_escaped_closure [objc] %0 : $@callee_guaranteed () -> ()
|
|
%1 = destroy_not_escaped_closure %0: $@callee_guaranteed () -> ()
|
|
%2 = destroy_not_escaped_closure [objc] %0: $@callee_guaranteed () -> ()
|
|
return %1 : $Builtin.Int1
|
|
}
|
|
|
|
// CHECK-LABEL: sil @box_type : $@convention(thin) (<τ_0_0> { var τ_0_0 } <Int>, Int) -> () {
|
|
sil @box_type : $@convention(thin) (<τ_0_0> { var τ_0_0 } <Int>, Int) -> () {
|
|
// CHECK: bb0(%0 : $<τ_0_0> { var τ_0_0 } <Int>, %1 : $Int):
|
|
bb0(%0 : $<τ_0_0> { var τ_0_0 } <Int>, %1 : $Int):
|
|
// CHECK-NEXT: strong_retain %0 : $<τ_0_0> { var τ_0_0 } <Int>
|
|
strong_retain %0 : $<τ_0_0> { var τ_0_0 } <Int>
|
|
// CHECK-NEXT: %3 = project_box %0 : $<τ_0_0> { var τ_0_0 } <Int>, 0
|
|
%3 = project_box %0 : $<τ_0_0> { var τ_0_0 } <Int>, 0
|
|
// CHECK-NEXT: store %1 to %3 : $*Int
|
|
store %1 to %3 : $*Int
|
|
// CHECK-NEXT: strong_release %0 : $<τ_0_0> { var τ_0_0 } <Int>
|
|
strong_release %0 : $<τ_0_0> { var τ_0_0 } <Int>
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @value_names : $@convention(thin) (Builtin.Int1) -> () {
|
|
sil @value_names : $@convention(thin) (Builtin.Int1) -> () {
|
|
// CHECK: bb0(%0 : $Builtin.Int1):
|
|
entry(%param : $Builtin.Int1):
|
|
// CHECK-NEXT: %1 = tuple ()
|
|
%v_o_i_d = tuple ()
|
|
// CHECK-NEXT: cond_br %0, bb1, bb2
|
|
cond_br %param, then, else
|
|
|
|
// CHECK: bb1:
|
|
then:
|
|
// CHECK-NEXT: %3 = tuple ()
|
|
%void2 = tuple ()
|
|
// CHECK-NEXT: br bb2
|
|
br else
|
|
|
|
// CHECK: bb2:
|
|
else:
|
|
// CHECK-NEXT: %5 = tuple ()
|
|
%3void = tuple ()
|
|
// CHECK-NEXT: return %5 : $()
|
|
return %3void : $()
|
|
}
|
|
// CHECK: } // end sil function 'value_names'
|
|
|
|
// CHECK-LABEL: sil @test_pointer_to_address
|
|
sil @test_pointer_to_address : $(Builtin.RawPointer, X) -> () {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $X):
|
|
%2 = pointer_to_address %0 : $Builtin.RawPointer to $*X
|
|
store %1 to %2 : $*X
|
|
// CHECK: [[T2:%.*]] = pointer_to_address {{%.*}} : $Builtin.RawPointer to $*X
|
|
// CHECK-NEXT: store %1 to [[T2]] : $*X
|
|
%3 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*X
|
|
store %1 to %3 : $*X
|
|
// CHECK: [[T3:%.*]] = pointer_to_address {{%.*}} : $Builtin.RawPointer to [strict] $*X
|
|
// CHECK-NEXT: store %1 to [[T3]] : $*X
|
|
%5 = pointer_to_address %0 : $Builtin.RawPointer to [align=1] $*X
|
|
store %1 to %5 : $*X
|
|
// CHECK: [[T4:%.*]] = pointer_to_address {{%.*}} : $Builtin.RawPointer to [align=1] $*X
|
|
// CHECK-NEXT: store %1 to [[T4]] : $*X
|
|
%7 = pointer_to_address %0 : $Builtin.RawPointer to [align=8] $*X
|
|
store %1 to %7 : $*X
|
|
// CHECK: [[T5:%.*]] = pointer_to_address {{%.*}} : $Builtin.RawPointer to [align=8] $*X
|
|
// CHECK-NEXT: store %1 to [[T5]] : $*X
|
|
%9 = pointer_to_address %0 : $Builtin.RawPointer to [align=4294967296] $*X
|
|
store %1 to %9 : $*X
|
|
// CHECK: [[T6:%.*]] = pointer_to_address {{%.*}} : $Builtin.RawPointer to [align=4294967296] $*X
|
|
// CHECK-NEXT: store %1 to [[T6]] : $*X
|
|
%28 = tuple ()
|
|
return %28 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_bind_memory
|
|
sil @test_bind_memory : $(Builtin.RawPointer, Builtin.Word) -> () {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
|
|
%2 = bind_memory %0 : $Builtin.RawPointer, %1 : $Builtin.Word to $*X
|
|
// CHECK: [[BIND:%.*]] = bind_memory %0 : $Builtin.RawPointer, %1 : $Builtin.Word to $*X
|
|
%3 = rebind_memory %0 : $Builtin.RawPointer to %2 : $Builtin.Word
|
|
// CHECK: [[REBIND:%.*]] = rebind_memory %0 : $Builtin.RawPointer to [[BIND]] : $Builtin.Word
|
|
%4 = rebind_memory %0 : $Builtin.RawPointer to %3 : $Builtin.Word
|
|
// CHECK: %{{.*}} = rebind_memory %0 : $Builtin.RawPointer to [[REBIND]] : $Builtin.Word
|
|
%28 = tuple ()
|
|
return %28 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_end_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK: end_lifetime {{%.*}} : $Builtin.NativeObject
|
|
sil [ossa] @test_end_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
end_lifetime %0 : $Builtin.NativeObject
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_unchecked_ownership_conversion : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
|
|
// CHECK: unchecked_ownership_conversion {{%.*}} : $Builtin.NativeObject, @guaranteed to @owned
|
|
sil [ossa] @test_unchecked_ownership_conversion : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
|
|
bb0(%0 : @guaranteed $Builtin.NativeObject):
|
|
%1 = unchecked_ownership_conversion %0 : $Builtin.NativeObject, @guaranteed to @owned
|
|
end_lifetime %1 : $Builtin.NativeObject
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_drop_deinit :
|
|
sil [ossa] @test_drop_deinit : $@convention(thin) (@owned MoveOnlyStruct) -> () {
|
|
bb0(%0 : @owned $MoveOnlyStruct):
|
|
// CHECK: drop_deinit %0 : $MoveOnlyStruct
|
|
%1 = drop_deinit %0 : $MoveOnlyStruct
|
|
destroy_value %1 : $MoveOnlyStruct
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
sil @test_destructure_struct_tuple : $@convention(thin) (@owned (Builtin.NativeObject, Builtin.Int32), @owned TestArray2) -> @owned (Builtin.NativeObject, Builtin.Int32, TestArrayStorage, Int32, TestArrayStorage) {
|
|
bb0(%0 : $(Builtin.NativeObject, Builtin.Int32), %1 : $TestArray2):
|
|
(%2, %3) = destructure_tuple %0 : $(Builtin.NativeObject, Builtin.Int32)
|
|
(%4, %5, %6) = destructure_struct %1 : $TestArray2
|
|
%7 = tuple(%2 : $Builtin.NativeObject, %3 : $Builtin.Int32, %4 : $TestArrayStorage, %5 : $Int32, %6 : $TestArrayStorage)
|
|
return %7 : $(Builtin.NativeObject, Builtin.Int32, TestArrayStorage, Int32, TestArrayStorage)
|
|
}
|
|
|
|
class A {
|
|
@_hasStorage var property: Any { get set }
|
|
deinit
|
|
init()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_access : $@convention(thin) (@guaranteed A) -> () {
|
|
// CHECK: begin_access [read] [dynamic]
|
|
// CHECK: begin_access [read] [dynamic] [no_nested_conflict]
|
|
// CHECK: begin_unpaired_access [read] [dynamic]
|
|
// CHECK: begin_unpaired_access [read] [dynamic] [no_nested_conflict]
|
|
// CHECK-LABEL: } // end sil function 'test_access'
|
|
sil @test_access : $(@guaranteed A) -> () {
|
|
bb0(%0 : $A):
|
|
%1 = alloc_stack $Any
|
|
%2 = ref_element_addr %0 : $A, #A.property
|
|
%3 = begin_access [dynamic] [read] %2 : $*Any
|
|
copy_addr %3 to [init] %1 : $*Any
|
|
end_access %3 : $*Any
|
|
%6 = begin_access [read] [dynamic] [no_nested_conflict] %2 : $*Any
|
|
copy_addr %6 to %1 : $*Any
|
|
end_access %6 : $*Any
|
|
%9 = alloc_stack $Builtin.UnsafeValueBuffer
|
|
begin_unpaired_access [read] [dynamic] %2 : $*Any, %9 : $*Builtin.UnsafeValueBuffer
|
|
copy_addr %2 to %1 : $*Any
|
|
end_unpaired_access [dynamic] %9 : $*Builtin.UnsafeValueBuffer
|
|
begin_unpaired_access [read] [dynamic] [no_nested_conflict] %2 : $*Any, %9 : $*Builtin.UnsafeValueBuffer
|
|
copy_addr %2 to %1 : $*Any
|
|
destroy_addr %1 : $*Any
|
|
dealloc_stack %9 : $*Builtin.UnsafeValueBuffer
|
|
dealloc_stack %1 : $*Any
|
|
%20 = tuple ()
|
|
return %20 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_builtin_access : $@convention(thin) (@guaranteed A) -> () {
|
|
// CHECK: begin_access [read] [dynamic] [builtin]
|
|
// CHECK: begin_unpaired_access [read] [dynamic] [builtin]
|
|
// CHECK: end_unpaired_access [dynamic] [builtin]
|
|
// CHECK-LABEL: } // end sil function 'test_builtin_access'
|
|
sil @test_builtin_access : $(@guaranteed A) -> () {
|
|
bb0(%0 : $A):
|
|
%1 = alloc_stack $Any
|
|
%2 = ref_element_addr %0 : $A, #A.property
|
|
%6 = begin_access [read] [dynamic] [builtin] %2 : $*Any
|
|
copy_addr %6 to %1 : $*Any
|
|
end_access %6 : $*Any
|
|
%9 = alloc_stack $Builtin.UnsafeValueBuffer
|
|
begin_unpaired_access [read] [dynamic] [builtin] %2 : $*Any, %9 : $*Builtin.UnsafeValueBuffer
|
|
copy_addr %2 to %1 : $*Any
|
|
end_unpaired_access [dynamic] [builtin] %9 : $*Builtin.UnsafeValueBuffer
|
|
destroy_addr %1 : $*Any
|
|
dealloc_stack %9 : $*Builtin.UnsafeValueBuffer
|
|
dealloc_stack %1 : $*Any
|
|
%20 = tuple ()
|
|
return %20 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [dynamically_replacable] @test_dynamically_replaceable
|
|
sil [dynamically_replacable] @test_dynamically_replaceable : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = tuple ()
|
|
return %0 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [dynamic_replacement_for "test_dynamically_replaceable"] @test_dynamic_replacement_for
|
|
sil [dynamic_replacement_for "test_dynamically_replaceable"] @test_dynamic_replacement_for : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = tuple ()
|
|
return %0 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [lazy_getter] @test_lazy_getter
|
|
sil [lazy_getter] @test_lazy_getter : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = tuple ()
|
|
return %0 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [distributed] @test_distributed_method
|
|
sil hidden [distributed] @test_distributed_method : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = tuple ()
|
|
return %0 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [runtime_accessible] @test_runtime_accessible_method
|
|
sil hidden [runtime_accessible] @test_runtime_accessible_method : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = tuple ()
|
|
return %0 : $()
|
|
}
|
|
|
|
struct EmptyStruct {}
|
|
|
|
sil @test_empty_destructure : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = struct $EmptyStruct()
|
|
() = destructure_struct %0 : $EmptyStruct
|
|
%1 = tuple()
|
|
() = destructure_tuple %1 : $()
|
|
return %1 : $()
|
|
}
|
|
|
|
protocol P2 {
|
|
associatedtype A
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_dependent_existential_archetype :
|
|
// CHECK: %2 = alloc_stack $(@opened("0B7C132E-8010-11F0-8526-0EA13E3AABB4", any P2) Self).A
|
|
// CHECK-LABEL: } // end sil function 'test_dependent_existential_archetype'
|
|
sil [ossa] @test_dependent_existential_archetype : $@convention(thin) (@thick any P2.Type) -> () {
|
|
bb0(%0 : $@thick any P2.Type):
|
|
%1 = open_existential_metatype %0 to $@thick (@opened("0B7C132E-8010-11F0-8526-0EA13E3AABB4", any P2) Self).Type
|
|
%2 = alloc_stack $(@opened("0B7C132E-8010-11F0-8526-0EA13E3AABB4", any P2) Self).A
|
|
dealloc_stack %2
|
|
%r = tuple ()
|
|
return %r
|
|
}
|
|
|
|
// CHECK-LABEL: sil [heuristic_always_inline] @heuristic_always_inline_attribute
|
|
sil [heuristic_always_inline] @heuristic_always_inline_attribute : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = tuple ()
|
|
return %0 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [always_inline] @always_inline_attribute
|
|
sil [always_inline] @always_inline_attribute : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = tuple ()
|
|
return %0 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @value_borrow :
|
|
sil @value_borrow : $@convention(thin) (@guaranteed AnyObject) -> () {
|
|
// CHECK: bb0([[VALUE:%[0-9]+]] :
|
|
entry(%value : $AnyObject):
|
|
// CHECK: [[BORROW:%.*]] = make_borrow [[VALUE]]
|
|
%borrow = make_borrow %value
|
|
// CHECK: [[VALUE2:%.*]] = dereference_borrow [[BORROW]]
|
|
%value2 = dereference_borrow %borrow
|
|
|
|
%f = function_ref @value_borrow : $@convention(thin) (@guaranteed AnyObject) -> ()
|
|
%r = apply %f(%value2) : $@convention(thin) (@guaranteed AnyObject) -> ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @addr_borrow :
|
|
sil @addr_borrow : $@convention(thin) (@in_guaranteed String) -> () {
|
|
// CHECK: bb0([[ADDR:%[0-9]+]] :
|
|
entry(%addr : $*String):
|
|
// CHECK: [[BORROW:%.*]] = make_addr_borrow [[ADDR]]
|
|
%borrow = make_addr_borrow %addr
|
|
// CHECK: [[ADDR:%.*]] = dereference_addr_borrow [[BORROW]]
|
|
%addr2 = dereference_addr_borrow %borrow
|
|
|
|
%f = function_ref @addr_borrow : $@convention(thin) (@in_guaranteed String) -> ()
|
|
%r = apply %f(%addr2) : $@convention(thin) (@in_guaranteed String) -> ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @addr_only_borrow :
|
|
sil @addr_only_borrow : $@convention(thin) <T> (@in_guaranteed T) -> () {
|
|
// CHECK: bb0([[ADDR:%[0-9]+]] :
|
|
entry(%addr : $*T):
|
|
// CHECK: [[BORROW_BUF:%.*]] = alloc_stack
|
|
%borrow_buf = alloc_stack $Builtin.Borrow<T>
|
|
// CHECK: init_borrow_addr [[BORROW_BUF]] : $*Builtin.Borrow<T> with [[ADDR]] : $*T
|
|
init_borrow_addr %borrow_buf with %addr
|
|
// CHECK: [[ADDR2:%.*]] = dereference_borrow_addr [[BORROW_BUF]]
|
|
%addr2 = dereference_borrow_addr %borrow_buf
|
|
|
|
%f = function_ref @addr_only_borrow : $@convention(thin) <U> (@in_guaranteed U) -> ()
|
|
%r = apply %f<T>(%addr2) : $@convention(thin) <U> (@in_guaranteed U) -> ()
|
|
dealloc_stack %borrow_buf
|
|
return %r : $()
|
|
}
|
|
|
|
class Foo2: Foo, Q {}
|
|
|
|
// CHECK-LABEL: sil_vtable Foo {
|
|
// CHECK-NEXT: #Foo.subscript!getter: {{.*}} : @Foo_subscript_getter [nonoverridden]
|
|
// CHECK-NEXT: #Foo.subscript!setter: {{.*}} : @Foo_subscript_setter
|
|
// CHECK-NEXT: }
|
|
sil_vtable Foo {
|
|
#Foo.subscript!getter: @Foo_subscript_getter [nonoverridden]
|
|
#Foo.subscript!setter: @Foo_subscript_setter
|
|
}
|
|
|
|
// CHECK-LABEL: sil_vtable Foo2 {
|
|
// CHECK-NEXT: no_conformance P
|
|
// CHECK-NEXT: conformance Foo2: Q module main
|
|
// CHECK-NEXT: no_conformance P2
|
|
// CHECK-NEXT: #Foo.subscript!getter: {{.*}} : @Foo_subscript_getter [inherited] [nonoverridden]
|
|
// CHECK-NEXT: #Foo.subscript!setter: {{.*}} : @Foo_subscript_setter [override]
|
|
// CHECK-NEXT: }
|
|
sil_vtable Foo2 {
|
|
no_conformance P
|
|
conformance Foo2: Q module main
|
|
no_conformance P2
|
|
#Foo.subscript!getter: @Foo_subscript_getter [inherited] [nonoverridden]
|
|
#Foo.subscript!setter: @Foo_subscript_setter [override]
|
|
}
|
|
|
|
class GenKlass<T> {}
|
|
|
|
// CHECK-LABEL: sil_vtable GenKlass {
|
|
sil_vtable GenKlass {
|
|
}
|
|
|
|
// CHECK-LABEL: sil_vtable $GenKlass<Int> {
|
|
sil_vtable $GenKlass<Int> {
|
|
}
|