This is used when materializing an LValue to share state between
the read and write phases of the access, replacing the 'temporary'
and 'extraInfo' parameters that were previously being passed around.
It adds two new fields, origSelfType and genericSig, which will be
used in an upcoming patch to actually apply the callback with the
current generic signature.
This will finally allow us to make use of materializeForSet
implementations in protocol extensions, which is a prerequisite
for enabling resilient default implementations of property and
subscript requirements.
When we emit calls to getters and setters with emitApply(), the call
emission code ends up re-abstracting the result of a getter or the
parameter to a setter.
As a result, getOrigFormalType() was incorrect for logical path
components. This was worked around by only adding an OrigToSubst
path component to an lvalue if the last path component was physical.
This caused a problem in the following case:
1) There was an abstraction difference between the storage of the
protocol requirement and the storage of the protocol witness
2) There was an abstraction difference between the storage of the
protocol witness, and the fully-substituted type of the witness
An example is when the witness is in a protocol extension, and uses
'Self' or some other associated type which is concrete and loadable
in the conformance.
Fix this properly by splitting up getStorageTypeData() into two
functions, one used when adding physical path components and another
one used for logical.
As a result, we can now give the correct abstraction pattern to
logical path components.
Similarly to how we've always handled parameter types, we
now recursively expand tuples in result types and separately
determine a result convention for each result.
The most important code-generation change here is that
indirect results are now returned separately from each
other and from any direct results. It is generally far
better, when receiving an indirect result, to receive it
as an independent result; the caller is much more likely
to be able to directly receive the result in the address
they want to initialize, rather than having to receive it
in temporary memory and then copy parts of it into the
target.
The most important conceptual change here that clients and
producers of SIL must be aware of is the new distinction
between a SILFunctionType's *parameters* and its *argument
list*. The former is just the formal parameters, derived
purely from the parameter types of the original function;
indirect results are no longer in this list. The latter
includes the indirect result arguments; as always, all
the indirect results strictly precede the parameters.
Apply instructions and entry block arguments follow the
argument list, not the parameter list.
A relatively minor change is that there can now be multiple
direct results, each with its own result convention.
This is a minor change because I've chosen to leave
return instructions as taking a single operand and
apply instructions as producing a single result; when
the type describes multiple results, they are implicitly
bound up in a tuple. It might make sense to split these
up and allow e.g. return instructions to take a list
of operands; however, it's not clear what to do on the
caller side, and this would be a major change that can
be separated out from this already over-large patch.
Unsurprisingly, the most invasive changes here are in
SILGen; this requires substantial reworking of both call
emission and reabstraction. It also proved important
to switch several SILGen operations over to work with
RValue instead of ManagedValue, since otherwise they
would be forced to spuriously "implode" buffers.
There's a group of methods in `DeclContext` with names that start with *is*,
such as `isClassOrClassExtensionContext()`. These names suggests a boolean
return value, while the methods actually return a type declaration. This
patch replaces the *is* prefix with *getAs* to better reflect their interface.
If we're accessing a field of a struct, ignore materializeForSet;
it will only have been synthesized if the struct conforms to a
protocol, and we don't want the presence of a conformance to
affect generated code.
A more principled fix would change the SILGen logic to use a
materializeForSet if it would have been synthesized anyway,
asserting that it was synthesized in that case. I'll clean this
up in the 'master' branch once these fixes settle.
This improves MaterializeForSetEmitter to support emission
of static materializeForSet thunks, as well as witnesses.
This is now done by passing in a nullptr as the conformance
and requirement parameters, and adding some conditional code.
Along the way, I fixed a few limitations of the old code,
namely weak/unowned and static stored properties weren't
completely plumbed through. There was also a memory leak in
addressed materializeForSet, the valueBuffer was never freed.
Finally, remove the materializeForSet synthesis in Sema since
it is no longer needed, which fixes at least one known crash
case.
In order to fix some other issues that came up with materializeForSet
and resilience, I had to bite the bullet and finish off John's code
for open-coding materializeForSet emission in SILGen. This patch
makes the subsequent changes easier to review.
This commit changes the Swift mangler from a utility that writes tokens into a
stream into a name-builder that has two phases: "building a name", and "ready".
This clear separation is needed for the implementation of the compression layer.
Users of the mangler can continue to build the name using the mangleXXX methods,
but to access the results the users of the mangler need to call the finalize()
method. This method can write the result into a stream, like before, or return
an std::string.
This commit fixes all of the places where users of the Mangler write to the stream that's used by the Mangler. The plan is to make the Mangler buffered, and this means that users can't assume that the mangler immediately writes the mangled tokens to the output stream.
Modeling nonescaping captures as @inout parameters is wrong, because captures are allowed to share state, unlike 'inout' parameters, which are allowed to assume to some degree that there are no aliases during the parameter's scope. To model this, introduce a new @inout_aliasable parameter convention to indicate an indirect parameter that can be written to, not only by the current function, but by well-typed, well-synchronized aliasing accesses too. (This is unrelated to our discussions of adding a "type-unsafe-aliasable" annotation to pointer_to_address to allow for safe pointer punning.)
Take apart exploded one-element tuples and be more careful with
passing around tuple abstraction patterns.
Also, now we can remove the inputSubstType parameter from
emitOrigToSubstValue() and emitSubstToOrigValue(), making the
signatures of these functions nice and simple once again.
Fixes <rdar://problem/19506347> and <rdar://problem/22502450>.
The CaptureInfo computed by Sema now records if the body of the
function uses any generic parameters from the outer context.
SIL type lowering only adds a generic signature if this is the
case, instead of unconditionally.
This might yield a marginal performance improvement in some cases,
but more interestingly will allow @convention(c) conversions from
generic context.
Swift SVN r32161
Right now, re-abstraction thunks are set up to convert values
as follows, where L is type lowering:
- OrigToSubst: L(origType, substType) -> L(substType)
- SubstToOrig: L(substType) -> L(origType, substType)
This assumes there's no AST-level type conversion, because
when we visit a type in contravariant position, we flip the
direction of the transform but we're still converting *to*
substType -- which will now equal to the type of the input,
not the type of the expected result!
This caused several problems:
- VTable thunk generation had a bunch of special logic to
compute a substOverrideType, and wrap the thunk result
in an optional, duplicating work done in the transform
- Witness thunk generation similarly had to handle the case
of upcasting to a base class to call the witness, and
casting the result of materializeForSet back to the right
type for properties defined on the base.
Now the materializeForSet cast sequence is a bit longer,
we unpack the returned tuple and do a convert_function
on the function, then pack it again -- before we would
unchecked_ref_cast the tuple, which is technically
incorrect since the tuple is not a ref, but IRGen didn't
seem to care...
To handle the conversions correctly, we add a third AST type
parameter to a transform, named inputType. Now, transforms
perform these conversions:
- OrigToSubst: L(origType, inputType) -> L(substType)
- SubstToOrig: L(inputType) -> L(origType, substType)
When we flip the direction of the transform while visiting
types in contravariant position, we also swap substType with
inputType.
Note that this is similar to how bridging thunks work, for
the same reason -- bridging thunks convert between AST types.
This is mostly just a nice cleanup that fixes some obscure
corner cases for now, but this functionality will be used
in a subsequent patch.
Swift SVN r31486
We need to be able to introduce and eliminate existentials inside
reabstraction thunks, so make this logic independent of RValue
and Expr emission.
NFC for now.
Swift SVN r31375
If we didn't initialize the existential, we have to emit a cleanup
because we may have allocated a buffer on the heap to store the value.
Factor out the TakeExistentialCleanup that appears in a few places,
rename it to DeinitExistentialCleanup and add support for deallocating
boxed existentials.
Then, use a special Initialization subclass to keep track of the
state of the memory in emit{AddressOnly,Boxed}Erasure().
Swift SVN r31259
subscripts defined in protocol extensions.
The right condition for this is really direct uses of the
default implementation; right now, that just means all
direct uses of something from a protocol extension.
Fixes rdar://22109071.
Swift SVN r31228
peephole reabstraction components by applying them to
the r-value instead of materializing to a temporary
and then assigning to that.
Removes a completely unnecessary use of the getter
from simple assignments to properties or subscripts
at a different abstraction level.
Swift SVN r31197
r31072 (<rdar://21836671>).
Passes the primary test suite; I'm still working on giving it
proper tests, but since time is of the essence, we can
streamline this process by doing a few things in parallel.
The test suite change here is interesting: we're no longer
emitting materializeForSet entrypoints for storage in
protocol extensions, because they were only getting emitted
lazily and we're no longer using them at all. I think
that's fine because, well, we're no longer using them at
all.
Swift SVN r31192
If the compiler can prove that a throwing function actually does not throw it can
replace a try_apply with an "apply [nothrow]". Such an apply_inst calls a function
with an error result but does not have the overhead of checking for the error case.
Currently this flag is not set, yet.
Swift SVN r31151
the type-checker. The strategy for now is to just use this
for protocol witness thunk emission, where it is required
when generating a materializeForSet for storage that is
either implemented in a protocol extension or requires
reabstraction to the requirement's pattern.
Eventually, this should be generalized to the point that
we can use it for all materializeForSet emission, which
I don't think will take much. However, that's not really
the sort of instability we want to embrace for the current
release.
WIP towards rdar://21836671; currently disabled, so NFC.
Swift SVN r31072
We need to keep the AST formal type of the base around when building up
lvalues.
When the getter or setter involves an accessor call, we would use the
lowered type of the self argument to form the call. However, it might be
at the wrong level of abstraction, causing a @thin -vs- @thick metatype
mismatch. Using the formal type instead allows SILGenApply logic to emit
a thin to thick metatype conversion if necessary.
Fixes <rdar://problem/21358641>.
Swift SVN r30913
This is a bit unfortunate since the natural result of 'get' was probably already at the right abstraction level and already got abstracted in the wrong direction, but we don't have the infrastructure to peephole away the redundancy yet. Fixes rdar://problem/20341012.
Swift SVN r30483
Before the fix we were inserting the dealloc_stack in the wrong basic block. Adding a scope to
performWriteback ensures that the different writeback methods don't leak cleanups into the their
caller cleanup scope.
Swift SVN r30428
This reverts commit r30272.
There's a way to fix Builtin.reinterpretCast that preserves SILGen
RValue invariants better according to JohnM. So although these changes
are valid, there will be no way for me to test them.
After reverting this, I will roll back in the change to
emitImplicitValueConstructor because I think the old code was
violating SILGen invariants.
Swift SVN r30306
This is required in order to fix Builtin.reinterpretCast for
address-only types. That upcoming fix will include a test case that
exposes this SILGen path.
Swift SVN r30272
This requires some really ugly copies at -O0 in order to
avoid changing whether enclosing cleanups are active during
the emission of those cleanups. (There may also be complex
situations where values are forwarded to the writeback but
the writeback cleanup can't take advantage of that --- not
sure yet.) These should generally be trivial to clean up,
but I'm still thinking about how to avoid emitting them in
the first place.
Swift SVN r30180
The other part of rdar://problem/21444126. This is a little trickier since SIL doesn't track uses of witness tables in a principled way. Track uses in SILGen by putting a "SILGenBuilder" wrapper in front of SILBuilder, which marks conformances from apply, existential erasure, and metatype lookup instructions as used, so we can avoid emitting shared Clang importer witnesses when they aren't needed.
Swift SVN r29544
in memory when it is address-only. This leads to better -O0 performance and
easier to read silgen output. This is ongoing progress towards rdar://20642198.
Swift SVN r28318
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
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
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