@@ -66,50 +66,62 @@ class ManagedValue {
6666 : valueAndFlag(value, isLValue), cleanup(cleanup) {
6767 }
6868
69- public:
70-
71- ManagedValue () = default ;
69+ // / Create a managed value for a +0 rvalue.
70+ // /
71+ // / Please do not introduce new uses of this method! Instead use one of the
72+ // / static constructors below!
73+ static ManagedValue forUnmanaged (SILValue value) {
74+ assert (value && " No value specified" );
75+ return ManagedValue (value, false , CleanupHandle::invalid ());
76+ }
7277
7378 // / Create a managed value for a +1 rvalue.
7479 // /
7580 // / Please do not introduce new uses of this method! Instead use one of the
7681 // / static constructors below.
77- ManagedValue (SILValue value, CleanupHandle cleanup)
78- : valueAndFlag(value, false ), cleanup(cleanup) {
82+ explicit ManagedValue (SILValue value,
83+ CleanupHandle cleanup = CleanupHandle::invalid())
84+ : valueAndFlag(value, false ), cleanup(cleanup) {
7985 assert (value && " No value specified?!" );
8086 assert ((!getType ().isObject () ||
8187 value->getOwnershipKind () != OwnershipKind::None ||
8288 !hasCleanup ()) &&
8389 " Objects with trivial ownership should never have a cleanup" );
8490 }
8591
86- // / Create a managed value for a +0 rvalue.
92+ public:
93+ ManagedValue () = default ;
94+
95+ // / Sometimes SILGen wants to represent an owned value or owned address
96+ // / without a cleanup as a +0 value that must be copied to be consumed.
8797 // /
88- // / Please do not introduce new uses of this method! Instead use one of the
89- // / static constructors below!
90- static ManagedValue forUnmanaged (SILValue value) {
91- assert (value && " No value specified" );
92- return ManagedValue (value, false , CleanupHandle::invalid ());
98+ // / Please do not introduce new uses of this.
99+ // /
100+ // / DISCUSSION: We purposely provide a specific API for code paths that use
101+ // / owned values (and assert the values are owned) so that users do not
102+ // / attempt to use this for borrowed values. All borrowed values need to use
103+ // / the borrowed value APIs.
104+ static ManagedValue forUnmanagedOwnedValue (SILValue value) {
105+ assert (value);
106+ assert (!value->getType ().isObject () ||
107+ value->getOwnershipKind ().isCompatibleWith (OwnershipKind::Owned));
108+ return ManagedValue (value);
109+ }
110+
111+ // / Wrap a value with OwnershipKind::Unowned in a ManagedValue. This must be
112+ // / copied before it is used.
113+ static ManagedValue forUnownedObjectValue (SILValue value) {
114+ assert (value);
115+ assert (value->getType ().isObject ());
116+ assert (value->getOwnershipKind ().isCompatibleWith (OwnershipKind::Unowned));
117+ return ManagedValue (value);
93118 }
94119
95120 enum class ScopeKind {
96121 Lexical,
97122 FormalAccess,
98123 };
99124
100- // / Given a value \p value, create a copy of it and return the relevant
101- // / ManagedValue.
102- static ManagedValue forCopyOwnedObjectRValue (SILGenFunction &SGF,
103- SILLocation loc, SILValue value,
104- ScopeKind kind) {
105- assert (value && " No value specified" );
106- assert (value->getType ().isObject ());
107- auto mv = ManagedValue::forUnmanaged (value);
108- if (kind == ScopeKind::Lexical)
109- return mv.copy (SGF, loc);
110- return mv.formalAccessCopy (SGF, loc);
111- }
112-
113125 // / Create a managed value for a SILValue whose ownership is
114126 // / forwarded. Creates a new cleanup for +1 values. Forwarded +0 values
115127 // / require no cleanup.
@@ -160,7 +172,10 @@ class ManagedValue {
160172 assert (value && " No value specified" );
161173 assert (value->getType ().isObject () &&
162174 " Expected borrowed rvalues to be objects" );
163- assert (value->getOwnershipKind () != OwnershipKind::None);
175+ if (value->getOwnershipKind () == OwnershipKind::None) {
176+ return forObjectRValueWithoutOwnership (value);
177+ }
178+ assert (value->getOwnershipKind () == OwnershipKind::Guaranteed);
164179 return ManagedValue (value, false , CleanupHandle::invalid ());
165180 }
166181
@@ -169,6 +184,13 @@ class ManagedValue {
169184 forBorrowedAddressRValue (SILValue value) {
170185 assert (value && " No value specified" );
171186 assert (value->getType ().isAddress () && " Expected value to be an address" );
187+ // We check for value->getFunction() here since we /could/ be passed
188+ // SILUndef here.
189+ if (auto *f = value->getFunction ()) {
190+ if (value->getType ().isTrivial (f)) {
191+ return forTrivialAddressRValue (value);
192+ }
193+ }
172194 assert (value->getOwnershipKind () == OwnershipKind::None &&
173195 " Addresses always have trivial ownership" );
174196 return ManagedValue (value, false , CleanupHandle::invalid ());
@@ -193,6 +215,16 @@ class ManagedValue {
193215 static ManagedValue forTrivialAddressRValue (SILValue value) {
194216 assert (value->getType ().isAddress () && " Expected an address" );
195217 assert (value->getOwnershipKind () == OwnershipKind::None);
218+
219+ // TODO: Add an assert that we have a trivial type here.
220+ //
221+ // DISCUSSION: We cannot do this today since we have problems along certain
222+ // materialization paths where we want to emit a borrow operation. To handle
223+ // those cases, we have loosened the rules of OSSA by allowing for store
224+ // [trivial] to take non-trivial .none parameters. This has hidden bugs
225+ // where SILGen emits a borrow to materialize a parameter for an @in
226+ // parameter. It just coincidently works since when we emit the
227+ // store_borrow, we use the store [trivial] instead. This should be fixed.
196228 return ManagedValue (value, false , CleanupHandle::invalid ());
197229 }
198230
@@ -476,8 +508,8 @@ class ConsumableManagedValue {
476508 // /
477509 // / You probably should not be using this; it's here to make it easy
478510 // / to find code that is probably wrong.
479- ManagedValue asUnmanagedValue () const {
480- return ManagedValue::forUnmanaged (Value.getValue ());
511+ ManagedValue asUnmanagedOwnedValue () const {
512+ return ManagedValue::forUnmanagedOwnedValue (Value.getValue ());
481513 }
482514
483515 // / Return the consumption rules appropriate for the final use of
@@ -489,15 +521,19 @@ class ConsumableManagedValue {
489521 ConsumableManagedValue asBorrowedOperand (SILGenFunction &SGF,
490522 SILLocation loc) const {
491523 if (getType ().isAddress ())
492- return {asUnmanagedValue (), CastConsumptionKind::CopyOnSuccess};
493- return {asUnmanagedValue ().borrow (SGF, loc),
524+ return {asUnmanagedOwnedValue (), CastConsumptionKind::CopyOnSuccess};
525+
526+ if (Value.getOwnershipKind () == OwnershipKind::Guaranteed)
527+ return {Value, CastConsumptionKind::BorrowAlways};
528+
529+ return {asUnmanagedOwnedValue ().borrow (SGF, loc),
494530 CastConsumptionKind::BorrowAlways};
495531 }
496532
497533 // / Return a managed value that's appropriate for copying this value and
498534 // / always consuming it.
499535 ConsumableManagedValue copy (SILGenFunction &SGF, SILLocation loc) const {
500- return ConsumableManagedValue::forOwned (asUnmanagedValue () .copy (SGF, loc));
536+ return ConsumableManagedValue::forOwned (Value .copy (SGF, loc));
501537 }
502538};
503539
0 commit comments