Skip to content

Commit ee5090a

Browse files
authored
Merge pull request #8924 from swiftix/partial_spec_no_return_fixes
[generic-specializer] Fix for specializations which are no-return functions
2 parents 5494424 + 7e7252d commit ee5090a

File tree

2 files changed

+68
-4
lines changed

2 files changed

+68
-4
lines changed

lib/SILOptimizer/Utils/Generics.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1670,10 +1670,19 @@ static ApplySite replaceWithSpecializedCallee(ApplySite AI,
16701670
Arguments, A->isNonThrowing());
16711671
if (StoreResultTo) {
16721672
assert(substConv.useLoweredAddresses());
1673-
// Store the direct result to the original result address.
1674-
fixUsedVoidType(A, Loc, Builder);
1675-
Builder.createStore(Loc, NewAI, StoreResultTo,
1676-
StoreOwnershipQualifier::Unqualified);
1673+
if (!CalleeSILSubstFnTy.isNoReturnFunction()) {
1674+
// Store the direct result to the original result address.
1675+
fixUsedVoidType(A, Loc, Builder);
1676+
Builder.createStore(Loc, NewAI, StoreResultTo,
1677+
StoreOwnershipQualifier::Unqualified);
1678+
} else {
1679+
Builder.createUnreachable(Loc);
1680+
// unreachable should be the terminator instruction.
1681+
// So, split the current basic block right after the
1682+
// inserted unreachable instruction.
1683+
Builder.getInsertionPoint()->getParent()->split(
1684+
Builder.getInsertionPoint());
1685+
}
16771686
}
16781687
A->replaceAllUsesWith(NewAI);
16791688
return NewAI;

test/SILOptimizer/specialize.sil

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,3 +527,58 @@ bb0(%0 : $Builtin.RawPointer):
527527
%5 = tuple ()
528528
return %5 : $()
529529
}
530+
531+
// invokeGenericClosure<A>(todo:)
532+
sil [noinline] @invokeGenericClosure : $@convention(thin) <R> (@owned @callee_owned () -> (@out R, @error Error)) -> (@out R, @error Error) {
533+
bb0(%0 : $*R, %1 : $@callee_owned () -> (@out R, @error Error)):
534+
debug_value %1 : $@callee_owned () -> (@out R, @error Error), let, name "todo", argno 1 // id: %2
535+
debug_value undef : $Error, var, name "$error", argno 2 // id: %3
536+
strong_retain %1 : $@callee_owned () -> (@out R, @error Error) // id: %4
537+
try_apply %1(%0) : $@callee_owned () -> (@out R, @error Error), normal bb1, error bb2 // id: %5
538+
539+
bb1(%6 : $()): // Preds: bb0
540+
strong_release %1 : $@callee_owned () -> (@out R, @error Error) // id: %7
541+
%8 = tuple () // user: %9
542+
return %8 : $() // id: %9
543+
544+
// %10 // user: %12
545+
bb2(%10 : $Error): // Preds: bb0
546+
strong_release %1 : $@callee_owned () -> (@out R, @error Error) // id: %11
547+
throw %10 : $Error // id: %12
548+
} // end sil function 'invokeGenericClosure'
549+
550+
sil public_external @error : $@convention(thin) () -> Never
551+
552+
// action()
553+
sil @action : $@convention(thin) () -> Never
554+
555+
// thunk for @callee_owned () -> (@unowned Never, @error @owned Error)
556+
sil @action_thunk : $@convention(thin) (@owned @callee_owned () -> (Never, @error Error)) -> (@out Never, @error Error)
557+
558+
// Check that in a case where a generic specialization is a non-return function,
559+
// the return value is not stored after the call and an unreachable instruction
560+
// is inserted as a terminator of a basic block.
561+
//
562+
// CHECK-LABEL: sil @testGenericClosureSpecialization
563+
// Call of the generic specialization of invokeGenericClosure<Never>
564+
// CHECK: function_ref @_T020invokeGenericClosures5NeverO_Tg5 : $@convention(thin) (@owned @callee_owned () -> (@out Never, @error Error)) -> (Never, @error Error)
565+
// CHECK: apply [nothrow]
566+
// CHECK: unreachable
567+
// CHECK: end sil function 'testGenericClosureSpecialization'
568+
sil @testGenericClosureSpecialization : $@convention(thin) () -> @error Error {
569+
bb0:
570+
// function_ref invokeGenericClosure<A>(todo:)
571+
%1 = function_ref @invokeGenericClosure : $@convention(thin) <τ_0_0> (@owned @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
572+
%2 = alloc_stack $Never
573+
// function_ref action()
574+
%3 = function_ref @action : $@convention(thin) () -> Never
575+
%4 = thin_to_thick_function %3 : $@convention(thin) () -> Never to $@callee_owned () -> Never
576+
%5 = convert_function %4 : $@callee_owned () -> Never to $@callee_owned () -> (Never, @error Error)
577+
// function_ref thunk for @callee_owned () -> (@unowned Never, @error @owned Error)
578+
%6 = function_ref @action_thunk : $@convention(thin) (@owned @callee_owned () -> (Never, @error Error)) -> (@out Never, @error Error)
579+
%7 = partial_apply %6(%5) : $@convention(thin) (@owned @callee_owned () -> (Never, @error Error)) -> (@out Never, @error Error)
580+
%8 = apply [nothrow] %1<Never>(%2, %7) : $@convention(thin) <τ_0_0> (@owned @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
581+
dealloc_stack %2 : $*Never
582+
%12 = tuple ()
583+
return %12 : $()
584+
} // end sil function 'testGenericClosureSpecialization'

0 commit comments

Comments
 (0)