File tree Expand file tree Collapse file tree 2 files changed +43
-5
lines changed Expand file tree Collapse file tree 2 files changed +43
-5
lines changed Original file line number Diff line number Diff line change @@ -675,24 +675,30 @@ static bool isSupportedClosure(const SILInstruction *Closure) {
675
675
return false ;
676
676
677
677
if (auto *PAI = dyn_cast<PartialApplyInst>(Closure)) {
678
- // Bail if any of the arguments are passed by address and
679
- // are not @inout.
680
- // This is a temporary limitation.
678
+ // Check whether each argument is supported.
681
679
auto ClosureCallee = FRI->getReferencedFunction ();
682
680
auto ClosureCalleeConv = ClosureCallee->getConventions ();
683
681
unsigned ClosureArgIdxBase =
684
682
ClosureCalleeConv.getNumSILArguments () - PAI->getNumArguments ();
685
683
for (auto pair : llvm::enumerate (PAI->getArguments ())) {
686
684
auto Arg = pair.value ();
687
685
auto ClosureArgIdx = pair.index () + ClosureArgIdxBase;
686
+ auto ArgConvention =
687
+ ClosureCalleeConv.getSILArgumentConvention (ClosureArgIdx);
688
+
688
689
SILType ArgTy = Arg->getType ();
690
+ // Specializing (currently) always produces a retain in the caller.
691
+ // That's not allowed for values of move-only type.
692
+ if (ArgTy.isMoveOnly ()) {
693
+ return false ;
694
+ }
695
+
696
+ // Only @inout/@inout_aliasable addresses are (currently) supported.
689
697
// If our argument is an object, continue...
690
698
if (ArgTy.isObject ()) {
691
699
++ClosureArgIdx;
692
700
continue ;
693
701
}
694
- auto ArgConvention =
695
- ClosureCalleeConv.getSILArgumentConvention (ClosureArgIdx);
696
702
if (ArgConvention != SILArgumentConvention::Indirect_Inout &&
697
703
ArgConvention != SILArgumentConvention::Indirect_InoutAliasable)
698
704
return false ;
Original file line number Diff line number Diff line change @@ -938,3 +938,35 @@ bb0(%0 : $Int):
938
938
%empty = tuple ()
939
939
return %empty : $()
940
940
}
941
+
942
+ struct NC : ~Copyable {
943
+ deinit {}
944
+ }
945
+
946
+ sil hidden [noinline] @noncopyable_arg_closure : $@convention(thin) (@guaranteed NC) -> () {
947
+ bb0(%0 : $NC):
948
+ %retval = tuple ()
949
+ return %retval : $()
950
+ }
951
+
952
+ sil hidden [noinline] @use_noncopyable_arg_closure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> () {
953
+ bb0(%0 : $@noescape @callee_guaranteed () -> ()):
954
+ %2 = apply %0() : $@noescape @callee_guaranteed () -> ()
955
+ %3 = tuple ()
956
+ return %3 : $()
957
+ }
958
+
959
+ // Ensure that a retain_value of a noncopyable value isn't created.
960
+ // CHECK-LABEL: sil @dont_specialize_noncopyable_arg_closure : {{.*}} {
961
+ // CHECK-NOT: retain_value {{%.*}} : $NC
962
+ // CHECK-LABEL: } // end sil function 'dont_specialize_noncopyable_arg_closure'
963
+ sil @dont_specialize_noncopyable_arg_closure : $@convention(thin) (@guaranteed NC) -> () {
964
+ bb0(%nc : $NC):
965
+ %closure_fn = function_ref @noncopyable_arg_closure : $@convention(thin) (@guaranteed NC) -> ()
966
+ %closure = partial_apply [callee_guaranteed] [on_stack] %closure_fn(%nc) : $@convention(thin) (@guaranteed NC) -> ()
967
+ %use = function_ref @use_noncopyable_arg_closure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
968
+ apply %use(%closure) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
969
+ dealloc_stack %closure : $@noescape @callee_guaranteed () -> ()
970
+ %11 = tuple ()
971
+ return %11 : $()
972
+ }
You can’t perform that action at this time.
0 commit comments