| // 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> |
| } |
| |