@@ -841,6 +841,13 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM,
841841 (origType->hasSelfParam () &&
842842 isSelfContextParameter (origType->getSelfParameter ()));
843843
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+
844851 // If there's a data pointer required, but it's a swift-retainable
845852 // value being passed as the context, just forward it down.
846853 if (!layout) {
@@ -993,9 +1000,11 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM,
9931000 emitApplyArgument (subIGF, origParamInfo,
9941001 substType->getParameters ()[origParamI],
9951002 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);
9991008 ++origParamI;
10001009 } else {
10011010 args.add (param.claimAll ());
@@ -1043,8 +1052,7 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM,
10431052 // witness table. Metadata for Self is derived inside the partial
10441053 // application thunk and doesn't need to be stored in the outer
10451054 // context.
1046- if (origType->getRepresentation () ==
1047- SILFunctionTypeRepresentation::WitnessMethod) {
1055+ if (isWitnessMethodCallee) {
10481056 assert (fnContext->getType () == IGM.Int8PtrTy );
10491057 llvm::Value *wtable = subIGF.Builder .CreateBitCast (
10501058 fnContext, IGM.WitnessTablePtrTy );
@@ -1061,6 +1069,11 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM,
10611069 args.add (llvm::UndefValue::get (IGM.RefCountedPtrTy ));
10621070 }
10631071
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+
10641077 // Pass down the error result.
10651078 if (origType->hasErrorResult ()) {
10661079 llvm::Value *errorResultPtr = origParams.claimNext ();
@@ -1070,8 +1083,7 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM,
10701083
10711084 assert (origParams.empty ());
10721085
1073- if (origType->getRepresentation () ==
1074- SILFunctionTypeRepresentation::WitnessMethod) {
1086+ if (isWitnessMethodCallee) {
10751087 assert (witnessMetadata.SelfMetadata ->getType () == IGM.TypeMetadataPtrTy );
10761088 args.add (witnessMetadata.SelfMetadata );
10771089 assert (witnessMetadata.SelfWitnessTable ->getType () == IGM.WitnessTablePtrTy );
0 commit comments