@@ -37,7 +37,8 @@ class InPlaceInitializationResultPlan final : public ResultPlan {
37
37
InPlaceInitializationResultPlan (Initialization *init) : init(init) {}
38
38
39
39
RValue finish (SILGenFunction &SGF, SILLocation loc, CanType substType,
40
- ArrayRef<ManagedValue> &directResults) override {
40
+ ArrayRef<ManagedValue> &directResults,
41
+ SILValue bridgedForeignError) override {
41
42
init->finishInitialization (SGF);
42
43
return RValue::forInContext ();
43
44
}
@@ -169,7 +170,8 @@ class IndirectOpenedSelfResultPlan final : public ResultPlan {
169
170
}
170
171
171
172
RValue finish (SILGenFunction &SGF, SILLocation loc, CanType substType,
172
- ArrayRef<ManagedValue> &directResults) override {
173
+ ArrayRef<ManagedValue> &directResults,
174
+ SILValue bridgedForeignError) override {
173
175
assert (resultBox && " never emitted temporary?!" );
174
176
175
177
// Lower the unabstracted result type.
@@ -209,7 +211,8 @@ class ScalarResultPlan final : public ResultPlan {
209
211
rep (rep) {}
210
212
211
213
RValue finish (SILGenFunction &SGF, SILLocation loc, CanType substType,
212
- ArrayRef<ManagedValue> &directResults) override {
214
+ ArrayRef<ManagedValue> &directResults,
215
+ SILValue bridgedForeignError) override {
213
216
// Lower the unabstracted result type.
214
217
auto &substTL = SGF.getTypeLowering (substType);
215
218
@@ -309,8 +312,10 @@ class InitValueFromTemporaryResultPlan final : public ResultPlan {
309
312
temporary (std::move(temporary)) {}
310
313
311
314
RValue finish (SILGenFunction &SGF, SILLocation loc, CanType substType,
312
- ArrayRef<ManagedValue> &directResults) override {
313
- RValue subResult = subPlan->finish (SGF, loc, substType, directResults);
315
+ ArrayRef<ManagedValue> &directResults,
316
+ SILValue bridgedForeignError) override {
317
+ RValue subResult = subPlan->finish (SGF, loc, substType, directResults,
318
+ bridgedForeignError);
314
319
assert (subResult.isInContext () && " sub-plan didn't emit into context?" );
315
320
(void )subResult;
316
321
@@ -339,8 +344,10 @@ class InitValueFromRValueResultPlan final : public ResultPlan {
339
344
: init(init), subPlan(std::move(subPlan)) {}
340
345
341
346
RValue finish (SILGenFunction &SGF, SILLocation loc, CanType substType,
342
- ArrayRef<ManagedValue> &directResults) override {
343
- RValue subResult = subPlan->finish (SGF, loc, substType, directResults);
347
+ ArrayRef<ManagedValue> &directResults,
348
+ SILValue bridgedForeignError) override {
349
+ RValue subResult = subPlan->finish (SGF, loc, substType, directResults,
350
+ bridgedForeignError);
344
351
ManagedValue value = std::move (subResult).getAsSingleValue (SGF, loc);
345
352
346
353
init->copyOrInitValueInto (SGF, loc, value, /* init*/ true );
@@ -374,15 +381,17 @@ class TupleRValueResultPlan final : public ResultPlan {
374
381
}
375
382
376
383
RValue finish (SILGenFunction &SGF, SILLocation loc, CanType substType,
377
- ArrayRef<ManagedValue> &directResults) override {
384
+ ArrayRef<ManagedValue> &directResults,
385
+ SILValue bridgedForeignError) override {
378
386
RValue tupleRV (substType);
379
387
380
388
// Finish all the component tuples.
381
389
auto substTupleType = cast<TupleType>(substType);
382
390
assert (substTupleType.getElementTypes ().size () == eltPlans.size ());
383
391
for (auto i : indices (substTupleType.getElementTypes ())) {
384
- RValue eltRV = eltPlans[i]->finish (
385
- SGF, loc, substTupleType.getElementType (i), directResults);
392
+ RValue eltRV =
393
+ eltPlans[i]->finish (SGF, loc, substTupleType.getElementType (i),
394
+ directResults, bridgedForeignError);
386
395
tupleRV.addElement (std::move (eltRV));
387
396
}
388
397
@@ -428,12 +437,14 @@ class TupleInitializationResultPlan final : public ResultPlan {
428
437
}
429
438
430
439
RValue finish (SILGenFunction &SGF, SILLocation loc, CanType substType,
431
- ArrayRef<ManagedValue> &directResults) override {
440
+ ArrayRef<ManagedValue> &directResults,
441
+ SILValue bridgedForeignError) override {
432
442
auto substTupleType = cast<TupleType>(substType);
433
443
assert (substTupleType.getElementTypes ().size () == eltPlans.size ());
434
444
for (auto i : indices (substTupleType.getElementTypes ())) {
435
445
auto eltType = substTupleType.getElementType (i);
436
- RValue eltRV = eltPlans[i]->finish (SGF, loc, eltType, directResults);
446
+ RValue eltRV = eltPlans[i]->finish (SGF, loc, eltType, directResults,
447
+ bridgedForeignError);
437
448
assert (eltRV.isInContext ());
438
449
(void )eltRV;
439
450
}
@@ -482,9 +493,11 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
482
493
AbstractionPattern origFormalType,
483
494
SILLocation loc) override {
484
495
// Get the current continuation for the task.
485
- bool throws = calleeTypeInfo.foreign .async
486
- ->completionHandlerErrorParamIndex ().hasValue ();
487
-
496
+ bool throws =
497
+ calleeTypeInfo.foreign .async ->completionHandlerErrorParamIndex ()
498
+ .hasValue () ||
499
+ calleeTypeInfo.foreign .error .hasValue ();
500
+
488
501
continuation = SGF.B .createGetAsyncContinuationAddr (loc, resumeBuf,
489
502
calleeTypeInfo.substResultType , throws);
490
503
@@ -534,7 +547,8 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
534
547
cast<SILFunctionType>(
535
548
impFnTy->mapTypeOutOfContext ()->getCanonicalType (sig)),
536
549
continuationTy->mapTypeOutOfContext ()->getCanonicalType (sig),
537
- origFormalType, sig, *calleeTypeInfo.foreign .async );
550
+ origFormalType, sig, *calleeTypeInfo.foreign .async ,
551
+ calleeTypeInfo.foreign .error );
538
552
auto impRef = SGF.B .createFunctionRef (loc, impl);
539
553
540
554
// Initialize the block object for the completion handler.
@@ -554,18 +568,95 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
554
568
}
555
569
556
570
RValue finish (SILGenFunction &SGF, SILLocation loc, CanType substType,
557
- ArrayRef<ManagedValue> &directResults) override {
571
+ ArrayRef<ManagedValue> &directResults,
572
+ SILValue bridgedForeignError) override {
558
573
// There should be no direct results from the call.
559
574
assert (directResults.empty ());
560
575
561
576
// Await the continuation we handed off to the completion handler.
562
577
SILBasicBlock *resumeBlock = SGF.createBasicBlock ();
563
578
SILBasicBlock *errorBlock = nullptr ;
564
- auto errorParamIndex = calleeTypeInfo.foreign .async ->completionHandlerErrorParamIndex ();
565
- if (errorParamIndex) {
579
+ bool throws =
580
+ calleeTypeInfo.foreign .async ->completionHandlerErrorParamIndex ()
581
+ .hasValue () ||
582
+ calleeTypeInfo.foreign .error .hasValue ();
583
+ if (throws) {
566
584
errorBlock = SGF.createBasicBlock (FunctionSection::Postmatter);
567
585
}
568
-
586
+
587
+ auto *awaitBB = SGF.B .getInsertionBB ();
588
+ if (bridgedForeignError) {
589
+ // Avoid a critical edge from the block which branches to the await and
590
+ // foreign error blocks to the await block (to which the error block will
591
+ // be made to branch in a moment) by introducing a trampoline which will
592
+ // branch to the await block.
593
+ awaitBB = SGF.createBasicBlock ();
594
+ SGF.B .createBranch (loc, awaitBB);
595
+
596
+ // Finish emitting the foreign error block:
597
+ // (1) fulfill the unsafe continuation with the foreign error
598
+ // (2) branch to the await block
599
+ {
600
+ // First, fulfill the unsafe continuation with the foreign error.
601
+ // Currently, that block's code looks something like
602
+ // %foreignError = ... : $*Optional<NSError>
603
+ // %converter = function_ref _convertNSErrorToError(_:)
604
+ // %error = apply %converter(%foreignError)
605
+ // [... insert here ...]
606
+ // destroy_value %error
607
+ // destroy_value %foreignError
608
+ // Insert code to fulfill it after the native %error is defined. That
609
+ // code should structure the RawUnsafeContinuation (continuation) into
610
+ // an appropriately typed UnsafeContinuation and then pass that together
611
+ // with (a copy of) the error to
612
+ // _resumeUnsafeThrowingContinuationWithError.
613
+ // [foreign_error_block_with_foreign_async_convention]
614
+ SGF.B .setInsertionPoint (
615
+ ++bridgedForeignError->getDefiningInstruction ()->getIterator ());
616
+
617
+ auto continuationDecl = SGF.getASTContext ().getUnsafeContinuationDecl ();
618
+
619
+ auto errorTy = SGF.getASTContext ().getExceptionType ();
620
+ auto continuationBGT =
621
+ BoundGenericType::get (continuationDecl, Type (),
622
+ {calleeTypeInfo.substResultType , errorTy});
623
+ auto env = SGF.F .getGenericEnvironment ();
624
+ auto sig = env ? env->getGenericSignature ().getCanonicalSignature ()
625
+ : CanGenericSignature ();
626
+ auto mappedContinuationTy =
627
+ continuationBGT->mapTypeOutOfContext ()->getCanonicalType (sig);
628
+ auto resumeType =
629
+ cast<BoundGenericType>(mappedContinuationTy).getGenericArgs ()[0 ];
630
+ auto continuationTy = continuationBGT->getCanonicalType ();
631
+
632
+ auto errorIntrinsic =
633
+ SGF.SGM .getResumeUnsafeThrowingContinuationWithError ();
634
+ Type replacementTypes[] = {
635
+ SGF.F .mapTypeIntoContext (resumeType)->getCanonicalType ()};
636
+ auto subs = SubstitutionMap::get (errorIntrinsic->getGenericSignature (),
637
+ replacementTypes,
638
+ ArrayRef<ProtocolConformanceRef>{});
639
+ auto wrappedContinuation = SGF.B .createStruct (
640
+ loc, SILType::getPrimitiveObjectType (continuationTy),
641
+ {continuation});
642
+
643
+ auto continuationMV =
644
+ ManagedValue::forUnmanaged (SILValue (wrappedContinuation));
645
+ SGF.emitApplyOfLibraryIntrinsic (
646
+ loc, errorIntrinsic, subs,
647
+ {continuationMV,
648
+ ManagedValue::forUnmanaged (bridgedForeignError).copy (SGF, loc)},
649
+ SGFContext ());
650
+
651
+ // Second, emit a branch from the end of the foreign error block to the
652
+ // await block, to await the continuation which was just fulfilled.
653
+ SGF.B .setInsertionPoint (
654
+ bridgedForeignError->getDefiningInstruction ()->getParent ());
655
+ SGF.B .createBranch (loc, awaitBB);
656
+ }
657
+
658
+ SGF.B .emitBlock (awaitBB);
659
+ }
569
660
SGF.B .createAwaitAsyncContinuation (loc, continuation, resumeBlock, errorBlock);
570
661
571
662
// Propagate an error if we have one.
@@ -655,8 +746,10 @@ class ForeignErrorInitializationPlan final : public ResultPlan {
655
746
}
656
747
657
748
RValue finish (SILGenFunction &SGF, SILLocation loc, CanType substType,
658
- ArrayRef<ManagedValue> &directResults) override {
659
- return subPlan->finish (SGF, loc, substType, directResults);
749
+ ArrayRef<ManagedValue> &directResults,
750
+ SILValue bridgedForeignError) override {
751
+ return subPlan->finish (SGF, loc, substType, directResults,
752
+ bridgedForeignError);
660
753
}
661
754
662
755
void
@@ -665,6 +758,13 @@ class ForeignErrorInitializationPlan final : public ResultPlan {
665
758
subPlan->gatherIndirectResultAddrs (SGF, loc, outList);
666
759
}
667
760
761
+ ManagedValue
762
+ emitForeignAsyncCompletionHandler (SILGenFunction &SGF,
763
+ AbstractionPattern origFormalType,
764
+ SILLocation loc) override {
765
+ return subPlan->emitForeignAsyncCompletionHandler (SGF, origFormalType, loc);
766
+ }
767
+
668
768
Optional<std::pair<ManagedValue, ManagedValue>>
669
769
emitForeignErrorArgument (SILGenFunction &SGF, SILLocation loc) override {
670
770
SILGenFunction::PointerAccessInfo pointerInfo = {
@@ -695,12 +795,7 @@ class ForeignErrorInitializationPlan final : public ResultPlan {
695
795
ResultPlanPtr ResultPlanBuilder::buildTopLevelResult (Initialization *init,
696
796
SILLocation loc) {
697
797
// First check if we have a foreign error and/or async convention.
698
- if (auto foreignAsync = calleeTypeInfo.foreign .async ) {
699
- // Create a result plan that gets the result schema from the completion
700
- // handler callback's arguments.
701
- // completion handler.
702
- return ResultPlanPtr (new ForeignAsyncInitializationPlan (SGF, loc, calleeTypeInfo));
703
- } else if (auto foreignError = calleeTypeInfo.foreign .error ) {
798
+ if (auto foreignError = calleeTypeInfo.foreign .error ) {
704
799
// Handle the foreign error first.
705
800
//
706
801
// The plan needs to be built using the formal result type after foreign-error
@@ -709,7 +804,8 @@ ResultPlanPtr ResultPlanBuilder::buildTopLevelResult(Initialization *init,
709
804
// These conventions make the formal result type ().
710
805
case ForeignErrorConvention::ZeroResult:
711
806
case ForeignErrorConvention::NonZeroResult:
712
- assert (calleeTypeInfo.substResultType ->isVoid ());
807
+ assert (calleeTypeInfo.substResultType ->isVoid () ||
808
+ calleeTypeInfo.foreign .async );
713
809
allResults.clear ();
714
810
break ;
715
811
@@ -734,10 +830,21 @@ ResultPlanPtr ResultPlanBuilder::buildTopLevelResult(Initialization *init,
734
830
}
735
831
}
736
832
737
- ResultPlanPtr subPlan = build (init, calleeTypeInfo.origResultType .getValue (),
738
- calleeTypeInfo.substResultType );
833
+ ResultPlanPtr subPlan;
834
+ if (auto foreignAsync = calleeTypeInfo.foreign .async ) {
835
+ subPlan = ResultPlanPtr (
836
+ new ForeignAsyncInitializationPlan (SGF, loc, calleeTypeInfo));
837
+ } else {
838
+ subPlan = build (init, calleeTypeInfo.origResultType .getValue (),
839
+ calleeTypeInfo.substResultType );
840
+ }
739
841
return ResultPlanPtr (new ForeignErrorInitializationPlan (
740
842
SGF, loc, calleeTypeInfo, std::move (subPlan)));
843
+ } else if (auto foreignAsync = calleeTypeInfo.foreign .async ) {
844
+ // Create a result plan that gets the result schema from the completion
845
+ // handler callback's arguments.
846
+ return ResultPlanPtr (
847
+ new ForeignAsyncInitializationPlan (SGF, loc, calleeTypeInfo));
741
848
} else {
742
849
// Otherwise, we can just call build.
743
850
return build (init, calleeTypeInfo.origResultType .getValue (),
0 commit comments