mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
In case of `var` initializations, SILGen creates a dynamic begin/end_access pair around the initialization store. If it's an initialization (and not a re-assign) it's guanranteed that it's an exlusive access and we can convert the access to an `[init] [static]` access. https://github.com/apple/swift/issues/66496
187 lines
7.5 KiB
Plaintext
187 lines
7.5 KiB
Plaintext
// RUN: %target-sil-opt -enable-sil-verify-all %s -definite-init -raw-sil-inst-lowering -verify | %FileCheck %s
|
|
|
|
// This file tests mark_uninitialized [rootself]
|
|
|
|
sil_stage raw
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
class RootClassWithIVars {
|
|
var x: Int // expected-note {{'self.x' not initialized}}
|
|
var y: Int
|
|
var z: (Int, Int) // expected-note 2 {{'self.z.1' not initialized}} expected-note {{'self.z.0' not initialized}}
|
|
init()
|
|
}
|
|
|
|
class RootClassWithNontrivialStoredProperties {
|
|
var x, y: SomeClass
|
|
|
|
init()
|
|
}
|
|
|
|
class SomeClass {}
|
|
|
|
final class IntClass {
|
|
var i: Int
|
|
init(_ i: Int)
|
|
}
|
|
|
|
final class GenericClass<T> {
|
|
var t: T
|
|
init(_ t: T)
|
|
}
|
|
|
|
sil @getSomeClass : $@convention(thin) () -> @owned SomeClass
|
|
sil @getSomeOptionalClass : $@convention(thin) () -> Optional<SomeClass>
|
|
|
|
// CHECK-LABEL: sil [ossa] @rootclass_test1
|
|
sil [ossa] @rootclass_test1 : $@convention(method) (@owned RootClassWithIVars, Int) -> @owned RootClassWithIVars {
|
|
bb0(%0 : @owned $RootClassWithIVars, %1 : $Int):
|
|
%3 = mark_uninitialized [rootself] %0 : $RootClassWithIVars
|
|
|
|
%4 = begin_borrow %3 : $RootClassWithIVars
|
|
%10 = ref_element_addr %4 : $RootClassWithIVars, #RootClassWithIVars.x
|
|
assign %1 to %10 : $*Int
|
|
end_borrow %4 : $RootClassWithIVars
|
|
|
|
%5 = begin_borrow %3 : $RootClassWithIVars
|
|
%11 = ref_element_addr %5 : $RootClassWithIVars, #RootClassWithIVars.y
|
|
assign %1 to %11 : $*Int
|
|
end_borrow %5 : $RootClassWithIVars
|
|
|
|
%6 = begin_borrow %3 : $RootClassWithIVars
|
|
%12 = ref_element_addr %6 : $RootClassWithIVars, #RootClassWithIVars.z
|
|
%13 = tuple_element_addr %12 : $*(Int, Int), 0
|
|
assign %1 to %13 : $*Int
|
|
%14 = tuple_element_addr %12 : $*(Int, Int), 1
|
|
assign %1 to %14 : $*Int
|
|
end_borrow %6 : $RootClassWithIVars
|
|
|
|
return %3 : $RootClassWithIVars
|
|
}
|
|
|
|
// CHECK-LABEL: sil [_semantics "sil.optimizer.moveonly.diagnostic.ignore"] [ossa] @rootclass_test2
|
|
sil [ossa] @rootclass_test2 : $@convention(method) (@owned RootClassWithIVars, Int) -> @owned RootClassWithIVars {
|
|
bb0(%0 : @owned $RootClassWithIVars, %1 : $Int):
|
|
%3 = mark_uninitialized [rootself] %0 : $RootClassWithIVars
|
|
|
|
%4 = begin_borrow %3 : $RootClassWithIVars
|
|
%10 = ref_element_addr %4 : $RootClassWithIVars, #RootClassWithIVars.x
|
|
assign %1 to %10 : $*Int
|
|
end_borrow %4 : $RootClassWithIVars
|
|
|
|
%5 = begin_borrow %3 : $RootClassWithIVars
|
|
%11 = ref_element_addr %5 : $RootClassWithIVars, #RootClassWithIVars.y
|
|
assign %1 to %11 : $*Int
|
|
end_borrow %5 : $RootClassWithIVars
|
|
|
|
%6 = begin_borrow %3 : $RootClassWithIVars
|
|
%12 = ref_element_addr %6 : $RootClassWithIVars, #RootClassWithIVars.z
|
|
%13 = tuple_element_addr %12 : $*(Int, Int), 0
|
|
assign %1 to %13 : $*Int
|
|
end_borrow %6 : $RootClassWithIVars
|
|
|
|
return %3 : $RootClassWithIVars // expected-error {{return from initializer without initializing all stored properties}}
|
|
}
|
|
|
|
// CHECK-LABEL: sil [_semantics "sil.optimizer.moveonly.diagnostic.ignore"] [ossa] @rootclass_test3
|
|
sil [ossa] @rootclass_test3 : $@convention(method) (@owned RootClassWithIVars, Int) -> @owned RootClassWithIVars {
|
|
bb0(%0 : @owned $RootClassWithIVars, %1 : $Int):
|
|
%3 = mark_uninitialized [rootself] %0 : $RootClassWithIVars
|
|
|
|
%4 = begin_borrow %3 : $RootClassWithIVars
|
|
%11 = ref_element_addr %4 : $RootClassWithIVars, #RootClassWithIVars.y
|
|
assign %1 to %11 : $*Int
|
|
end_borrow %4 : $RootClassWithIVars
|
|
|
|
return %3 : $RootClassWithIVars // expected-error {{return from initializer without initializing all stored properties}}
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_root_release
|
|
// CHECK: bb0(%0 : @owned $RootClassWithNontrivialStoredProperties):
|
|
// CHECK-NEXT: [[METATYPE:%[0-9]+]] = metatype $@thick RootClassWithNontrivialStoredProperties.Type
|
|
// CHECK-NEXT: dealloc_partial_ref %0 : $RootClassWithNontrivialStoredProperties, [[METATYPE]] : $@thick RootClassWithNontrivialStoredProperties.Type
|
|
sil [ossa] @test_root_release : $@convention(method) (@owned RootClassWithNontrivialStoredProperties) -> () {
|
|
bb0(%0 : @owned $RootClassWithNontrivialStoredProperties):
|
|
%4 = mark_uninitialized [rootself] %0 : $RootClassWithNontrivialStoredProperties
|
|
destroy_value %4 : $RootClassWithNontrivialStoredProperties
|
|
|
|
%13 = tuple ()
|
|
return %13 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_root_partial_release
|
|
// CHECK: bb0([[SELF:%.*]] : @owned $RootClassWithNontrivialStoredProperties):
|
|
// CHECK: [[FIELD_VALUE:%.*]] = alloc_ref
|
|
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
|
|
// CHECK: [[SELF_FIELD:%.*]] = ref_element_addr [[BORROWED_SELF]]
|
|
// CHECK: store [[FIELD_VALUE]] to [init] [[SELF_FIELD]]
|
|
// CHECK: end_borrow [[BORROWED_SELF]]
|
|
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
|
|
// CHECK: [[SELF_FIELD:%.*]] = ref_element_addr [[BORROWED_SELF]]
|
|
// CHECK: [[SELF_FIELD_ACCESS:%.*]] = begin_access [deinit] [static] [[SELF_FIELD]]
|
|
// CHECK: destroy_addr [[SELF_FIELD_ACCESS]]
|
|
// CHECK: end_access [[SELF_FIELD_ACCESS]]
|
|
// CHECK: end_borrow [[BORROWED_SELF]]
|
|
// CHECK: [[METATYPE:%[0-9]+]] = metatype $@thick RootClassWithNontrivialStoredProperties.Type
|
|
// CHECK: dealloc_partial_ref [[SELF]] : $RootClassWithNontrivialStoredProperties, [[METATYPE]] : $@thick RootClassWithNontrivialStoredProperties.Type
|
|
// CHECK: } // end sil function 'test_root_partial_release'
|
|
sil [ossa] @test_root_partial_release : $@convention(method) (@owned RootClassWithNontrivialStoredProperties) -> () {
|
|
bb0(%0 : @owned $RootClassWithNontrivialStoredProperties):
|
|
%4 = mark_uninitialized [rootself] %0 : $RootClassWithNontrivialStoredProperties
|
|
|
|
%1 = alloc_ref $SomeClass
|
|
%5 = begin_borrow %4 : $RootClassWithNontrivialStoredProperties
|
|
%2 = ref_element_addr %5 : $RootClassWithNontrivialStoredProperties, #RootClassWithNontrivialStoredProperties.x
|
|
assign %1 to %2 : $*SomeClass
|
|
end_borrow %5 : $RootClassWithNontrivialStoredProperties
|
|
|
|
destroy_value %4 : $RootClassWithNontrivialStoredProperties
|
|
|
|
%13 = tuple ()
|
|
return %13 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @init_IntClass :
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [init] [static]
|
|
// CHECK: store %0 to [trivial] [[ACCESS]]
|
|
// CHECK: [[ACCESS2:%.*]] = begin_access [modify] [dynamic]
|
|
// CHECK: store %0 to [trivial] [[ACCESS2]]
|
|
// CHECK: } // end sil function 'init_IntClass'
|
|
sil [ossa] @init_IntClass : $@convention(method) (Int, @owned IntClass) -> @owned IntClass {
|
|
bb0(%0 : $Int, %1 : @owned $IntClass):
|
|
%4 = mark_uninitialized [rootself] %1 : $IntClass
|
|
%5 = begin_borrow %4 : $IntClass
|
|
%6 = ref_element_addr %5 : $IntClass, #IntClass.i
|
|
%7 = begin_access [modify] [dynamic] %6 : $*Int
|
|
assign %0 to %7 : $*Int
|
|
end_access %7 : $*Int
|
|
%10 = begin_access [modify] [dynamic] %6 : $*Int
|
|
assign %0 to %10 : $*Int
|
|
end_access %10 : $*Int
|
|
end_borrow %5 : $IntClass
|
|
return %4 : $IntClass
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @init_GenericClass :
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [init] [static]
|
|
// CHECK: copy_addr %0 to [init] [[ACCESS]]
|
|
// CHECK: [[ACCESS2:%.*]] = begin_access [modify] [dynamic]
|
|
// CHECK: copy_addr [take] %0 to [[ACCESS2]]
|
|
// CHECK: } // end sil function 'init_GenericClass'
|
|
sil [ossa] @init_GenericClass : $@convention(method) <T> (@in T, @owned GenericClass<T>) -> @owned GenericClass<T> {
|
|
bb0(%0 : $*T, %1 : @owned $GenericClass<T>):
|
|
%4 = mark_uninitialized [rootself] %1 : $GenericClass<T>
|
|
%5 = begin_borrow %4 : $GenericClass<T>
|
|
%8 = ref_element_addr %5 : $GenericClass<T>, #GenericClass.t
|
|
%9 = begin_access [modify] [dynamic] %8 : $*T
|
|
copy_addr %0 to %9 : $*T
|
|
end_access %9 : $*T
|
|
%12 = begin_access [modify] [dynamic] %8 : $*T
|
|
copy_addr [take] %0 to %12 : $*T
|
|
end_access %12 : $*T
|
|
end_borrow %5 : $GenericClass<T>
|
|
return %4 : $GenericClass<T>
|
|
}
|