Files
swift-mirror/test/SIL/OwnershipVerifier/load_borrow_invalidation_test.sil

491 lines
16 KiB
Plaintext

// RUN: %target-sil-opt -o /dev/null %s
sil_stage canonical
import Builtin
// These are patterns that we should never consider as broken. For positive
// patterns look next door for verifier error checks.
sil @inoutCallee : $@convention(thin) (@inout Builtin.NativeObject) -> ()
sil @guaranteedUser : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
sil @useRawPointer : $@convention(thin) (Builtin.RawPointer) -> ()
//////////////////////////
// InOut Argument Tests //
//////////////////////////
sil [ossa] @inout_earlier_user_same_block : $@convention(thin) (@inout Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject):
%inout_user = function_ref @inoutCallee : $@convention(thin) (@inout Builtin.NativeObject) -> ()
br bb1
bb1:
apply %inout_user(%0) : $@convention(thin) (@inout Builtin.NativeObject) -> ()
%2 = load_borrow %0 : $*Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
br bb2
bb2:
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @inout_earlier_user_different_block : $@convention(thin) (@inout Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject):
%inout_user = function_ref @inoutCallee : $@convention(thin) (@inout Builtin.NativeObject) -> ()
br bb1
bb1:
apply %inout_user(%0) : $@convention(thin) (@inout Builtin.NativeObject) -> ()
br bb2
bb2:
%2 = load_borrow %0 : $*Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @inout_later_user_same_block : $@convention(thin) (@inout Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject):
%inout_user = function_ref @inoutCallee : $@convention(thin) (@inout Builtin.NativeObject) -> ()
br bb1
bb1:
%2 = load_borrow %0 : $*Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
apply %inout_user(%0) : $@convention(thin) (@inout Builtin.NativeObject) -> ()
br bb2
bb2:
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @inout_later_user_different_block : $@convention(thin) (@inout Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject):
%inout_user = function_ref @inoutCallee : $@convention(thin) (@inout Builtin.NativeObject) -> ()
br bb1
bb1:
%2 = load_borrow %0 : $*Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
br bb2
bb2:
apply %inout_user(%0) : $@convention(thin) (@inout Builtin.NativeObject) -> ()
%9999 = tuple()
return %9999 : $()
}
////////////////////////
// Begin Access Tests //
////////////////////////
// Read tests
sil [ossa] @begin_access_read_write_before_same_block : $@convention(thin) (@inout Builtin.NativeObject, @owned Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
br bb1
bb1:
store %1 to [assign] %0 : $*Builtin.NativeObject
%3 = begin_access [read] [unsafe] %0 : $*Builtin.NativeObject
%2 = load_borrow %3 : $*Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
end_access %3 : $*Builtin.NativeObject
br bb2
bb2:
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @begin_access_read_write_after_same_block : $@convention(thin) (@inout Builtin.NativeObject, @owned Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
br bb1
bb1:
%3 = begin_access [read] [unsafe] %0 : $*Builtin.NativeObject
%2 = load_borrow %3 : $*Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
end_access %3 : $*Builtin.NativeObject
store %1 to [assign] %0 : $*Builtin.NativeObject
br bb2
bb2:
%9999 = tuple()
return %9999 : $()
}
// Modify tests
sil [ossa] @begin_access_modify_write_before_same_block : $@convention(thin) (@inout Builtin.NativeObject, @owned Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
br bb1
bb1:
store %1 to [assign] %0 : $*Builtin.NativeObject
%3 = begin_access [modify] [unsafe] %0 : $*Builtin.NativeObject
%2 = load_borrow %3 : $*Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
end_access %3 : $*Builtin.NativeObject
br bb2
bb2:
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @begin_access_modify_write_before_different_block : $@convention(thin) (@inout Builtin.NativeObject, @owned Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
store %1 to [assign] %0 : $*Builtin.NativeObject
br bb1
bb1:
%3 = begin_access [modify] [unsafe] %0 : $*Builtin.NativeObject
%2 = load_borrow %3 : $*Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
end_access %3 : $*Builtin.NativeObject
br bb2
bb2:
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @begin_access_modify_write_after_same_block : $@convention(thin) (@inout Builtin.NativeObject, @owned Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
br bb1
bb1:
%3 = begin_access [modify] [unsafe] %0 : $*Builtin.NativeObject
%2 = load_borrow %3 : $*Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
end_access %3 : $*Builtin.NativeObject
store %1 to [assign] %0 : $*Builtin.NativeObject
br bb2
bb2:
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @begin_access_modify_write_after_different_block : $@convention(thin) (@inout Builtin.NativeObject, @owned Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
br bb1
bb1:
%3 = begin_access [modify] [unsafe] %0 : $*Builtin.NativeObject
%2 = load_borrow %3 : $*Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
end_access %3 : $*Builtin.NativeObject
br bb2
bb2:
store %1 to [assign] %0 : $*Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// [modify] Writes in scope
sil [ossa] @begin_access_modify_same_scope_write_before_same_block : $@convention(thin) (@inout Builtin.NativeObject, @owned Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
br bb1
bb1:
%3 = begin_access [modify] [unsafe] %0 : $*Builtin.NativeObject
store %1 to [assign] %3 : $*Builtin.NativeObject
%2 = load_borrow %3 : $*Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
end_access %3 : $*Builtin.NativeObject
br bb2
bb2:
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @begin_access_modify_same_scope_write_before_different_block : $@convention(thin) (@inout Builtin.NativeObject, @owned Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
%3 = begin_access [modify] [unsafe] %0 : $*Builtin.NativeObject
store %1 to [assign] %3 : $*Builtin.NativeObject
br bb1
bb1:
%2 = load_borrow %3 : $*Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
end_access %3 : $*Builtin.NativeObject
br bb2
bb2:
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @begin_access_modify_same_scope_write_after_same_block : $@convention(thin) (@inout Builtin.NativeObject, @owned Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
br bb1
bb1:
%3 = begin_access [modify] [unsafe] %0 : $*Builtin.NativeObject
%2 = load_borrow %3 : $*Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
store %1 to [assign] %3 : $*Builtin.NativeObject
end_access %3 : $*Builtin.NativeObject
br bb2
bb2:
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @begin_access_modify_same_scope_write_after_different_block : $@convention(thin) (@inout Builtin.NativeObject, @owned Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
br bb1
bb1:
%3 = begin_access [modify] [unsafe] %0 : $*Builtin.NativeObject
%2 = load_borrow %3 : $*Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
br bb2
bb2:
store %1 to [assign] %3 : $*Builtin.NativeObject
end_access %3 : $*Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
//////////////////////////////
// pointer_to_address tests //
//////////////////////////////
sil [ossa] @pointer_to_address_test : $@convention(thin) (Builtin.RawPointer) -> () {
bb0(%0 : $Builtin.RawPointer):
%1 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*Builtin.NativeObject
%2 = load_borrow %1 : $*Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
////////////////////////
// Address Cast Tests //
////////////////////////
sil [ossa] @unconditional_checked_cast_addr_test : $@convention(thin) (@in Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject):
%0a = load_borrow %0 : $*Builtin.NativeObject
end_borrow %0a : $Builtin.NativeObject
%stack0 = alloc_stack $Builtin.NativeObject
unconditional_checked_cast_addr Builtin.NativeObject in %0 : $*Builtin.NativeObject to Builtin.NativeObject in %stack0 : $*Builtin.NativeObject
destroy_addr %stack0 : $*Builtin.NativeObject
dealloc_stack %stack0 : $*Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @conditional_addr_cast_always_take : $@convention(thin) (@in Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject):
%0a = load_borrow %0 : $*Builtin.NativeObject
end_borrow %0a : $Builtin.NativeObject
%stack0 = alloc_stack $Builtin.NativeObject
checked_cast_addr_br take_always Builtin.NativeObject in %0 : $*Builtin.NativeObject to Builtin.NativeObject in %stack0 : $*Builtin.NativeObject, bb1, bb2
bb1:
destroy_addr %stack0 : $*Builtin.NativeObject
br bb3
bb2:
br bb3
bb3:
dealloc_stack %stack0 : $*Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @conditional_addr_cast_take_on_success : $@convention(thin) (@in Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject):
%0a = load_borrow %0 : $*Builtin.NativeObject
end_borrow %0a : $Builtin.NativeObject
%stack0 = alloc_stack $Builtin.NativeObject
checked_cast_addr_br take_on_success Builtin.NativeObject in %0 : $*Builtin.NativeObject to Builtin.NativeObject in %stack0 : $*Builtin.NativeObject, bb1, bb2
bb1:
destroy_addr %stack0 : $*Builtin.NativeObject
br bb3
bb2:
destroy_addr %0 : $*Builtin.NativeObject
br bb3
bb3:
dealloc_stack %stack0 : $*Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @conditional_addr_cast_copyonsuccess_1 : $@convention(thin) (@in Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject):
%0a = load_borrow %0 : $*Builtin.NativeObject
end_borrow %0a : $Builtin.NativeObject
%stack0 = alloc_stack $Builtin.NativeObject
checked_cast_addr_br copy_on_success Builtin.NativeObject in %0 : $*Builtin.NativeObject to Builtin.NativeObject in %stack0 : $*Builtin.NativeObject, bb1, bb2
bb1:
destroy_addr %stack0 : $*Builtin.NativeObject
br bb3
bb2:
br bb3
bb3:
dealloc_stack %stack0 : $*Builtin.NativeObject
destroy_addr %0 : $*Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @conditional_addr_cast_copyonsuccess_2 : $@convention(thin) (@in Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject):
%0a = load_borrow %0 : $*Builtin.NativeObject
%stack0 = alloc_stack $Builtin.NativeObject
checked_cast_addr_br copy_on_success Builtin.NativeObject in %0 : $*Builtin.NativeObject to Builtin.NativeObject in %stack0 : $*Builtin.NativeObject, bb1, bb2
bb1:
destroy_addr %stack0 : $*Builtin.NativeObject
br bb3
bb2:
br bb3
bb3:
dealloc_stack %stack0 : $*Builtin.NativeObject
end_borrow %0a : $Builtin.NativeObject
destroy_addr %0 : $*Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @pointer_to_address_is_assumed_to_be_safe : $@convention(thin) (@owned Builtin.NativeObject) -> () {
bb0(%0 : @owned $Builtin.NativeObject):
%1 = alloc_stack $Builtin.NativeObject
store %0 to [init] %1 : $*Builtin.NativeObject
%2 = load_borrow %1 : $*Builtin.NativeObject
%gUser = function_ref @guaranteedUser : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
apply %gUser(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
end_borrow %2 : $Builtin.NativeObject
%3 = address_to_pointer %1 : $*Builtin.NativeObject to $Builtin.RawPointer
%4 = mark_dependence %3 : $Builtin.RawPointer on %1 : $*Builtin.NativeObject
%rawPointerUser = function_ref @useRawPointer : $@convention(thin) (Builtin.RawPointer) -> ()
apply %rawPointerUser(%4) : $@convention(thin) (Builtin.RawPointer) -> ()
destroy_addr %1 : $*Builtin.NativeObject
dealloc_stack %1 : $*Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
struct Bool {
var _value: Builtin.Int1
}
sil [ossa] @test_withisunique : $@convention(method) <Element> (@inout Builtin.NativeObject) -> Bool {
bb0(%0 : $*Builtin.NativeObject):
%1 = is_unique %0 : $*Builtin.NativeObject
%2 = struct $Bool (%1 : $Builtin.Int1)
%3 = load_borrow %0 : $*Builtin.NativeObject
end_borrow %3 : $Builtin.NativeObject
return %2 : $Bool
}
sil [ossa] @test_valuemetatype : $@convention(thin) (@owned Builtin.NativeObject) -> () {
bb0(%0 : @owned $Builtin.NativeObject):
%1 = alloc_stack $Builtin.NativeObject
store %0 to [init] %1 : $*Builtin.NativeObject
%3a = value_metatype $@thick Builtin.NativeObject.Type, %1 : $*Builtin.NativeObject
%2 = load_borrow %1 : $*Builtin.NativeObject
%gUser = function_ref @guaranteedUser : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
apply %gUser(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
end_borrow %2 : $Builtin.NativeObject
%3 = address_to_pointer %1 : $*Builtin.NativeObject to $Builtin.RawPointer
%4 = mark_dependence %3 : $Builtin.RawPointer on %1 : $*Builtin.NativeObject
%rawPointerUser = function_ref @useRawPointer : $@convention(thin) (Builtin.RawPointer) -> ()
apply %rawPointerUser(%4) : $@convention(thin) (Builtin.RawPointer) -> ()
destroy_addr %1 : $*Builtin.NativeObject
dealloc_stack %1 : $*Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
class KlassWithStruct {
var val : NonTrivialStruct
}
class Klass {
}
struct NonTrivialStruct {
var val : Klass
}
sil [ossa] @test_borrow : $@convention(thin) (@owned KlassWithStruct) -> () {
bb0(%0 : @owned $KlassWithStruct):
%2 = copy_value %0 : $KlassWithStruct
%4 = begin_borrow %2 : $KlassWithStruct
%5 = ref_element_addr %4 : $KlassWithStruct, #KlassWithStruct.val
%6 = load_borrow %5 : $*NonTrivialStruct
destroy_value %0 : $KlassWithStruct
end_borrow %6 : $NonTrivialStruct
end_borrow %4 : $KlassWithStruct
destroy_value %2 : $KlassWithStruct
%ret = tuple ()
return %ret : $()
}
sil [ossa] @test_overlapping_write1 : $@convention(method) (@guaranteed KlassWithStruct) -> () {
bb0(%0 : @guaranteed $KlassWithStruct):
%2 = copy_value %0 : $KlassWithStruct
%5 = ref_element_addr %0 : $KlassWithStruct, #KlassWithStruct.val
%6 = begin_access [read] [dynamic] %5 : $*NonTrivialStruct
%7 = load_borrow %6 : $*NonTrivialStruct
%11 = alloc_stack $KlassWithStruct
store %2 to [init] %11 : $*KlassWithStruct
destroy_addr %11 : $*KlassWithStruct
dealloc_stack %11 : $*KlassWithStruct
end_borrow %7 : $NonTrivialStruct
end_access %6 : $*NonTrivialStruct
%t = tuple ()
return %t : $()
}
sil [ossa] @test_overlapping_write2 : $@convention(method) (@guaranteed KlassWithStruct) -> () {
bb0(%0 : @guaranteed $KlassWithStruct):
%2 = copy_value %0 : $KlassWithStruct
%3 = begin_borrow %2 : $KlassWithStruct
%5 = ref_element_addr %3 : $KlassWithStruct, #KlassWithStruct.val
%6 = begin_access [read] [dynamic] %5 : $*NonTrivialStruct
%7 = load_borrow %6 : $*NonTrivialStruct
%11 = alloc_stack $KlassWithStruct
%12 = store_borrow %0 to %11 : $*KlassWithStruct
end_borrow %12 : $*KlassWithStruct
dealloc_stack %11 : $*KlassWithStruct
end_borrow %7 : $NonTrivialStruct
end_access %6 : $*NonTrivialStruct
end_borrow %3 : $KlassWithStruct
destroy_value %2 : $KlassWithStruct
%t = tuple ()
return %t : $()
}