in a trivial struct, the 'self' argument in an initializer won't have
a cleanup, so don't disable or reenable it when rebinding self due to delegation.
Swift SVN r28674
instead of being an expression.
To the user, this has a couple of behavior changes, stemming from its non-expression-likeness.
- #available cannot be parenthesized anymore
- #available is in its own clause, not used in a 'where' clause of if/let.
Also, the implementation in the compiler is simpler and fits the model better. This
fixes:
<rdar://problem/20904820> Following a "let" condition with #available is incorrectly rejected
Swift SVN r28521
And take advantage of the guaranteed peephole when available to emit the base expression at +0 in general existential-to-existential erasures. Fixes rdar://problem/20890504.
Swift SVN r28447
This reapplies commit r27632 with additional fixes, tests.
I turned off the guaranteed struct optimization since we really don't have the
infrastructure to do it right and more importantly I don't have the time to do
so (and was not asked to do so).
We still have the class optimization though!
This means that there is one retain in ClassIntTreeMethod.find.
class ClassIntTreeNode {
let value : Int
let left, right : ClassIntTreeNode
init() {}
func find(v : Int) -> ClassIntTreeNode {
if v == value { return self }
if v < value { return left.find(v) }
return right.find(v)
}
}
Swift SVN r28264
Two pieces to this:
- Peephole OptionalEvaluationExpr(InjectOptionalExpr(BindOptionalExpr(X))) to bitcast x to the result type.
- Enhance OptionalEvaluationExpr to delete the failure block if not needed.
This is the same as r28150, but it includes a fix for the case when a non-address-only type
is initializing a contextally-provided-and-addressible buffer, tested by the new
testContextualInitOfNonAddrOnlyType testcase.
Swift SVN r28153
Two pieces to this:
- Peephole OptionalEvaluationExpr(InjectOptionalExpr(BindOptionalExpr(X))) to
bitcast x to the result type.
- Enhance OptionalEvaluationExpr to delete the failure block if not needed.
This is the same as r28111, except that we finalize the initialization in the
address-only case. A reduced testcase for the specific issue is added to
optional-casts.swift.
Swift SVN r28150
and r28105: "implement <rdar://problem/17013042> T! <-> T? conversions should not produce a diamond"
r28111 broke the stdlib build. I also reverted r28105, because r28111 fixes regressions introduced in r2805.
Swift SVN r28114
Instead of immediately creating closures for local function declarations and treating them directly as capturable values, break function captures down and transitively capture the storage necessary to invoke the captured functions. Change the way SILGen emits calls to closures and local functions so that it treats the capture list as the first curry level of an invocation, so that full applications of closure literals or nested functions don't require a partial apply at all. This allows references among local functions with captures to work within the existing confines of partial_apply, and also has the nice benefit that circular references would work without creating reference cycles (though Sema unfortunately rejects them; something we arguably ought to fix.)
This fixes rdar://problem/11266246 and improves codegen of local functions. Full applications of functions, or immediate applications of closure literals like { }(), now never need to allocate a closure.
Swift SVN r28112
on inject_into_optional/bind_optional_expr isn't safe because we don't know what
optional_evaluation_expr is actually being bound, or if it is bound to the result of the
injection.
Instead, make this more careful to look for the evaluation_expr as well, matching
the specific pattern:
(optional_evaluation_expr type='T?'
(inject_into_optional type='T?'
(bind_optional_expr type='T'
(whatever type='T?' ...)
This fixes the two interpreter testcases that regressed in r28105.
Swift SVN r28111
Two pieces to this:
- Peephole InjectOptionalExpr(BindOptionalExpr(X)) to bitcast x to the result type.
- Enhance OptionalEvaluationExpr to delete the failure block if not needed.
Swift SVN r28105
nil path. This avoids emitting a "release" operation on an optional temporary that is
always guaranteed to be dynamically nil. This cleans up the generated code for x?.foo().
Swift SVN r28103
to not drop optionals in memory all the time. We now generate a lot better code
for them in many cases. This makes generated SIL more readable and should help
-O0 perf.
This is progress towards <rdar://problem/20642198> SILGen shouldn't be dropping optionals into memory all the time
Swift SVN r28102
emit{StrongRelease,ReleaseValue} => emit{StrongRelease,ReleaseValue}AndFold.
Then introduce a new method emit{StrongRelease,ReleaseValue} that returns a
PointerUnion containing the increment to be deleted if it exists. This obviates
the need for the callback.
Swift SVN r27804
When emitting default arguments for a parameter, emitApplyOfDefaultArgGenerator
was trying to reconstruct the original type by looking at the decl that it came
from. However, it doesn't know the number of curry levels already applied, so it
was wrong in the case of default arguments on methods and initializers (which already
have self applied).
Fix this by having the caller pass this information in, since it knows the original
type.
While we're at it, remove the code for handling default arguments from the general
SILGenExpr logic. Default arguments in tuples are no longer a general thing, they
are only valid in argument lists.
Swift SVN r27800
Specifically this patch makes the following changes:
1. We properly propagate down the SGFContext of a tuple to its elements
when extracting from a tuple. There was a typo that caused us to use
data from the newly created default initialized copy instead of from the
actual SGFContext of the parent tuple.
2. If we are accessing a member ref of self in a guaranteed context:
a. If self is a struct, regardless of whether or not the field is a
var or a let we no longer emit a retain. This is b/c self in a
guaranteed context is immutable. This implies even a var in the
struct can not be reassigned to.
b. If self is a class, if the field is a let, we no longer emit an
extra retain.
This makes it so that the only rr traffic in IntTreeNode::find is in the
block of code where we return self.
class IntTreeNode {
let value : Int
let left, right : IntTreeNode
init() {} // not needed for -emit-silgen
func find(v : Int) -> IntTreeNode {
if v == value { return self }
if v < value { return left.find(v) }
return right.find(v)
}
}
One gets the same effect using a struct for IntTreeNode and a generic
box class, i.e.:
class Box<T> {
let value: T
init(newValue: T) { value = newValue }
}
class Kraken {}
struct IntTreeNode {
let k : Kraken // Just to make IntTreeNode non-trivial for rr purposes.
let left, right : Box<IntTreeNode>
init() {} // not needed for -emit-silgen
func find(v : Int) -> IntTreeNode {
if v == value { return self }
if v < value { return left.value.find(v) }
return right.value.find(v)
}
}
There is more work that can be done here by applying similar logic to
enums, i.e. switching on self in an enum should not generate any rr
traffic over the switch. Also it seems that there are some places in SILGen
where isGuaranteedValid is not being propagated to SILGenFunction::emitLoad. But
that is for another day.
I am going to gather data over night and send an email to the list.
rdar://15729033
Swift SVN r27632
registers instead of eagerly dumping them in memory and operating on
them by-address. This avoids a lot of temporaries and traffic to
manipulate them.
As part of this, add some new SGF::getOptionalNoneValue/getOptionalSomeValue
helper methods for forming loading optional values.
Many thanks to JoeG for helping with the abstraction difference change in
getOptionalSomeValue.
Swift SVN r27537
emission instead of hand coded magic. Eliminating special cases allows simplifying
other parts of the compiler, and this probably helps the error handling initiative
as well.
This uses the (horrible) new null_class instruction to properly model rebinding of
self. The code that SILGen was producing before was wildly incorrect and we only
got lucky that it seemed to work in most cases before.
NFC except that SILGen tests see the new null_class instructions, and we get better
location info for 'return nil' for obscure reasons that don't really matter.
Swift SVN r27530
it would drop in a dealloc_box or strong_release after rebinding, which is incorrect
(the box is used for any loads of self after the rebind!) but also pointless:
the AllocBoxToStack pass saved the day by promoting the box to a stack address and
zapping these instructions.
Interestingly, AllocBoxToStack *always* succeeds in class initializers, because the
self value is treated as a let value (even though in a box) and captured by value,
therefore there is no way to block the stack promotion that I can find.
In any case, this code is in my way and not doing anything, buhbye.
Swift SVN r27517
- In the normal optional-to-optional init case, use
"emitUncheckedGetOptionalValueFrom" instead of
"emitCheckedGetOptionalValueFrom" since we have already
checked to see if the optional is present. This avoids a
function call (that is mandatory inlined away) along with a ton
of SIL that gets mandatory inlined in that shows an assertion
failure that can never fail.
- Teach SGF::emitDoesOptionalHaveValue and
SILGenFunction::emitUncheckedGetOptionalValueFrom to work with
optionals in memory and optional values.
- Based on this, stop dropping the optional self into a materialized
temporary all the time. Just use whatever we have (a value or the
address of an address-only thing) and operate on it directly.
- Use Cleanups.emitBlockForCleanups instead of emitting a block and
using emitBranchAndCleanups. This leads to cleaner code in SILGen
and avoids emitting a dead block in the common case where there are
no cleanups to perform.
Overall, these changes lead to better super.init calls in failable
inits, and more importantly enable understanding the output of -emit-sil
on them :-)
Swift SVN r27477
already set up, allowing clients to generate code before the top-level
cleanup stack is emitted.
Use this to switch value constructors onto emitEpilog() and, more importantly,
to start managing the self box as a normal local variable tracked with cleanups
instead of being tracked with ad-hoc code spread through SILGen.
Among other things, once classes are switched over to the same model, we can
remove SGF.FailSelfDecl and the code to support it. NFC.
Swift SVN r27472
- Privatize "kind" in the base Initialization class.
- Simplify canForwardInBranch() to just isSingleBuffer().
There is only one client of it (which avoids emitting the
formation of an optional temporary) and the only cases we're
dropping is for "_" patterns and single element tuple patterns,
which are not worth optimizing for.
- Change getSubInitializationsForTuple() into a virtual method
since it has wildly different behavior based on the subclass and
requires otherwise private implementation details of those subclasses
to implement it.
- Simplify subclasses based on these changes.
Swift SVN r27463
- Use virtual dispatch to localize some predicates instead
of having special cases for LetValue inits in global places.
- Improve 'const'ness of methods.
- Introduce a common "KnownAddressInitialization" class to centralize
the notion of an initialization corresponding to a specific physical
address that is known up front. Consolidate dupes of this concept into
uses of it.
NFC.
Swift SVN r27462
to make it take a ManagedValue instead of an Expr*.
NFC, except that the temporaries are emitted a bit later in some cases,
accounting for the diffs in the testcases.
Swift SVN r27458
Consistently open all references into existentials into
opened-existential archetypes within the constraint solver. Then,
during constraint application, use OpenExistentialExprs to record in
the AST where an existential is opened into an archetype, then use
that archetype throughout the subexpression. This simplifies the
overall representation, since we don't end up with a mix of operations
on existentials and operations on archetypes; it's all archetypes,
which tend to have better support down the line in SILGen already.
Start simplifying the code in SILGen by taking away the existential
paths that are no longer needed. I suspect there are more
simplifications to be had here.
The rules for placing OpenExistentialExprs are still a bit ad hoc;
this will get cleaned up later so that we can centralize that
information. Indeed, the one regression in the compiler-crasher suite
is because we're not closing out an open existential along an error
path.
Swift SVN r27230
Try to emit the existential as a guaranteed value, and if we succeed, only +1 the bound opaque value if it's needed as a consumed value. This lets us avoid retaining or copying the existential if the existential can be produced and its contained value consumed at +0.
Swift SVN r27200
Place OpenExistentialExprs for references to lvalue subscripts or properties
(in protocol extensions) via existentials just outside of the member
or subscript reference, rather than far outside the expression. This
gives us a tighter bound on the open-existential expressions without
introducing the post-pass I was threatening.
OpenExistentialExprs just outside of lvalue member/subscript are
themselves lvalues. Resurrect John's OpenOpaqueExistentialComponent to
handle the opening of a (materialized) existential lvalues as an
lvalue path component. This has the nice effect of codifying the
formal access rules for opened existentials as well as handling inout
on opened existentials appropriately.
Big thanks to John for talking through the model with me and leaving
dead code around for me to use.
Swift SVN r27105
This isn't the right solution; we should be folding open-existentials
into the LValue machinery rather than subverting it. However, the test
cases are useful for we do get the right solution in place.
Swift SVN r27103
These aren't really orthogonal concerns--you'll never have a @thick @cc(objc_method), or an @objc_block @cc(witness_method)--and we have gross decision trees all over the codebase that try to hopscotch between the subset of combinations that make sense. Stop the madness by eliminating AbstractCC and folding its states into SILFunctionTypeRepresentation. This cleans up a ton of code across the compiler.
I couldn't quite eliminate AbstractCC's information from AST function types, since SIL type lowering transiently created AnyFunctionTypes with AbstractCCs set, even though these never occur at the source level. To accommodate type lowering, allow AnyFunctionType::ExtInfo to carry a SILFunctionTypeRepresentation, and arrange for the overlapping representations to share raw values.
In order to avoid disturbing test output, AST and SILFunctionTypes are still printed and parsed using the existing @thin/@thick/@objc_block and @cc() attributes, which is kind of gross, but lets me stage in the real source-breaking change separately.
Swift SVN r27095
The set of attributes that make sense at the AST level is increasingly divergent from those at the SIL level, so it doesn't really make sense for these to be the same. It'll also help prevent us from accidental unwanted propagation of attributes from the AST to SIL, which has caused bugs in the past. For staging purposes, start off with SILFunctionType's versions exactly the same as the FunctionType versions, which necessitates some ugly glue code but minimizes the potential disruption.
Swift SVN r27022