@@ -708,11 +708,37 @@ static Expr *lookThroughProjections(Expr *expr) {
708708 return lookThroughProjections (lookupExpr->getBase ());
709709}
710710
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+
711726bool SILGenFunction::emitGuaranteedReturn (
712727 SILLocation loc, Expr *ret, SmallVectorImpl<SILValue> &directResults) {
713728 auto *afd = cast<AbstractFunctionDecl>(FunctionDC->getAsDecl ());
714729 assert (cast<AccessorDecl>(afd)->isBorrowAccessor ());
715730
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+
716742 // If the return expression is a literal, emit as a regular return
717743 // expression.
718744 if (isa<LiteralExpr>(ret)) {
@@ -737,10 +763,10 @@ bool SILGenFunction::emitGuaranteedReturn(
737763 FormalEvaluationScope scope (*this );
738764 LValueOptions options;
739765 auto lvalue = emitLValue (ret,
740- F.getConventions (). hasGuaranteedResult ()
766+ F.getSelfArgument ()-> getType (). isObject ()
741767 ? SGFAccessKind::BorrowedObjectRead
742768 : SGFAccessKind::BorrowedAddressRead,
743- F.getConventions (). hasGuaranteedResult ()
769+ F.getSelfArgument ()-> getType (). isObject ()
744770 ? options.forGuaranteedReturn (true )
745771 : options.forGuaranteedAddressReturn (true ));
746772
@@ -766,8 +792,14 @@ bool SILGenFunction::emitGuaranteedReturn(
766792 // }
767793 // }
768794 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);
771803 return false ;
772804 }
773805
@@ -782,8 +814,9 @@ bool SILGenFunction::emitGuaranteedReturn(
782814 return true ;
783815 }
784816
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) {
787820 diagnose (getASTContext (), ret->getStartLoc (),
788821 diag::invalid_borrow_accessor_return);
789822 diagnose (getASTContext (), ret->getStartLoc (),
@@ -800,15 +833,24 @@ bool SILGenFunction::emitGuaranteedReturn(
800833 return true ;
801834 }
802835
803- auto resultValue = result ->getValue ();
836+ SILValue result = resultMV ->getValue ();
804837 SILType selfType = F.getSelfArgument ()->getType ();
805- if (selfType.isMoveOnly () && F.getConventions ().hasGuaranteedResult ()) {
838+
839+ if (F.getConventions ().hasGuaranteedResult ()) {
806840 // If we are returning the result of borrow accessor, strip the
807841 // unnecessary copy_value + mark_unresolved_non_copyable_value
808842 // 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+ }
810851 }
811- directResults.push_back (resultValue);
852+
853+ directResults.push_back (result);
812854 return false ;
813855}
814856
0 commit comments