Skip to content

Commit fb073be

Browse files
committed
SILGen: Fix some issues with @pseudogeneric thunks
This would manifest as crashes in IRGen when bridging a block taking another block in generic context. - When emitting a re-abstraction thunk, make it pseudogeneric if its parent function is pseudogeneric. This ensures we don't try to get runtime type metadata when it doesn't exist. - Mangle pseudogeneric-ness of a reabstraction thunk correctly. Otherwise we could emit thunks with different signatures under the same mangling. - Only set the pseudogeneric attribute if the thunk has a generic signature, since otherwise the mangling is no longer unique. Fixes <rdar://problem/27718566>.
1 parent 5c08690 commit fb073be

File tree

7 files changed

+44
-16
lines changed

7 files changed

+44
-16
lines changed

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/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)