@@ -708,11 +708,37 @@ static Expr *lookThroughProjections(Expr *expr) {
708
708
return lookThroughProjections (lookupExpr->getBase ());
709
709
}
710
710
711
+ SILValue SILGenFunction::emitUncheckedGuaranteedConversion (SILValue value) {
712
+ assert (value->getType ().isObject ());
713
+ assert (F.getConventions ().hasGuaranteedResult ());
714
+ auto regularLoc = RegularLocation::getAutoGeneratedLocation ();
715
+ // Introduce a pair of unchecked_ownership_conversion instructions to
716
+ // avoid ownership errors from returning a load borrowed value.
717
+ // TODO: Introduce new SIL semantics to allow returning borrowed
718
+ // values from within a local borrow scope.
719
+ auto result = B.createUncheckedOwnershipConversion (regularLoc, value,
720
+ OwnershipKind::Unowned);
721
+ result = B.createUncheckedOwnershipConversion (regularLoc, result,
722
+ OwnershipKind::Guaranteed);
723
+ return result;
724
+ }
725
+
711
726
bool SILGenFunction::emitGuaranteedReturn (
712
727
SILLocation loc, Expr *ret, SmallVectorImpl<SILValue> &directResults) {
713
728
auto *afd = cast<AbstractFunctionDecl>(FunctionDC->getAsDecl ());
714
729
assert (cast<AccessorDecl>(afd)->isBorrowAccessor ());
715
730
731
+
732
+ auto emitLoadBorrowFromGuaranteedAddress =
733
+ [&](ManagedValue guaranteedAddress) -> SILValue {
734
+ assert (guaranteedAddress.getValue ()->getType ().isAddress ());
735
+ assert (F.getConventions ().hasGuaranteedResult ());
736
+ auto regularLoc = RegularLocation::getAutoGeneratedLocation ();
737
+ auto load =
738
+ B.createLoadBorrow (regularLoc, guaranteedAddress).getValue ();
739
+ return emitUncheckedGuaranteedConversion (load);
740
+ };
741
+
716
742
// If the return expression is a literal, emit as a regular return
717
743
// expression.
718
744
if (isa<LiteralExpr>(ret)) {
@@ -737,10 +763,10 @@ bool SILGenFunction::emitGuaranteedReturn(
737
763
FormalEvaluationScope scope (*this );
738
764
LValueOptions options;
739
765
auto lvalue = emitLValue (ret,
740
- F.getConventions (). hasGuaranteedResult ()
766
+ F.getSelfArgument ()-> getType (). isObject ()
741
767
? SGFAccessKind::BorrowedObjectRead
742
768
: SGFAccessKind::BorrowedAddressRead,
743
- F.getConventions (). hasGuaranteedResult ()
769
+ F.getSelfArgument ()-> getType (). isObject ()
744
770
? options.forGuaranteedReturn (true )
745
771
: options.forGuaranteedAddressReturn (true ));
746
772
@@ -766,8 +792,14 @@ bool SILGenFunction::emitGuaranteedReturn(
766
792
// }
767
793
// }
768
794
if (afd->getAttrs ().hasAttribute <UnsafeSelfDependentResultAttr>()) {
769
- auto resultValue = emitBorrowedLValue (ret, std::move (lvalue));
770
- directResults.push_back (resultValue.getValue ());
795
+ auto regularLoc = RegularLocation::getAutoGeneratedLocation ();
796
+ auto resultMV = emitBorrowedLValue (regularLoc, std::move (lvalue));
797
+ SILValue result = resultMV.getValue ();
798
+ if (resultMV.getType ().isAddress () &&
799
+ F.getConventions ().hasGuaranteedResult ()) {
800
+ result = emitLoadBorrowFromGuaranteedAddress (resultMV);
801
+ }
802
+ directResults.push_back (result);
771
803
return false ;
772
804
}
773
805
@@ -782,8 +814,9 @@ bool SILGenFunction::emitGuaranteedReturn(
782
814
return true ;
783
815
}
784
816
785
- auto result = tryEmitProjectedLValue (ret, std::move (lvalue), TSanKind::None);
786
- if (!result) {
817
+ auto resultMV =
818
+ tryEmitProjectedLValue (ret, std::move (lvalue), TSanKind::None);
819
+ if (!resultMV) {
787
820
diagnose (getASTContext (), ret->getStartLoc (),
788
821
diag::invalid_borrow_accessor_return);
789
822
diagnose (getASTContext (), ret->getStartLoc (),
@@ -800,15 +833,24 @@ bool SILGenFunction::emitGuaranteedReturn(
800
833
return true ;
801
834
}
802
835
803
- auto resultValue = result ->getValue ();
836
+ SILValue result = resultMV ->getValue ();
804
837
SILType selfType = F.getSelfArgument ()->getType ();
805
- if (selfType.isMoveOnly () && F.getConventions ().hasGuaranteedResult ()) {
838
+
839
+ if (F.getConventions ().hasGuaranteedResult ()) {
806
840
// If we are returning the result of borrow accessor, strip the
807
841
// unnecessary copy_value + mark_unresolved_non_copyable_value
808
842
// instructions.
809
- resultValue = lookThroughMoveOnlyCheckerPattern (resultValue);
843
+ if (selfType.isMoveOnly ()) {
844
+ result = lookThroughMoveOnlyCheckerPattern (result);
845
+ }
846
+ // If the SIL convention is @guaranteed and the generated result is an
847
+ // address, emit a load_borrow.
848
+ if (result->getType ().isAddress ()) {
849
+ result = emitLoadBorrowFromGuaranteedAddress (*resultMV);
850
+ }
810
851
}
811
- directResults.push_back (resultValue);
852
+
853
+ directResults.push_back (result);
812
854
return false ;
813
855
}
814
856
0 commit comments