@@ -841,6 +841,13 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM,
841
841
(origType->hasSelfParam () &&
842
842
isSelfContextParameter (origType->getSelfParameter ()));
843
843
844
+ // Witness method calls expect self, followed by the self type followed by,
845
+ // the witness table at the end of the parameter list. But polymorphic
846
+ // arguments come before this.
847
+ bool isWitnessMethodCallee = origType->getRepresentation () ==
848
+ SILFunctionTypeRepresentation::WitnessMethod;
849
+ Explosion witnessMethodSelfValue;
850
+
844
851
// If there's a data pointer required, but it's a swift-retainable
845
852
// value being passed as the context, just forward it down.
846
853
if (!layout) {
@@ -993,9 +1000,11 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM,
993
1000
emitApplyArgument (subIGF, origParamInfo,
994
1001
substType->getParameters ()[origParamI],
995
1002
param, origParam);
996
-
997
- needsAllocas |=
998
- addNativeArgument (subIGF, origParam, origParamInfo, args);
1003
+ bool isWitnessMethodCalleeSelf = (isWitnessMethodCallee &&
1004
+ origParamI + 1 == origType->getParameters ().size ());
1005
+ needsAllocas |= addNativeArgument (
1006
+ subIGF, origParam, origParamInfo,
1007
+ isWitnessMethodCalleeSelf ? witnessMethodSelfValue : args);
999
1008
++origParamI;
1000
1009
} else {
1001
1010
args.add (param.claimAll ());
@@ -1043,8 +1052,7 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM,
1043
1052
// witness table. Metadata for Self is derived inside the partial
1044
1053
// application thunk and doesn't need to be stored in the outer
1045
1054
// context.
1046
- if (origType->getRepresentation () ==
1047
- SILFunctionTypeRepresentation::WitnessMethod) {
1055
+ if (isWitnessMethodCallee) {
1048
1056
assert (fnContext->getType () == IGM.Int8PtrTy );
1049
1057
llvm::Value *wtable = subIGF.Builder .CreateBitCast (
1050
1058
fnContext, IGM.WitnessTablePtrTy );
@@ -1061,6 +1069,11 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM,
1061
1069
args.add (llvm::UndefValue::get (IGM.RefCountedPtrTy ));
1062
1070
}
1063
1071
1072
+ // Add the witness methods self argument before the error parameter after the
1073
+ // polymorphic arguments.
1074
+ if (isWitnessMethodCallee)
1075
+ witnessMethodSelfValue.transferInto (args, witnessMethodSelfValue.size ());
1076
+
1064
1077
// Pass down the error result.
1065
1078
if (origType->hasErrorResult ()) {
1066
1079
llvm::Value *errorResultPtr = origParams.claimNext ();
@@ -1070,8 +1083,7 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM,
1070
1083
1071
1084
assert (origParams.empty ());
1072
1085
1073
- if (origType->getRepresentation () ==
1074
- SILFunctionTypeRepresentation::WitnessMethod) {
1086
+ if (isWitnessMethodCallee) {
1075
1087
assert (witnessMetadata.SelfMetadata ->getType () == IGM.TypeMetadataPtrTy );
1076
1088
args.add (witnessMetadata.SelfMetadata );
1077
1089
assert (witnessMetadata.SelfWitnessTable ->getType () == IGM.WitnessTablePtrTy );
0 commit comments