Skip to content

Commit 234aabb

Browse files
committed
SILGen: Emit reabtraction thunks that can capture DynamicSelfType
Fixes <https://bugs.swift.org/browse/SR-9429>.
1 parent efa9966 commit 234aabb

File tree

4 files changed

+89
-13
lines changed

4 files changed

+89
-13
lines changed

lib/SILGen/SILGenBridging.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -934,9 +934,11 @@ SILGenFunction::emitBlockToFunc(SILLocation loc,
934934
loweredFuncTy, loweredFuncTy->getExtInfo().withNoEscape(false),
935935
loweredFuncTy->getWitnessMethodConformanceOrNone());
936936

937+
CanType dynamicSelfType;
937938
auto thunkTy = buildThunkType(loweredBlockTy, loweredFuncTyWithoutNoEscape,
938939
inputSubstType, outputSubstType,
939-
genericEnv, interfaceSubs);
940+
genericEnv, interfaceSubs, dynamicSelfType);
941+
assert(!dynamicSelfType && "Not implemented");
940942

941943
auto thunk = SGM.getOrCreateReabstractionThunk(thunkTy,
942944
loweredBlockTy,

lib/SILGen/SILGenFunction.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1757,6 +1757,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
17571757
CanType &outputSubstType,
17581758
GenericEnvironment *&genericEnv,
17591759
SubstitutionMap &interfaceSubs,
1760+
CanType &dynamicSelfType,
17601761
bool withoutActuallyEscaping=false);
17611762

17621763
//===--------------------------------------------------------------------===//

