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
This is necessary for correctly dealing with non-standard
ownership conventions in secondary positions, and it should
also help with non-injective type imports (like BOOL/_Bool).
But right now we aren't doing much with it.
Swift SVN r26954
Previously some parts of the compiler referred to them as "fields",
and most referred to them as "elements". Use the more generic 'elements'
nomenclature because that's what we refer to other things in the compiler
(e.g. the elements of a bracestmt).
At the same time, make the API better by providing "getElement" consistently
and using it, instead of getElements()[i].
NFC.
Swift SVN r26894
Remove the semantic restrictions that prohibited extensions of
protocol types, and start making some systematic changes so that
protocol extensions start to make sense:
- Replace a lot of occurrences of isa<ProtocolDecl> and
dyn_cast<ProtocolDecl> on DeclContexts to use the new
DeclContext::isProtocolOrProtocolExtensionContext(), where we want
that behavior to apply equally to protocols and protocol extensions.
- Eliminate ProtocolDecl::getSelf() in favor of
DeclContext::getProtocolSelf(), which produces the appropriate
generic type parameter for the 'Self' of a protocol or protocol
extension. Update all of the callers of ProtocolDecl::getSelf()
appropriately.
- Update extension validation to appropriately form generic
parameter lists for protocol extensions.
- Methods in protocol extensions always use the witnesscc calling
convention.
At this point, we can type check and SILGen very basic definitions of
protocol extensions with methods that can call protocol requirements,
generic free functions, and other methods within the same protocol
extension.
Regresses four compiler crashers but improves three compiler
crashers... we'll call that "progress"; the four regressions all hit
the same assertion in the constraint system that will likely be
addressed as protocol extensions starts working.
Swift SVN r26579
We no longer need or use it since we can always refer to the same bit on
the applied function when deciding whether to inline during mandatory
inlining.
Resolves rdar://problem/19478366.
Swift SVN r26534
The string version of r26479. There's a lot of backstory and justification
there, so just read that commit message again. The one addition for String
is that global NSString constants are loaded as String as well, so that
also has to go through the bridging code even though there's no function
call involved.
Finishes rdar://problem/19734621.
Swift SVN r26510
...and similar for NSDictionary and NSSet.
For APIs that don't have a reason to distinguish "empty" and "absent" cases,
we encourage standardizing on "empty" and marking the result as non-optional
(or in Objective-C, __nonnull). However, there are system APIs whose
implementations currently do return nil rather than an empty collection
instance. In these cases, we recommend /changing/ the API to return the
appropriate "empty" value instead.
However, this can cause problems for backwards-deployment: while the API is
truly non-optional on system vN, a program may encounter a nil return value
if run on system vN-1. Objective-C can generally deal with this (especially
if the only thing you do is ask for the count or try to iterate over the
collection) but Swift can't. Therefore, we've decided to "play nice" and
accept nil return values for the collection types (NSArray, NSDictionary,
and NSSet) and implicitly treat them as "empty" values if they are the
result of an imported function or method.
Note that the current implementation has a hole regarding subscript getters,
since we still make an AST-level thunk for these in the Clang importer.
We can probably get rid of those these days, but I didn't want to touch
them at this point. It seems unlikely that there will be a subscript that
(a) is for a collection type, and (b) mistakenly returned nil in the past
rather than an empty collection.
There's another hole where an ObjC client calls one of these mistakenly-nil-
returning methods and then immediately hands the result off by calling a
Swift method. However, we have to draw the line somewhere.
(We're actually going to do this for strings as well; coming soon.)
rdar://problem/19734621
Swift SVN r26479