Skip to content

Commit 5043ed4

Browse files
Merge pull request #24453 from aschwaighofer/fix_generic_specialization_noreturn
Fix generic specialization that can result in noreturn apply without …
2 parents 9ba1d8a + 6e3d69f commit 5043ed4

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

include/swift/SIL/TypeSubstCloner.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,13 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
193193
Helper.getArguments(), Inst->isNonThrowing(),
194194
GenericSpecializationInformation::create(
195195
Inst, getBuilder()));
196+
// Specialization can return noreturn applies that were not identified as
197+
// such before.
198+
if (N->isCalleeNoReturn() &&
199+
!isa<UnreachableInst>(*std::next(SILBasicBlock::iterator(Inst)))) {
200+
noReturnApplies.push_back(N);
201+
}
202+
196203
recordClonedInstruction(Inst, N);
197204
}
198205

@@ -381,6 +388,9 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
381388
SILFunction &Original;
382389
/// True, if used for inlining.
383390
bool Inlining;
391+
// Generic specialization can create noreturn applications that where
392+
// previously not identifiable as such.
393+
SmallVector<ApplyInst *, 16> noReturnApplies;
384394
};
385395

386396
} // end namespace swift

include/swift/SILOptimizer/Utils/GenericCloner.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ class GenericCloner
7474
return SC.getCloned();
7575
}
7676

77+
void fixUp(SILFunction *calleeFunction);
78+
7779
protected:
7880
void visitTerminator(SILBasicBlock *BB);
7981

lib/SILOptimizer/Utils/GenericCloner.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,12 @@ const SILDebugScope *GenericCloner::remapScope(const SILDebugScope *DS) {
191191
RemappedScopeCache.insert({DS, RemappedScope});
192192
return RemappedScope;
193193
}
194+
195+
void GenericCloner::fixUp(SILFunction *f) {
196+
for (auto *apply : noReturnApplies) {
197+
auto applyBlock = apply->getParent();
198+
applyBlock->split(std::next(SILBasicBlock::iterator(apply)));
199+
getBuilder().setInsertionPoint(applyBlock);
200+
getBuilder().createUnreachable(apply->getLoc());
201+
}
202+
}

test/SILOptimizer/specialize.sil

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,3 +692,37 @@ bb0(%0 : $*T):
692692
%13 = tuple ()
693693
return %13 : $()
694694
} // end sil function 'testSelfRecursiveFunction'
695+
696+
sil @id : $@convention(thin) <T> (@in T) -> @out T {
697+
bb0(%0 : $*T, %1 :$*T):
698+
copy_addr [take] %1 to [initialization] %0 : $*T
699+
%t = tuple ()
700+
return %t : $()
701+
}
702+
703+
// This should not assert.
704+
// CHECK-LABEL: sil shared @$s26specialize_no_return_applys5NeverO_Tg5
705+
// CHECK: apply
706+
// CHECK-NEXT: unreachable
707+
708+
sil @specialize_no_return_apply: $@convention(thin) <T> (@thick T.Type) -> () {
709+
bb0(%0 : $@thick T.Type):
710+
%in = alloc_stack $T
711+
%out = alloc_stack $T
712+
%f = function_ref @id : $@convention(thin) <T> (@in T) -> @out T
713+
%r = apply %f<T>(%out, %in) : $@convention(thin) <T> (@in T) -> @out T
714+
dealloc_stack %out : $*T
715+
dealloc_stack %in : $*T
716+
%t = tuple ()
717+
return %t : $()
718+
}
719+
720+
sil @test_specialize_noreturn_apply : $@convention(thin) () -> () {
721+
bb0:
722+
%f = function_ref @specialize_no_return_apply : $@convention(thin) <T> (@thick T.Type) -> ()
723+
%m = metatype $@thick Never.Type
724+
%r = apply %f<Never>(%m) : $@convention(thin) <T> (@thick T.Type) -> ()
725+
%t = tuple ()
726+
return %t : $()
727+
728+
}

0 commit comments

Comments
 (0)