20
20
#include " swift/AST/ParameterList.h"
21
21
#include " swift/Basic/Fallthrough.h"
22
22
#include " swift/SIL/SILArgument.h"
23
+ #include " swift/SIL/SILUndef.h"
23
24
#include " swift/SIL/TypeLowering.h"
24
25
25
26
using namespace swift ;
@@ -280,13 +281,26 @@ static void buildFuncToBlockInvokeBody(SILGenFunction &gen,
280
281
funcParam.getType ()));
281
282
}
282
283
284
+ CanType resultType;
285
+ SILValue indirectResult;
286
+
287
+ if (funcTy->getNumAllResults () == 0 )
288
+ resultType = TupleType::getEmpty (gen.SGM .getASTContext ());
289
+ else {
290
+ auto result = funcTy->getSingleResult ();
291
+ resultType = result.getType ();
292
+
293
+ auto &tl = gen.getTypeLowering (result.getSILType ());
294
+ if (tl.isAddressOnly ()) {
295
+ assert (result.getConvention () == ResultConvention::Indirect);
296
+ assert (resultType->isAny () &&
297
+ " Should not be trying to bridge anything except for Any here" );
298
+ }
299
+ }
300
+
283
301
// Call the native function.
284
- assert (!funcTy->hasIndirectResults ()
285
- && " block thunking func with indirect result not supported" );
286
- assert (funcTy->getNumDirectResults () <= 1
287
- && " block thunking func with multiple results not supported" );
288
302
ManagedValue result = gen.emitMonomorphicApply (loc, fn, args,
289
- funcTy-> getSILResult (). getSwiftRValueType () ,
303
+ resultType ,
290
304
ApplyOptions::None,
291
305
None, None)
292
306
.getAsSingleValue (gen, loc);
@@ -437,16 +451,43 @@ static ManagedValue emitNativeToCBridgedNonoptionalValue(SILGenFunction &gen,
437
451
return gen.emitNativeToBridgedError (loc, v, loweredBridgedTy);
438
452
}
439
453
440
- return v;
454
+ // Fall back to dynamic Any-to-id bridging.
455
+ // The destination type should be AnyObject in this case.
456
+ //
457
+ // TODO: Should only get here if -enable-id-as-any is active.
458
+ assert (gen.getASTContext ().LangOpts .EnableIdAsAny
459
+ && loweredBridgedTy->isEqual (
460
+ gen.getASTContext ().getProtocol (KnownProtocolKind::AnyObject)
461
+ ->getDeclaredType ()));
462
+
463
+ // If the input argument is known to be an existential, save the runtime
464
+ // some work by opening it.
465
+ if (loweredNativeTy->isExistentialType ()) {
466
+ auto openedTy = ArchetypeType::getOpened (loweredNativeTy);
467
+
468
+ auto openedExistential = gen.emitOpenExistential (loc, v, openedTy,
469
+ gen.getLoweredType (openedTy));
470
+ v = openedExistential.Value ;
471
+ loweredNativeTy = openedTy;
472
+ }
473
+
474
+ // Call into the stdlib intrinsic.
475
+ if (auto bridgeAnything =
476
+ gen.getASTContext ().getBridgeAnythingToObjectiveC (nullptr )) {
477
+ Substitution sub (loweredNativeTy, {});
478
+ return gen.emitApplyOfLibraryIntrinsic (loc, bridgeAnything, sub, v,
479
+ SGFContext ())
480
+ .getAsSingleValue (gen, loc);
481
+ }
482
+
483
+ // Shouldn't get here unless the standard library is busted.
484
+ return gen.emitUndef (loc, bridgedTy);
441
485
}
442
486
443
487
static ManagedValue emitNativeToCBridgedValue (SILGenFunction &gen,
444
488
SILLocation loc,
445
489
ManagedValue v,
446
490
SILType bridgedTy) {
447
- assert (v.getType ().isLoadable (gen.F .getModule ()) &&
448
- " Cannot bridge address-only types" );
449
-
450
491
CanType loweredBridgedTy = bridgedTy.getSwiftRValueType ();
451
492
CanType loweredNativeTy = v.getType ().getSwiftRValueType ();
452
493
if (loweredNativeTy == loweredBridgedTy)
@@ -472,9 +513,9 @@ static ManagedValue emitNativeToCBridgedValue(SILGenFunction &gen,
472
513
}
473
514
474
515
ManagedValue SILGenFunction::emitNativeToBridgedValue (SILLocation loc,
475
- ManagedValue v,
476
- SILFunctionTypeRepresentation destRep,
477
- CanType loweredBridgedTy){
516
+ ManagedValue v,
517
+ SILFunctionTypeRepresentation destRep,
518
+ CanType loweredBridgedTy){
478
519
switch (getSILFunctionLanguage (destRep)) {
479
520
case SILFunctionLanguage::Swift:
480
521
// No additional bridging needed for native functions.
@@ -499,15 +540,29 @@ static void buildBlockToFuncThunkBody(SILGenFunction &gen,
499
540
500
541
SmallVector<ManagedValue, 4 > args;
501
542
SILBasicBlock *entry = &*gen.F .begin ();
543
+
544
+ CanType resultType;
545
+ SILValue indirectResult;
546
+
547
+ if (funcTy->getNumAllResults () == 0 )
548
+ resultType = TupleType::getEmpty (gen.SGM .getASTContext ());
549
+ else {
550
+ auto result = funcTy->getSingleResult ();
551
+ resultType = result.getType ();
552
+
553
+ auto &tl = gen.getTypeLowering (result.getSILType ());
554
+ if (tl.isAddressOnly ()) {
555
+ assert (result.getConvention () == ResultConvention::Indirect);
556
+
557
+ indirectResult = new (gen.SGM .M ) SILArgument (entry, result.getSILType ());
558
+ }
559
+ }
560
+
502
561
for (unsigned i : indices (funcTy->getParameters ())) {
503
562
auto ¶m = funcTy->getParameters ()[i];
504
563
auto &blockParam = blockTy->getParameters ()[i];
505
564
506
565
auto &tl = gen.getTypeLowering (param.getSILType ());
507
- assert ((tl.isTrivial ()
508
- ? param.getConvention () == ParameterConvention::Direct_Unowned
509
- : param.getConvention () == ParameterConvention::Direct_Owned)
510
- && " nonstandard conventions for native functions not implemented" );
511
566
SILValue v = new (gen.SGM .M ) SILArgument (entry, param.getSILType ());
512
567
auto mv = gen.emitManagedRValueWithCleanup (v, tl);
513
568
args.push_back (gen.emitNativeToBridgedValue (loc, mv,
@@ -522,26 +577,22 @@ static void buildBlockToFuncThunkBody(SILGenFunction &gen,
522
577
ManagedValue block = gen.emitManagedRValueWithCleanup (blockV);
523
578
524
579
// Call the block.
525
- assert (!funcTy->hasIndirectResults ()
526
- && " block thunking func with indirect result not supported" );
527
580
ManagedValue result = gen.emitMonomorphicApply (loc, block, args,
528
- funcTy-> getSILResult (). getSwiftRValueType () ,
529
- ApplyOptions::None,
530
- /* override CC*/ SILFunctionTypeRepresentation::Block,
531
- /* foreign error*/ None)
581
+ resultType ,
582
+ ApplyOptions::None,
583
+ /* override CC*/ SILFunctionTypeRepresentation::Block,
584
+ /* foreign error*/ None)
532
585
.getAsSingleValue (gen, loc);
533
586
534
587
// Return the result at +1.
535
- # ifndef NDEBUG
536
- for ( auto result : funcTy-> getDirectResults ()) {
537
- assert ((gen. getTypeLowering (result. getSILType ()). isTrivial ()
538
- ? result. getConvention () == ResultConvention::Unowned
539
- : result. getConvention () == ResultConvention::Owned)
540
- && " nonstandard conventions for return not implemented " );
588
+ auto r = result. forward (gen);
589
+
590
+ if (indirectResult) {
591
+ gen. B . createCopyAddr (loc, r, indirectResult,
592
+ IsTake, IsInitialization);
593
+ r = gen. B . createTuple (loc, funcTy-> getSILResult (), {} );
541
594
}
542
- #endif
543
595
544
- auto r = result.forward (gen);
545
596
scope.pop ();
546
597
gen.B .createReturn (loc, r);
547
598
}
@@ -584,9 +635,6 @@ static ManagedValue emitCBridgedToNativeValue(SILGenFunction &gen,
584
635
SILLocation loc,
585
636
ManagedValue v,
586
637
SILType nativeTy) {
587
- assert (nativeTy.isLoadable (gen.F .getModule ()) &&
588
- " Cannot bridge address-only types" );
589
-
590
638
CanType loweredNativeTy = nativeTy.getSwiftRValueType ();
591
639
CanType loweredBridgedTy = v.getType ().getSwiftRValueType ();
592
640
if (loweredNativeTy == loweredBridgedTy)
@@ -640,8 +688,29 @@ static ManagedValue emitCBridgedToNativeValue(SILGenFunction &gen,
640
688
}
641
689
642
690
// Bridge NSError to Error.
643
- if (loweredBridgedTy == gen.SGM .Types .getNSErrorType ()) {
691
+ if (loweredBridgedTy == gen.SGM .Types .getNSErrorType ())
644
692
return gen.emitBridgedToNativeError (loc, v);
693
+
694
+ // id-to-Any bridging.
695
+ if (loweredNativeTy->isAny ()) {
696
+ assert (loweredBridgedTy->isEqual (
697
+ gen.getASTContext ().getProtocol (KnownProtocolKind::AnyObject)
698
+ ->getDeclaredType ())
699
+ && " Any should bridge to AnyObject" );
700
+
701
+ // Open the type of the reference and use it to build an Any.
702
+ auto openedTy = ArchetypeType::getOpened (loweredBridgedTy);
703
+ auto openedSILTy = SILType::getPrimitiveObjectType (openedTy);
704
+ // TODO: Ever need to handle +0 values here?
705
+ assert (v.hasCleanup ());
706
+ auto opened = gen.B .createOpenExistentialRef (loc, v.forward (gen),
707
+ openedSILTy);
708
+ auto result = gen.emitTemporaryAllocation (loc, nativeTy);
709
+ auto resultVal = gen.B .createInitExistentialAddr (loc, result,
710
+ openedTy, openedSILTy,
711
+ {});
712
+ gen.B .createStore (loc, opened, resultVal);
713
+ return gen.emitManagedRValueWithCleanup (result);
645
714
}
646
715
647
716
return v;
@@ -779,13 +848,9 @@ static SILFunctionType *emitObjCThunkArguments(SILGenFunction &gen,
779
848
assert (foreignError && " couldn't find foreign error convention!" );
780
849
}
781
850
782
- // Emit the indirect result arguments, if any.
783
- // FIXME: we're just assuming that these match up exactly?
784
- for (auto indirectResult : objcFnTy->getIndirectResults ()) {
785
- SILType argTy = indirectResult.getSILType ();
786
- auto arg = new (gen.F .getModule ()) SILArgument (gen.F .begin (), argTy);
787
- args.push_back (arg);
788
- }
851
+ // We don't know what to do with indirect results from the Objective-C side.
852
+ assert (objcFnTy->getNumIndirectResults () == 0 &&
853
+ " Objective-C methods cannot have indirect results" );
789
854
790
855
// Emit the other arguments, taking ownership of arguments if necessary.
791
856
auto inputs = objcFnTy->getParameters ();
@@ -839,7 +904,13 @@ static SILFunctionType *emitObjCThunkArguments(SILGenFunction &gen,
839
904
" didn't find foreign error slot" );
840
905
841
906
// Bridge the input types.
842
- Scope scope (gen.Cleanups , CleanupLocation::get (loc));
907
+
908
+ // FIXME: We really want alloc_stacks to outlive this scope, because
909
+ // bridging id-to-Any requires allocating an Any which gets passed to
910
+ // the native entry point.
911
+
912
+ // Scope scope(gen.Cleanups, CleanupLocation::get(loc));
913
+
843
914
assert (bridgedArgs.size () == nativeInputs.size ());
844
915
for (unsigned i = 0 , size = bridgedArgs.size (); i < size; ++i) {
845
916
SILType argTy = swiftFnTy->getParameters ()[i].getSILType ();
@@ -864,28 +935,43 @@ static SILFunctionType *emitObjCThunkArguments(SILGenFunction &gen,
864
935
void SILGenFunction::emitNativeToForeignThunk (SILDeclRef thunk) {
865
936
assert (thunk.isForeign );
866
937
SILDeclRef native = thunk.asForeign (false );
867
-
938
+ auto nativeInfo = getConstantInfo (native);
939
+ auto subs = F.getForwardingSubstitutions ();
940
+ auto substTy = nativeInfo.SILFnType ->substGenericArgs (
941
+ SGM.M , SGM.M .getSwiftModule (), subs);
942
+ SILType substSILTy = SILType::getPrimitiveObjectType (substTy);
943
+
868
944
auto loc = thunk.getAsRegularLocation ();
869
945
loc.markAutoGenerated ();
870
946
Scope scope (Cleanups, CleanupLocation::get (loc));
871
947
872
- // Bridge the arguments.
948
+ // If we are bridging a Swift method with an Any return value, create a
949
+ // stack allocation to hold the result, since Any is address-only.
873
950
SmallVector<SILValue, 4 > args;
951
+
952
+ if (substTy->getNumIndirectResults () > 0 ) {
953
+ SILResultInfo indirectResult = substTy->getSingleResult ();
954
+ assert (indirectResult.getType ()->isAny () &&
955
+ " Should not be trying to bridge anything except for Any here" );
956
+ args.push_back (emitTemporaryAllocation (loc, indirectResult.getSILType ()));
957
+ }
958
+
959
+ // Now, enter a cleanup used for bridging the arguments. Note that if we
960
+ // have an indirect result, it must be outside of this scope, otherwise
961
+ // we will deallocate it too early.
962
+ Scope argScope (Cleanups, CleanupLocation::get (loc));
963
+
964
+ // Bridge the arguments.
874
965
Optional<ForeignErrorConvention> foreignError;
875
966
SILValue foreignErrorSlot;
876
967
auto objcFnTy = emitObjCThunkArguments (*this , loc, thunk, args,
877
968
foreignErrorSlot, foreignError);
878
- auto nativeInfo = getConstantInfo (native);
879
969
auto swiftResultTy =
880
970
F.mapTypeIntoContext (nativeInfo.SILFnType ->getSILResult ());
881
971
auto objcResultTy = objcFnTy->getSILResult ();
882
972
883
973
// Call the native entry point.
884
974
SILValue nativeFn = emitGlobalFunctionRef (loc, native, nativeInfo);
885
- auto subs = F.getForwardingSubstitutions ();
886
- auto substTy = nativeInfo.SILFnType ->substGenericArgs (
887
- SGM.M , SGM.M .getSwiftModule (), subs);
888
- SILType substSILTy = SILType::getPrimitiveObjectType (substTy);
889
975
890
976
CanType bridgedResultType = objcResultTy.getSwiftRValueType ();
891
977
@@ -896,9 +982,14 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
896
982
result = B.createApply (loc, nativeFn, substSILTy,
897
983
swiftResultTy, subs, args);
898
984
899
- // Leave the scope immediately. This isn't really necessary; it
900
- // just limits lifetimes a little bit more.
901
- scope.pop ();
985
+ if (substTy->hasIndirectResults ()) {
986
+ assert (substTy->getNumAllResults () == 1 );
987
+ result = args[0 ];
988
+ }
989
+
990
+ // Leave the argument cleanup scope immediately. This isn't really
991
+ // necessary; it just limits lifetimes a little bit more.
992
+ argScope.pop ();
902
993
903
994
// Now bridge the return value.
904
995
result = emitBridgeReturnValue (*this , loc, result,
@@ -946,9 +1037,10 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
946
1037
result = contBB->createBBArg (objcResultTy);
947
1038
948
1039
// Leave the scope now.
949
- scope .pop ();
1040
+ argScope .pop ();
950
1041
}
951
1042
1043
+ scope.pop ();
952
1044
B.createReturn (loc, result);
953
1045
}
954
1046
0 commit comments