lib/SILGen/SILGenPoly.cpp

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2818,11 +2818,14 @@ void ResultPlanner::execute(ArrayRef<SILValue> innerDirectResults,
28182818
/// \param inputSubstType Formal AST type of function value being thunked
28192819
/// \param outputOrigType Abstraction pattern of the thunk
28202820
/// \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
28212823
static void buildThunkBody(SILGenFunction &SGF, SILLocation loc,
28222824
AbstractionPattern inputOrigType,
28232825
CanAnyFunctionType inputSubstType,
28242826
AbstractionPattern outputOrigType,
2825-
CanAnyFunctionType outputSubstType) {
2827+
CanAnyFunctionType outputSubstType,
2828+
CanType dynamicSelfType) {
28262829
PrettyStackTraceSILFunction stackTrace("emitting reabstraction thunk in",
28272830
&SGF.F);
28282831
auto thunkType = SGF.F.getLoweredFunctionType();
@@ -2832,6 +2835,11 @@ static void buildThunkBody(SILGenFunction &SGF, SILLocation loc,
28322835
SmallVector<ManagedValue, 8> params;
28332836
SGF.collectThunkParams(loc, params);
28342837

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+
28352843
ManagedValue fnValue = params.pop_back_val();
28362844
auto fnType = fnValue.getType().castTo<SILFunctionType>();
28372845
assert(!fnType->isPolymorphic());
@@ -2981,6 +2989,7 @@ CanSILFunctionType SILGenFunction::buildThunkType(
29812989
CanType &outputSubstType,
29822990
GenericEnvironment *&genericEnv,
29832991
SubstitutionMap &interfaceSubs,
2992+
CanType &dynamicSelfType,
29842993
bool withoutActuallyEscaping) {
29852994
assert(!expectedType->isPolymorphic());
29862995
assert(!sourceType->isPolymorphic());
@@ -3080,6 +3089,18 @@ CanSILFunctionType SILGenFunction::buildThunkType(
30803089
? contextConvention
30813090
: ParameterConvention::Direct_Unowned});
30823091

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+
30833104
// Map the parameter and expected types out of context to get the interface
30843105
// type of the thunk.
30853106
SmallVector<SILParameterInfo, 4> interfaceParams;
@@ -3147,11 +3168,13 @@ static ManagedValue createThunk(SILGenFunction &SGF,
31473168
GenericEnvironment *genericEnv = nullptr;
31483169
auto toType = expectedType->getWithExtInfo(
31493170
expectedType->getExtInfo().withNoEscape(false));
3171+
CanType dynamicSelfType;
31503172
auto thunkType = SGF.buildThunkType(sourceType, toType,
31513173
inputSubstType,
31523174
outputSubstType,
31533175
genericEnv,
3154-
interfaceSubs);
3176+
interfaceSubs,
3177+
dynamicSelfType);
31553178
auto thunk = SGF.SGM.getOrCreateReabstractionThunk(
31563179
thunkType,
31573180
sourceType,
@@ -3167,7 +3190,8 @@ static ManagedValue createThunk(SILGenFunction &SGF,
31673190
inputOrigType,
31683191
inputSubstType,
31693192
outputOrigType,
3170-
outputSubstType);
3193+
outputSubstType,
3194+
dynamicSelfType);
31713195
}
31723196

31733197
CanSILFunctionType substFnType = thunkType;
@@ -3179,10 +3203,18 @@ static ManagedValue createThunk(SILGenFunction &SGF,
31793203

31803204
// Create it in our current function.
31813205
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+
31823214
ManagedValue thunkedFn =
31833215
SGF.B.createPartialApply(loc, thunkValue,
31843216
SILType::getPrimitiveObjectType(substFnType),
3185-
interfaceSubs, fn.ensurePlusOne(SGF, loc),
3217+
interfaceSubs, thunkArgs,
31863218
SILType::getPrimitiveObjectType(toType));
31873219

31883220
if (!expectedType->isNoEscape()) {
@@ -3204,10 +3236,14 @@ static CanSILFunctionType buildWithoutActuallyEscapingThunkType(
32043236
noEscapingType->getExtInfo().withNoEscape(false));
32053237

32063238
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;
32113247
}
32123248

32133249
static void buildWithoutActuallyEscapingThunkBody(SILGenFunction &SGF) {
@@ -3984,8 +4020,11 @@ SILGenFunction::emitCanonicalFunctionThunk(SILLocation loc, ManagedValue fn,
39844020
// type
39854021
CanType inputSubstType;
39864022
CanType outputSubstType;
4023+
CanType dynamicSelfType;
39874024
auto thunkTy = buildThunkType(nonCanonicalTy, canonicalTy, inputSubstType,
3988-
outputSubstType, genericEnv, interfaceSubs);
4025+
outputSubstType, genericEnv, interfaceSubs,
4026+
dynamicSelfType);
4027+
assert(!dynamicSelfType && "not implemented");
39894028
auto thunk = SGM.getOrCreateReabstractionThunk(thunkTy, nonCanonicalTy,
39904029
canonicalTy, F.isSerialized());
39914030
if (thunk->empty()) {

test/SILGen/dynamic_self.swift

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
// RUN: %target-swift-emit-silgen -module-name dynamic_self -enable-sil-ownership %s -disable-objc-attr-requires-foundation-module -enable-objc-interop | %FileCheck %s
2-
// RUN: %target-swift-emit-sil -module-name dynamic_self -O %s -disable-objc-attr-requires-foundation-module -enable-objc-interop
3-
// RUN: %target-swift-emit-ir -module-name dynamic_self %s -disable-objc-attr-requires-foundation-module -enable-objc-interop
1+
// RUN: %target-swift-emit-silgen -swift-version 4 %s -enable-sil-ownership -disable-objc-attr-requires-foundation-module -enable-objc-interop | %FileCheck %s
2+
// RUN: %target-swift-emit-sil -swift-version 4 -O %s -enable-sil-ownership -disable-objc-attr-requires-foundation-module -enable-objc-interop
3+
// RUN: %target-swift-emit-ir -swift-version 4 %s -enable-sil-ownership -disable-objc-attr-requires-foundation-module -enable-objc-interop
4+
5+
// RUN: %target-swift-emit-silgen -swift-version 5 %s -enable-sil-ownership -disable-objc-attr-requires-foundation-module -enable-objc-interop | %FileCheck %s
6+
// RUN: %target-swift-emit-sil -swift-version 5 -O %s -enable-sil-ownership -disable-objc-attr-requires-foundation-module -enable-objc-interop
7+
// RUN: %target-swift-emit-ir -swift-version 5 %s -enable-sil-ownership -disable-objc-attr-requires-foundation-module -enable-objc-interop
48

59
protocol P {
610
func f() -> Self
@@ -380,6 +384,36 @@ class Generic<T> {
380384
}
381385
}
382386

387+
protocol SelfReplaceable {
388+
init<T>(t: T)
389+
}
390+
391+
extension SelfReplaceable {
392+
init(with fn: (Self.Type) -> Self) {
393+
self = fn(Self.self)
394+
}
395+
396+
init<T>(with genericFn: (Self.Type) -> T) {
397+
self.init(t: genericFn(Self.self))
398+
}
399+
}
400+
401+
class SelfReplaceClass : SelfReplaceable {
402+
let t: Any
403+
404+
required init<T>(t: T) {
405+
self.t = t
406+
}
407+
408+
convenience init(y: Int) {
409+
self.init(with: { type in type.init(t: y) })
410+
}
411+
412+
convenience init(z: Int) {
413+
self.init(with: { type in z })
414+
}
415+
}
416+
383417
// CHECK-LABEL: sil_witness_table hidden X: P module dynamic_self {
384418
// CHECK: method #P.f!1: {{.*}} : @$s12dynamic_self1XCAA1PA2aDP1f{{[_0-9a-zA-Z]*}}FTW
385419

0 commit comments

Comments
 (0)