This lets you do isa<AllocRefInst> to determine if the underlying ManagedValue
contains within it an AllocRefInst without needing to call getValue(). I would
like to restrict the number of places where getValue() needs to be called as
much as possible.
I realized over the weekend the follie of storing a borrowed cleanup on
ManagedValues themselves. The reasons for this are:
1. We assume all over SILGen that ManagedValue::hasCleanup() => Owned. I would
have to fix all of those parts of the compiler.
2. The reason for having a cleanup handle on ManagedValue is to be able to
forward owned arguments, so there is really no purpose since we never want to be
able to forward these arguments.
This is the first step towards eliminating:
* ManagedValue::forUnmanaged(SILValue)
* ManagedValue::ManagedValue(SILValue, CleanupHandle).
The reason why these two methods must be eliminated is that:
1. Currently non-trivial values are "borrowed" using
ManagedValue::forUnmanaged. With Semantic SIL, we are now able to represent
borrows via begin_borrow and end_borrow. This will make the semantics that
SILGen is trying to describe more accurate.
2. ManagedValue::ManagedValue can be used to add arbitrary cleanups. We want
methods that add cleanups, but that at the same time allow the caller to specify
what it expects the ownership of the given SILValue to be. This would then cause
an assertion to trip giving greater clarity.
rdar://29791263
In SILGen, we often times want to transform a ManagedValue, while maintaining
the underlying cleanup. The ManagedValue::transform API attempts to formalize
this pattern through the usage of std::move to create a movable rvalue, but
returning a different ManagedValue as a full value. This ensure that the
original ManagedValue is destroyed at end of statement, will allowing the
underlying cleanup to be forwarded.
From an ownership perspective, I think the majority of these cases should
actually recreate the underlying cleanup since in most cases they involve
forwarding. For today though I am using this to just formalize this pattern at
the relevant call sites.
rdar://29791263
conservatively copying them.
Also, fix a number of issues with mutating getters that
I noticed while examining and changing this code. In
particular, stop relying on suppressing writeback scopes
during loads.
Fixes rdar://19002913, a bug where an unnecessary copy of
an array for a getter call left the array in a non-unique
state when a subsequent mutation occurred.
Swift SVN r23642
declare whether it's owned by the emission code that's
working with it.
This is convenient when working extensively with values
that are being propagated into multiple, often-disjoint
paths, like switches.
Swift SVN r19333
- purge @inout from comments in the compiler except for places talking about
the SIL argument convention.
- change diagnostics to not refer to @inout
- Change the astprinter to print InoutType without the @, so it doesn't show
up in diagnostics or in closure argument types in code completion.
- Implement type parsing support for the new inout syntax (before we just
handled patterns).
- Switch the last couple of uses in the stdlib (in types) to inout.
- Various testcase updates (more to come).
Swift SVN r13564
- Remove my previous local hack.
- Add a new flag to SGFContext indicating that clients are ok with +0 rvalues.
- Teach emitRValueForPropertyLoad and emitRValueForDecl how to work with +0 rvalues.
This allows us to avoid retaining bases in arbitrarily nested struct rvalue
member_ref_expr's. For example, this:
class SomeClass {}
struct AnotherStruct {
var x : Int
var c : SomeClass
}
struct StructMemberTest {
var c1 : SomeClass, c2 : SomeClass
var s : AnotherStruct
func testRecursiveStruct() -> Int {
return s.x
}
}
used to compile to:
sil @_TFV1t16StructMemberTest19testRecursiveStructfS0_FT_Si : $@cc(method) @thin (@owned StructMemberTest) -> Int64 {
bb0(%0 : $StructMemberTest):
debug_value %0 : $StructMemberTest // let self // id: %1
%2 = struct_extract %0 : $StructMemberTest, #s // user: %3
%3 = copy_value %2 : $AnotherStruct // users: %5, %4
%4 = struct_extract %3 : $AnotherStruct, #x // user: %7
destroy_value %3 : $AnotherStruct // id: %5
destroy_value %0 : $StructMemberTest // id: %6
return %4 : $Int64 // id: %7
}
and now it compiles to:
sil @_TFV1t16StructMemberTest19testRecursiveStructfS0_FT_Si : $@cc(method) @thin (@owned StructMemberTest) -> Int64 {
bb0(%0 : $StructMemberTest):
debug_value %0 : $StructMemberTest // let self // id: %1
%2 = struct_extract %0 : $StructMemberTest, #s // user: %3
%3 = struct_extract %2 : $AnotherStruct, #x // user: %5
destroy_value %0 : $StructMemberTest // id: %4
return %3 : $Int64 // id: %5
}
There is more that can come from this, but it is a start. This cuts out 50 retain/release pairs from the stdlib.
Swift SVN r12857
emission routines use the SGFContext passed in. To help with this and
to help the handshake, add a new "isInContext()" representation to
ManagedValue. This makes the code producing and consuming these more
explicit. NFC.
Swift SVN r12783
can often produce an lvalue, for everything else it produces an RValue.
Split it up a bit so that all of the lvalue cases are handled by
emitLValueForDecl (which it calls). This allows clients that only
expect an lvalue back to have a simpler path, and allows one that
wants to probe to see if something is an lvalue or not to be simpler.
Swift SVN r12715