Files
swift-mirror/test/SILOptimizer/access_summary_analysis.sil
Michael Gottesman f854547c55 [ownership] Enable ownership verification by default.
I also removed the -verify-sil-ownership flag in favor of a disable flag
-disable-sil-ownership-verifier. I used this on only two tests that still need
work to get them to pass with ownership, but whose problems are well understood,
small corner cases. I am going to fix them in follow on commits. I detail them
below:

1. SILOptimizer/definite_init_inout_super_init.swift. This is a test case where
DI is supposed to error. The only problem is that we crash before we error since
the code emitting by SILGen to trigger this error does not pass ownership
invariants. I have spoken with JoeG about this and he suggested that I fix this
earlier in the compiler. Since we do not run the ownership verifier without
asserts enabled, this should not affect compiler users. Given that it has
triggered DI errors previously I think it is safe to disable ownership here.

2. PrintAsObjC/extensions.swift. In this case, the signature generated by type
lowering for one of the thunks here uses an unsafe +0 return value instead of
doing an autorelease return. The ownership checker rightly flags this leak. This
is going to require either an AST level change or a change to TypeLowering. I
think it is safe to turn this off since it is such a corner case that it was
found by a test that has nothing to do with it.

rdar://43398898
2019-03-25 00:11:52 -07:00

507 lines
23 KiB
Plaintext

