Delay allocating the result buffer for an opened Self return until right before it's needed. When a mutating method is invoked on an existential, the Self type won't be opened until late, when the formal access to the mutable value begins. Fixes rdar://problem/43507711.
For now, the accessors have been underscored as `_read` and `_modify`.
I'll prepare an evolution proposal for this feature which should allow
us to remove the underscores or, y'know, rename them to `purple` and
`lettuce`.
`_read` accessors do not make any effort yet to avoid copying the
value being yielded. I'll work on it in follow-up patches.
Opaque accesses to properties and subscripts defined with `_modify`
accessors will use an inefficient `materializeForSet` pattern that
materializes the value to a temporary instead of accessing it in-place.
That will be fixed by migrating to `modify` over `materializeForSet`,
which is next up after the `read` optimizations.
SIL ownership verification doesn't pass yet for the test cases here
because of a general fault in SILGen where borrows can outlive their
borrowed value due to being cleaned up on the general cleanup stack
when the borrowed value is cleaned up on the formal-access stack.
Michael, Andy, and I discussed various ways to fix this, but it seems
clear to me that it's not in any way specific to coroutine accesses.
rdar://35399664
closure lifetimes.
SILGen will now unconditionally emit
%cvt = convert_escape_to_noescape [guaranteed] %op
instructions. The mandatory ClosureLifetimeFixup pass ensures that %op's
lifetime spans %cvt's uses.
The code in DefiniteInitialization that handled a subset of cases is
removed.
- Emit a withoutActuallyEscapingClosure partial apply
This is to convert an @noescape closure to an escaping closure.
This needs to be done in preparation of @noescape closure contexts
becoming trivial.
- Insert escaping to noescape conversions
- Fix SILGen for @noescape
- Postpone closure cleanups to outside the argument scope
- Apply postponement recursively for closures passed to subscripts
- Only skip applying escapeness conversions for Swift thick functions
- Fix parameter convention for noescape closures in thunks
Part of:
SR-5441
rdar://36116691
Emit a borrow scope whenever exploding tuples in to a list of arguments.
I spent a lot of time attempting to refactor the reabstraction thunk generation
code with code that handles RValue. However, there is a subtle difference in how
tuples are handled when they are packed into a single "RValue" as opposed to a
list of arguments.
Eventually, I ditched that effort because of subtle complexity and fell back on
Michael's suggestion of handling the extra thunk-sepcific work inside
Scope.popPreservingValues. This will just go away though once we have the
'destructure' instruction.
What this routine does is:
1. "Imprints" a cleanup cloner with the managed value.
2. Forwards the managed value.
3. Pop the scope.
4. Use the imprinted cleanup cloner to recreate the managed value in the scope
outside of the current scope.
This just automates the work of:
1. Grabbing the cleanup manager from the SGF.
2. Forming a CleanupLocation from a SILLocation.
Much of the time when one creates a scope, that is the information that one has
available. So lets make it... wait for it... convenient to construct a scope
with this data.
This is a closure based API for creating switches that obey ownership
convensions. The way you use it with objects is as follows:
SwitchEnumBuilder S(...);
S.addCase(Decl, Block, [](ManagedValue Arg) -> void {
...
});
S.addCase(Decl, Block, [](ManagedValue Arg) -> void {
...
});
S.addDefaultCase(Block, [](ManagedValue Arg) -> void {
...
});
std::move(S).emit();
What is important is that it sets up the switch_enum destination blocks with the
proper cleanups for code emitted into the destination block and also provides
the default error with the passed in value with the appropriate cleanups.
It does not handle exits from the switch_enum on purpose since diamond
switch_enum APIs form a subset of APIs. It also expects the closure to create
terminators if appropriate.
In the switch_enum_addr case you have to do a bit more work, but it is still a
nicer API than doing it by hand as we do today.
rdar://29791263
weak copies for capture list variables. Other wise two variables with
identical names will end up in the same scope.
This fixes a crash in the compiler.
rdar://problem/24150188
SR-526
The drivers for this change are providing a simpler API to SIL pass
authors, having a more efficient of the in-memory representation,
and ruling out an entire class of common bugs that usually result
in hard-to-debug backend crashes.
Summary
-------
SILInstruction
Old New
+---------------+ +------------------+ +-----------------+
|SILInstruction | |SILInstruction | |SILDebugLocation |
+---------------+ +------------------+ +-----------------+
| ... | | ... | | ... |
|SILLocation | |SILDebugLocation *| -> |SILLocation |
|SILDebugScope *| +------------------+ |SILDebugScope * |
+---------------+ +-----------------+
We’re introducing a new class SILDebugLocation which represents the
combination of a SILLocation and a SILDebugScope.
Instead of storing an inline SILLocation and a SILDebugScope pointer,
SILInstruction now only has one SILDebugLocation pointer. The APIs of
SILBuilder and SILDebugLocation guarantees that every SILInstruction
has a nonempty SILDebugScope.
Developer-visible changes include:
SILBuilder
----------
In the old design SILBuilder populated the InsertedInstrs list to
allow setting the debug scopes of all built instructions in bulk
at the very end (as the responsibility of the user). In the new design,
SILBuilder now carries a "current debug scope" state and immediately
sets the debug scope when an instruction is inserted.
This fixes a use-after-free issue with with SIL passes that delete
instructions before destroying the SILBuilder that created them.
Because of this, SILBuilderWithScopes no longer needs to be a template,
which simplifies its call sites.
SILInstruction
--------------
It is neither possible or necessary to manually call setDebugScope()
on a SILInstruction any more. The function still exists as a private
method, but is only used when splicing instructions from one function
to another.
Efficiency
----------
In addition to dropping 20 bytes from each SILInstruction,
SILDebugLocations are now allocated in the SILModule's bump pointer
allocator and are uniqued by SILBuilder. Unfortunately repeat compiles
of the standard library already vary by about 5% so I couldn’t yet
produce reliable numbers for how much this saves overall.
rdar://problem/22017421
When emitting try_apply, don't start a new scope between adding
a cleanup and forwarding the value. This would leave behind a
dead cleanup, which would fire an assertion in emitSharedCaseBlocks().
Fixes <rdar://problem/20923654>.
Swift SVN r28572
Mandatory-inlined (aka transparent functions) are still treated as if they
had the location and scope of the call site. <rdar://problem/14845844>
Support inline scopes once we have an optimizing SIL-based inliner
Patch by Adrian Prantl.
Swift SVN r18835
Allow IfStmts and WhileStmts to have as their condition either an expression, as usual, or a pattern binding introduced by 'var' or 'let', which will conditionally bind to the value inside an optional. Unlike normal pattern bindings, these bindings require an in-line initializer, which will be required to be Optional type. Parse variable bindings in this position, and type-check them by requiring an Optional on the right-hand side and unwrapping it to form the pattern type. Extend SILGen's lowering of if and while statements to handle conditionally binding variables.
Swift SVN r13146
I've decided to keep only the location of the scope AST node that corresponds to the cleanup. (Currently, there is no user that needs the originator expression, which caused the cleanup. So keeping things simple.)
Added the cleanup location to the Scope and JumpDest classes, which gets assigned on construction of those. The Scope's and JumpDest locations are used when we emit the cleanup instructions.
We now give better location info for 2 existing tests for definitive initialization.
(+ Rather sparse testing of all this.)
Swift SVN r7764