blob: 06bcbd72372adc79eda86fbe299c434c1825c32c [file] [log] [blame]
// RUN: %target-sil-opt -enable-sil-verify-all %s -release-devirtualizer -module-name=test | FileCheck %s
sil_stage canonical
import Builtin
import Swift
class B {
}
// CHECK-LABEL: sil @devirtualize_object
// CHECK: [[A:%[0-9]+]] = alloc_ref
// CHECK-NEXT: set_deallocating [[A]]
// CHECK-NOT: strong_release
// CHECK: [[D:%[0-9]+]] = function_ref @_TFC4test1BD
// CHECK-NEXT: apply [[D]]([[A]])
// CHECK-NEXT: dealloc_ref [stack] [[A]]
// CHECK: return
sil @devirtualize_object : $@convention(thin) () -> () {
bb0:
%1 = alloc_ref [stack] $B
strong_release %1 : $B
dealloc_ref [stack] %1 : $B
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_devirtualize_heap_allocated
// CHECK: alloc_ref
// CHECK-NEXT: strong_release
// CHECK-NEXT: dealloc_ref
// CHECK: return
sil @dont_devirtualize_heap_allocated : $@convention(thin) () -> () {
bb0:
%1 = alloc_ref $B
strong_release %1 : $B
dealloc_ref %1 : $B
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_devirtualize_wrong_release
// CHECK: alloc_ref
// CHECK-NEXT: strong_release
// CHECK-NEXT: strong_release
// CHECK-NEXT: dealloc_ref
// CHECK: return
sil @dont_devirtualize_wrong_release : $@convention(thin) (@owned B) -> () {
bb0(%0 : $B):
%1 = alloc_ref $B
strong_release %1 : $B
strong_release %0 : $B
dealloc_ref %1 : $B
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_devirtualize_unknown_release
// CHECK: alloc_ref
// CHECK-NEXT: strong_release
// CHECK: [[F:%[0-9]+]] = function_ref @unknown_func
// CHECK-NEXT: apply [[F]]()
// CHECK-NEXT: dealloc_ref
// CHECK: return
sil @dont_devirtualize_unknown_release : $@convention(thin) (@owned B) -> () {
bb0(%0 : $B):
%1 = alloc_ref $B
strong_release %1 : $B
%f = function_ref @unknown_func : $@convention(thin) () -> ()
%a = apply %f() : $@convention(thin) () -> ()
dealloc_ref %1 : $B
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_crash_with_missing_release
// CHECK: [[A:%[0-9]+]] = alloc_ref
// CHECK-NEXT: set_deallocating [[A]]
// CHECK-NOT: strong_release
// CHECK: [[D:%[0-9]+]] = function_ref @_TFC4test1BD
// CHECK-NEXT: apply [[D]]([[A]])
// CHECK-NEXT: dealloc_ref [stack] [[A]]
// CHECK: return
sil @dont_crash_with_missing_release : $@convention(thin) () -> () {
bb0:
%1 = alloc_ref [stack] $B
strong_release %1 : $B
dealloc_ref [stack] %1 : $B
%2 = alloc_ref [stack] $B
dealloc_ref [stack] %2 : $B
%r = tuple ()
return %r : $()
}
class MyArrayStorage<Element> {
}
struct WrongStorage {
}
// CHECK-LABEL: sil @devirtualize_buffer
// CHECK: [[A:%[0-9]+]] = function_ref @swift_bufferAllocateOnStack
// CHECK: [[B:%[0-9]+]] = apply [[A]]
// CHECK-NOT: strong_release
// CHECK: unchecked_ref_cast
// CHECK: [[C:%[0-9]+]] = unchecked_ref_cast [[B]]
// CHECK: set_deallocating [[C]]
// CHECK: [[D:%[0-9]+]] = function_ref @_TFC4test14MyArrayStorageD
// CHECK: apply [[D]]<Int64>([[C]])
// CHECK: [[X:%[0-9]+]] = function_ref @swift_bufferDeallocateFromStack
// CHECK: apply [[X]]([[B]])
// CHECK: return
sil @devirtualize_buffer : $@convention(thin) () -> () {
bb0:
%3 = integer_literal $Builtin.Int64, 7
%4 = struct $Int64 (%3 : $Builtin.Int64)
%mt = metatype $@thick MyArrayStorage<Int64>.Type // user: %5
%5 = init_existential_metatype %mt : $@thick MyArrayStorage<Int64>.Type, $@thick AnyObject.Type
%66 = function_ref @swift_bufferAllocateOnStack : $@convention(thin) (@thick AnyObject.Type, Int64, Int64) -> @owned AnyObject
%67 = apply %66(%5, %4, %4) : $@convention(thin) (@thick AnyObject.Type, Int64, Int64) -> @owned AnyObject
%95 = unchecked_ref_cast %67 : $AnyObject to $Builtin.BridgeObject
strong_release %95 : $Builtin.BridgeObject
%119 = function_ref @swift_bufferDeallocateFromStack : $@convention(thin) (@guaranteed AnyObject) -> @owned ()
%120 = apply %119(%67) : $@convention(thin) (@guaranteed AnyObject) -> @owned ()
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_devirtualize_buffer_with_unknown_release
// CHECK: function_ref @swift_bufferAllocateOnStack
// CHECK-NEXT: apply
// CHECK-NOT: apply
// CHECK: strong_release
// CHECK-NEXT: strong_release
// CHECK-NOT: apply
// CHECK: function_ref @swift_bufferDeallocateFromStack
// CHECK-NEXT: apply
// CHECK: return
sil @dont_devirtualize_buffer_with_unknown_release : $@convention(thin) (@owned Builtin.BridgeObject) -> () {
bb0(%0 : $Builtin.BridgeObject):
%3 = integer_literal $Builtin.Int64, 7
%4 = struct $Int64 (%3 : $Builtin.Int64)
%mt = metatype $@thick MyArrayStorage<Int64>.Type // user: %5
%5 = init_existential_metatype %mt : $@thick MyArrayStorage<Int64>.Type, $@thick AnyObject.Type
%66 = function_ref @swift_bufferAllocateOnStack : $@convention(thin) (@thick AnyObject.Type, Int64, Int64) -> @owned AnyObject
%67 = apply %66(%5, %4, %4) : $@convention(thin) (@thick AnyObject.Type, Int64, Int64) -> @owned AnyObject
%95 = unchecked_ref_cast %67 : $AnyObject to $Builtin.BridgeObject
strong_release %95 : $Builtin.BridgeObject
strong_release %0 : $Builtin.BridgeObject
%119 = function_ref @swift_bufferDeallocateFromStack : $@convention(thin) (@guaranteed AnyObject) -> @owned ()
%120 = apply %119(%67) : $@convention(thin) (@guaranteed AnyObject) -> @owned ()
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_devirtualize_buffer_with_unknown_allocation
// CHECK: function_ref @swift_bufferAllocate
// CHECK-NEXT: apply
// CHECK-NOT: apply
// CHECK: strong_release
// CHECK-NOT: apply
// CHECK: function_ref @swift_bufferDeallocateFromStack
// CHECK-NEXT: apply
// CHECK: return
sil @dont_devirtualize_buffer_with_unknown_allocation : $@convention(thin) () -> () {
bb0:
%3 = integer_literal $Builtin.Int64, 7
%4 = struct $Int64 (%3 : $Builtin.Int64)
%mt = metatype $@thick MyArrayStorage<Int64>.Type // user: %5
%5 = init_existential_metatype %mt : $@thick MyArrayStorage<Int64>.Type, $@thick AnyObject.Type
%66 = function_ref @swift_bufferAllocate: $@convention(thin) (@thick AnyObject.Type, Int64, Int64) -> @owned AnyObject
%67 = apply %66(%5, %4, %4) : $@convention(thin) (@thick AnyObject.Type, Int64, Int64) -> @owned AnyObject
%95 = unchecked_ref_cast %67 : $AnyObject to $Builtin.BridgeObject
strong_release %95 : $Builtin.BridgeObject
%119 = function_ref @swift_bufferDeallocateFromStack : $@convention(thin) (@guaranteed AnyObject) -> @owned ()
%120 = apply %119(%67) : $@convention(thin) (@guaranteed AnyObject) -> @owned ()
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_devirtualize_buffer_with_unknown_metatype
// CHECK: function_ref @swift_bufferAllocateOnStack
// CHECK-NEXT: apply
// CHECK-NOT: apply
// CHECK: strong_release
// CHECK-NOT: apply
// CHECK: function_ref @swift_bufferDeallocateFromStack
// CHECK-NEXT: apply
// CHECK: return
sil @dont_devirtualize_buffer_with_unknown_metatype : $@convention(thin) (@thick AnyObject.Type) -> () {
bb0(%0 : $@thick AnyObject.Type):
%3 = integer_literal $Builtin.Int64, 7
%4 = struct $Int64 (%3 : $Builtin.Int64)
%66 = function_ref @swift_bufferAllocateOnStack: $@convention(thin) (@thick AnyObject.Type, Int64, Int64) -> @owned AnyObject
%67 = apply %66(%0, %4, %4) : $@convention(thin) (@thick AnyObject.Type, Int64, Int64) -> @owned AnyObject
%95 = unchecked_ref_cast %67 : $AnyObject to $Builtin.BridgeObject
strong_release %95 : $Builtin.BridgeObject
%119 = function_ref @swift_bufferDeallocateFromStack : $@convention(thin) (@guaranteed AnyObject) -> @owned ()
%120 = apply %119(%67) : $@convention(thin) (@guaranteed AnyObject) -> @owned ()
%r = tuple ()
return %r : $()
}
// CHECK-LABEL: sil @dont_devirtualize_buffer_with_wrong_metatype
// CHECK: function_ref @swift_bufferAllocateOnStack
// CHECK-NEXT: apply
// CHECK-NOT: apply
// CHECK: strong_release
// CHECK-NOT: apply
// CHECK: function_ref @swift_bufferDeallocateFromStack
// CHECK-NEXT: apply
// CHECK: return
sil @dont_devirtualize_buffer_with_wrong_metatype : $@convention(thin) () -> () {
bb0:
%3 = integer_literal $Builtin.Int64, 7
%4 = struct $Int64 (%3 : $Builtin.Int64)
%mt = metatype $@thick WrongStorage.Type // user: %5
%5 = init_existential_metatype %mt : $@thick WrongStorage.Type, $@thick AnyObject.Type
%66 = function_ref @swift_bufferAllocateOnStack : $@convention(thin) (@thick AnyObject.Type, Int64, Int64) -> @owned AnyObject
%67 = apply %66(%5, %4, %4) : $@convention(thin) (@thick AnyObject.Type, Int64, Int64) -> @owned AnyObject
%95 = unchecked_ref_cast %67 : $AnyObject to $Builtin.BridgeObject
strong_release %95 : $Builtin.BridgeObject
%119 = function_ref @swift_bufferDeallocateFromStack : $@convention(thin) (@guaranteed AnyObject) -> @owned ()
%120 = apply %119(%67) : $@convention(thin) (@guaranteed AnyObject) -> @owned ()
%r = tuple ()
return %r : $()
}
sil hidden_external @swift_bufferAllocate : $@convention(thin) (@thick AnyObject.Type, Int64, Int64) -> @owned AnyObject
sil hidden_external @swift_bufferAllocateOnStack : $@convention(thin) (@thick AnyObject.Type, Int64, Int64) -> @owned AnyObject
sil hidden_external @swift_bufferDeallocateFromStack : $@convention(thin) (@guaranteed AnyObject) -> @owned ()
sil @unknown_func : $@convention(thin) () -> ()
// test.B.__deallocating_deinit
sil hidden @_TFC4test1BD : $@convention(method) (@owned B) -> () {
// %0 // users: %1, %3
bb0(%0 : $B):
debug_value %0 : $B, let, name "self" // id: %1
// function_ref test.B.deinit
%2 = function_ref @_TFC4test1Bd : $@convention(method) (@guaranteed B) -> @owned Builtin.NativeObject // user: %3
%3 = apply %2(%0) : $@convention(method) (@guaranteed B) -> @owned Builtin.NativeObject // user: %4
%4 = unchecked_ref_cast %3 : $Builtin.NativeObject to $B // user: %5
dealloc_ref %4 : $B // id: %5
%6 = tuple () // user: %7
return %6 : $() // id: %7
}
// test.B.deinit
sil hidden @_TFC4test1Bd : $@convention(method) (@guaranteed B) -> @owned Builtin.NativeObject {
// %0 // users: %1, %2
bb0(%0 : $B):
debug_value %0 : $B, let, name "self" // id: %1
%2 = unchecked_ref_cast %0 : $B to $Builtin.NativeObject // user: %3
return %2 : $Builtin.NativeObject // id: %3
}
// test.B.init () -> test.B
sil hidden @_TFC4test1BcfT_S0_ : $@convention(method) (@owned B) -> @owned B {
// %0 // users: %1, %2
bb0(%0 : $B):
debug_value %0 : $B, let, name "self" // id: %1
return %0 : $B // id: %2
}
sil_vtable B {
#B.deinit!deallocator: _TFC4test1BD // test.B.__deallocating_deinit
#B.init!initializer.1: _TFC4test1BcfT_S0_ // test.B.init () -> test.B
}
// test.MyArrayStorage.__deallocating_deinit
sil hidden @_TFC4test14MyArrayStorageD : $@convention(method) <Element> (@owned MyArrayStorage<Element>) -> () {
// %0 // users: %1, %3
bb0(%0 : $MyArrayStorage<Element>):
debug_value %0 : $MyArrayStorage<Element>, let, name "self" // id: %1
// function_ref test.MyArrayStorage.deinit
%2 = function_ref @_TFC4test14MyArrayStoraged : $@convention(method) _0_0> (@guaranteed MyArrayStorage_0_0>) -> @owned Builtin.NativeObject // user: %3
%3 = apply %2<Element>(%0) : $@convention(method) _0_0> (@guaranteed MyArrayStorage_0_0>) -> @owned Builtin.NativeObject // user: %4
%4 = unchecked_ref_cast %3 : $Builtin.NativeObject to $MyArrayStorage<Element> // user: %5
dealloc_ref %4 : $MyArrayStorage<Element> // id: %5
%6 = tuple () // user: %7
return %6 : $() // id: %7
}
// test.MyArrayStorage.deinit
sil hidden @_TFC4test14MyArrayStoraged : $@convention(method) <Element> (@guaranteed MyArrayStorage<Element>) -> @owned Builtin.NativeObject {
// %0 // users: %1, %2
bb0(%0 : $MyArrayStorage<Element>):
debug_value %0 : $MyArrayStorage<Element>, let, name "self" // id: %1
%2 = unchecked_ref_cast %0 : $MyArrayStorage<Element> to $Builtin.NativeObject // user: %3
return %2 : $Builtin.NativeObject // id: %3
}
// test.MyArrayStorage.init () -> test.MyArrayStorage<A>
sil hidden @_TFC4test14MyArrayStoragecfT_GS0_x_ : $@convention(method) <Element> (@owned MyArrayStorage<Element>) -> @owned MyArrayStorage<Element> {
// %0 // users: %1, %2
bb0(%0 : $MyArrayStorage<Element>):
debug_value %0 : $MyArrayStorage<Element>, let, name "self" // id: %1
return %0 : $MyArrayStorage<Element> // id: %2
}
sil_vtable MyArrayStorage {
#MyArrayStorage.deinit!deallocator: _TFC4test14MyArrayStorageD // test.MyArrayStorage.__deallocating_deinit
#MyArrayStorage.init!initializer.1: _TFC4test14MyArrayStoragecfT_GS0_x_ // test.MyArrayStorage.init () -> test.MyArrayStorage<A>
}