@@ -2818,11 +2818,14 @@ void ResultPlanner::execute(ArrayRef<SILValue> innerDirectResults,
2818
2818
// / \param inputSubstType Formal AST type of function value being thunked
2819
2819
// / \param outputOrigType Abstraction pattern of the thunk
2820
2820
// / \param outputSubstType Formal AST type of the thunk
2821
+ // / \param dynamicSelfType If true, the last parameter is a dummy used to pass
2822
+ // / DynamicSelfType metadata
2821
2823
static void buildThunkBody (SILGenFunction &SGF, SILLocation loc,
2822
2824
AbstractionPattern inputOrigType,
2823
2825
CanAnyFunctionType inputSubstType,
2824
2826
AbstractionPattern outputOrigType,
2825
- CanAnyFunctionType outputSubstType) {
2827
+ CanAnyFunctionType outputSubstType,
2828
+ CanType dynamicSelfType) {
2826
2829
PrettyStackTraceSILFunction stackTrace (" emitting reabstraction thunk in" ,
2827
2830
&SGF.F );
2828
2831
auto thunkType = SGF.F .getLoweredFunctionType ();
@@ -2832,6 +2835,11 @@ static void buildThunkBody(SILGenFunction &SGF, SILLocation loc,
2832
2835
SmallVector<ManagedValue, 8 > params;
2833
2836
SGF.collectThunkParams (loc, params);
2834
2837
2838
+ // Ignore the self parameter at the SIL level. IRGen will use it to
2839
+ // recover type metadata.
2840
+ if (dynamicSelfType)
2841
+ params.pop_back ();
2842
+
2835
2843
ManagedValue fnValue = params.pop_back_val ();
2836
2844
auto fnType = fnValue.getType ().castTo <SILFunctionType>();
2837
2845
assert (!fnType->isPolymorphic ());
@@ -2981,6 +2989,7 @@ CanSILFunctionType SILGenFunction::buildThunkType(
2981
2989
CanType &outputSubstType,
2982
2990
GenericEnvironment *&genericEnv,
2983
2991
SubstitutionMap &interfaceSubs,
2992
+ CanType &dynamicSelfType,
2984
2993
bool withoutActuallyEscaping) {
2985
2994
assert (!expectedType->isPolymorphic ());
2986
2995
assert (!sourceType->isPolymorphic ());
@@ -3080,6 +3089,18 @@ CanSILFunctionType SILGenFunction::buildThunkType(
3080
3089
? contextConvention
3081
3090
: ParameterConvention::Direct_Unowned});
3082
3091
3092
+ // If this thunk involves DynamicSelfType in any way, add a capture for it
3093
+ // in case we need to recover metadata.
3094
+ if (sourceType->hasDynamicSelfType () ||
3095
+ expectedType->hasDynamicSelfType ()) {
3096
+ dynamicSelfType = F.getSelfMetadataArgument ()->getType ().getASTType ();
3097
+ if (!isa<MetatypeType>(dynamicSelfType)) {
3098
+ dynamicSelfType = CanMetatypeType::get (dynamicSelfType,
3099
+ MetatypeRepresentation::Thick);
3100
+ }
3101
+ params.push_back ({dynamicSelfType, ParameterConvention::Direct_Unowned});
3102
+ }
3103
+
3083
3104
// Map the parameter and expected types out of context to get the interface
3084
3105
// type of the thunk.
3085
3106
SmallVector<SILParameterInfo, 4 > interfaceParams;
@@ -3147,11 +3168,13 @@ static ManagedValue createThunk(SILGenFunction &SGF,
3147
3168
GenericEnvironment *genericEnv = nullptr ;
3148
3169
auto toType = expectedType->getWithExtInfo (
3149
3170
expectedType->getExtInfo ().withNoEscape (false ));
3171
+ CanType dynamicSelfType;
3150
3172
auto thunkType = SGF.buildThunkType (sourceType, toType,
3151
3173
inputSubstType,
3152
3174
outputSubstType,
3153
3175
genericEnv,
3154
- interfaceSubs);
3176
+ interfaceSubs,
3177
+ dynamicSelfType);
3155
3178
auto thunk = SGF.SGM .getOrCreateReabstractionThunk (
3156
3179
thunkType,
3157
3180
sourceType,
@@ -3167,7 +3190,8 @@ static ManagedValue createThunk(SILGenFunction &SGF,
3167
3190
inputOrigType,
3168
3191
inputSubstType,
3169
3192
outputOrigType,
3170
- outputSubstType);
3193
+ outputSubstType,
3194
+ dynamicSelfType);
3171
3195
}
3172
3196
3173
3197
CanSILFunctionType substFnType = thunkType;
@@ -3179,10 +3203,18 @@ static ManagedValue createThunk(SILGenFunction &SGF,
3179
3203
3180
3204
// Create it in our current function.
3181
3205
auto thunkValue = SGF.B .createFunctionRefFor (loc, thunk);
3206
+ SmallVector<ManagedValue, 2 > thunkArgs;
3207
+ thunkArgs.push_back (fn.ensurePlusOne (SGF, loc));
3208
+ if (dynamicSelfType) {
3209
+ SILType dynamicSILType = SGF.getLoweredType (dynamicSelfType);
3210
+ SILValue value = SGF.B .createMetatype (loc, dynamicSILType);
3211
+ thunkArgs.push_back (ManagedValue::forUnmanaged (value));
3212
+ }
3213
+
3182
3214
ManagedValue thunkedFn =
3183
3215
SGF.B .createPartialApply (loc, thunkValue,
3184
3216
SILType::getPrimitiveObjectType (substFnType),
3185
- interfaceSubs, fn. ensurePlusOne (SGF, loc) ,
3217
+ interfaceSubs, thunkArgs ,
3186
3218
SILType::getPrimitiveObjectType (toType));
3187
3219
3188
3220
if (!expectedType->isNoEscape ()) {
@@ -3204,10 +3236,14 @@ static CanSILFunctionType buildWithoutActuallyEscapingThunkType(
3204
3236
noEscapingType->getExtInfo ().withNoEscape (false ));
3205
3237
3206
3238
CanType inputSubstType, outputSubstType;
3207
- return SGF.buildThunkType (noEscapingType, escapingType,
3208
- inputSubstType, outputSubstType,
3209
- genericEnv, interfaceSubs,
3210
- /* withoutActuallyEscaping=*/ true );
3239
+ CanType dynamicSelfType;
3240
+ auto type = SGF.buildThunkType (noEscapingType, escapingType,
3241
+ inputSubstType, outputSubstType,
3242
+ genericEnv, interfaceSubs,
3243
+ dynamicSelfType,
3244
+ /* withoutActuallyEscaping=*/ true );
3245
+ assert (!dynamicSelfType && " not implemented" );
3246
+ return type;
3211
3247
}
3212
3248
3213
3249
static void buildWithoutActuallyEscapingThunkBody (SILGenFunction &SGF) {
@@ -3984,8 +4020,11 @@ SILGenFunction::emitCanonicalFunctionThunk(SILLocation loc, ManagedValue fn,
3984
4020
// type
3985
4021
CanType inputSubstType;
3986
4022
CanType outputSubstType;
4023
+ CanType dynamicSelfType;
3987
4024
auto thunkTy = buildThunkType (nonCanonicalTy, canonicalTy, inputSubstType,
3988
- outputSubstType, genericEnv, interfaceSubs);
4025
+ outputSubstType, genericEnv, interfaceSubs,
4026
+ dynamicSelfType);
4027
+ assert (!dynamicSelfType && " not implemented" );
3989
4028
auto thunk = SGM.getOrCreateReabstractionThunk (thunkTy, nonCanonicalTy,
3990
4029
canonicalTy, F.isSerialized ());
3991
4030
if (thunk->empty ()) {
0 commit comments