mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Previously, CallerAnalysis::FunctionInfo.foundAllCallers(), which is documented to return true only when specialization of a function will not require a thunk, returned true for functions which are possibly used externally. Now, that member function only returns false for functions which may be used externally since dead code elimination will not be able to remove them.
520 lines
19 KiB
Plaintext
520 lines
19 KiB
Plaintext
// RUN: %target-sil-opt -enable-sil-verify-all %s -caller-analysis-printer -o /dev/null | %FileCheck --check-prefix=CHECK %s
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
|
|
// CHECK-LABEL: calleeName: dead_func
|
|
// CHECK-NEXT: hasCaller: false
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: ...
|
|
sil private @dead_func : $@convention(thin) () -> () {
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: call_top
|
|
// CHECK-NEXT: hasCaller: false
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: ...
|
|
sil private @call_top : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @call_middle : $@convention(thin) () -> ()
|
|
%1 = apply %0() : $@convention(thin) () -> ()
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: call_middle
|
|
// CHECK-NEXT: hasCaller: true
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: - call_top
|
|
// CHECK-NEXT: ...
|
|
sil private @call_middle : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @call_bottom : $@convention(thin) () -> ()
|
|
%1 = apply %0() : $@convention(thin) () -> ()
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: call_bottom
|
|
// CHECK-NEXT: hasCaller: true
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: - call_middle
|
|
// CHECK-NEXT: ...
|
|
sil private @call_bottom : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = tuple ()
|
|
return %0 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: self_recursive_func
|
|
// CHECK-NEXT: hasCaller: true
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: - self_recursive_func
|
|
// CHECK-NEXT: ...
|
|
sil private @self_recursive_func : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @self_recursive_func : $@convention(thin) () -> ()
|
|
%1 = apply %0() : $@convention(thin) () -> ()
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: mutual_recursive_func1
|
|
// CHECK-NEXT: hasCaller: true
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: - mutual_recursive_func2
|
|
// CHECK-NEXT: ...
|
|
sil private @mutual_recursive_func1 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @mutual_recursive_func2 : $@convention(thin) () -> ()
|
|
%1 = apply %0() : $@convention(thin) () -> ()
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: mutual_recursive_func2
|
|
// CHECK-NEXT: hasCaller: true
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: - mutual_recursive_func1
|
|
// CHECK-NEXT: ...
|
|
sil private @mutual_recursive_func2 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @mutual_recursive_func1 : $@convention(thin) () -> ()
|
|
%1 = apply %0() : $@convention(thin) () -> ()
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: multi_called
|
|
// CHECK-NEXT: hasCaller: true
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: - multi_calles
|
|
// CHECK-NEXT: ...
|
|
sil private @multi_called : $@convention(thin) () -> () {
|
|
bb0:
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: multi_calles
|
|
// CHECK-NEXT: hasCaller: false
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: ...
|
|
sil private @multi_calles : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @multi_called : $@convention(thin) () -> ()
|
|
%1 = apply %0() : $@convention(thin) () -> ()
|
|
cond_br undef, bb1, bb2
|
|
bb1:
|
|
%2 = apply %0() : $@convention(thin) () -> ()
|
|
br bb3
|
|
bb2:
|
|
%3 = apply %0() : $@convention(thin) () -> ()
|
|
br bb3
|
|
bb3:
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: multi_callers
|
|
// CHECK-NEXT: hasCaller: true
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: - multi_caller1
|
|
// CHECK-NEXT: - multi_caller2
|
|
// CHECK-NEXT: ...
|
|
sil private @multi_callers : $@convention(thin) () -> () {
|
|
bb0:
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: multi_caller1
|
|
// CHECK-NEXT: hasCaller: false
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: ...
|
|
sil private @multi_caller1 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @multi_callers : $@convention(thin) () -> ()
|
|
%1 = apply %0() : $@convention(thin) () -> ()
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: multi_caller2
|
|
// CHECK-NEXT: hasCaller: false
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: ...
|
|
sil private @multi_caller2 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @multi_callers : $@convention(thin) () -> ()
|
|
%1 = apply %0() : $@convention(thin) () -> ()
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// This doesn't have all the direct caller sets since we return the
|
|
// partial_apply.
|
|
//
|
|
// CHECK-LABEL: calleeName: closure1
|
|
// CHECK-NEXT: hasCaller: false
|
|
// CHECK-NEXT: minPartialAppliedArgs: 1
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: false
|
|
// CHECK-NEXT: hasAllCallers: false
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: - partial_apply_one_arg
|
|
// CHECK-NEXT: - partial_apply_two_args1
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: ...
|
|
sil @closure1 : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32, %1 : $Builtin.Int32):
|
|
return %0 : $Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: closure2
|
|
// CHECK-NEXT: hasCaller: false
|
|
// CHECK-NEXT: minPartialAppliedArgs: 2
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: false
|
|
// CHECK-NEXT: hasAllCallers: false
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: - partial_apply_two_args2
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: ...
|
|
sil @closure2 : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32, %1 : $Builtin.Int32):
|
|
return %0 : $Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: partial_apply_one_arg
|
|
// CHECK-NEXT: hasCaller: false
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: ...
|
|
sil private @partial_apply_one_arg : $@convention(thin) (Builtin.Int32) -> @owned @callee_owned (Builtin.Int32) -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%1 = function_ref @closure1 : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
%2 = partial_apply %1(%0) : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
return %2 : $@callee_owned (Builtin.Int32) -> Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: partial_apply_two_args1
|
|
// CHECK-NEXT: hasCaller: false
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: ...
|
|
sil private @partial_apply_two_args1 : $@convention(thin) (Builtin.Int32) -> @owned @callee_owned () -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%1 = function_ref @closure1 : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
%2 = partial_apply %1(%0, %0) : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
return %2 : $@callee_owned () -> Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: partial_apply_two_args2
|
|
// CHECK-NEXT: hasCaller: false
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: ...
|
|
sil private @partial_apply_two_args2 : $@convention(thin) (Builtin.Int32) -> @owned @callee_owned () -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%1 = function_ref @closure2 : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
%2 = partial_apply %1(%0, %0) : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
return %2 : $@callee_owned () -> Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: called_closure
|
|
// CHECK-NEXT: hasCaller: true
|
|
// CHECK-NEXT: minPartialAppliedArgs: 2
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: - partial_apply_that_is_applied
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: - partial_apply_that_is_applied
|
|
// CHECK-NEXT: ...
|
|
sil private @called_closure : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32, %1 : $Builtin.Int32):
|
|
return %0 : $Builtin.Int32
|
|
}
|
|
|
|
sil @partial_apply_that_is_applied : $@convention(thin) (Builtin.Int32) -> () {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%1 = function_ref @called_closure : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
%2 = partial_apply %1(%0, %0) : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
%3 = apply %2() : $@callee_owned () -> Builtin.Int32
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We should ignore destroys in the fullness of time. Once we handle that
|
|
// correctly, we should have the complete caller set here.
|
|
//
|
|
// CHECK-LABEL: calleeName: called_closure_then_destroy
|
|
// CHECK-NEXT: hasCaller: true
|
|
// CHECK-NEXT: minPartialAppliedArgs: 2
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: - partial_apply_that_is_applied
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: - partial_apply_that_is_applied
|
|
// CHECK-NEXT: ...
|
|
sil private @called_closure_then_destroy : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32, %1 : $Builtin.Int32):
|
|
return %0 : $Builtin.Int32
|
|
}
|
|
|
|
sil @partial_apply_that_is_applied_and_destroyed : $@convention(thin) (Builtin.Int32) -> () {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%1 = function_ref @called_closure_then_destroy : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
%2 = partial_apply %1(%0, %0) : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
%3 = apply %2() : $@callee_owned () -> Builtin.Int32
|
|
strong_release %2 : $@callee_owned () -> Builtin.Int32
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: called_escaping_closure
|
|
// CHECK-NEXT: hasCaller: true
|
|
// CHECK-NEXT: minPartialAppliedArgs: 2
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: false
|
|
// CHECK-NEXT: hasAllCallers: false
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: - partial_apply_that_is_applied
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: - partial_apply_that_is_applied
|
|
// CHECK-NEXT: ...
|
|
sil @called_escaping_closure : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32, %1 : $Builtin.Int32):
|
|
return %0 : $Builtin.Int32
|
|
}
|
|
|
|
sil @partial_apply_that_is_applied_and_escapes : $@convention(thin) (Builtin.Int32) -> @owned @callee_guaranteed () -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%1 = function_ref @called_escaping_closure : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
%2 = partial_apply [callee_guaranteed] %1(%0, %0) : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
%3 = apply %2() : $@callee_guaranteed () -> Builtin.Int32
|
|
return %2 : $@callee_guaranteed () -> Builtin.Int32
|
|
}
|
|
|
|
// Make sure that we ignore strong_retain.
|
|
//
|
|
// CHECK-LABEL: calleeName: called_closure_then_copy_destroy
|
|
// CHECK-NEXT: hasCaller: true
|
|
// CHECK-NEXT: minPartialAppliedArgs: 2
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: - partial_apply_that_is_applied
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: - partial_apply_that_is_applied
|
|
// CHECK-NEXT: ...
|
|
sil private @called_closure_then_copy_destroy : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32, %1 : $Builtin.Int32):
|
|
return %0 : $Builtin.Int32
|
|
}
|
|
|
|
sil @partial_apply_that_is_applied_and_copy_destroy : $@convention(thin) (Builtin.Int32) -> () {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%1 = function_ref @called_closure_then_copy_destroy : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
%2 = partial_apply %1(%0, %0) : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
strong_retain %2 : $@callee_owned () -> Builtin.Int32
|
|
retain_value %2 : $@callee_owned () -> Builtin.Int32
|
|
%3 = apply %2() : $@callee_owned () -> Builtin.Int32
|
|
release_value %2 : $@callee_owned () -> Builtin.Int32
|
|
strong_release %2 : $@callee_owned () -> Builtin.Int32
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We should ignore escapes of non-escaping partial applies in the fullness of
|
|
// time. Once we handle that correctly, we should have the complete caller set
|
|
// here as well as an application. This would require us to have a flow
|
|
// sensitive callgraph analysis.
|
|
//
|
|
// CHECK-LABEL: calleeName: noescape_callee
|
|
// CHECK-NEXT: hasCaller: false
|
|
// CHECK-NEXT: minPartialAppliedArgs: 2
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: false
|
|
// CHECK-NEXT: hasAllCallers: false
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: - partial_apply_that_is_applied_and_passed_noescape
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: ...
|
|
sil @noescape_callee : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32, %1 : $Builtin.Int32):
|
|
return %0 : $Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: noescape_caller
|
|
// CHECK-NEXT: hasCaller: true
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: true
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: - partial_apply_that_is_applied_and_passed_noescape
|
|
// CHECK-NEXT: - thin_to_thick_is_applied_and_passed_noescape
|
|
// CHECK-NEXT: ...
|
|
sil private @noescape_caller : $@convention(thin) (@noescape @callee_owned () -> Builtin.Int32) -> () {
|
|
bb0(%0 : $@noescape @callee_owned () -> Builtin.Int32):
|
|
%1 = apply %0() : $@noescape @callee_owned () -> Builtin.Int32
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
sil @partial_apply_that_is_applied_and_passed_noescape : $@convention(thin) (Builtin.Int32) -> () {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%1 = function_ref @noescape_callee : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
%2 = partial_apply %1(%0, %0) : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
%3 = convert_escape_to_noescape %2 : $@callee_owned () -> Builtin.Int32 to $@noescape @callee_owned () -> Builtin.Int32
|
|
%4 = function_ref @noescape_caller : $@convention(thin) (@noescape @callee_owned () -> Builtin.Int32) -> ()
|
|
apply %4(%3) : $@convention(thin) (@noescape @callee_owned () -> Builtin.Int32) -> ()
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: calleeName: noescape_callee2
|
|
// CHECK-NEXT: hasCaller: false
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: false
|
|
// CHECK-NEXT: hasAllCallers: false
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: ...
|
|
sil @noescape_callee2 : $@convention(thin) () -> Builtin.Int32 {
|
|
bb0:
|
|
return undef : $Builtin.Int32
|
|
}
|
|
|
|
sil @thin_to_thick_is_applied_and_passed_noescape : $@convention(thin) (Builtin.Int32) -> () {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%1 = function_ref @noescape_callee2 : $@convention(thin) () -> Builtin.Int32
|
|
%2 = thin_to_thick_function %1 : $@convention(thin) () -> Builtin.Int32 to $@callee_owned () -> Builtin.Int32
|
|
%3 = convert_escape_to_noescape %2 : $@callee_owned () -> Builtin.Int32 to $@noescape @callee_owned () -> Builtin.Int32
|
|
%4 = function_ref @noescape_caller : $@convention(thin) (@noescape @callee_owned () -> Builtin.Int32) -> ()
|
|
apply %4(%3) : $@convention(thin) (@noescape @callee_owned () -> Builtin.Int32) -> ()
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
class Klass {
|
|
@_silgen_name("called_method")
|
|
func doSomething() {}
|
|
|
|
@_silgen_name("final_called_method")
|
|
final func finalDoSomething() {}
|
|
|
|
}
|
|
|
|
// Check that we know that we have a complete direct caller set, but that we do
|
|
// not have all callers since based on our trivial heuristic today, we always
|
|
// assume methods could be called indirectly.
|
|
//
|
|
// CHECK-LABEL: calleeName: called_method
|
|
// CHECK-NEXT: hasCaller: true
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: false
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: - apply_called_method
|
|
// CHECK-NEXT: ...
|
|
sil @called_method : $@convention(method) (@guaranteed Klass) -> () {
|
|
bb0(%0 : $Klass):
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
sil @apply_called_method : $@convention(thin) (@guaranteed Klass) -> () {
|
|
bb0(%0 : $Klass):
|
|
%1 = function_ref @called_method : $@convention(method) (@guaranteed Klass) -> ()
|
|
apply %1(%0) : $@convention(method) (@guaranteed Klass) -> ()
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// Once we understand final, in the fullness of time we should find all callers
|
|
// in this example. Today we do not though.
|
|
//
|
|
// CHECK-LABEL: calleeName: final_called_method
|
|
// CHECK-NEXT: hasCaller: true
|
|
// CHECK-NEXT: minPartialAppliedArgs: 0
|
|
// CHECK-NEXT: hasOnlyCompleteDirectCallerSets: true
|
|
// CHECK-NEXT: hasAllCallers: false
|
|
// CHECK-NEXT: partialAppliers:
|
|
// CHECK-NEXT: fullAppliers:
|
|
// CHECK-NEXT: - final_apply_called_method
|
|
// CHECK-NEXT: ...
|
|
sil @final_called_method : $@convention(method) (@guaranteed Klass) -> () {
|
|
bb0(%0 : $Klass):
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
sil @final_apply_called_method : $@convention(thin) (@guaranteed Klass) -> () {
|
|
bb0(%0 : $Klass):
|
|
%1 = function_ref @final_called_method : $@convention(method) (@guaranteed Klass) -> ()
|
|
apply %1(%0) : $@convention(method) (@guaranteed Klass) -> ()
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|