@@ -319,6 +319,82 @@ static bool canOptimizeCast(const swift::Type &BridgedTargetTy,
319319 return false ;
320320}
321321
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+
322398// / Create a call of _bridgeToObjectiveC which converts an _ObjectiveCBridgeable
323399// / instance into a bridged ObjC type.
324400SILInstruction *
@@ -328,7 +404,6 @@ CastOptimizer::optimizeBridgedSwiftToObjCCast(SILDynamicCastInst dynamicCast) {
328404 bool isConditional = dynamicCast.isConditional ();
329405 SILValue Src = dynamicCast.getSource ();
330406 SILValue Dest = dynamicCast.getDest ();
331- CanType Source = dynamicCast.getSourceType ();
332407 CanType BridgedTargetTy = dynamicCast.getBridgedTargetType ();
333408 SILBasicBlock *SuccessBB = dynamicCast.getSuccessBlock ();
334409 SILBasicBlock *FailureBB = dynamicCast.getFailureBlock ();
@@ -341,91 +416,26 @@ CastOptimizer::optimizeBridgedSwiftToObjCCast(SILDynamicCastInst dynamicCast) {
341416 }
342417
343418 // 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 ();
388426 }
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 ;
415427
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);
421429 SILFunctionConventions substConv (SubstFnTy.castTo <SILFunctionType>(), M);
422430
423431 // check that we can go through with the optimization
424432 if (!canOptimizeCast (BridgedTargetTy, M, substConv)) {
425433 return nullptr ;
426434 }
427435
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 ();
429439 if (Src->getType ().isAddress () && !substConv.isSILIndirect (ParamTypes[0 ])) {
430440 // Create load
431441 Src = Builder.createLoad (Loc, Src, LoadOwnershipQualifier::Unqualified);
@@ -512,7 +522,7 @@ CastOptimizer::optimizeBridgedSwiftToObjCCast(SILDynamicCastInst dynamicCast) {
512522 }
513523
514524 // 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 );
516526
517527 auto releaseSrc = [&](SILBuilder &Builder) {
518528 if (AddressOnlyType) {
0 commit comments