// RUN: %target-sil-opt %s -access-summary-dump -o /dev/null | %FileCheck %s
sil_stage raw
import Builtin
import Swift
import SwiftShims
struct StructWithStoredProperties {
@_hasStorage var f: Int
@_hasStorage var g: Int
}
struct StructWithStructWithStoredProperties {
@_hasStorage var a: StructWithStoredProperties
@_hasStorage var b: StructWithStoredProperties
}
// CHECK-LABEL: @assignsToCapture
// CHECK-NEXT: ([modify], [])
sil private [ossa] @assignsToCapture : $@convention(thin) (@inout_aliasable Int, Int) -> () {
bb0(%0 : $*Int, %1: $Int):
%2 = begin_access [modify] [unknown] %0 : $*Int
assign %1 to %2 : $*Int
end_access %2 : $*Int
%3 = tuple ()
return %3 : $()
}
// CHECK-LABEL: @readsAndModifiesSameCapture
// CHECK-NEXT: ([modify])
sil private [ossa] @readsAndModifiesSameCapture : $@convention(thin) (@inout_aliasable Int) -> () {
bb0(%0 : $*Int):
%1 = begin_access [read] [unknown] %0 : $*Int
end_access %1 : $*Int
%2 = begin_access [modify] [unknown] %0 : $*Int
end_access %2 : $*Int
%3 = tuple ()
return %3 : $()
}
// CHECK-LABEL: @readsAndModifiesSeparateCaptures
// CHECK-NEXT: ([read], [modify])
sil private [ossa] @readsAndModifiesSeparateCaptures : $@convention(thin) (@inout_aliasable Int, @inout_aliasable Int) -> () {
bb0(%0 : $*Int, %1 : $*Int):
%2 = begin_access [read] [unknown] %0 : $*Int
end_access %2 : $*Int
%3 = begin_access [modify] [unknown] %1 : $*Int
end_access %3 : $*Int
%4 = tuple ()
return %4 : $()
}
// CHECK-LABEL: @modifyInModifySubAccess
// CHECK-NEXT: ([modify])
sil private [ossa] @modifyInModifySubAccess : $@convention(thin) (@inout_aliasable Int) -> () {
bb0(%0 : $*Int):
%1 = begin_access [modify] [unknown] %0 : $*Int
%2 = begin_access [modify] [unknown] %1 : $*Int
end_access %2 : $*Int
end_access %1 : $*Int
%3 = tuple ()
return %3 : $()
}
// CHECK-LABEL: @readInModifySubAccess
// CHECK-NEXT: ([modify])
sil private [ossa] @readInModifySubAccess : $@convention(thin) (@inout_aliasable Int) -> () {
bb0(%0 : $*Int):
%1 = begin_access [modify] [unknown] %0 : $*Int
%2 = begin_access [read] [unknown] %1 : $*Int
end_access %2 : $*Int
end_access %1 : $*Int
%3 = tuple ()
return %3 : $()
}
// CHECK-LABEL: @accessSeparateStoredPropertiesOfSameCapture
// CHECK-NEXT: ([.f modify, .g read])
sil private [ossa] @accessSeparateStoredPropertiesOfSameCapture : $@convention(thin) (@inout_aliasable StructWithStoredProperties) -> () {
bb0(%0 : $*StructWithStoredProperties):
%1 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
%2 = struct_element_addr %1 : $*StructWithStoredProperties, #StructWithStoredProperties.f
end_access %1 : $*StructWithStoredProperties
%4 = begin_access [read] [unknown] %0: $*StructWithStoredProperties
%5 = struct_element_addr %4 : $*StructWithStoredProperties, #StructWithStoredProperties.g
end_access %4 : $*StructWithStoredProperties
%7 = tuple ()
return %7 : $()
}
// CHECK-LABEL: @accessSeparateElementsOfSameCapture
// CHECK-NEXT: ([.0 modify, .1 read])
sil private [ossa] @accessSeparateElementsOfSameCapture : $@convention(thin) (@inout_aliasable (Int, Int)) -> () {
bb0(%0 : $*(Int, Int)):
%1 = begin_access [modify] [unknown] %0: $*(Int, Int)
%2 = tuple_element_addr %1 : $*(Int, Int), 0
end_access %1 : $*(Int, Int)
%4 = begin_access [read] [unknown] %0: $*(Int, Int)
%5 = tuple_element_addr %4 : $*(Int, Int), 1
end_access %4 : $*(Int, Int)
%7 = tuple ()
return %7 : $()
}
// CHECK-LABEL: @accessSeparateNestedStoredPropertiesOfSameCapture
// CHECK-NEXT: ([.a.f modify, .b.g modify])
sil private [ossa] @accessSeparateNestedStoredPropertiesOfSameCapture : $@convention(thin) (@inout_aliasable StructWithStructWithStoredProperties) -> () {
bb0(%0 : $*StructWithStructWithStoredProperties):
%1 = begin_access [modify] [unknown] %0: $*StructWithStructWithStoredProperties
%2 = struct_element_addr %1 : $*StructWithStructWithStoredProperties, #StructWithStructWithStoredProperties.a
%3 = struct_element_addr %2 : $*StructWithStoredProperties, #StructWithStoredProperties.f
end_access %1 : $*StructWithStructWithStoredProperties
%5 = begin_access [modify] [unknown] %0: $*StructWithStructWithStoredProperties
%6 = struct_element_addr %5 : $*StructWithStructWithStoredProperties, #StructWithStructWithStoredProperties.b
%7 = struct_element_addr %6 : $*StructWithStoredProperties, #StructWithStoredProperties.g
end_access %5 : $*StructWithStructWithStoredProperties
%9 = tuple ()
return %9 : $()
}
// CHECK-LABEL: @accessSeparateStoredPropertiesOfSameCaptureOppositeOfDeclarationOrder
// CHECK-NEXT: ([.f read, .g modify])
sil private [ossa] @accessSeparateStoredPropertiesOfSameCaptureOppositeOfDeclarationOrder : $@convention(thin) (@inout_aliasable StructWithStoredProperties) -> () {
bb0(%0 : $*StructWithStoredProperties):
%1 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
%2 = struct_element_addr %1 : $*StructWithStoredProperties, #StructWithStoredProperties.g
end_access %1 : $*StructWithStoredProperties
%4 = begin_access [read] [unknown] %0: $*StructWithStoredProperties
%5 = struct_element_addr %4 : $*StructWithStoredProperties, #StructWithStoredProperties.f
end_access %4 : $*StructWithStoredProperties
%7 = tuple ()
return %7 : $()
}
// CHECK-LABEL: @accessAggregateDoesNotSubsumeAccessStoredProp
// CHECK-NEXT: ([modify, .g modify])
sil private [ossa] @accessAggregateDoesNotSubsumeAccessStoredProp : $@convention(thin) (@inout_aliasable StructWithStoredProperties) -> () {
bb0(%0 : $*StructWithStoredProperties):
%1 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
end_access %1 : $*StructWithStoredProperties
%4 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
%5 = struct_element_addr %4 : $*StructWithStoredProperties, #StructWithStoredProperties.g
end_access %4 : $*StructWithStoredProperties
%7 = tuple ()
return %7 : $()
}
// CHECK-LABEL: @accessAggregateDoesNotSubsumeAccessStoredPropWithAggregateSecond
// CHECK-NEXT: ([modify, .f modify])
sil private [ossa] @accessAggregateDoesNotSubsumeAccessStoredPropWithAggregateSecond : $@convention(thin) (@inout_aliasable StructWithStoredProperties) -> () {
bb0(%0 : $*StructWithStoredProperties):
%1 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
%2 = struct_element_addr %1 : $*StructWithStoredProperties, #StructWithStoredProperties.f
end_access %1 : $*StructWithStoredProperties
%4 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
end_access %4 : $*StructWithStoredProperties
%7 = tuple ()
return %7 : $()
}
// CHECK-LABEL: @accessSameStoredPropertyOfSameCapture
// CHECK-NEXT: ([.f modify])
sil private [ossa] @accessSameStoredPropertyOfSameCapture : $@convention(thin) (@inout_aliasable StructWithStoredProperties) -> () {
bb0(%0 : $*StructWithStoredProperties):
%1 = begin_access [read] [unknown] %0: $*StructWithStoredProperties
%2 = struct_element_addr %1 : $*StructWithStoredProperties, #StructWithStoredProperties.f
end_access %1 : $*StructWithStoredProperties
%4 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
%5 = struct_element_addr %4 : $*StructWithStoredProperties, #StructWithStoredProperties.f
end_access %4 : $*StructWithStoredProperties
%7 = tuple ()
return %7 : $()
}
// CHECK-LABEL: @accessSeparateStoredPropertiesOfSameCaptureWithTSanInstrumentation
// CHECK-NEXT: ([.f modify, .g read])
sil private [ossa] @accessSeparateStoredPropertiesOfSameCaptureWithTSanInstrumentation : $@convention(thin) (@inout_aliasable StructWithStoredProperties) -> () {
bb0(%0 : $*StructWithStoredProperties):
%1 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
%2 = builtin "tsanInoutAccess"(%1 : $*StructWithStoredProperties) : $()
%3 = struct_element_addr %1 : $*StructWithStoredProperties, #StructWithStoredProperties.f
%4 = builtin "tsanInoutAccess"(%3 : $*Int) : $()
end_access %1 : $*StructWithStoredProperties
%6 = begin_access [read] [unknown] %0: $*StructWithStoredProperties
%7 = builtin "tsanInoutAccess"(%6 : $*StructWithStoredProperties) : $()
%8 = struct_element_addr %6 : $*StructWithStoredProperties, #StructWithStoredProperties.g
%9 = builtin "tsanInoutAccess"(%8 : $*Int) : $()
end_access %6 : $*StructWithStoredProperties
%11 = tuple ()
return %11 : $()
}
// CHECK-LABEL: @addressToPointerOfStructElementAddr
// CHECK-NEXT: ([])
// This mirrors the code pattern for materializeForSet on a struct stored
// property
sil private [ossa] @addressToPointerOfStructElementAddr : $@convention(method) (@inout StructWithStoredProperties) -> (Builtin.RawPointer) {
bb0(%1 : $*StructWithStoredProperties):
%2 = struct_element_addr %1 : $*StructWithStoredProperties, #StructWithStoredProperties.f
%3 = address_to_pointer %2 : $*Int to $Builtin.RawPointer
return %3 : $(Builtin.RawPointer)
}
// CHECK-LABEL: @endUnpairedAccess
// CHECK-NEXT: ([])
sil private [ossa] @endUnpairedAccess : $@convention(method) (@inout Builtin.UnsafeValueBuffer) -> () {
bb0(%0 : $*Builtin.UnsafeValueBuffer):
end_unpaired_access [dynamic] %0 : $*Builtin.UnsafeValueBuffer
%1 = tuple ()
return %1 : $()
}
// CHECK-LABEL: @tupleElementAddr
// CHECK-NEXT: ([modify])
sil private [ossa] @tupleElementAddr : $@convention(thin) (@inout_aliasable (Int, Int)) -> () {
bb0(%0 : $*(Int, Int)):
%1 = tuple_element_addr %0 : $*(Int, Int), 1
%2 = begin_access [modify] [unknown] %1 : $*Int
end_access %2 : $*Int
%3 = tuple ()
return %3 : $()
}
sil @closureWithMissingBody : $@convention(thin) (@inout_aliasable Int, Int) -> ()
// CHECK-LABEL: @callClosureWithMissingBody
// CHECK-NEXT: ([], [])
sil private [ossa] @callClosureWithMissingBody : $@convention(thin) (@inout_aliasable Int, Int) -> () {
bb0(%0 : $*Int, %1 : $Int):
%2 = function_ref @closureWithMissingBody : $@convention(thin) (@inout_aliasable Int, Int) -> ()
%3 = apply %2(%0, %1) : $@convention(thin) (@inout_aliasable Int, Int) -> () // no-crash
%4 = tuple ()
return %4 : $()
}
// CHECK-LABEL: @callClosureThatModifiesCapture
// CHECK-NEXT: ([modify], [])
sil private [ossa] @callClosureThatModifiesCapture : $@convention(thin) (@inout_aliasable Int, Int) -> () {
bb0(%0 : $*Int, %1 : $Int):
%2 = function_ref @assignsToCapture : $@convention(thin) (@inout_aliasable Int, Int) -> ()
%3 = apply %2(%0, %1) : $@convention(thin) (@inout_aliasable Int, Int) -> ()
%4 = tuple ()
return %4 : $()
}
// CHECK-LABEL: @throwingClosureThatModifesCapture
// CHECK-NEXT: ([modify])
sil private [ossa] @throwingClosureThatModifesCapture : $@convention(thin) (@inout_aliasable Int) -> @error Error {
bb0(%0 : $*Int):
%1 = begin_access [modify] [unknown] %0 : $*Int
end_access %1 : $*Int
%2 = tuple ()
return %2 : $()
}
// CHECK-LABEL: @callThrowingClosureThatModifiesCapture
// CHECK-NEXT: ([modify])
sil private [ossa] @callThrowingClosureThatModifiesCapture : $@convention(thin) (@inout_aliasable Int) -> () {
bb0(%0 : $*Int):
%1 = function_ref @throwingClosureThatModifesCapture : $@convention(thin) (@inout_aliasable Int) -> @error Error
try_apply %1(%0) : $@convention(thin) (@inout_aliasable Int) -> @error Error, normal bb1, error bb2
bb1(%3 : $()):
%4 = tuple ()
return %4 : $()
bb2(%5: @owned $Error):
%6 = builtin "unexpectedError"(%5 : $Error) : $()
unreachable
}
sil @takesNoEscapeClosure : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
// CHECK-LABEL: @partialApplyPassedOffToFunction
// CHECK-NEXT: ([modify], [])
sil private [ossa] @partialApplyPassedOffToFunction : $@convention(thin) (@inout_aliasable Int, Int) -> () {
bb0(%0 : $*Int, %1: $Int):
%2 = function_ref @assignsToCapture : $@convention(thin) (@inout_aliasable Int, Int) -> ()
%3 = partial_apply %2(%0, %1) : $@convention(thin) (@inout_aliasable Int, Int) -> ()
%4 = function_ref @takesNoEscapeClosure : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
%5 = apply %4(%3) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
%6 = tuple ()
return %6 : $()
}
sil @takesNoEscapeClosureTakingArgument : $@convention(thin) (@owned @callee_owned (Int) -> ()) -> ()
sil @takesNoEscapeClosureTakingArgumentThrowing : $@convention(thin) (@owned @callee_owned (Int) -> (@error Error)) -> ()
sil @takesGuaranteedNoEscapeClosureTakingArgumentThrowing : $@convention(thin) (@guaranteed @callee_owned (Int) -> @error Error) -> ()
// CHECK-LABEL: @hasThreeCapturesAndTakesArgument
// CHECK-NEXT: ([], [modify], [], [read])
sil private [ossa] @hasThreeCapturesAndTakesArgument : $@convention(thin) (Int, @inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> () {
bb0(%0 : $Int, %1: $*Int, %2: $*Int, %3: $*Int):
%4 = begin_access [modify] [unknown] %1 : $*Int
end_access %4 : $*Int
%5 = begin_access [read] [unknown] %3 : $*Int
end_access %5 : $*Int
%6 = tuple ()
return %6 : $()
}
// CHECK-LABEL: @partialApplyOfClosureTakingArgumentPassedOffToFunction
// CHECK-NEXT: ([modify], [], [read])
sil private [ossa] @partialApplyOfClosureTakingArgumentPassedOffToFunction : $@convention(thin) (@inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> () {
bb0(%0 : $*Int, %1 : $*Int, %2 : $*Int):
%3 = function_ref @hasThreeCapturesAndTakesArgument : $@convention(thin) (Int, @inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> ()
%4 = partial_apply %3(%0, %1, %2) : $@convention(thin) (Int, @inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> ()
%5 = function_ref @takesNoEscapeClosureTakingArgument : $@convention(thin) (@owned @callee_owned (Int) -> ()) -> ()
%6 = apply %5(%4) : $@convention(thin) (@owned @callee_owned (Int) -> ()) -> ()
%7 = tuple ()
return %7 : $()
}
// CHECK-LABEL: @partialApplyFollowedByConvertFunction
// CHECK-NEXT: ([modify], [], [read])
sil private [ossa] @partialApplyFollowedByConvertFunction : $@convention(thin) (@inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> () {
bb0(%0 : $*Int, %1 : $*Int, %2 : $*Int):
%3 = function_ref @hasThreeCapturesAndTakesArgument : $@convention(thin) (Int, @inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> ()
%4 = partial_apply %3(%0, %1, %2) : $@convention(thin) (Int, @inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> ()
%5 = convert_function %4 : $@callee_owned (Int) -> () to $@callee_owned (Int) -> @error Error
%6 = function_ref @takesNoEscapeClosureTakingArgumentThrowing : $@convention(thin) (@owned @callee_owned (Int) -> @error Error) -> ()
%7 = apply %6(%5) : $@convention(thin) (@owned @callee_owned (Int) -> @error Error) -> ()
%8 = tuple ()
return %8 : $()
}
sil @takesAutoClosureReturningGeneric : $@convention(thin) <T where T : Equatable> (@owned @callee_owned () -> (@out T, @error Error)) -> ()
sil @thunkForAutoClosure : $@convention(thin) (@owned @callee_owned () -> (Int, @error Error)) -> (@out Int, @error Error)
// CHECK-LABEL: @readsAndThrows
// CHECK-NEXT: ([read])
sil private [ossa] @readsAndThrows : $@convention(thin) (@inout_aliasable Int) -> (Int, @error Error) {
bb0(%0 : $*Int):
%3 = begin_access [read] [unknown] %0 : $*Int
%4 = load [trivial] %3 : $*Int
end_access %3 : $*Int
return %4 : $Int
}
// CHECK-LABEL: @passPartialApplyAsArgumentToPartialApply
// CHECK-NEXT: ([read])
sil hidden [ossa] @passPartialApplyAsArgumentToPartialApply : $@convention(thin) (@inout_aliasable Int) -> () {
bb0(%0 : $*Int):
%2 = function_ref @takesAutoClosureReturningGeneric : $@convention(thin) <τ_0_0 where τ_0_0 : Equatable> (@owned @callee_owned () -> (@out τ_0_0, @error Error)) -> ()
%3 = function_ref @readsAndThrows : $@convention(thin) (@inout_aliasable Int) -> (Int, @error Error)
%4 = partial_apply %3(%0) : $@convention(thin) (@inout_aliasable Int) -> (Int, @error Error)
%5 = function_ref @thunkForAutoClosure : $@convention(thin) (@owned @callee_owned () -> (Int, @error Error)) -> (@out Int, @error Error)
%6 = partial_apply %5(%4) : $@convention(thin) (@owned @callee_owned () -> (Int, @error Error)) -> (@out Int, @error Error)
%7 = apply %2<Int>(%6) : $@convention(thin) <τ_0_0 where τ_0_0 : Equatable> (@owned @callee_owned () -> (@out τ_0_0, @error Error)) -> ()
%8 = tuple ()
return %8 : $()
}
// CHECK-LABEL: @reads
// CHECK-NEXT: ([read])
sil private [ossa] @reads : $@convention(thin) (@inout_aliasable Int) -> Int {
bb0(%0 : $*Int):
%3 = begin_access [read] [unknown] %0 : $*Int
%4 = load [trivial] %3 : $*Int
end_access %3 : $*Int
return %4 : $Int
}
// CHECK-LABEL: @convertPartialApplyAndPassToPartialApply
// CHECK-NEXT: ([read])
sil hidden [ossa] @convertPartialApplyAndPassToPartialApply : $@convention(thin) (@inout_aliasable Int) -> () {
bb0(%0 : $*Int):
%2 = function_ref @takesAutoClosureReturningGeneric : $@convention(thin) <τ_0_0 where τ_0_0 : Equatable> (@owned @callee_owned () -> (@out τ_0_0, @error Error)) -> ()
%3 = function_ref @reads : $@convention(thin) (@inout_aliasable Int) -> Int
%4 = partial_apply %3(%0) : $@convention(thin) (@inout_aliasable Int) -> Int
%5 = convert_function %4 : $@callee_owned () -> Int to $@callee_owned () -> (Int, @error Error)
%6 = function_ref @thunkForAutoClosure : $@convention(thin) (@owned @callee_owned () -> (Int, @error Error)) -> (@out Int, @error Error)
%7 = partial_apply %6(%5) : $@convention(thin) (@owned @callee_owned () -> (Int, @error Error)) -> (@out Int, @error Error)
%8 = apply %2<Int>(%7) : $@convention(thin) <τ_0_0 where τ_0_0 : Equatable> (@owned @callee_owned () -> (@out τ_0_0, @error Error)) -> ()
%9 = tuple ()
return %9 : $()
}
// CHECK-LABEL: @selfRecursion
// CHECK-NEXT: ([modify], [])
sil private [ossa] @selfRecursion : $@convention(thin) (@inout_aliasable Int, Int) -> () {
bb0(%0 : $*Int, %1 : $Int):
%2 = function_ref @selfRecursion : $@convention(thin) (@inout_aliasable Int, Int) -> ()
%3 = apply %2(%0, %1) : $@convention(thin) (@inout_aliasable Int, Int) -> ()
%4 = begin_access [modify] [unknown] %0 : $*Int
end_access %4 : $*Int
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: @callsMutuallyRecursive
// CHECK-NEXT: ([modify], [])
sil private [ossa] @callsMutuallyRecursive : $@convention(thin) (@inout_aliasable Int, Int) -> () {
bb0(%0 : $*Int, %1 : $Int):
%2 = function_ref @mutualRecursion1 : $@convention(thin) (@inout_aliasable Int, Int) -> ()
%3 = apply %2(%0, %1) : $@convention(thin) (@inout_aliasable Int, Int) -> ()
%4 = tuple ()
return %4 : $()
}
// CHECK-LABEL: @mutualRecursion1
// CHECK-NEXT: ([modify], [])
sil private [ossa] @mutualRecursion1 : $@convention(thin) (@inout_aliasable Int, Int) -> () {
bb0(%0 : $*Int, %1 : $Int):
%2 = function_ref @mutualRecursion2 : $@convention(thin) (@inout_aliasable Int, Int) -> ()
%3 = apply %2(%0, %1) : $@convention(thin) (@inout_aliasable Int, Int) -> ()
%4 = begin_access [modify] [unknown] %0 : $*Int
end_access %4 : $*Int
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: @mutualRecursion2
// CHECK-NEXT: ([modify], [])
sil private [ossa] @mutualRecursion2 : $@convention(thin) (@inout_aliasable Int, Int) -> () {
bb0(%0 : $*Int, %1 : $Int):
%2 = function_ref @mutualRecursion1 : $@convention(thin) (@inout_aliasable Int, Int) -> ()
%3 = apply %2(%0, %1) : $@convention(thin) (@inout_aliasable Int, Int) -> ()
%4 = begin_access [read] [unknown] %0 : $*Int
end_access %4 : $*Int
%5 = tuple ()
return %5 : $()
}
// Multiple cycles. This requires two iterations of the edge propagation.
// Once to propagate the modify from A to B and one to propagate from
// B to C
//
// A [Call B then later modify param]
// / |
// \ |
// B
// / |
// \ |
// C
//
// CHECK-LABEL: @multipleCycleA
// CHECK-NEXT: ([modify])
sil private [ossa] @multipleCycleA : $@convention(thin) (@inout_aliasable Int) -> () {
bb0(%0 : $*Int):
%1 = function_ref @multipleCycleB : $@convention(thin) (@inout_aliasable Int) -> ()
%2 = apply %1(%0) : $@convention(thin) (@inout_aliasable Int) -> ()
%3 = begin_access [modify] [unknown] %0 : $*Int
end_access %3 : $*Int
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: @multipleCycleB
// CHECK-NEXT: ([modify])
sil private [ossa] @multipleCycleB : $@convention(thin) (@inout_aliasable Int) -> () {
bb0(%0 : $*Int):
%1 = function_ref @multipleCycleA : $@convention(thin) (@inout_aliasable Int) -> ()
%2 = apply %1(%0) : $@convention(thin) (@inout_aliasable Int) -> ()
%3 = function_ref @multipleCycleC : $@convention(thin) (@inout_aliasable Int) -> ()
%4 = apply %3(%0) : $@convention(thin) (@inout_aliasable Int) -> ()
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: @multipleCycleC
// CHECK-NEXT: ([modify])
sil private [ossa] @multipleCycleC : $@convention(thin) (@inout_aliasable Int) -> () {
bb0(%0 : $*Int):
%1 = function_ref @multipleCycleB : $@convention(thin) (@inout_aliasable Int) -> ()
%2 = apply %1(%0) : $@convention(thin) (@inout_aliasable Int) -> ()
%4 = tuple ()
return %4 : $()
}
// Make sure that we can accept borrows of partial apply by looking through the
// borrow.
// CHECK-LABEL: @partialApplyFollowedByConvertFunctionWithBorrow
// CHECK-NEXT: ([modify], [], [read])
sil private [ossa] @partialApplyFollowedByConvertFunctionWithBorrow : $@convention(thin) (@inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> () {
bb0(%0 : $*Int, %1 : $*Int, %2 : $*Int):
%3 = function_ref @hasThreeCapturesAndTakesArgument : $@convention(thin) (Int, @inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> ()
%4 = partial_apply %3(%0, %1, %2) : $@convention(thin) (Int, @inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> ()
%5 = convert_function %4 : $@callee_owned (Int) -> () to $@callee_owned (Int) -> @error Error
%6 = begin_borrow %5 : $@callee_owned (Int) -> @error Error
%7 = function_ref @takesGuaranteedNoEscapeClosureTakingArgumentThrowing : $@convention(thin) (@guaranteed @callee_owned (Int) -> @error Error) -> ()
%8 = apply %7(%6) : $@convention(thin) (@guaranteed @callee_owned (Int) -> @error Error) -> ()
end_borrow %6 : $@callee_owned (Int) -> @error Error
destroy_value %5 : $@callee_owned (Int) -> @error Error
%9999 = tuple ()
return %9999 : $()
}
sil @use : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
sil @subject : $@convention(thin) (Builtin.Int64) -> ()
// CHECK-LABEL: @partial_apply_convert
sil [ossa] @partial_apply_convert : $@convention(thin) () -> () {
entry:
%f = function_ref @subject : $@convention(thin) (Builtin.Int64) -> ()
%z = integer_literal $Builtin.Int64, 0
%e = partial_apply [callee_guaranteed] %f(%z) : $@convention(thin) (Builtin.Int64) -> ()
%b = begin_borrow %e : $@callee_guaranteed () -> ()
%n = convert_escape_to_noescape %b : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
%n2 = mark_dependence %n : $@noescape @callee_guaranteed () -> () on %e : $@callee_guaranteed () -> ()
%f2 = function_ref @use : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
apply %f2(%n2) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
end_borrow %b : $@callee_guaranteed () -> ()
destroy_value %e : $@callee_guaranteed () -> ()
%t = tuple ()
return %t : $()
}