- Change the AST for get/set functions to take self @inout only when they
are @mutating. Setters default to @mutating, but can be explicitly marked
@!mutating. Getters default to not mutating, but can be marked @mutating.
This causes self to follow.
- Change sema to handle semantic analysis of a.y (and subscripts) based on
whether the computed type of a allows mutation (which is when 'a' is an
lvalue, or both the getter and setter are non-mutating). When both of
these conditions fail, 'a.y' has rvalue type, and is thus non-mutable.
- Rework silgen of lvalues to handle this: now properties and subscripts
can have rvalues as bases, which means that all the lvalue machinery needs
to be able to handle the full generality of base expressions (which is
what my recent patches have been paving the way towards).
- Rework silgen of rvalues to similarly handle rvalue bases.
- Rework silgen of both to handle the case where the AST has found a base
expression that is an lvalue, but where only a non-mutating getter or
setter is needed. Right now, we just emit a load of the lvalue, but
it would result in better code to not require the base be an lvalue at
all (todo).
The upshot of all of this is that we are doing *much* less AST-level
materialization (MaterializeExpr goes down), we generate a lot better SIL
out of SILGen in many cases, and 'self' being an rvalue in properties and
subscripts means that we correctly reject code like the examples in
test/Sema/immutability.swift.
Swift SVN r11884
making LValue ManagedValues, and switch SILGenLValue to use
this form of managed value consistently for lvalues, instead of
using unmanaged values in some cases. NFC.
Swift SVN r11878
the things that apparently care about it. The LValue/RValue machinery is
happy to pass around the VarDecl/SubscriptDecl for the entity being
referenced, and this simplifies things.
Swift SVN r11857
not as part of the lvalue path. This means that the arguments to a
function (for example) are always rvalues - @inout arguments are not a
special case all over the place.
This removes emitLValueOrRValueAsRValue and emitLValueAsRValue, because
the lvalue that both of them were trying to handle was @inout, not @lvalue.
Swift SVN r11805
is no longer an lvalue, since it doesn't make sense to assign to super.
This eliminates a bunch of special cases and simplifies things.
Swift SVN r11803
with qualifiers on it, we have two distinct types:
- LValueType(T) aka @lvalue T, which is used for mutable values on the LHS of an
assignment in the typechecker.
- InOutType(T) aka @inout T, which is used for @inout arguments, and the implicit
@inout self argument of mutable methods on value types. This type is also used
at the SIL level for address types.
While I detangled a number of cases that were checking for LValueType (without checking
qualifiers) and only meant @inout or @lvalue, there is more to be done here. Notably,
getRValueType() still strips @inout, which is totally and unbearably wrong.
Swift SVN r11727
properties are represented as rvalues, not non-mutable lvalues. As part of
this, isReferencedAsLValue() only returns true for mutable VarDecls.
This required some pretty serious rearrangement and refactoring of code,
because now (among other things) get-only properties can be emitted as rvalues,
so the rvalue machinery needs to be able to produce getter calls.
This is an important step towards getting proper value semantics going (for
'let's etc) and also allows us to materialize addresses less often. As a
simple example, before we would silgen this:
struct S {
var i : Int
}
var P : S { get: ... }
func f() {
print(P.i)
}
into:
%2 = function_ref @_TF1tg1PVS_1S : $@thin () -> S // user: %3
%3 = apply %2() : $@thin () -> S // user: %5
%4 = alloc_stack $S // users: %9, %6, %5
store %3 to %4#1 : $*S // id: %5
%6 = struct_element_addr %4#1 : $*S, #i // user: %7
%7 = load %6 : $*Int64 // user: %8
now we generate:
%2 = function_ref @_TF1tg1PVS_1S : $@thin () -> S // user: %3
%3 = apply %2() : $@thin () -> S // user: %4
%4 = struct_extract %3 : $S, #i // user: %5
Swift SVN r11632
struct rvalue, to produce a struct element directly, without converting the rvalue
to an lvalue.
This means that it no longer materializes an lvalue when applied to a let declaration
or other rvalue. For example, this testcase:
struct X { var a,b : Int}
func g() -> X { return X(1,2) }
func f() {
let a = g().a
}
used to sema into:
(load_expr implicit type='Int'
(member_ref_expr type='@inout (implicit, nonsettable)Int' decl=t.(file).X.a@t.swift:2:16
(materialize_expr implicit type='@inout (implicit)X'
(call_expr type='X'
and silgen into:
%1 = function_ref @_TF1t1gFT_VS_1X : $@thin () -> X // user: %2
%2 = apply %1() : $@thin () -> X // user: %4
%3 = alloc_stack $X // users: %7, %5, %4
store %2 to %3#1 : $*X // id: %4
%5 = struct_element_addr %3#1 : $*X, #a // user: %6
%6 = load %5 : $*Int64
It now sema's into:
(member_ref_expr type='Int' decl=t.(file).X.a@t.swift:1:16
(call_expr type='X'
and silgens into:
%1 = function_ref @_TF1t1gFT_VS_1X : $@thin () -> X // user: %2
%2 = apply %1() : $@thin () -> X // user: %3
%3 = struct_extract %2 : $X, #a
I think I'm finally starting to grok Doug's crazy typechecker magic.
Swift SVN r11599
only handle rvalues. Clients that can either have an lvalue or an rvalue (which
are few, and will be diminishing as other planned changes happen like the tuple
vs argument split) use a specific api to indicate such.
Swift SVN r11572
When we produce a physical LValue with an abstraction difference, cap off the LValue with a logical "OrigToSubstComponent", which enacts the abstraction change on load or store, and introduces a writeback for the property when used in an @inout context.
Swift SVN r11498
(various) FunctionType::get's, ArrayType::get,
ArraySliceType::get, OptionalType::get, and a few
other places.
There is more to be done here, but this is all I plan to do
for now.
Swift SVN r11497
as values, without a box at all. This generalizes some of the
previous hacks I had for silgen'ing 'self' as a value instead of
a box, and capturing them with CaptureKind::Constant.
Swift SVN r11360
This gives more predictable semantics for initializers and destructors under the DI model, and also unblocks enabling the DI model at all for @objc initializers. <rdar://problem/15614052>
Swift SVN r11029
When assigning between physical lvalues, emit a 'copy_addr' instead of a load + assign sequence. This provides a higher-level semantic instruction to SIL passes, and also produces better code in many cases.
It unfortunately exposes another bug in DI which affects the test/IRGen/objc.swift test, which I've XFAILed until it can be fixed.
Swift SVN r10564
Instead of cutting corners by emitting a static property reference as a DeclRef, do the right thing and build a MemberRef on the metatype. Add the smarts to SILGen to recognize static property MemberRefs and emit global_addr instructions for (nongeneric, nondynamic) static properties.
Swift SVN r10482
of having to lower to an RValue.
This is valuable because we can often emit an expression to a
desired abstraction level more efficiently than just emitting
it to minimal abstraction and then generalizing.
Swift SVN r10455
- Enhance SILBuilder::emitStrongRelease to be smarter.
- Start using emitStrongRelease in type lowering, SILGen,
CapturePromotion (replacing its implementation of the
same logic), and MandatoryInlining (one more place)
- Rename the primitive createStrongRetain/ReleaseInst
instructions to lose their suffix.
- Now that createStrongRetain/ReleaseInst are not special
cases from the naming perspective, remove some special cases
from DeserializeSIL and ParseSIL.
Swift SVN r10449
They are the same as createStrongRetainInst and createStrongReleaseInst, but
peephole away FunctionRefInst. It turns out that there is only a couple
places in SILGen where this behavior is necessary, and this tramples on the
general pattern used in SILBuilder.
Swift SVN r10448
Instead of trying to anticipate every combination of source and destination [unowned]/[weak] qualifiers, just back off on the copy_addr peephole and let the old path handle these cases as before.
Swift SVN r9030
If we're using emitExprInto to emit a LoadExpr, we can handle that by emitting a copy_addr from the underlying lvalue to the initialization instead of building and storing the rvalue, which plays better with the direction we're taking for value semantics optimizations.
This is currently guarded behind a flag -enable-silgen-lvalue-peepholes because it introduces a miscompile in the stdlib that crashes some tests; requires further investigation before making live.
Swift SVN r9027
Chris and I want to move toward canonicalizing on more abstract aggregate operations (copy_addr) instead of on the component load/store/copy|destroy_value/retain|release operations, which is easier for early passes like inout deshadowing, NRVO, and move optimization to reason about. As a first step, replace the handful of places where SILGen currently used TypeLowering::emitCopyInto with simple CopyAddrInst insertions. This affects inout initializations and emitSemanticLoadInto, neither of which should disturb early passes that relied on the old behavior.
Swift SVN r8991
As with the monadic '?', we treat any left-bound '!' as a postfix
operator. Currently, it extracts the value of its optional
subexpression, failing at run-time if the optional is empty.
Swift SVN r8948