Skip to content

Commit f902873

Browse files
committed
fix a crash when de-virtualizing class or actor methods with typed throws
The de-virtualizer utility didn't handle indirect error results when de-virtualizing class or actor methods. This resulted in a missing argument for the indirect error result in the new try_apply instruction. rdar://130545338
1 parent 20eb180 commit f902873

File tree

4 files changed

+63
-0
lines changed

4 files changed

+63
-0
lines changed

include/swift/SIL/ApplySite.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,11 @@ class FullApplySite : public ApplySite {
741741
return getArguments().slice(0, getNumIndirectSILResults());
742742
}
743743

744+
OperandValueArrayRef getIndirectSILErrorResults() const {
745+
return getArguments().slice(getNumIndirectSILResults(),
746+
getNumIndirectSILErrorResults());
747+
}
748+
744749
OperandValueArrayRef getArgumentsWithoutIndirectResults() const {
745750
return getArguments().slice(getNumIndirectSILResults() +
746751
getNumIndirectSILErrorResults());

lib/SILOptimizer/Utils/Devirtualize.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,17 @@ swift::devirtualizeClassMethod(FullApplySite applySite,
800800
++indirectResultArgIter;
801801
}
802802

803+
if (SILType errorTy = substConv.getIndirectErrorResultType(applySite.getFunction()->getTypeExpansionContext())) {
804+
auto errorArgs = applySite.getIndirectSILErrorResults();
805+
assert(errorArgs.size() == 1);
806+
SILValue errorArg = errorArgs[0];
807+
auto castRes = castValueToABICompatibleType(
808+
&builder, loc, errorArg, errorArg->getType(),
809+
errorTy, {applySite.getInstruction()});
810+
newArgs.push_back(castRes.first);
811+
changedCFG |= castRes.second;
812+
}
813+
803814
auto paramArgIter = applySite.getArgumentsWithoutIndirectResults().begin();
804815
// Skip the last parameter, which is `self`. Add it below.
805816
for (auto param : substConv.getParameters()) {

test/SILOptimizer/mandatory_inlining.sil

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1503,3 +1503,39 @@ entry(%executor: $Builtin.Executor):
15031503
%r = tuple ()
15041504
return %r : $()
15051505
}
1506+
1507+
private class X {
1508+
func foo<E>(_ e: E.Type) throws(E) where E : Error
1509+
}
1510+
1511+
sil private [ossa] @X_foo : $@convention(method) <E where E : Error> (@thick E.Type, @guaranteed X) -> @error_indirect E {
1512+
bb0(%0 : $*E, %1 : $@thick E.Type, %2 : @guaranteed $X):
1513+
%5 = tuple ()
1514+
return %5 : $()
1515+
}
1516+
1517+
// CHECK-LABEL: sil [ossa] @class_method_with_typed_throw
1518+
// CHECK: function_ref
1519+
// CHECK: } // end sil function 'class_method_with_typed_throw'
1520+
sil [ossa] @class_method_with_typed_throw : $@convention(thin) <E where E : Error> (@guaranteed X, @thick E.Type) -> () {
1521+
bb0(%0 : @guaranteed $X, %1 : $@thick E.Type):
1522+
%4 = alloc_stack $E
1523+
%5 = class_method %0 : $X, #X.foo : <E where E : Error> (X) -> (E.Type) throws(E) -> (), $@convention(method) <τ_0_0 where τ_0_0 : Error> (@thick τ_0_0.Type, @guaranteed X) -> @error_indirect τ_0_0
1524+
%6 = alloc_stack $E
1525+
try_apply %5<E>(%6, %1, %0) : $@convention(method) <τ_0_0 where τ_0_0 : Error> (@thick τ_0_0.Type, @guaranteed X) -> @error_indirect τ_0_0, normal bb1, error bb2
1526+
1527+
bb1(%8 : $()):
1528+
dealloc_stack %6 : $*E
1529+
dealloc_stack %4 : $*E
1530+
%11 = tuple ()
1531+
return %11 : $()
1532+
1533+
bb2:
1534+
unreachable
1535+
}
1536+
1537+
1538+
sil_vtable X {
1539+
#X.foo: <E where E : Error> (X) -> (E.Type) throws(E) -> () : @X_foo
1540+
}
1541+

test/SILOptimizer/mandatory_inlining.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,14 @@ func switchLoopWithPartialApplyCaller() {
203203
print(error)
204204
}
205205
}
206+
207+
private class Cl {
208+
func foo<E: Error>(_ e: E.Type) throws(E) {
209+
}
210+
}
211+
212+
213+
private func devirtualizeClassMethodWithTypedThrow<E: Error>(_ x: Cl, e: E.Type) {
214+
try! x.foo(e)
215+
}
216+

0 commit comments

Comments
 (0)