mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
306 lines
13 KiB
Plaintext
306 lines
13 KiB
Plaintext
// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %s --check-prefix=CHECK --check-prefix=NO-LIBRARY-EVOLUTION
|
|
// RUN: %target-swift-frontend -enable-library-evolution -emit-ir %s | %FileCheck %s --check-prefix=CHECK --check-prefix=LIBRARY-EVOLUTION
|
|
|
|
sil_stage canonical
|
|
|
|
class InternalA {
|
|
init()
|
|
func foo()
|
|
func bar()
|
|
func bas()
|
|
}
|
|
|
|
sil @InternalA_foo : $@convention(method) (@guaranteed InternalA) -> ()
|
|
sil @InternalA_bar : $@convention(method) (@guaranteed InternalA) -> ()
|
|
sil @InternalA_bas : $@convention(method) (@guaranteed InternalA) -> ()
|
|
sil @InternalA_init : $@convention(method) (@thick InternalA.Type) -> @owned InternalA
|
|
sil @InternalA_dealloc : $@convention(method) (@owned InternalA) -> ()
|
|
|
|
sil_vtable InternalA {
|
|
#InternalA.deinit!deallocator : @InternalA_dealloc
|
|
#InternalA.init!allocator : @InternalA_init
|
|
#InternalA.foo : @InternalA_foo [nonoverridden]
|
|
#InternalA.bar : @InternalA_bar
|
|
#InternalA.bas : @InternalA_bas [nonoverridden]
|
|
}
|
|
|
|
// -- we should still generate method descriptors for the elided methods
|
|
// CHECK-LABEL: @"$s21vtable_non_overridden9InternalAC3fooyyFTq" = hidden constant %swift.method_descriptor {{.*}} section "{{(__TEXT,__const|\.rodata|\.rdata)}}"
|
|
// CHECK-LABEL: @"$s21vtable_non_overridden9InternalAC3basyyFTq" = hidden constant %swift.method_descriptor {{.*}} section "{{(__TEXT,__const|\.rodata|\.rdata)}}"
|
|
|
|
// -- only overridden entries in internal method descriptor table
|
|
// CHECK-LABEL: @"$s21vtable_non_overridden9InternalACMn" =
|
|
// CHECK-SAME: i32 2, %swift.method_descriptor
|
|
// CHECK-SAME: @InternalA_init
|
|
// CHECK-NOT: @InternalA_foo
|
|
// CHECK-SAME: @InternalA_bar
|
|
// CHECK-NOT: @InternalA_bas
|
|
|
|
// -- only overridden entries in internal vtable
|
|
// CHECK-LABEL: @"$s21vtable_non_overridden9InternalACMf" =
|
|
// CHECK-SAME: @InternalA_init
|
|
// CHECK-NOT: @InternalA_foo
|
|
// CHECK-SAME: @InternalA_bar
|
|
// CHECK-NOT: @InternalA_bas
|
|
|
|
sil @InternalB_bar : $@convention(method) (@guaranteed InternalB) -> ()
|
|
sil @InternalB_init : $@convention(method) (@thick InternalB.Type) -> @owned InternalB
|
|
sil @InternalB_dealloc : $@convention(method) (@owned InternalB) -> ()
|
|
|
|
class InternalB: InternalA {
|
|
override func bar()
|
|
}
|
|
|
|
sil_vtable InternalB {
|
|
#InternalB.deinit!deallocator : @InternalB_dealloc
|
|
#InternalA.init!allocator : @InternalB_init [override]
|
|
#InternalA.foo : @InternalA_foo [inherited] [nonoverridden]
|
|
#InternalA.bar : @InternalB_bar [override]
|
|
#InternalA.bas : @InternalA_bas [inherited] [nonoverridden]
|
|
}
|
|
|
|
// -- only overridden entries in internal method descriptor table
|
|
// CHECK-LABEL: @"$s21vtable_non_overridden9InternalBCMn" =
|
|
// CHECK-SAME: i32 2, %swift.method_override_descriptor
|
|
// CHECK-NOT: @InternalA_foo
|
|
// CHECK-SAME: @InternalB_bar
|
|
// CHECK-NOT: @InternalA_bas
|
|
// CHECK-SAME: @InternalB_init
|
|
|
|
// -- only overridden entries in internal vtable
|
|
// CHECK-LABEL: @"$s21vtable_non_overridden9InternalBCMf" =
|
|
// CHECK-SAME: @InternalB_init
|
|
// CHECK-NOT: @InternalA_foo
|
|
// CHECK-SAME: @InternalB_bar
|
|
// CHECK-NOT: @InternalA_bas
|
|
// CHECK-SAME: {{$}}
|
|
|
|
@_fixed_layout
|
|
public class PublicFragileA {
|
|
init()
|
|
func foo()
|
|
func bar()
|
|
func bas()
|
|
}
|
|
|
|
sil @PublicFragileA_foo : $@convention(method) (@guaranteed PublicFragileA) -> ()
|
|
sil @PublicFragileA_bar : $@convention(method) (@guaranteed PublicFragileA) -> ()
|
|
sil @PublicFragileA_bas : $@convention(method) (@guaranteed PublicFragileA) -> ()
|
|
sil @PublicFragileA_init : $@convention(method) (@thick PublicFragileA.Type) -> @owned PublicFragileA
|
|
sil @PublicFragileA_dealloc : $@convention(method) (@owned PublicFragileA) -> ()
|
|
|
|
sil_vtable PublicFragileA {
|
|
#PublicFragileA.deinit!deallocator : @PublicFragileA_dealloc
|
|
#PublicFragileA.init!allocator : @PublicFragileA_init
|
|
#PublicFragileA.foo : @PublicFragileA_foo [nonoverridden]
|
|
#PublicFragileA.bar : @PublicFragileA_bar
|
|
#PublicFragileA.bas : @PublicFragileA_bas [nonoverridden]
|
|
}
|
|
|
|
// -- all entries should be preserved in public fragile method descriptor table
|
|
// CHECK-LABEL: @"$s21vtable_non_overridden14PublicFragileACMn" =
|
|
// CHECK-SAME: i32 4, %swift.method_descriptor
|
|
// CHECK-SAME: @PublicFragileA_init
|
|
// CHECK-SAME: @PublicFragileA_foo
|
|
// CHECK-SAME: @PublicFragileA_bar
|
|
// CHECK-SAME: @PublicFragileA_bas
|
|
|
|
// -- all entries should be preserved in public fragile vtable
|
|
// CHECK-LABEL: @"$s21vtable_non_overridden14PublicFragileACMf" =
|
|
// CHECK-SAME: @PublicFragileA_init
|
|
// CHECK-SAME: @PublicFragileA_foo
|
|
// CHECK-SAME: @PublicFragileA_bar
|
|
// CHECK-SAME: @PublicFragileA_bas
|
|
|
|
sil @PublicFragileB_bar : $@convention(method) (@guaranteed PublicFragileB) -> ()
|
|
sil @PublicFragileB_init : $@convention(method) (@thick PublicFragileB.Type) -> @owned PublicFragileB
|
|
sil @PublicFragileB_dealloc : $@convention(method) (@owned PublicFragileB) -> ()
|
|
|
|
@_fixed_layout
|
|
public class PublicFragileB: PublicFragileA {
|
|
override func bar()
|
|
}
|
|
|
|
sil_vtable PublicFragileB {
|
|
#PublicFragileB.deinit!deallocator : @PublicFragileB_dealloc
|
|
#PublicFragileA.init!allocator : @PublicFragileB_init [override]
|
|
#PublicFragileA.foo : @PublicFragileA_foo [inherited] [nonoverridden]
|
|
#PublicFragileA.bar : @PublicFragileB_bar [override]
|
|
#PublicFragileA.bas : @PublicFragileA_bas [inherited] [nonoverridden]
|
|
}
|
|
|
|
// -- all entries should be preserved in public fragile method descriptor table
|
|
// CHECK-LABEL: @"$s21vtable_non_overridden14PublicFragileBCMn" =
|
|
// CHECK-SAME: i32 2, %swift.method_override_descriptor
|
|
// CHECK-SAME: @PublicFragileB_bar
|
|
// CHECK-SAME: @PublicFragileB_init
|
|
|
|
// -- all entries should be preserved in public fragile vtable
|
|
// CHECK-LABEL: @"$s21vtable_non_overridden14PublicFragileBCMf" =
|
|
// CHECK-SAME: @PublicFragileB_init
|
|
// CHECK-SAME: @PublicFragileA_foo
|
|
// CHECK-SAME: @PublicFragileB_bar
|
|
// CHECK-SAME: @PublicFragileA_bas
|
|
|
|
sil @PublicResilientSubclassOfFragile_bar : $@convention(method) (@guaranteed PublicResilientSubclassOfFragile) -> ()
|
|
sil @PublicResilientSubclassOfFragile_init : $@convention(method) (@thick PublicResilientSubclassOfFragile.Type) -> @owned PublicResilientSubclassOfFragile
|
|
sil @PublicResilientSubclassOfFragile_dealloc : $@convention(method) (@owned PublicResilientSubclassOfFragile) -> ()
|
|
|
|
public class PublicResilientSubclassOfFragile: PublicFragileA {
|
|
override func bar()
|
|
}
|
|
|
|
sil_vtable PublicResilientSubclassOfFragile {
|
|
#PublicResilientSubclassOfFragile.deinit!deallocator : @PublicResilientSubclassOfFragile_dealloc
|
|
#PublicFragileA.init!allocator : @PublicResilientSubclassOfFragile_init [override]
|
|
#PublicFragileA.foo : @PublicFragileA_foo [inherited] [nonoverridden]
|
|
#PublicFragileA.bar : @PublicResilientSubclassOfFragile_bar [override]
|
|
#PublicFragileA.bas : @PublicFragileA_bas [inherited] [nonoverridden]
|
|
}
|
|
|
|
// -- all entries from fragile base class should be preserved in public method descriptor table
|
|
// CHECK-LABEL: @"$s21vtable_non_overridden32PublicResilientSubclassOfFragileCMn" =
|
|
// CHECK-SAME: i32 2, %swift.method_override_descriptor
|
|
// CHECK-SAME: @PublicResilientSubclassOfFragile_bar
|
|
// CHECK-SAME: @PublicResilientSubclassOfFragile_init
|
|
|
|
// -- all entries from fragile base class should be preserved in public vtable
|
|
// CHECK-LABEL: @"$s21vtable_non_overridden32PublicResilientSubclassOfFragileCMf" =
|
|
// CHECK-SAME: @PublicResilientSubclassOfFragile_init
|
|
// CHECK-SAME: @PublicFragileA_foo
|
|
// CHECK-SAME: @PublicResilientSubclassOfFragile_bar
|
|
// CHECK-SAME: @PublicFragileA_bas
|
|
|
|
public class PublicA {
|
|
init()
|
|
public func foo()
|
|
public func bar()
|
|
func bas()
|
|
}
|
|
|
|
sil @PublicA_foo : $@convention(method) (@guaranteed PublicA) -> ()
|
|
sil @PublicA_bar : $@convention(method) (@guaranteed PublicA) -> ()
|
|
sil @PublicA_bas : $@convention(method) (@guaranteed PublicA) -> ()
|
|
sil @PublicA_init : $@convention(method) (@thick PublicA.Type) -> @owned PublicA
|
|
sil @PublicA_dealloc : $@convention(method) (@owned PublicA) -> ()
|
|
|
|
sil_vtable PublicA {
|
|
#PublicA.deinit!deallocator : @PublicA_dealloc
|
|
#PublicA.init!allocator : @PublicA_init
|
|
#PublicA.foo : @PublicA_foo [nonoverridden]
|
|
#PublicA.bar : @PublicA_bar
|
|
#PublicA.bas : @PublicA_bas [nonoverridden]
|
|
}
|
|
|
|
// -- nonoverridden entries can be dropped in resilient method descriptor table
|
|
// LIBRARY-EVOLUTION-LABEL: @"$s21vtable_non_overridden7PublicACMn" =
|
|
// LIBRARY-EVOLUTION-SAME: i32 2, %swift.method_descriptor
|
|
// LIBRARY-EVOLUTION-SAME: @PublicA_init
|
|
// LIBRARY-EVOLUTION-NOT: @PublicA_foo
|
|
// LIBRARY-EVOLUTION-SAME: @PublicA_bar
|
|
// LIBRARY-EVOLUTION-NOT: @PublicA_bas
|
|
|
|
// -- nonoverridden entries can be dropped in resilient method descriptor table
|
|
// LIBRARY-EVOLUTION-LABEL: @"$s21vtable_non_overridden7PublicACMf" =
|
|
// LIBRARY-EVOLUTION-SAME: @PublicA_init
|
|
// LIBRARY-EVOLUTION-NOT: @PublicA_foo
|
|
// LIBRARY-EVOLUTION-SAME: @PublicA_bar
|
|
// LIBRARY-EVOLUTION-NOT: @PublicA_bas
|
|
// LIBRARY-EVOLUTION-SAME: {{$}}
|
|
|
|
// -- with library evolution disabled, treat the vtable as fragile
|
|
|
|
// NO-LIBRARY-EVOLUTION-LABEL: @"$s21vtable_non_overridden7PublicACMn" =
|
|
// NO-LIBRARY-EVOLUTION-SAME: i32 4, %swift.method_descriptor
|
|
// NO-LIBRARY-EVOLUTION-SAME: @PublicA_init
|
|
// NO-LIBRARY-EVOLUTION-SAME: @PublicA_foo
|
|
// NO-LIBRARY-EVOLUTION-SAME: @PublicA_bar
|
|
// NO-LIBRARY-EVOLUTION-SAME: @PublicA_bas
|
|
|
|
// NO-LIBRARY-EVOLUTION-LABEL: @"$s21vtable_non_overridden7PublicACMf" =
|
|
// NO-LIBRARY-EVOLUTION-SAME: @PublicA_init
|
|
// NO-LIBRARY-EVOLUTION-SAME: @PublicA_foo
|
|
// NO-LIBRARY-EVOLUTION-SAME: @PublicA_bar
|
|
// NO-LIBRARY-EVOLUTION-SAME: @PublicA_bas
|
|
|
|
sil @PublicB_bar : $@convention(method) (@guaranteed PublicB) -> ()
|
|
sil @PublicB_init : $@convention(method) (@thick PublicB.Type) -> @owned PublicB
|
|
sil @PublicB_dealloc : $@convention(method) (@owned PublicB) -> ()
|
|
|
|
class PublicB: PublicA {
|
|
override func bar()
|
|
}
|
|
|
|
sil_vtable PublicB {
|
|
#PublicB.deinit!deallocator : @PublicB_dealloc
|
|
#PublicA.init!allocator : @PublicB_init [override]
|
|
#PublicA.foo : @PublicA_foo [inherited] [nonoverridden]
|
|
#PublicA.bar : @PublicB_bar [override]
|
|
#PublicA.bas : @PublicA_bas [inherited] [nonoverridden]
|
|
}
|
|
|
|
// -- nonoverridden entries can be dropped in resilient method descriptor table
|
|
// LIBRARY-EVOLUTION-LABEL: @"$s21vtable_non_overridden7PublicBCMn" =
|
|
// LIBRARY-EVOLUTION-SAME: i32 2, %swift.method_override_descriptor
|
|
// LIBRARY-EVOLUTION-NOT: @PublicA_foo
|
|
// LIBRARY-EVOLUTION-SAME: @PublicB_bar
|
|
// LIBRARY-EVOLUTION-NOT: @PublicA_bas
|
|
// LIBRARY-EVOLUTION-SAME: @PublicB_init
|
|
|
|
// -- nonoverridden entries can be dropped in resilient method descriptor table
|
|
// LIBRARY-EVOLUTION-LABEL: @"$s21vtable_non_overridden7PublicBCMf" =
|
|
// LIBRARY-EVOLUTION-SAME: @PublicB_init
|
|
// LIBRARY-EVOLUTION-NOT: @PublicA_foo
|
|
// LIBRARY-EVOLUTION-SAME: @PublicB_bar
|
|
// LIBRARY-EVOLUTION-NOT: @PublicA_bas
|
|
// LIBRARY-EVOLUTION-SAME: {{$}}
|
|
|
|
// -- with library evolution disabled, treat the vtable as fragile
|
|
|
|
// NO-LIBRARY-EVOLUTION-LABEL: @"$s21vtable_non_overridden7PublicBCMn" =
|
|
// NO-LIBRARY-EVOLUTION-SAME: i32 2, %swift.method_override_descriptor
|
|
// NO-LIBRARY-EVOLUTION-SAME: @PublicB_bar
|
|
// NO-LIBRARY-EVOLUTION-SAME: @PublicB_init
|
|
|
|
// NO-LIBRARY-EVOLUTION-LABEL: @"$s21vtable_non_overridden7PublicBCMf" =
|
|
// NO-LIBRARY-EVOLUTION-SAME: @PublicB_init
|
|
// NO-LIBRARY-EVOLUTION-SAME: @PublicB_bar
|
|
|
|
// Ensure we still emit a method lookup function even if the vtable is
|
|
// completely optimized away.
|
|
sil @PublicOnlyNonoverridden_foo : $@convention(method) (@guaranteed PublicOnlyNonoverridden) -> ()
|
|
sil @PublicOnlyNonoverridden_init : $@convention(method) (@thick PublicOnlyNonoverridden.Type) -> @owned PublicOnlyNonoverridden
|
|
sil @PublicOnlyNonoverridden_dealloc : $@convention(method) (@owned PublicOnlyNonoverridden) -> ()
|
|
|
|
public class PublicOnlyNonoverridden {
|
|
public func foo()
|
|
}
|
|
|
|
sil_vtable PublicOnlyNonoverridden {
|
|
#PublicOnlyNonoverridden.deinit!deallocator : @PublicOnlyNonoverridden_dealloc
|
|
#PublicOnlyNonoverridden.init!allocator : @PublicOnlyNonoverridden_init [nonoverridden]
|
|
#PublicOnlyNonoverridden.foo : @PublicOnlyNonoverridden_foo [nonoverridden]
|
|
}
|
|
|
|
// Ensure that `class_method` lookups of nonoverridden vtable entries resolve
|
|
// to the one implementation instead of trying to load a nonexistent runtime
|
|
// vtable entry.
|
|
|
|
// CHECK-LABEL: define {{.*}}@non_overridable_invocation
|
|
sil @non_overridable_invocation : $@convention(thin) (@guaranteed InternalA, @guaranteed InternalB) -> () {
|
|
entry(%a : $InternalA, %b : $InternalB):
|
|
// CHECK: call swiftcc void @InternalA_foo
|
|
%am = class_method %a : $InternalA, #InternalA.foo, $@convention(method) (@guaranteed InternalA) -> ()
|
|
apply %am(%a) : $@convention(method) (@guaranteed InternalA) -> ()
|
|
|
|
// CHECK: call swiftcc void @InternalA_foo
|
|
%bm = class_method %b : $InternalB, #InternalA.foo, $@convention(method) (@guaranteed InternalA) -> ()
|
|
%ba = upcast %b : $InternalB to $InternalA
|
|
apply %bm(%ba) : $@convention(method) (@guaranteed InternalA) -> ()
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// LIBRARY-EVOLUTION-LABEL: define{{.*}}@"$s21vtable_non_overridden23PublicOnlyNonoverriddenCMu"
|
|
|