@@ -319,6 +319,82 @@ static bool canOptimizeCast(const swift::Type &BridgedTargetTy,
319
319
return false ;
320
320
}
321
321
322
+ static Optional<std::pair<SILFunction *, SubstitutionMap>>
323
+ findBridgeToObjCFunc (SILOptFunctionBuilder &functionBuilder,
324
+ SILDynamicCastInst dynamicCast) {
325
+ CanType sourceType = dynamicCast.getSourceType ();
326
+ auto loc = dynamicCast.getLocation ();
327
+ auto &mod = dynamicCast.getModule ();
328
+ auto bridgedProto =
329
+ mod.getASTContext ().getProtocol (KnownProtocolKind::ObjectiveCBridgeable);
330
+
331
+ auto conf = mod.getSwiftModule ()->lookupConformance (sourceType, bridgedProto);
332
+ assert (conf && " _ObjectiveCBridgeable conformance should exist" );
333
+ (void )conf;
334
+
335
+ // Generate code to invoke _bridgeToObjectiveC
336
+
337
+ auto *ntd = sourceType.getNominalOrBoundGenericNominal ();
338
+ assert (ntd);
339
+ auto members = ntd->lookupDirect (mod.getASTContext ().Id_bridgeToObjectiveC );
340
+ if (members.empty ()) {
341
+ SmallVector<ValueDecl *, 4 > foundMembers;
342
+ if (ntd->getDeclContext ()->lookupQualified (
343
+ ntd, mod.getASTContext ().Id_bridgeToObjectiveC ,
344
+ NLOptions::NL_ProtocolMembers, foundMembers)) {
345
+ // Returned members are starting with the most specialized ones.
346
+ // Thus, the first element is what we are looking for.
347
+ members.push_back (foundMembers.front ());
348
+ }
349
+ }
350
+
351
+ // There should be exactly one implementation of _bridgeToObjectiveC.
352
+ if (members.size () != 1 )
353
+ return None;
354
+
355
+ auto bridgeFuncDecl = members.front ();
356
+ ModuleDecl *modDecl =
357
+ mod.getASTContext ().getLoadedModule (mod.getASTContext ().Id_Foundation );
358
+ if (!modDecl)
359
+ return None;
360
+ SmallVector<ValueDecl *, 2 > results;
361
+ modDecl->lookupMember (results, sourceType.getNominalOrBoundGenericNominal (),
362
+ mod.getASTContext ().Id_bridgeToObjectiveC ,
363
+ Identifier ());
364
+ ArrayRef<ValueDecl *> resultsRef (results);
365
+ if (resultsRef.empty ()) {
366
+ mod.getSwiftModule ()->lookupMember (
367
+ results, sourceType.getNominalOrBoundGenericNominal (),
368
+ mod.getASTContext ().Id_bridgeToObjectiveC , Identifier ());
369
+ resultsRef = results;
370
+ }
371
+ if (resultsRef.size () != 1 )
372
+ return None;
373
+
374
+ auto *resultDecl = results.front ();
375
+ auto memberDeclRef = SILDeclRef (resultDecl);
376
+ auto *bridgedFunc = functionBuilder.getOrCreateFunction (
377
+ loc, memberDeclRef, ForDefinition_t::NotForDefinition);
378
+
379
+ // Get substitutions, if source is a bound generic type.
380
+ auto subMap = sourceType->getContextSubstitutionMap (
381
+ mod.getSwiftModule (), bridgeFuncDecl->getDeclContext ());
382
+
383
+ // Implementation of _bridgeToObjectiveC could not be found.
384
+ if (!bridgedFunc)
385
+ return None;
386
+
387
+ if (dynamicCast.getFunction ()->isSerialized () &&
388
+ !bridgedFunc->hasValidLinkageForFragileRef ())
389
+ return None;
390
+
391
+ if (bridgedFunc->getLoweredFunctionType ()
392
+ ->getSingleResult ()
393
+ .isFormalIndirect ())
394
+ return None;
395
+ return std::make_pair (bridgedFunc, subMap);
396
+ }
397
+
322
398
// / Create a call of _bridgeToObjectiveC which converts an _ObjectiveCBridgeable
323
399
// / instance into a bridged ObjC type.
324
400
SILInstruction *
@@ -328,7 +404,6 @@ CastOptimizer::optimizeBridgedSwiftToObjCCast(SILDynamicCastInst dynamicCast) {
328
404
bool isConditional = dynamicCast.isConditional ();
329
405
SILValue Src = dynamicCast.getSource ();
330
406
SILValue Dest = dynamicCast.getDest ();
331
- CanType Source = dynamicCast.getSourceType ();
332
407
CanType BridgedTargetTy = dynamicCast.getBridgedTargetType ();
333
408
SILBasicBlock *SuccessBB = dynamicCast.getSuccessBlock ();
334
409
SILBasicBlock *FailureBB = dynamicCast.getFailureBlock ();
@@ -341,91 +416,26 @@ CastOptimizer::optimizeBridgedSwiftToObjCCast(SILDynamicCastInst dynamicCast) {
341
416
}
342
417
343
418
// Find the _BridgedToObjectiveC protocol.
344
- auto BridgedProto =
345
- M.getASTContext ().getProtocol (KnownProtocolKind::ObjectiveCBridgeable);
346
-
347
- auto Conf = M.getSwiftModule ()->lookupConformance (Source, BridgedProto);
348
-
349
- assert (Conf && " _ObjectiveCBridgeable conformance should exist" );
350
- (void )Conf;
351
-
352
- // Generate code to invoke _bridgeToObjectiveC
353
- SILBuilderWithScope Builder (Inst, BuilderContext);
354
-
355
- auto *NTD = Source.getNominalOrBoundGenericNominal ();
356
- assert (NTD);
357
- auto Members = NTD->lookupDirect (M.getASTContext ().Id_bridgeToObjectiveC );
358
- if (Members.empty ()) {
359
- SmallVector<ValueDecl *, 4 > FoundMembers;
360
- if (NTD->getDeclContext ()->lookupQualified (
361
- NTD, M.getASTContext ().Id_bridgeToObjectiveC ,
362
- NLOptions::NL_ProtocolMembers, FoundMembers)) {
363
- // Returned members are starting with the most specialized ones.
364
- // Thus, the first element is what we are looking for.
365
- Members.push_back (FoundMembers.front ());
366
- }
367
- }
368
-
369
- // There should be exactly one implementation of _bridgeToObjectiveC.
370
- if (Members.size () != 1 )
371
- return nullptr ;
372
-
373
- auto BridgeFuncDecl = Members.front ();
374
- auto BridgeFuncDeclRef = SILDeclRef (BridgeFuncDecl);
375
- ModuleDecl *Mod =
376
- M.getASTContext ().getLoadedModule (M.getASTContext ().Id_Foundation );
377
- if (!Mod)
378
- return nullptr ;
379
- SmallVector<ValueDecl *, 2 > Results;
380
- Mod->lookupMember (Results, Source.getNominalOrBoundGenericNominal (),
381
- M.getASTContext ().Id_bridgeToObjectiveC , Identifier ());
382
- ArrayRef<ValueDecl *> ResultsRef (Results);
383
- if (ResultsRef.empty ()) {
384
- M.getSwiftModule ()->lookupMember (
385
- Results, Source.getNominalOrBoundGenericNominal (),
386
- M.getASTContext ().Id_bridgeToObjectiveC , Identifier ());
387
- ResultsRef = Results;
419
+ SILFunction *bridgedFunc = nullptr ;
420
+ SubstitutionMap subMap;
421
+ {
422
+ auto result = findBridgeToObjCFunc (FunctionBuilder, dynamicCast);
423
+ if (!result)
424
+ return nullptr ;
425
+ std::tie (bridgedFunc, subMap) = result.getValue ();
388
426
}
389
- if (ResultsRef.size () != 1 )
390
- return nullptr ;
391
-
392
- auto *resultDecl = Results.front ();
393
- auto MemberDeclRef = SILDeclRef (resultDecl);
394
- auto *BridgedFunc = FunctionBuilder.getOrCreateFunction (
395
- Loc, MemberDeclRef, ForDefinition_t::NotForDefinition);
396
-
397
- // Implementation of _bridgeToObjectiveC could not be found.
398
- if (!BridgedFunc)
399
- return nullptr ;
400
-
401
- if (Inst->getFunction ()->isSerialized () &&
402
- !BridgedFunc->hasValidLinkageForFragileRef ())
403
- return nullptr ;
404
-
405
- auto ParamTypes = BridgedFunc->getLoweredFunctionType ()->getParameters ();
406
-
407
- auto SILFnTy = SILType::getPrimitiveObjectType (
408
- M.Types .getConstantFunctionType (BridgeFuncDeclRef));
409
-
410
- // TODO: Handle return from witness function.
411
- if (BridgedFunc->getLoweredFunctionType ()
412
- ->getSingleResult ()
413
- .isFormalIndirect ())
414
- return nullptr ;
415
427
416
- // Get substitutions, if source is a bound generic type.
417
- auto SubMap = Source->getContextSubstitutionMap (
418
- M.getSwiftModule (), BridgeFuncDecl->getDeclContext ());
419
-
420
- SILType SubstFnTy = SILFnTy.substGenericArgs (M, SubMap);
428
+ SILType SubstFnTy = bridgedFunc->getLoweredType ().substGenericArgs (M, subMap);
421
429
SILFunctionConventions substConv (SubstFnTy.castTo <SILFunctionType>(), M);
422
430
423
431
// check that we can go through with the optimization
424
432
if (!canOptimizeCast (BridgedTargetTy, M, substConv)) {
425
433
return nullptr ;
426
434
}
427
435
428
- auto FnRef = Builder.createFunctionRef (Loc, BridgedFunc);
436
+ SILBuilderWithScope Builder (Inst, BuilderContext);
437
+ auto FnRef = Builder.createFunctionRef (Loc, bridgedFunc);
438
+ auto ParamTypes = SubstFnTy.castTo <SILFunctionType>()->getParameters ();
429
439
if (Src->getType ().isAddress () && !substConv.isSILIndirect (ParamTypes[0 ])) {
430
440
// Create load
431
441
Src = Builder.createLoad (Loc, Src, LoadOwnershipQualifier::Unqualified);
@@ -512,7 +522,7 @@ CastOptimizer::optimizeBridgedSwiftToObjCCast(SILDynamicCastInst dynamicCast) {
512
522
}
513
523
514
524
// Generate a code to invoke the bridging function.
515
- auto *NewAI = Builder.createApply (Loc, FnRef, SubMap , Src, false );
525
+ auto *NewAI = Builder.createApply (Loc, FnRef, subMap , Src, false );
516
526
517
527
auto releaseSrc = [&](SILBuilder &Builder) {
518
528
if (AddressOnlyType) {
0 commit comments