Skip to content

Commit d87cb5b

Browse files
authored
Merge pull request #10901 from rjmccall/bridging-function-bugs
2 parents 69eb4d6 + 650e705 commit d87cb5b

File tree

3 files changed

+59
-3
lines changed

3 files changed

+59
-3
lines changed

lib/SIL/TypeLowering.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,9 +1567,26 @@ CanType TypeConverter::getLoweredRValueType(AbstractionPattern origType,
15671567
// on the abstract CC
15681568
// - ownership conventions are deduced
15691569
if (auto substFnType = dyn_cast<AnyFunctionType>(substType)) {
1570-
auto bridgedFnType = getBridgedFunctionType(origType, substFnType,
1571-
substFnType->getExtInfo());
1572-
return getNativeSILFunctionType(M, origType, bridgedFnType);
1570+
// If the formal type uses a C convention, it is not formally
1571+
// abstractable, and it may be subject to implicit bridging.
1572+
auto extInfo = substFnType->getExtInfo();
1573+
if (getSILFunctionLanguage(extInfo.getSILRepresentation())
1574+
== SILFunctionLanguage::C) {
1575+
// Bridge the parameters and result of the function type.
1576+
auto bridgedFnType = getBridgedFunctionType(origType, substFnType,
1577+
extInfo);
1578+
substFnType = bridgedFnType;
1579+
1580+
// Also rewrite the type of the abstraction pattern.
1581+
auto signature = getCurGenericContext();
1582+
if (origType.isTypeParameter()) {
1583+
origType = AbstractionPattern(signature, bridgedFnType);
1584+
} else {
1585+
origType.rewriteType(signature, bridgedFnType);
1586+
}
1587+
}
1588+
1589+
return getNativeSILFunctionType(M, origType, substFnType);
15731590
}
15741591

15751592
// Ignore dynamic self types.

lib/SILGen/SILGenBridging.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,12 @@ static void buildFuncToBlockInvokeBody(SILGenFunction &SGF,
359359
SILFunctionConventions blockConv(blockTy, SGF.SGM.M);
360360
SILFunctionConventions funcConv(funcTy, SGF.SGM.M);
361361

362+
// Make sure we lower the component types of the formal block type.
363+
formalBlockType =
364+
SGF.SGM.Types.getBridgedFunctionType(AbstractionPattern(formalBlockType),
365+
formalBlockType,
366+
formalBlockType->getExtInfo());
367+
362368
// Set up the indirect result.
363369
SILType blockResultTy = blockTy->getAllResultsType();
364370
SILValue indirectResult;

test/SILGen/objc_bridging.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,3 +637,36 @@ func callNonStandardBlock(value: Int) {
637637
// CHECK: enum $Optional<@convention(block) () -> @owned Optional<AnyObject>>
638638
takesNonStandardBlock { return value }
639639
}
640+
641+
func takeTwoAnys(_ lhs: Any, _ rhs: Any) -> Any { return lhs }
642+
643+
// CHECK-LABEL: sil hidden @_T013objc_bridging22defineNonStandardBlockyyp1x_tF
644+
func defineNonStandardBlock(x: Any) {
645+
// CHECK: function_ref @_T013objc_bridging22defineNonStandardBlockyyp1x_tFypypcfU_
646+
// CHECK: function_ref @_T0ypypIxir_yXlyXlIyBya_TR : $@convention(c) (@inout_aliasable @block_storage @callee_owned (@in Any) -> @out Any, AnyObject) -> @autoreleased AnyObject
647+
648+
let fn : @convention(block) (Any) -> Any = { y in takeTwoAnys(x, y) }
649+
}
650+
651+
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0ypypIxir_yXlyXlIyBya_TR : $@convention(c) (@inout_aliasable @block_storage @callee_owned (@in Any) -> @out Any, AnyObject) -> @autoreleased AnyObject
652+
// CHECK: bb0(%0 : $*@block_storage @callee_owned (@in Any) -> @out Any, %1 : $AnyObject):
653+
// CHECK: [[T0:%.*]] = copy_value %1 : $AnyObject
654+
// CHECK: [[T1:%.*]] = open_existential_ref [[T0]] : $AnyObject
655+
// CHECK: [[ARG:%.*]] = alloc_stack $Any
656+
// CHECK: [[T2:%.*]] = init_existential_addr [[ARG]]
657+
// CHECK: store [[T1]] to [init] [[T2]]
658+
// CHECK: [[RESULT:%.*]] = alloc_stack $Any
659+
// CHECK: apply {{.*}}([[RESULT]], [[ARG]])
660+
661+
// CHECK-LABEL: sil hidden @_T013objc_bridging15castToCFunctionySV3ptr_tF : $@convention(thin) (UnsafeRawPointer) -> () {
662+
func castToCFunction(ptr: UnsafeRawPointer) {
663+
// CHECK: [[CASTFN:%.*]] = function_ref @_T0s13unsafeBitCastq_x_q_m2totr0_lF
664+
// CHECK: [[OUT:%.*]] = alloc_stack $@convention(c) (Optional<AnyObject>) -> ()
665+
// CHECK: [[IN:%.]] = alloc_stack $UnsafeRawPointer
666+
// CHECK: store %0 to [trivial] [[IN]] : $*UnsafeRawPointer
667+
// CHECK: [[META:%.*]] = metatype $@thick (@convention(c) (Optional<AnyObject>) -> ()).Type
668+
// CHECK: apply [[CASTFN]]<UnsafeRawPointer, @convention(c) (AnyObject?) -> ()>([[OUT]], [[IN]], [[META]]) : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @thick τ_0_1.Type) -> @out τ_0_1
669+
// CHECK: [[RESULT:%.*]] = load [trivial] %3 : $*@convention(c) (Optional<AnyObject>) -> ()
670+
typealias Fn = @convention(c) (AnyObject?) -> Void
671+
unsafeBitCast(ptr, to: Fn.self)(nil)
672+
}

0 commit comments

Comments
 (0)