Files
swift-mirror/test/SILOptimizer/moveonly_deinit_devirtualization_library_evolution.sil
Michael Gottesman d0938a906f [move-only] Ban resilient noncopyable types.
One can still in resilient frameworks have noncopyable frozen types.

This means that one cannot make a noncopyable:

1. Full resilient public type.
2. @usableFromInline type.

NOTE: One can still use a frozen noncopyable type as a usableFromInline class
field. I validated in the attached tests that we get the correct code
generation.

I also eliminated a small bug in TypeCheckDeclPrimary where we weren't using a
requestified attr check and instead were checking directly.

rdar://111125845
2023-06-21 16:57:44 -07:00

403 lines
15 KiB
Plaintext

// RUN: %target-sil-opt -enable-library-evolution -module-name main -enable-sil-verify-all -sil-move-only-deinit-devirtualization -enable-experimental-feature MoveOnlyClasses -enable-experimental-feature MoveOnlyEnumDeinits -enable-experimental-feature MoveOnlyResilientTypes %s | %FileCheck %s
sil_stage raw
import Builtin
//===----------------------------------------------------------------------===//
// Declarations
//===----------------------------------------------------------------------===//
@_moveOnly
public class Klass {
deinit
}
@_moveOnly
public struct StructDeinit {
var i: Builtin.Int32
deinit
}
@_moveOnly
public struct SingleFieldNonTrivial {
var k: Klass
}
@_moveOnly
public struct ThreeNonTrivial {
var k: Klass
var i: Builtin.Int32
var k2: Klass
}
@_moveOnly
struct ThreeNonTrivialNoDeinit {
var k: Klass
var i: Builtin.Int32
var k2: Klass
}
@_moveOnly enum TrivialMoveOnlyEnum {
case first
case second(Builtin.Int32)
case third(Builtin.Int64, Builtin.Int64)
deinit
}
@_moveOnly enum NonTrivialMoveOnlyEnum {
case first
case second(Builtin.Int32)
case third(Klass, Klass)
case fourth(Builtin.Int64, Builtin.Int64)
case fifth(TrivialMoveOnlyEnum)
deinit
}
//===----------------------------------------------------------------------===//
// Object Tests
//===----------------------------------------------------------------------===//
// CHECK-LABEL: sil [ossa] @klassTest : $@convention(thin) (@owned Klass) -> () {
// CHECK: bb0([[ARG:%.*]] : @owned $Klass):
// CHECK: [[FUNC:%.*]] = function_ref @$s4main5KlassCfD :
// CHECK: apply [[FUNC]]([[ARG]])
// CHECK: } // end sil function 'klassTest'
sil [ossa] @klassTest : $@convention(thin) (@owned Klass) -> () {
bb0(%0 : @owned $Klass):
destroy_value %0 : $Klass
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil [ossa] @structDeinitTest : $@convention(thin) (@owned StructDeinit) -> () {
// CHECK: bb0([[ARG:%.*]] : @owned $StructDeinit):
// CHECK: [[STACK:%.*]] = alloc_stack $
// CHECK: store [[ARG]] to [init] [[STACK]]
// CHECK: [[FUNC:%.*]] = function_ref @$s4main12StructDeinitVfD :
// CHECK: apply [[FUNC]]([[STACK]])
// CHECK: } // end sil function 'structDeinitTest'
sil [ossa] @structDeinitTest : $@convention(thin) (@owned StructDeinit) -> () {
bb0(%0 : @owned $StructDeinit):
destroy_value %0 : $StructDeinit
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil [ossa] @singleFieldNonTrivialTest : $@convention(thin) (@owned SingleFieldNonTrivial) -> () {
// CHECK: bb0([[ARG:%.*]] : @owned $Single
// CHECK: [[STACK:%.*]] = alloc_stack $
// CHECK: store [[ARG]] to [init] [[STACK]]
// CHECK: [[FUNC:%.*]] = function_ref @$s4main21SingleFieldNonTrivialVfD :
// CHECK: apply [[FUNC]]([[STACK]])
// CHECK: } // end sil function 'singleFieldNonTrivialTest'
sil [ossa] @singleFieldNonTrivialTest : $@convention(thin) (@owned SingleFieldNonTrivial) -> () {
bb0(%0 : @owned $SingleFieldNonTrivial):
destroy_value %0 : $SingleFieldNonTrivial
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil [ossa] @multiFieldNonTrivialTest : $@convention(thin) (@owned ThreeNonTrivial) -> () {
// CHECK: bb0([[ARG:%.*]] : @owned $
// CHECK: [[STACK:%.*]] = alloc_stack $
// CHECK: store [[ARG]] to [init] [[STACK]]
// CHECK: [[FUNC:%.*]] = function_ref @$s4main15ThreeNonTrivialVfD :
// CHECK: apply [[FUNC]]([[STACK]])
// CHECK: } // end sil function 'multiFieldNonTrivialTest'
sil [ossa] @multiFieldNonTrivialTest : $@convention(thin) (@owned ThreeNonTrivial) -> () {
bb0(%0 : @owned $ThreeNonTrivial):
destroy_value %0 : $ThreeNonTrivial
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil [ossa] @trivialMoveOnlyEnum : $@convention(thin) (@owned TrivialMoveOnlyEnum) -> () {
// CHECK: [[STACK:%.*]] = alloc_stack $
// CHECK: store [[ARG]] to [init] [[STACK]]
// CHECK: [[FUNC:%.*]] = function_ref @$s4main19TrivialMoveOnlyEnumOfD :
// CHECK: apply [[FUNC]]([[STACK]])
// CHECK: } // end sil function 'trivialMoveOnlyEnum'
sil [ossa] @trivialMoveOnlyEnum : $@convention(thin) (@owned TrivialMoveOnlyEnum) -> () {
bb0(%0 : @owned $TrivialMoveOnlyEnum):
destroy_value %0 : $TrivialMoveOnlyEnum
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @nonTrivialMoveOnlyEnum : $@convention(thin) (@owned NonTrivialMoveOnlyEnum) -> () {
bb0(%0 : @owned $NonTrivialMoveOnlyEnum):
destroy_value %0 : $NonTrivialMoveOnlyEnum
%9999 = tuple()
return %9999 : $()
}
//===----------------------------------------------------------------------===//
// Var Tests
//===----------------------------------------------------------------------===//
// CHECK-LABEL: sil [ossa] @structDeinitAddrTest : $@convention(thin) (@in StructDeinit) -> () {
// CHECK: bb0([[ARG:%.*]] : $*StructDeinit):
// CHECK: [[FUNC:%.*]] = function_ref @$s4main12StructDeinitVfD :
// CHECK: apply [[FUNC]]([[ARG]])
// CHECK: } // end sil function 'structDeinitAddrTest'
sil [ossa] @structDeinitAddrTest : $@convention(thin) (@in StructDeinit) -> () {
bb0(%0 : $*StructDeinit):
destroy_addr %0 : $*StructDeinit
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil [ossa] @singleFieldNonTrivialAddrTest : $@convention(thin) (@in SingleFieldNonTrivial) -> () {
// CHECK: bb0([[ARG:%.*]] : $
// CHECK: [[FUNC:%.*]] = function_ref @$s4main21SingleFieldNonTrivialVfD :
// CHECK: apply [[FUNC]]([[ARG]])
// CHECK: } // end sil function 'singleFieldNonTrivialAddrTest'
sil [ossa] @singleFieldNonTrivialAddrTest : $@convention(thin) (@in SingleFieldNonTrivial) -> () {
bb0(%0 : $*SingleFieldNonTrivial):
destroy_addr %0 : $*SingleFieldNonTrivial
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil [ossa] @multiFieldNonTrivialAddrTest : $@convention(thin) (@in ThreeNonTrivial) -> () {
// CHECK: bb0([[ARG:%.*]] : $
// CHECK: [[FUNC:%.*]] = function_ref @$s4main15ThreeNonTrivialVfD :
// CHECK: apply [[FUNC]]([[ARG]])
// CHECK: } // end sil function 'multiFieldNonTrivialAddrTest'
sil [ossa] @multiFieldNonTrivialAddrTest : $@convention(thin) (@in ThreeNonTrivial) -> () {
bb0(%0 : $*ThreeNonTrivial):
destroy_addr %0 : $*ThreeNonTrivial
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil [ossa] @trivialMoveOnlyEnumArg : $@convention(thin) (@in TrivialMoveOnlyEnum) -> () {
// CHECK: bb0([[ARG:%.*]] : $*TrivialMoveOnlyEnum):
// CHECK: [[FUNC:%.*]] = function_ref @$s4main19TrivialMoveOnlyEnumOfD
// CHECK: apply [[FUNC]]([[ARG]])
// CHECK: } // end sil function 'trivialMoveOnlyEnumArg'
sil [ossa] @trivialMoveOnlyEnumArg : $@convention(thin) (@in TrivialMoveOnlyEnum) -> () {
bb0(%0 : $*TrivialMoveOnlyEnum):
destroy_addr %0 : $*TrivialMoveOnlyEnum
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil [ossa] @nonTrivialMoveOnlyEnumAddrTest : $@convention(thin) (@in NonTrivialMoveOnlyEnum) -> () {
// CHECK: bb0([[ARG:%.*]] : $*NonTrivialMoveOnlyEnum):
// CHECK: [[FUNC:%.*]] = function_ref @$s4main22NonTrivialMoveOnlyEnumOfD :
// CHECK: apply [[FUNC]]([[ARG]])
// CHECK: } // end sil function 'nonTrivialMoveOnlyEnumAddrTest'
sil [ossa] @nonTrivialMoveOnlyEnumAddrTest : $@convention(thin) (@in NonTrivialMoveOnlyEnum) -> () {
bb0(%0 : $*NonTrivialMoveOnlyEnum):
destroy_addr %0 : $*NonTrivialMoveOnlyEnum
%9999 = tuple()
return %9999 : $()
}
//===----------------------------------------------------------------------===//
// Type Without Deinit
//===----------------------------------------------------------------------===//
// CHECK-LABEL: sil [ossa] @multiFieldNonTrivialNoDeinitTest : $@convention(thin) (@owned ThreeNonTrivialNoDeinit) -> () {
// CHECK: destroy_value
// CHECK: } // end sil function 'multiFieldNonTrivialNoDeinitTest'
sil [ossa] @multiFieldNonTrivialNoDeinitTest : $@convention(thin) (@owned ThreeNonTrivialNoDeinit) -> () {
bb0(%0 : @owned $ThreeNonTrivialNoDeinit):
destroy_value %0 : $ThreeNonTrivialNoDeinit
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil [ossa] @multiFieldNonTrivialNoDeinitAddrTest : $@convention(thin) (@in ThreeNonTrivialNoDeinit) -> () {
// CHECK: destroy_addr
// CHECK: } // end sil function 'multiFieldNonTrivialNoDeinitAddrTest'
sil [ossa] @multiFieldNonTrivialNoDeinitAddrTest : $@convention(thin) (@in ThreeNonTrivialNoDeinit) -> () {
bb0(%0 : $*ThreeNonTrivialNoDeinit):
destroy_addr %0 : $*ThreeNonTrivialNoDeinit
%9999 = tuple()
return %9999 : $()
}
//===----------------------------------------------------------------------===//
// Destructors
//===----------------------------------------------------------------------===//
sil hidden [ossa] @$s4main12StructDeinitVfD : $@convention(method) (@in StructDeinit) -> () {
bb0(%0 : $*StructDeinit):
debug_value %0 : $*StructDeinit, let, name "self", argno 1, implicit
%2 = drop_deinit %0 : $*StructDeinit
%3 = tuple ()
return %3 : $()
}
// CHECK-LABEL: sil hidden [ossa] @$s4main21SingleFieldNonTrivialVfD : $@convention(method) (@in SingleFieldNonTrivial) -> () {
// CHECK: bb0([[ARG:%.*]] : $*SingleFieldNonTrivial):
// CHECK: [[ADDR:%.*]] = struct_element_addr [[ARG]]
// CHECK: [[FUNC_REF:%.*]] = function_ref @$s4main5KlassCfD :
// CHECK: [[LOAD:%.*]] = load [take] [[ADDR]]
// CHECK: apply [[FUNC_REF]]([[LOAD]])
// CHECK: } // end sil function '$s4main21SingleFieldNonTrivialVfD'
sil hidden [ossa] @$s4main21SingleFieldNonTrivialVfD : $@convention(method) (@in SingleFieldNonTrivial) -> () {
bb0(%0 : $*SingleFieldNonTrivial):
debug_value %0 : $*SingleFieldNonTrivial, let, name "self", argno 1, implicit
%2 = struct_element_addr %0 : $*SingleFieldNonTrivial, #SingleFieldNonTrivial.k
destroy_addr %2 : $*Klass
%4 = tuple ()
return %4 : $()
}
// CHECK-LABEL: sil hidden [ossa] @$s4main15ThreeNonTrivialVfD : $@convention(method) (@in ThreeNonTrivial) -> () {
// CHECK: bb0([[ARG:%.*]] : $*ThreeNonTrivial):
// CHECK: [[LHS:%.*]] = struct_element_addr [[ARG]]
// CHECK: [[RHS:%.*]] = struct_element_addr [[ARG]]
// CHECK: [[FUNC_REF:%.*]] = function_ref @$s4main5KlassCfD :
// CHECK: [[LOAD_LHS:%.*]] = load [take] [[LHS]]
// CHECK: apply [[FUNC_REF]]([[LOAD_LHS]])
// CHECK: [[FUNC_REF:%.*]] = function_ref @$s4main5KlassCfD :
// CHECK: [[LOAD_RHS:%.*]] = load [take] [[RHS]]
// CHECK: apply [[FUNC_REF]]([[LOAD_RHS]])
// CHECK: } // end sil function '$s4main15ThreeNonTrivialVfD'
sil hidden [ossa] @$s4main15ThreeNonTrivialVfD : $@convention(method) (@in ThreeNonTrivial) -> () {
bb0(%0 : $*ThreeNonTrivial):
debug_value %0 : $*ThreeNonTrivial, let, name "self", argno 1, implicit
%2 = struct_element_addr %0 : $*ThreeNonTrivial, #ThreeNonTrivial.k
%3 = struct_element_addr %0 : $*ThreeNonTrivial, #ThreeNonTrivial.k2
destroy_addr %2 : $*Klass
destroy_addr %3 : $*Klass
%7 = tuple ()
return %7 : $()
}
sil hidden [ossa] @$s4main19TrivialMoveOnlyEnumOfD : $@convention(method) (@in TrivialMoveOnlyEnum) -> () {
bb0(%0 : $*TrivialMoveOnlyEnum):
debug_value %0 : $*TrivialMoveOnlyEnum, let, name "self", argno 1, implicit
switch_enum_addr %0 : $*TrivialMoveOnlyEnum, case #TrivialMoveOnlyEnum.first!enumelt: bb1, case #TrivialMoveOnlyEnum.second!enumelt: bb2, case #TrivialMoveOnlyEnum.third!enumelt: bb3
bb1:
br bb4
bb2:
br bb4
bb3:
br bb4
bb4:
%8 = tuple ()
return %8 : $()
}
// CHECK-LABEL: sil hidden [ossa] @$s4main22NonTrivialMoveOnlyEnumOfD : $@convention(method) (@in NonTrivialMoveOnlyEnum) -> () {
// CHECK: bb0([[ARG:%.*]] : $*
// CHECK: bb5:
// CHECK: [[ADDR:%.*]] = unchecked_take_enum_data_addr [[ARG]]
// CHECK: [[FUNC_REF:%.*]] = function_ref @$s4main19TrivialMoveOnlyEnumOfD : $@convention(method) (@in TrivialMoveOnlyEnum) -> ()
// CHECK: apply [[FUNC_REF]]([[ADDR]])
// CHECK: } // end sil function '$s4main22NonTrivialMoveOnlyEnumOfD'
sil hidden [ossa] @$s4main22NonTrivialMoveOnlyEnumOfD : $@convention(method) (@in NonTrivialMoveOnlyEnum) -> () {
bb0(%0 : $*NonTrivialMoveOnlyEnum):
debug_value %0 : $*NonTrivialMoveOnlyEnum, let, name "self", argno 1, implicit
switch_enum_addr %0 : $*NonTrivialMoveOnlyEnum, case #NonTrivialMoveOnlyEnum.first!enumelt: bb1, case #NonTrivialMoveOnlyEnum.second!enumelt: bb2, case #NonTrivialMoveOnlyEnum.third!enumelt: bb3, case #NonTrivialMoveOnlyEnum.fourth!enumelt: bb4, case #NonTrivialMoveOnlyEnum.fifth!enumelt: bb5
bb1:
br bb6
bb2:
br bb6
bb3:
%6 = unchecked_take_enum_data_addr %0 : $*NonTrivialMoveOnlyEnum, #NonTrivialMoveOnlyEnum.third
destroy_addr %6 : $*(Klass, Klass)
br bb6
bb4:
br bb6
bb5:
%11 = unchecked_take_enum_data_addr %0 : $*NonTrivialMoveOnlyEnum, #NonTrivialMoveOnlyEnum.fifth
destroy_addr %11 : $*TrivialMoveOnlyEnum
br bb6
bb6:
%14 = tuple ()
return %14 : $()
}
//===----------------------------------------------------------------------===//
// drop_deinit Tests
//===----------------------------------------------------------------------===//
// CHECK-LABEL: sil [ossa] @dropDeinitOnStruct : $@convention(thin) (@owned StructDeinit) -> () {
// CHECK: %1 = drop_deinit %0
// CHECK-NEXT: destroy_value %1
// CHECK: } // end sil function 'dropDeinitOnStruct'
sil [ossa] @dropDeinitOnStruct : $@convention(thin) (@owned StructDeinit) -> () {
bb0(%0 : @owned $StructDeinit):
%1 = drop_deinit %0 : $StructDeinit
destroy_value %1 : $StructDeinit
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil [ossa] @dropDeinitOnMovedStruct : $@convention(thin) (@owned StructDeinit) -> () {
// CHECK: %1 = drop_deinit %0
// CHECK-NEXT: %2 = move_value %1
// CHECK-NEXT: destroy_value %2
// CHECK: } // end sil function 'dropDeinitOnMovedStruct'
sil [ossa] @dropDeinitOnMovedStruct : $@convention(thin) (@owned StructDeinit) -> () {
bb0(%0 : @owned $StructDeinit):
%1 = drop_deinit %0 : $StructDeinit
%2 = move_value %1 : $StructDeinit
destroy_value %2 : $StructDeinit
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil [ossa] @dropDeinitOnIndirectStruct : $@convention(thin) (@in StructDeinit) -> () {
// CHECK: %1 = drop_deinit %0
// CHECK-NEXT: destroy_addr %1
// CHECK: } // end sil function 'dropDeinitOnIndirectStruct'
sil [ossa] @dropDeinitOnIndirectStruct : $@convention(thin) (@in StructDeinit) -> () {
bb0(%0 : $*StructDeinit):
%1 = drop_deinit %0 : $*StructDeinit
destroy_addr %1 : $*StructDeinit
%9999 = tuple()
return %9999 : $()
}
sil @$s4main5KlassCfD : $@convention(method) (@owned Klass) -> ()
sil @$s4main5KlassCACycfc : $@convention(method) (@owned Klass) -> @owned Klass
sil @$s4main5KlassCfd : $@convention(method) (@guaranteed Klass) -> @owned Builtin.NativeObject
sil_moveonlydeinit Klass {
@$s4main5KlassCfD
}
sil_moveonlydeinit StructDeinit {
@$s4main12StructDeinitVfD // StructDeinit.deinit
}
sil_moveonlydeinit SingleFieldNonTrivial {
@$s4main21SingleFieldNonTrivialVfD // SingleFieldNonTrivial.deinit
}
sil_moveonlydeinit ThreeNonTrivial {
@$s4main15ThreeNonTrivialVfD // ThreeNonTrivial.deinit
}
sil_vtable Klass {
#Klass.deinit!deallocator: @$s4main5KlassCfD // Klass.__deallocating_deinit
}
sil_moveonlydeinit TrivialMoveOnlyEnum {
@$s4main19TrivialMoveOnlyEnumOfD
}
sil_moveonlydeinit NonTrivialMoveOnlyEnum {
@$s4main22NonTrivialMoveOnlyEnumOfD
}