mirror of
https://github.com/apple/swift.git
synced 2026-10-22 19:15:50 +02:00
We will have SILGen mark accesses as unresolved when lifetime resolution needs to run in order to establish the final point where the access ends.
314 lines
13 KiB
Plaintext
314 lines
13 KiB
Plaintext
// First parse this and then emit a *.sib. Then read in the *.sib, then recreate
|
|
// RUN: %empty-directory(%t)
|
|
// RUN: %target-sil-opt -sil-print-types %s -emit-sib -o %t/tmp.sib -module-name borrow
|
|
// RUN: %target-sil-opt -sil-print-types %t/tmp.sib -o %t/tmp.2.sib -module-name borrow
|
|
// RUN: %target-sil-opt -sil-print-types %t/tmp.2.sib -module-name borrow -emit-sorted-sil | %FileCheck %s
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
class TestArrayStorage {
|
|
@_hasStorage var count: Int32
|
|
init()
|
|
}
|
|
|
|
class C {}
|
|
|
|
struct TestArray2 {
|
|
var storage : TestArrayStorage
|
|
var someValue : Int32
|
|
var storage2 : TestArrayStorage
|
|
}
|
|
|
|
struct Int32 {
|
|
var x: Builtin.Int32
|
|
}
|
|
|
|
struct EmptyStruct {}
|
|
|
|
struct MoveOnlyStruct: ~Copyable {
|
|
@_hasStorage var i: Int32
|
|
deinit
|
|
}
|
|
|
|
// CHECK-LABEL: sil @alloc_ref_non_nested : $@convention(thin) () -> ()
|
|
sil @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
|
|
}
|
|
|
|
// CHECK-LABEL: sil @async_test : $@convention(thin) @async
|
|
sil @async_test : $@async () -> () {
|
|
bb0:
|
|
%0 = tuple ()
|
|
return %0 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @end_formal_scope :
|
|
sil @end_formal_scope : $@convention(thin) (Builtin.Int32) -> () {
|
|
// CHECK: bb0([[ARG:%[0-9]+]] :
|
|
entry(%arg : $Builtin.Int32):
|
|
// CHECK: [[LOCAL_LET:%.*]] = integer_literal
|
|
%local_let = integer_literal $Builtin.Int32, 1
|
|
// CHECK: [[LOCAL_VAR:%.*]] = alloc_stack
|
|
%local_var = alloc_stack $Builtin.Int32
|
|
|
|
// CHECK: end_formal_scope [[LOCAL_VAR]]
|
|
end_formal_scope %local_var
|
|
dealloc_stack %local_var
|
|
// CHECK: end_formal_scope [[LOCAL_LET]]
|
|
end_formal_scope %local_let
|
|
// CHECK: end_formal_scope [[ARG]]
|
|
end_formal_scope %arg
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK: sil [ownership_for_trivial] [ossa] @ownership_for_trivial
|
|
sil [ossa] [ownership_for_trivial] @ownership_for_trivial : $@convention(thin) (Int) -> () {
|
|
entry(%0 : @owned $Int):
|
|
destroy_value %0
|
|
return undef : $()
|
|
}
|
|
|
|
sil [ossa] @strong_copy_unmanaged_value_test : $@convention(thin) (@sil_unmanaged Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : $@sil_unmanaged Builtin.NativeObject):
|
|
%1 = strong_copy_unmanaged_value %0 : $@sil_unmanaged Builtin.NativeObject
|
|
return %1 : $Builtin.NativeObject
|
|
}
|
|
|
|
class A {
|
|
@_hasStorage var property: Any { get set }
|
|
deinit
|
|
init()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @test_access : $@convention(thin) (@guaranteed A) -> () {
|
|
// CHECK: begin_access [read] [dynamic] [unresolved]
|
|
// 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 [unresolved] [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 : $()
|
|
}
|
|
|
|
sil [ossa] @test_destructure_struct_tuple : $@convention(thin) (@owned (Builtin.NativeObject, Builtin.Int32), @owned TestArray2) -> @owned (Builtin.NativeObject, Builtin.Int32, TestArrayStorage, Int32, TestArrayStorage) {
|
|
bb0(%0 : @owned $(Builtin.NativeObject, Builtin.Int32), %1 : @owned $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)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_drop_deinit :
|
|
// CHECK: %1 = drop_deinit %0 : $MoveOnlyStruct
|
|
// CHECK-LABEL: } // end sil function 'test_drop_deinit'
|
|
sil [ossa] @test_drop_deinit : $@convention(thin) (@owned MoveOnlyStruct) -> () {
|
|
bb0(%0 : @owned $MoveOnlyStruct):
|
|
%1 = drop_deinit %0 : $MoveOnlyStruct
|
|
destroy_value %1 : $MoveOnlyStruct
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
sil @test_empty_destructure : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = struct $EmptyStruct()
|
|
() = destructure_struct %0 : $EmptyStruct
|
|
%1 = tuple()
|
|
() = destructure_tuple %1 : $()
|
|
return %1 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [serialized] [ossa] @test_end_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
// CHECK: end_lifetime {{%.*}} : $Builtin.NativeObject
|
|
sil [serialized] [ossa] @test_end_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
end_lifetime %0 : $Builtin.NativeObject
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [lazy_getter] @test_lazy_getter
|
|
sil [lazy_getter] @test_lazy_getter : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = tuple ()
|
|
return %0 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_movevalue_parsing : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
// CHECK: bb0([[REGISTER_0:%[^,]+]] :
|
|
// CHECK-NEXT: [[REGISTER_1:%[^,]+]] = move_value [[REGISTER_0]]
|
|
// CHECK-NEXT: [[REGISTER_2:%[^,]+]] = move_value [allows_diagnostics] [[REGISTER_1]]
|
|
// CHECK-NEXT: [[REGISTER_3:%[^,]+]] = move_value [lexical] [[REGISTER_2]]
|
|
// CHECK-NEXT: [[REGISTER_4:%[^,]+]] = move_value [allows_diagnostics] [lexical] [[REGISTER_3]]
|
|
// CHECK-NEXT: [[REGISTER_5:%[^,]+]] = move_value [allows_diagnostics] [lexical] [[REGISTER_4]]
|
|
// CHECK-NEXT: [[REGISTER_6:%[^,]+]] = move_value [var_decl] [[REGISTER_5]]
|
|
// CHECK-NEXT: return [[REGISTER_6]]
|
|
// CHECK-NEXT: } // end sil function 'test_movevalue_parsing'
|
|
sil [ossa] @test_movevalue_parsing : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = move_value %0 : $Builtin.NativeObject
|
|
%2 = move_value [allows_diagnostics] %1 : $Builtin.NativeObject
|
|
%3 = move_value [lexical] %2 : $Builtin.NativeObject
|
|
%4 = move_value [allows_diagnostics] [lexical] %3 : $Builtin.NativeObject
|
|
%5 = move_value [lexical] [allows_diagnostics] %4 : $Builtin.NativeObject
|
|
%6 = move_value [var_decl] %5 : $Builtin.NativeObject
|
|
return %6 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [no_allocation] [ossa] @test_no_allocation : $@convention(thin) () -> () {
|
|
sil [no_allocation] [ossa] @test_no_allocation : $@convention(thin) () -> () {
|
|
bb0:
|
|
%1 = tuple ()
|
|
return %1 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [no_locks] [ossa] @test_no_locks : $@convention(thin) () -> () {
|
|
sil [no_locks] [ossa] @test_no_locks : $@convention(thin) () -> () {
|
|
bb0:
|
|
%1 = tuple ()
|
|
return %1 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_pointer_to_address : $@convention(thin) (Builtin.RawPointer, Builtin.Int64) -> () {
|
|
// CHECK: pointer_to_address %0 : $Builtin.RawPointer to [strict] $*Builtin.Int64
|
|
// CHECK: pointer_to_address %0 : $Builtin.RawPointer to [invariant] $*Builtin.Int64
|
|
// CHECK: pointer_to_address %0 : $Builtin.RawPointer to [align=1] $*Builtin.Int64
|
|
// CHECK: pointer_to_address %0 : $Builtin.RawPointer to [strict] [align=8] $*Builtin.Int64
|
|
// CHECK: pointer_to_address %0 : $Builtin.RawPointer to [align=4294967296] $*Builtin.Int64
|
|
sil [ossa] @test_pointer_to_address : $@convention(thin) (Builtin.RawPointer, Builtin.Int64) -> () {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Int64):
|
|
%3 = pointer_to_address %0 : $Builtin.RawPointer to $*Builtin.Int64
|
|
store %1 to [trivial] %3 : $*Builtin.Int64
|
|
%5 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*Builtin.Int64
|
|
store %1 to [trivial] %5 : $*Builtin.Int64
|
|
%7 = pointer_to_address %0 : $Builtin.RawPointer to [invariant] $*Builtin.Int64
|
|
store %1 to [trivial] %7 : $*Builtin.Int64
|
|
%9 = pointer_to_address %0 : $Builtin.RawPointer to [align=1] $*Builtin.Int64
|
|
store %1 to [trivial] %9 : $*Builtin.Int64
|
|
%11 = pointer_to_address %0 : $Builtin.RawPointer to [strict] [align=8] $*Builtin.Int64
|
|
store %1 to [trivial] %11 : $*Builtin.Int64
|
|
%13 = pointer_to_address %0 : $Builtin.RawPointer to [align=4294967296] $*Builtin.Int64
|
|
store %1 to [trivial] %13 : $*Builtin.Int64
|
|
%28 = tuple ()
|
|
return %28 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_raw_pointer_to_ref : $@convention(thin) (Builtin.RawPointer) -> () {
|
|
// CHECK: [[IMMORTAL:%.*]] = raw_pointer_to_ref [immortal] %0 : $Builtin.RawPointer to $Builtin.NativeObject
|
|
// CHECK: fix_lifetime [[IMMORTAL]] : $Builtin.NativeObject
|
|
// CHECK: [[OWNED:%.*]] = raw_pointer_to_ref %0 : $Builtin.RawPointer to $Builtin.NativeObject
|
|
// CHECK: destroy_value [[OWNED]] : $Builtin.NativeObject
|
|
// CHECK-LABEL: } // end sil function 'test_raw_pointer_to_ref'
|
|
sil [ossa] @test_raw_pointer_to_ref : $@convention(thin) (Builtin.RawPointer) -> () {
|
|
bb0(%0 : $Builtin.RawPointer):
|
|
// An immortal result has "none" ownership, so it must not be destroyed.
|
|
%1 = raw_pointer_to_ref [immortal] %0 : $Builtin.RawPointer to $Builtin.NativeObject
|
|
fix_lifetime %1 : $Builtin.NativeObject
|
|
// A non-immortal result is "owned", so it has to be destroyed.
|
|
%3 = raw_pointer_to_ref %0 : $Builtin.RawPointer to $Builtin.NativeObject
|
|
destroy_value %3 : $Builtin.NativeObject
|
|
%5 = tuple ()
|
|
return %5 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [serialized] [ossa] @test_subst_function_type : $@convention(thin) (@guaranteed @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> () for <Builtin.Int32, Builtin.Int64>) -> ()
|
|
sil [serialized] [ossa] @test_subst_function_type : $@convention(thin) (@guaranteed @callee_guaranteed @substituted <A, B> (@in A, @in B) -> () for <Builtin.Int32, Builtin.Int64>) -> () {
|
|
entry(%0 : @guaranteed $@callee_guaranteed @substituted <C, D> (@in C, @in D) -> () for <Builtin.Int32, Builtin.Int64>):
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [serialized] [ossa] @test_subst_function_type_generic_context : $@convention(thin) <X, Y> (@guaranteed @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> () for <X, Y>) -> ()
|
|
sil [serialized] [ossa] @test_subst_function_type_generic_context : $@convention(thin) <X, Y> (@guaranteed @callee_guaranteed @substituted <A, B> (@in A, @in B) -> () for <X, Y>) -> () {
|
|
entry(%0 : @guaranteed $@callee_guaranteed @substituted <C, D> (@in C, @in D) -> () for <X, Y>):
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [serialized] [ossa] @test_unchecked_ownership_conversion : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
|
|
// CHECK: unchecked_ownership_conversion {{%.*}} : $Builtin.NativeObject, @guaranteed to @owned
|
|
sil [serialized] [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
|
|
destroy_value %1 : $Builtin.NativeObject
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil @throwError : $@convention(thin) <τ_0_0, τ_0_1> (Builtin.Int64, @in τ_0_0) -> (@out τ_0_1, @error_indirect τ_0_0)
|
|
// CHECK: copy_addr [take] %3 to [init] %1 : $*τ_0_0
|
|
// CHECK: throw %1 : $*τ_0_0
|
|
sil @throwError : $@convention(thin) <τ_0_0, τ_0_1> (Builtin.Int64, @in τ_0_0) -> (@error_indirect τ_0_0, @out τ_0_1) {
|
|
bb0(%0: $*τ_0_1, %1: $*τ_0_0, %2 : $Builtin.Int64, %3 : $*τ_0_0):
|
|
copy_addr [take] %3 to [init] %1 : $*τ_0_0
|
|
throw %1 : $*τ_0_0
|
|
}
|
|
|
|
// CHECK: sil @throwError_unowned : $@convention(thin) (Builtin.Int64) -> @error_unowned Builtin.Int64 {
|
|
// CHECK: bb0(%0 : $Builtin.Int64):
|
|
// CHECK: throw %0 : $Builtin.Int64
|
|
sil @throwError_unowned : $@convention(thin) (Builtin.Int64) -> @error_unowned Builtin.Int64 {
|
|
bb0(%0 : $Builtin.Int64):
|
|
throw %0 : $Builtin.Int64
|
|
}
|
|
|
|
// CHECK: sil @try_apply : $@convention(thin) <T, V> (@in T) -> @out V
|
|
// CHECK: bb0(%0 : $*V, %1 : $*T):
|
|
// CHECK: %2 = alloc_stack $T
|
|
// CHECK: %3 = integer_literal $Builtin.Int64, 0
|
|
// CHECK: %4 = function_ref @throwError : $@convention(thin) <τ_0_0, τ_0_1> (Builtin.Int64, @in τ_0_0) -> (@out τ_0_1, @error_indirect τ_0_0)
|
|
// CHECK: try_apply %4<T, V>(%0, %2, %3, %1) : $@convention(thin) <τ_0_0, τ_0_1> (Builtin.Int64, @in τ_0_0) -> (@out τ_0_1, @error_indirect τ_0_0), normal bb2, error bb1
|
|
// CHECK: bb1:
|
|
// CHECK: destroy_addr %2 : $*T
|
|
// CHECK: br bb3
|
|
// CHECK: bb2(%8 : $()):
|
|
// CHECK: br bb3
|
|
|
|
sil @try_apply : $@convention(thin) <T, V> (@in T) -> @out V {
|
|
bb0(%0 : $*V, %1: $*T):
|
|
%2 = alloc_stack $T
|
|
%3 = integer_literal $Builtin.Int64, 0
|
|
%4 = function_ref @throwError : $@convention(thin) <T, V> (Builtin.Int64, @in T) -> (@error_indirect T, @out V)
|
|
try_apply %4<T, V>(%0, %2, %3, %1) : $@convention(thin) <T, V> (Builtin.Int64, @in T) -> (@error_indirect T, @out V), normal bb1, error bb2
|
|
|
|
bb1(%5 : $()):
|
|
br bb3
|
|
|
|
bb2:
|
|
destroy_addr %2 : $*T
|
|
br bb3
|
|
|
|
bb3:
|
|
dealloc_stack %2 : $*T
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|