@@ -1045,6 +1045,123 @@ emitBuiltinGlobalStringTablePointer(SILGenFunction &SGF, SILLocation loc,
10451045 return SGF.emitManagedRValueWithCleanup (resultVal);
10461046}
10471047
1048+ // / Emit SIL for the named builtin:
1049+ // / convertStrongToUnownedUnsafe. Unlike the default ownership
1050+ // / convention for named builtins, which is to take (non-trivial)
1051+ // / arguments as Owned, this builtin accepts owned as well as
1052+ // / guaranteed arguments, and hence doesn't require the arguments to
1053+ // / be at +1. Therefore, this builtin is emitted specially.
1054+ // /
1055+ // / We assume our convention is (T, @inout @unmanaged Optional<T>) -> ()
1056+ static ManagedValue emitBuiltinConvertStrongToUnownedUnsafe (
1057+ SILGenFunction &SGF, SILLocation loc, SubstitutionMap subs,
1058+ PreparedArguments &&preparedArgs, SGFContext C) {
1059+ auto argsOrError = decomposeArguments (SGF, loc, std::move (preparedArgs), 2 );
1060+ if (!argsOrError)
1061+ return ManagedValue::forUnmanaged (SGF.emitEmptyTuple (loc));
1062+
1063+ auto args = *argsOrError;
1064+
1065+ // First get our object at +0 if we can.
1066+ auto object = SGF.emitRValue (args[0 ], SGFContext::AllowGuaranteedPlusZero)
1067+ .getAsSingleValue (SGF, args[0 ]);
1068+
1069+ // Borrow it and get the value.
1070+ SILValue objectSrcValue = object.borrow (SGF, loc).getValue ();
1071+
1072+ // Then create our inout.
1073+ auto inout = cast<InOutExpr>(args[1 ]->getSemanticsProvidingExpr ());
1074+ auto lv =
1075+ SGF.emitLValue (inout->getSubExpr (), SGFAccessKind::BorrowedAddressRead);
1076+ lv.unsafelyDropLastComponent (PathComponent::OwnershipKind);
1077+ if (!lv.isPhysical () || !lv.isLoadingPure ()) {
1078+ llvm::report_fatal_error (" Builtin.convertStrongToUnownedUnsafe passed "
1079+ " non-physical, non-pure lvalue as 2nd arg" );
1080+ }
1081+
1082+ SILValue inoutDest =
1083+ SGF.emitAddressOfLValue (args[1 ], std::move (lv)).getLValueAddress ();
1084+ SILType destType = inoutDest->getType ().getObjectType ();
1085+
1086+ // Make sure our types match up as we expect.
1087+ if (objectSrcValue->getType () !=
1088+ destType.getReferenceStorageReferentType ().getOptionalObjectType ()) {
1089+ llvm::errs ()
1090+ << " Invalid usage of Builtin.convertStrongToUnownedUnsafe. lhsType "
1091+ " must be T and rhsType must be inout unsafe(unowned) Optional<T>"
1092+ << " lhsType: " << objectSrcValue->getType () << " \n "
1093+ << " rhsType: " << inoutDest->getType () << " \n " ;
1094+ llvm::report_fatal_error (" standard fatal error msg" );
1095+ }
1096+
1097+ // Ok. We have the right types. First convert objectSrcValue to its
1098+ // unowned representation.
1099+ SILType optionalType = SILType::getOptionalType (objectSrcValue->getType ());
1100+ SILValue someVal =
1101+ SGF.B .createOptionalSome (loc, objectSrcValue, optionalType);
1102+
1103+ SILType unmanagedOptType = someVal->getType ().getReferenceStorageType (
1104+ SGF.getASTContext (), ReferenceOwnership::Unmanaged);
1105+ SILValue unownedObjectSrcValue = SGF.B .createRefToUnmanaged (
1106+ loc, someVal, unmanagedOptType.getObjectType ());
1107+ SGF.B .emitStoreValueOperation (loc, unownedObjectSrcValue, inoutDest,
1108+ StoreOwnershipQualifier::Trivial);
1109+ return ManagedValue::forUnmanaged (SGF.emitEmptyTuple (loc));
1110+ }
1111+
1112+ // / Emit SIL for the named builtin: convertUnownedUnsafeToGuaranteed.
1113+ // /
1114+ // / We assume our convention is:
1115+ // /
1116+ // / <BaseT, T> (BaseT, @in_guaranteed @unmanaged Optional<T>) -> @guaranteed T
1117+ // /
1118+ static ManagedValue emitBuiltinConvertUnownedUnsafeToGuaranteed (
1119+ SILGenFunction &SGF, SILLocation loc, SubstitutionMap subs,
1120+ PreparedArguments &&preparedArgs, SGFContext C) {
1121+ auto argsOrError = decomposeArguments (SGF, loc, std::move (preparedArgs), 2 );
1122+ if (!argsOrError)
1123+ return ManagedValue::forUnmanaged (SGF.emitEmptyTuple (loc));
1124+
1125+ auto args = *argsOrError;
1126+
1127+ // First grab our base and borrow it.
1128+ auto baseMV =
1129+ SGF.emitRValueAsSingleValue (args[0 ], SGFContext::AllowGuaranteedPlusZero)
1130+ .borrow (SGF, args[0 ]);
1131+
1132+ // Then grab our LValue operand, drop the last ownership component.
1133+ auto srcLV = SGF.emitLValue (args[1 ]->getSemanticsProvidingExpr (),
1134+ SGFAccessKind::BorrowedAddressRead);
1135+ srcLV.unsafelyDropLastComponent (PathComponent::OwnershipKind);
1136+ if (!srcLV.isPhysical () || !srcLV.isLoadingPure ()) {
1137+ llvm::report_fatal_error (" Builtin.convertUnownedUnsafeToGuaranteed passed "
1138+ " non-physical, non-pure lvalue as 2nd arg" );
1139+ }
1140+
1141+ // Grab our address and load our unmanaged and convert it to a ref.
1142+ SILValue srcAddr =
1143+ SGF.emitAddressOfLValue (args[1 ], std::move (srcLV)).getLValueAddress ();
1144+ SILValue srcValue = SGF.B .emitLoadValueOperation (
1145+ loc, srcAddr, LoadOwnershipQualifier::Trivial);
1146+ SILValue unownedNonTrivialRef = SGF.B .createUnmanagedToRef (
1147+ loc, srcValue, srcValue->getType ().getReferenceStorageReferentType ());
1148+
1149+ // Now convert our unownedNonTrivialRef from unowned ownership to guaranteed
1150+ // ownership and create a cleanup for it.
1151+ SILValue guaranteedNonTrivialRef = SGF.B .createUncheckedOwnershipConversion (
1152+ loc, unownedNonTrivialRef, ValueOwnershipKind::Guaranteed);
1153+ auto guaranteedNonTrivialRefMV =
1154+ SGF.emitManagedBorrowedRValueWithCleanup (guaranteedNonTrivialRef);
1155+ auto someDecl = SGF.getASTContext ().getOptionalSomeDecl ();
1156+
1157+ // Then unsafely extract from the optional.
1158+ auto extMV =
1159+ SGF.B .createUncheckedEnumData (loc, guaranteedNonTrivialRefMV, someDecl);
1160+
1161+ // Now create a mark dependence on our base and return the result.
1162+ return SGF.B .createMarkDependence (loc, extMV, baseMV);
1163+ }
1164+
10481165Optional<SpecializedEmitter>
10491166SpecializedEmitter::forDecl (SILGenModule &SGM, SILDeclRef function) {
10501167 // Only consider standalone declarations in the Builtin module.
0 commit comments