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
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
- 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
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
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
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
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