| // RUN: %target-sil-opt %s -enable-sil-ownership -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 : $() |
| } |