Skip to content

Commit 584c5cf

Browse files
authored
Merge pull request #4823 from slavapestov/fix-pseudogeneric-thunks-3.0
Fix problems with pseudogeneric thunks (3.0)
2 parents 3e8db09 + fb073be commit 584c5cf

File tree

9 files changed

+83
-17
lines changed

9 files changed

+83
-17
lines changed

lib/IRGen/GenReflection.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,10 @@ class CaptureDescriptorBuilder : public ReflectionMetadataBuilder {
633633
MetadataSourceMap getMetadataSourceMap() {
634634
MetadataSourceMap SourceMap;
635635

636-
if (!OrigCalleeType->isPolymorphic())
636+
// Generic parameters of pseudogeneric functions do not have
637+
// runtime metadata.
638+
if (!OrigCalleeType->isPolymorphic() ||
639+
OrigCalleeType->isPseudogeneric())
637640
return SourceMap;
638641

639642
// Any generic parameters that are not fulfilled are passed in via the
@@ -702,6 +705,19 @@ class CaptureDescriptorBuilder : public ReflectionMetadataBuilder {
702705

703706
for (auto ElementType : getElementTypes()) {
704707
auto SwiftType = ElementType.getSwiftRValueType();
708+
709+
// Erase pseudogeneric captures down to AnyObject.
710+
if (OrigCalleeType->isPseudogeneric()) {
711+
SwiftType = SwiftType.transform([&](Type t) -> Type {
712+
if (auto *archetype = t->getAs<ArchetypeType>()) {
713+
assert(archetype->requiresClass() && "don't know what to do");
714+
return IGM.Context.getProtocol(KnownProtocolKind::AnyObject)
715+
->getDeclaredType();
716+
}
717+
return t;
718+
})->getCanonicalType();
719+
}
720+
705721
auto InterfaceType = Caller.mapTypeOutOfContext(SwiftType);
706722
CaptureTypes.push_back(InterfaceType->getCanonicalType());
707723
}

lib/SILGen/SILGenBridging.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,11 @@ ManagedValue SILGenFunction::emitFuncToBlock(SILLocation loc,
341341
blockInterfaceTy->getParameters().end(),
342342
std::back_inserter(params));
343343

344+
auto genericSig = F.getLoweredFunctionType()->getGenericSignature();
345+
auto extInfo =
346+
SILFunctionType::ExtInfo()
347+
.withRepresentation(SILFunctionType::Representation::CFunctionPointer);
348+
344349
// The block invoke function must be pseudogeneric. This should be OK for now
345350
// since a bridgeable function's parameters and returns should all be
346351
// trivially representable in ObjC so not need to exercise the type metadata.
@@ -349,17 +354,17 @@ ManagedValue SILGenFunction::emitFuncToBlock(SILLocation loc,
349354
// that will require a redesign of the interface to support dependent-layout
350355
// context. Currently we don't capture anything directly into a block but a
351356
// Swift closure, but that's totally dumb.
357+
if (genericSig)
358+
extInfo = extInfo.withIsPseudogeneric();
359+
352360
auto invokeTy =
353-
SILFunctionType::get(F.getLoweredFunctionType()->getGenericSignature(),
354-
SILFunctionType::ExtInfo()
355-
.withRepresentation(SILFunctionType::Representation::
356-
CFunctionPointer)
357-
.withIsPseudogeneric(),
358-
ParameterConvention::Direct_Unowned,
359-
params,
360-
blockInterfaceTy->getAllResults(),
361-
blockInterfaceTy->getOptionalErrorResult(),
362-
getASTContext());
361+
SILFunctionType::get(genericSig,
362+
extInfo,
363+
ParameterConvention::Direct_Unowned,
364+
params,
365+
blockInterfaceTy->getAllResults(),
366+
blockInterfaceTy->getOptionalErrorResult(),
367+
getASTContext());
363368

364369
// Create the invoke function. Borrow the mangling scheme from reabstraction
365370
// thunks, which is what we are in spirit.

lib/SILGen/SILGenDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1973,7 +1973,7 @@ getOrCreateReabstractionThunk(GenericParamList *thunkContextParams,
19731973
// makes the actual thunk.
19741974
mangler.append("_TTR");
19751975
if (auto generics = thunkType->getGenericSignature()) {
1976-
mangler.append('G');
1976+
mangler.append(thunkType->isPseudogeneric() ? 'g' : 'G');
19771977
mangler.setModuleContext(M.getSwiftModule());
19781978
mangler.mangleGenericSignature(generics);
19791979
}

lib/SILGen/SILGenPoly.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2377,7 +2377,12 @@ CanSILFunctionType SILGenFunction::buildThunkType(
23772377

23782378
auto extInfo = expectedType->getExtInfo()
23792379
.withRepresentation(SILFunctionType::Representation::Thin);
2380-
2380+
2381+
// If our parent function was pseudogeneric, this thunk must also be
2382+
// pseudogeneric, since we have no way to pass generic parameters.
2383+
if (F.getLoweredFunctionType()->isPseudogeneric())
2384+
extInfo = extInfo.withIsPseudogeneric();
2385+
23812386
// Map the parameter and expected types out of context to get the interface
23822387
// type of the thunk.
23832388
SmallVector<SILParameterInfo, 4> interfaceParams;

test/Reflection/capture_descriptors.sil

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,28 @@ sil_vtable GenericClass {}
192192
// CHECK-NEXT: (reference_capture index=0))
193193

194194

195+
// Pseudogeneric caller and pseudogeneric callee -- type parameters are
196+
// erased at runtime.
197+
198+
sil @pseudogeneric_callee : $@convention(thin) @pseudogeneric <T : AnyObject, U : AnyObject> (@owned T, @owned U) -> () {
199+
bb0(%t: $T, %u: $U):
200+
%12 = tuple ()
201+
return %12 : $()
202+
}
203+
204+
sil @pseudogeneric_caller : $@convention(thin) @pseudogeneric <A : AnyObject, B : AnyObject, C : AnyObject> (@owned A, @owned B) -> @owned @pseudogeneric @callee_owned () -> () {
205+
bb0(%a: $A, %b: $B):
206+
%f = function_ref @pseudogeneric_callee : $@convention(thin) @pseudogeneric <T : AnyObject, U : AnyObject> (@owned T, @owned U) -> ()
207+
%c = partial_apply %f<A, B>(%a, %b) : $@convention(thin) @pseudogeneric <A : AnyObject, B : AnyObject> (@owned A, @owned B) -> ()
208+
return %c : $@pseudogeneric @callee_owned () -> ()
209+
}
210+
211+
// CHECK: - Capture types:
212+
// CHECK-NEXT: (protocol Swift.AnyObject)
213+
// CHECK-NEXT: (protocol Swift.AnyObject)
214+
// CHECK-NEXT: - Metadata sources:
215+
216+
195217
// Capturing lowered function types
196218

197219
sil @function_callee : $@convention(thin) (@convention(thin) () -> (), @convention(c) () -> (), @convention(block) () -> (), @convention(thick) () -> (), @convention(method) () -> (), @convention(witness_method) () -> ()) -> () {

test/SILGen/objc_blocks_bridging.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,21 @@ func bridgeNoescapeBlock() {
136136
// CHECK: function_ref @_TTRXFo___XFdCb___
137137
noescapeNonnullBlockAlias { }
138138
}
139+
140+
class ObjCClass : NSObject {}
141+
142+
extension ObjCClass {
143+
func someDynamicMethod(closure: (() -> ()) -> ()) {}
144+
}
145+
146+
struct GenericStruct<T> {
147+
let closure: (() -> ()) -> ()
148+
149+
func doStuff(o: ObjCClass) {
150+
o.someDynamicMethod(closure: closure)
151+
}
152+
}
153+
154+
// CHECK-LABEL: sil shared [transparent] [reabstraction_thunk] @_TTRgrXFo_oXFo_____XFdCb_dXFdCb_____ : $@convention(c) @pseudogeneric <T> (@inout_aliasable @block_storage @callee_owned (@owned @callee_owned () -> ()) -> (), @convention(block) () -> ()) -> ()
155+
// CHECK-LABEL: sil shared [transparent] [reabstraction_thunk] @_TTRgrXFdCb___XFo___ : $@convention(thin) @pseudogeneric <T> (@owned @convention(block) () -> ()) -> ()
156+

test/SILGen/objc_bridging_any.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ class SwiftIdLover : NSObject, Anyable {
422422
// CHECK-NEXT: strong_release [[RESULT]]
423423
// CHECK-NEXT: return [[BLOCK]]
424424

425-
// CHECK-LABEL: sil shared [transparent] [reabstraction_thunk] @_TTRXFo_iP___XFdCb_dPs9AnyObject___ : $@convention(c) @pseudogeneric (@inout_aliasable @block_storage @callee_owned (@in Any) -> (), AnyObject) -> ()
425+
// CHECK-LABEL: sil shared [transparent] [reabstraction_thunk] @_TTRXFo_iP___XFdCb_dPs9AnyObject___ : $@convention(c) (@inout_aliasable @block_storage @callee_owned (@in Any) -> (), AnyObject) -> ()
426426
// CHECK: bb0(%0 : $*@block_storage @callee_owned (@in Any) -> (), %1 : $AnyObject):
427427
// CHECK-NEXT: [[BLOCK_STORAGE_ADDR:%.*]] = project_block_storage %0
428428
// CHECK-NEXT: [[FUNCTION:%.*]] = load [[BLOCK_STORAGE_ADDR]]
@@ -493,7 +493,7 @@ class SwiftIdLover : NSObject, Anyable {
493493
// CHECK-NEXT: strong_release [[FUNCTION]]
494494
// CHECK-NEXT: return [[BLOCK]]
495495

496-
// CHECK-LABEL: sil shared [transparent] [reabstraction_thunk] @_TTRXFo__iP__XFdCb__aPs9AnyObject__ : $@convention(c) @pseudogeneric (@inout_aliasable @block_storage @callee_owned () -> @out Any) -> @autoreleased AnyObject
496+
// CHECK-LABEL: sil shared [transparent] [reabstraction_thunk] @_TTRXFo__iP__XFdCb__aPs9AnyObject__ : $@convention(c) (@inout_aliasable @block_storage @callee_owned () -> @out Any) -> @autoreleased AnyObject
497497
// CHECK: bb0(%0 : $*@block_storage @callee_owned () -> @out Any):
498498
// CHECK-NEXT: [[BLOCK_STORAGE_ADDR:%.*]] = project_block_storage %0
499499
// CHECK-NEXT: [[FUNCTION:%.*]] = load [[BLOCK_STORAGE_ADDR]]

test/SILGen/objc_imported_generic.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public func genericBlockBridging<T: Ansible>(x: GenericClass<T>) {
7777
// CHECK-LABEL: sil @_TF21objc_imported_generic20genericBlockBridging
7878
// CHECK: [[BLOCK_TO_FUNC:%.*]] = function_ref @_TTRGRxs9AnyObjectx21objc_imported_generic7AnsiblerXFdCb_dx_ax_XFo_ox_ox_
7979
// CHECK: partial_apply [[BLOCK_TO_FUNC]]<T, {{.*}}>
80-
// CHECK: [[FUNC_TO_BLOCK:%.*]] = function_ref @_TTRGRxs9AnyObjectx21objc_imported_generic7AnsiblerXFo_ox_ox_XFdCb_dx_ax_
80+
// CHECK: [[FUNC_TO_BLOCK:%.*]] = function_ref @_TTRgRxs9AnyObjectx21objc_imported_generic7AnsiblerXFo_ox_ox_XFdCb_dx_ax_
8181
// CHECK: init_block_storage_header {{.*}} invoke [[FUNC_TO_BLOCK]]<T,{{.*}}>
8282

8383
// CHECK-LABEL: sil @_TF21objc_imported_generic20arraysOfGenericParam

test/SILGen/objc_thunks.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ func registerAnsible() {
470470

471471
// FIXME: would be nice if we didn't need to re-abstract as much here.
472472

473-
// CHECK-LABEL: sil shared [transparent] [reabstraction_thunk] @_TTRXFo_oGSqFT_T____XFdCb_dGSqbT_T____ : $@convention(c) @pseudogeneric (@inout_aliasable @block_storage @callee_owned (@owned Optional<() -> ()>) -> (), Optional<@convention(block) () -> ()>) -> ()
473+
// CHECK-LABEL: sil shared [transparent] [reabstraction_thunk] @_TTRXFo_oGSqFT_T____XFdCb_dGSqbT_T____ : $@convention(c) (@inout_aliasable @block_storage @callee_owned (@owned Optional<() -> ()>) -> (), Optional<@convention(block) () -> ()>) -> ()
474474
// CHECK: [[HEAP_BLOCK_IUO:%.*]] = copy_block %1
475475
// CHECK: select_enum [[HEAP_BLOCK_IUO]]
476476
// CHECK: bb1:

0 commit comments

Comments
 (0)