blob: 617e6dbc6ea38788851fcae2c50dc38f439c8887 [file] [log] [blame]
// 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"