@@ -891,6 +891,37 @@ void SILGenFunction::collectThunkParams(
891
891
}
892
892
}
893
893
894
+ // / If the inner function we are calling (with type \c fnType) from the thunk
895
+ // / created by \c SGF requires an indirect error argument, returns that
896
+ // / argument.
897
+ static llvm::Optional<SILValue>
898
+ emitThunkIndirectErrorArgument (SILGenFunction &SGF, SILLocation loc,
899
+ CanSILFunctionType fnType) {
900
+ // If the function we're calling has as indirect error result, create an
901
+ // argument for it.
902
+ auto innerError = fnType->getOptionalErrorResult ();
903
+ if (!innerError || innerError->getConvention () != ResultConvention::Indirect)
904
+ return llvm::None;
905
+
906
+ // If the type of the indirect error is the same for both the inner
907
+ // function and the thunk, so we can re-use the indirect error slot.
908
+ auto loweredErrorResultType = SGF.getSILType (*innerError, fnType);
909
+ if (SGF.IndirectErrorResult &&
910
+ SGF.IndirectErrorResult ->getType ().getObjectType ()
911
+ == loweredErrorResultType) {
912
+ return SGF.IndirectErrorResult ;
913
+ }
914
+
915
+ // The type of the indirect error in the inner function differs from
916
+ // that of the thunk, or the thunk has a direct error, so allocate a
917
+ // stack location for the inner indirect error.
918
+ SILValue innerIndirectErrorAddr =
919
+ SGF.B .createAllocStack (loc, loweredErrorResultType);
920
+ SGF.enterDeallocStackCleanup (innerIndirectErrorAddr);
921
+
922
+ return innerIndirectErrorAddr;
923
+ }
924
+
894
925
namespace {
895
926
896
927
class TranslateIndirect : public Cleanup {
@@ -4847,27 +4878,9 @@ static void buildThunkBody(SILGenFunction &SGF, SILLocation loc,
4847
4878
4848
4879
// If the function we're calling has as indirect error result, create an
4849
4880
// argument for it.
4850
- SILValue innerIndirectErrorAddr;
4851
- if (auto innerError = fnType->getOptionalErrorResult ()) {
4852
- if (innerError->getConvention () == ResultConvention::Indirect) {
4853
- auto loweredErrorResultType = SGF.getSILType (*innerError, fnType);
4854
- if (SGF.IndirectErrorResult &&
4855
- SGF.IndirectErrorResult ->getType ().getObjectType ()
4856
- == loweredErrorResultType) {
4857
- // The type of the indirect error is the same for both the inner
4858
- // function and the thunk, so we can re-use the indirect error slot.
4859
- innerIndirectErrorAddr = SGF.IndirectErrorResult ;
4860
- } else {
4861
- // The type of the indirect error in the inner function differs from
4862
- // that of the thunk, or the thunk has a direct error, so allocate a
4863
- // stack location for the inner indirect error.
4864
- innerIndirectErrorAddr =
4865
- SGF.B .createAllocStack (loc, loweredErrorResultType);
4866
- SGF.enterDeallocStackCleanup (innerIndirectErrorAddr);
4867
- }
4868
-
4869
- argValues.push_back (innerIndirectErrorAddr);
4870
- }
4881
+ if (auto innerIndirectErrorAddr =
4882
+ emitThunkIndirectErrorArgument (SGF, loc, fnType)) {
4883
+ argValues.push_back (*innerIndirectErrorAddr);
4871
4884
}
4872
4885
4873
4886
// Add the rest of the arguments.
@@ -6573,6 +6586,13 @@ void SILGenFunction::emitProtocolWitness(
6573
6586
witnessFTy, thunkTy);
6574
6587
}
6575
6588
6589
+ // If the function we're calling has as indirect error result, create an
6590
+ // argument for it.
6591
+ if (auto innerIndirectErrorAddr =
6592
+ emitThunkIndirectErrorArgument (*this , loc, witnessFTy)) {
6593
+ args.push_back (*innerIndirectErrorAddr);
6594
+ }
6595
+
6576
6596
// - the rest of the arguments
6577
6597
forwardFunctionArguments (*this , loc, witnessFTy, witnessParams, args);
6578
6598
0 commit comments