Commit Graph

268 Commits

Author SHA1 Message Date
Michael Gottesman
b80c96a2e7 [+0 self] Teach SILGen how to avoid emitting extra rr pairs when emitting RValues with Nominal Types and Tuples.
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
2015-04-23 10:10:43 +00:00
Chris Lattner
d9083d2e50 rework SGF::emitOptionalToOptional to keep loadable SILValue's as
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
2015-04-21 22:54:08 +00:00
Chris Lattner
2fd563616e improve SILGen of RebindSelfInConstructorExpr in several ways:
- 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
2015-04-20 05:15:06 +00:00
John McCall
a67452c72c SILGen for throwing foreign errors out of @objc thunks.
Also, create a new file specifically for the foreign-error
code.

Swift SVN r27347
2015-04-16 05:16:54 +00:00
Doug Gregor
997136962e Always open existential types in the type checker.
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
2015-04-11 03:20:22 +00:00
Joe Groff
7be9c21c8b SILGen: Rework OpenExistentialExpr emission to better handle guaranteed contexts.
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
2015-04-10 02:58:57 +00:00
Doug Gregor
595fb8c94f Introduce lvalue open-existential expressions and start using them.
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
2015-04-07 23:22:05 +00:00
Doug Gregor
b8a7ebc20f Add LValue::dump(). NFC
Swift SVN r27104
2015-04-07 23:22:04 +00:00
Joe Groff
ad0d20c07a Fold "AbstractCC" into SILFunctionType::Representation.
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
2015-04-07 21:59:39 +00:00
Doug Gregor
d3d20bbb4f Remove an unused LValue path component for opening opaque existentials.
NFC; this was dead code, and we're not going to be seeing these in
SILGen once the type checker is opening existentials.

Swift SVN r27084
2015-04-07 16:29:10 +00:00
Doug Gregor
441fb9856c Handle lvalue OpaqueValueExprs in SILGen.
Tests coming once Sema starts creating such entities.

Swift SVN r27066
2015-04-07 06:01:16 +00:00
Chris Lattner
95b7b4d5e4 rename CleanupLocation::getCleanupLocation -> CleanupLocation::get, NFC.
Swift SVN r26994
2015-04-04 22:56:01 +00:00
John McCall
dc4b8ff2c2 Incorporate an optional Clang type into AbstractionPattern.
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
2015-04-03 21:39:31 +00:00
John McCall
35b7db3ae1 Parsing support for error results from SILFunctionType.
Swift SVN r26566
2015-03-26 00:01:32 +00:00
Jordan Rose
d6bc8971c7 If imported calls return nil for __nonnull NSString *, pretend it was "".
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
2015-03-25 01:16:45 +00:00
John McCall
ee4aa14703 Stop reordering blocks in SILBuilder::emitBlock.
This change permits SILGen to make smarter decisions about
block placement by keeping related blocks together instead
of always inserting to the end to the function.  The
flipside is that SILGen needs to be somewhat careful to
create blocks in the right order.  Counter-intuitively,
that order is the reverse of the order in which the blocks
should be laid out, since blocks created later will be
inserted before blocks created earlier.  Note, however,
that this produces the right results for recursive
emission.

To that end, adjust a couple of places in SILGen to
create blocks in properly nested order.

All of the block-order differences in the tests seem
to be desirable; several of them even had confused
comments wondering how on earth a block got injected
where it did.

Also, fix the implementation of SILBuilder::moveBlockTo,
and fix a latent bug in epilogue emission where epilogBB
was erased from its parent (deleting it) and then
queried multiple times (!).

Swift SVN r26428
2015-03-23 06:38:20 +00:00
Joe Groff
962a87f444 SIL: Rename address-only existential instructions to '{init,deinit,open}_existential_addr'.
For better consistency with other address-only instruction variants, and to open the door to new exciting existential representations (such as a refcounted boxed representation for ErrorType).

Swift SVN r25902
2015-03-09 23:55:31 +00:00
Michael Gottesman
77b2e21eb5 Move buildForwardingSubstitutions onto GenericParamList::getForwardingSubstitutions(). NFC.
Swift SVN r25358
2015-02-17 23:01:02 +00:00
Dmitri Hrybenko
61286f0260 Fix warnings produced by a newer version of Clang
Swift SVN r25257
2015-02-12 23:50:47 +00:00
Chris Lattner
9c7417edc2 fix <rdar://problem/19782264> Immutable, optional class members can't have their subproperties read from during init()
The problem here was that the _preconditionImplicitlyUnwrappedOptionalHasValue
compiler intrinsic was taking the optional/IUO argument as inout as a performance
optimization, but DI would reject it (in narrow cases, in inits) because the inout
argument looks like a mutation.  

We could rework this to take it as an @in argument or something, but it is better
to just define this problem away: the precondition doesn't actually care about the
optional, it is just testing its presence, which SILGen does all the time.  Have
SILGen open code the switch_enum and just have the stdlib provide a simpler
_diagnoseUnexpectedNilOptional() to produce the error message.

This avoids the problem completely and produces slightly better -O0 codegen.



Swift SVN r25254
2015-02-12 22:35:51 +00:00
Joe Groff
735bd354a5 SILGen: Remove !hasDifferentTypeOfRValue assertion from emitConversionFromSemanticValue.
We "convert" unowned to unowned without decaying to the semantic strong type when an unowned reference is captured by a nested closure. If we remove the assert, the codegen looks correct, and external projects walk this code path oblivious to the assertion.

Swift SVN r25248
2015-02-12 20:41:56 +00:00
Joe Groff
f1b97a1ead SILGen: Admit inout aliasing of polymorphic properties.
A stored property of a class may be overridden by a computed one, and a property requirement may be witnessed by a computed property, but rejecting inout aliasing in these cases isn't very helpful. Only reject cases that are definitely computed and will always behave incorrectly. Fixes rdar://problem/19633414.

Swift SVN r24986
2015-02-05 01:22:02 +00:00
John McCall
bf75beeb7a Begin formal accesses on l-value arguments immediately before
the call instead of during the formal evaluation of the argument.

This is the last major chunk of the semantic changes proposed
in the accessors document.  It has two purposes, both related
to the fact that it shortens the duration of the formal access.

First, the change isolates later evaluations (as long as they
precede the call) from the formal access, preventing them from
spuriously seeing unspecified behavior.  For example::

  foo(&array[0], bar(array))

Here the value passed to bar is a proper copy of 'array',
and if bar() decides to stash it aside, any modifications
to 'array[0]' made by foo() will not spontaneously appear
in the copy.  (In contrast, if something caused a copy of
'array' during foo()'s execution, that copy would violate
our formal access rules and would therefore be allowed to
have an arbitrary value at index 0.)

Second, when a mutating access uses a pinning addressor, the
change limits the amount of arbitrary code that falls between
the pin and unpin.  For example::

  array[0] += countNodes(subtree)

Previously, we would begin the access to array[0] before the
call to countNodes().  To eliminate the pin and unpin, the
optimizer would have needed to prove that countNodes didn't
access the same array.  With this change, the call is evaluated
first, and the access instead begins immediately before the call
to +=.  Since that operator is easily inlined, it becomes
straightforward to eliminate the pin/unpin.

A number of other changes got bundled up with this in ways that
are hard to tease apart.  In particular:

  - RValueSource is now ArgumentSource and can now store LValues.

  - It is now illegal to use emitRValue to emit an l-value.

  - Call argument emission is now smart enough to emit tuple
    shuffles itself, applying abstraction patterns in reverse
    through the shuffle.  It also evaluates varargs elements
    directly into the array.

  - AllowPlusZero has been split in two.  AllowImmediatePlusZero
    is useful when you are going to immediately consume the value;
    this is good enough to avoid copies/retains when reading a 'var'.
    AllowGuaranteedPlusZero is useful when you need a stronger
    guarantee, e.g. when arbitrary code might intervene between
    evaluation and use; it's still good enough to avoid copies
    from a 'let'.  The upshot is that we're now a lot smarter
    about generally avoiding retains on lets, but we've also
    gotten properly paranoid about calling non-mutating methods
    on vars.

    (Note that you can't necessarily avoid a copy when passing
    something in a var to an @in_guaranteed parameter!  You
    first have to prove that nothing can assign to the var during
    the call.  That should be easy as long as the var hasn't
    escaped, but that does need to be proven first, so we can't
    do it in SILGen.)

Swift SVN r24709
2015-01-24 13:05:46 +00:00
Joe Groff
a449948275 SILGen: Emit vtable thunks to handle optional variance.
If a subclass overrides methods with variance in the optionality of non-class-type members, emit a thunk to handle wrapping more optional parameters or results and force-unwrapping any IUO parameters made non-optional in the derived. For this to be useful, we need IRGen to finally pay attention to SILVTables, but this is a step on the way to fixing rdar://problem/19321484.

Swift SVN r24705
2015-01-24 05:21:26 +00:00
Chris Willmore
94bf316fc2 <rdar://problem/16937737> global NSString constants showing as NSString, not String
Import global variables of type NSString * as String instead of
NSString. Emit bridging code in SIL when such a variable is loaded.

Swift SVN r24495
2015-01-17 04:00:55 +00:00
John McCall
cae0f6e3db Add the ability for a owning addressor to return
a non-native owner.  This is required by Slice, which
will use an ObjC immutable array object as the owner
as long as all the elements are contiguous.

As part of this, I decided it was best to encode the
native requirement in the accessor names.  This makes
some of these accessors really long; we can revisit this
if we productize this feature.

Note that pinning addressors still require a native
owner, since pinning as a feature is specific to swift
refcounting.

Swift SVN r24420
2015-01-14 19:14:20 +00:00
John McCall
48f7a19d74 Enter a writeback scope before performing an assignment.
We need this in order to unpin at the correct moment.

Add an assertion that there's a scope active when pushing
an unpin writeback, as well as an assertion to ensure that
we never finish a function with writebacks active.

Swift SVN r24411
2015-01-14 02:17:27 +00:00
John McCall
3b89751b08 Merge the subscript r-value path with the l-value path.
Fixes a dumb bug where r-value subscripts would
unnecessarily emit their bases as ReadWrite.

Swift SVN r24410
2015-01-14 01:38:56 +00:00
John McCall
6a46350546 Bugfixes for the new addressor kinds.
Permit non-Ordinary accesses on references to functions,
with the semantics of devirtualizing the call if the
function is a class member.  This is important for
constructing direct call to addressors from synthesized
materializeForSet accessors: for one, it's more
performant, and for another, addressors do not currently
appear in v-tables.

Synthesize trivial accessors for addressed class members.
We weren't doing this at all before, and I'm still not
sure we're doing it right in all cases.  This is a mess.

Assorted other fixes.  The new addressor kinds seem
to work now.

Swift SVN r24393
2015-01-13 10:37:22 +00:00
John McCall
dc4431ebff Split addressors into unsafe, owning, and pinning variants.
Change all the existing addressors to the unsafe variant.

Update the addressor mangling to include the variant.

The addressor and mutable-addressor may be any of the
variants, independent of the choice for the other.

SILGen and code synthesis for the new variants is still
untested.

Swift SVN r24387
2015-01-13 03:09:16 +00:00
John McCall
f3dc58667d Improve the typing of materializeForSet callbacks to
use a thin function type.

We still need thin-function-to-RawPointer conversions
for generic code, but that's fixable with some sort of
partial_apply_thin_recoverable instruction.

Swift SVN r24364
2015-01-11 21:13:35 +00:00
Joe Groff
40d4710d61 SILGen: Fix overly restrictive assertion on lvalue-derived-from-rvalue bases.
The base value can be an address if it's any address-only type, not exclusively archetypes or existentials. Fixes nonmutating setters of address-only structs (rdar://problem/17841127), which I ran into while writing test cases for +0 self.

Swift SVN r24327
2015-01-09 21:41:08 +00:00
David Farler
3530e542ca Static class stored properties
rdar://problem/19422120

Allow static/class final stored properties to get through to the
mangled global property implementations.

Swift SVN r24303
2015-01-09 09:54:18 +00:00
John McCall
44eec49842 Change the signature of materializeForSet to return an
optional callback; retrofit existing implementations.

There's a lot of unpleasant traffic in raw pointers here
which I'm going to try to clean up.

Swift SVN r24123
2014-12-23 22:14:38 +00:00
Chris Lattner
7530f406fd Implement <rdar://problem/19290065> retains and releases of 'let' values aren't necessary
teach SILGenLValue that let values guarantee the lifetime of their value for at least
the duration of whatever expression references the let value.  This allows us to eliminate
retains/release pairs in a lot of cases, and provides more value for people to use let
instead of var.  This combines particularly well with +0 self arguments (currently just
protocol/archetype dispatches, but perhaps someday soon all method dispatches).

Thanks to John for suggesting this.



Swift SVN r24004
2014-12-18 06:14:35 +00:00
Chris Lattner
8c916c31f4 Fix <rdar://problem/19275047> Extraneous retains/releases of self are bad
This teaches SILGenLValue that base expressions referring to self can always
be done at +0, avoiding retain/release traffic.  This eliminates some hacks 
where init() needed special code, and also reduces r/r traffic in general.

Before the example in the radar silgen'd to:

sil hidden @_TFC1x4Base3foofS0_FT_T_ : $@cc(method) @thin (@owned Base) -> () {
bb0(%0 : $Base):
  debug_value %0 : $Base  // let self             // id: %1
  strong_retain %0 : $Base                        // id: %2
  // function_ref x.Base.__allocating_init (x.Base.Type)() -> x.Base
  %3 = function_ref @_TFC1x4BaseCfMS0_FT_S0_ : $@thin (@thick Base.Type) -> @owned Base // user: %5
  %4 = metatype $@thick Base.Type                 // user: %5
  %5 = apply %3(%4) : $@thin (@thick Base.Type) -> @owned Base // user: %7
  %6 = ref_element_addr %0 : $Base, #Base.f       // user: %7
  assign %5 to %6 : $*Base                        // id: %7
  strong_release %0 : $Base                       // id: %8
  strong_release %0 : $Base                       // id: %9
  %10 = tuple ()                                  // user: %11
  return %10 : $()                                // id: %11
}

now the %2 and %8 instructions are gone.



Swift SVN r23977
2014-12-17 06:09:56 +00:00
Chris Lattner
ec00695c19 remove emitSelfForDirectPropertyInConstructor, we can just use emitRValueForDecl
now that +0 expressions are plumbed through.


Swift SVN r23976
2014-12-17 05:26:16 +00:00
Chris Lattner
e824b0b9ba fix <rdar://problem/19254812> DI bug when referencing let member of a class
SILGen was emitting extraneous retains/releases on self when accessing let
properties in a class, leading to bogus diagnostics.  Fixing this just 
amounted to realizing that emitDirectIVarLValue is already safe w.r.t. +0
bases.



Swift SVN r23975
2014-12-17 05:16:56 +00:00
John McCall
dd07c8ca10 Add 'mark_dependence', which indicates that an address
or pointer depends on another for validity in a
non-obvious way.

Also, document some basic value-propagation rules
based roughly on the optimization rules for ARC.

Swift SVN r23695
2014-12-04 22:38:09 +00:00
John McCall
6aa60ed1a8 Document how WritebackScope plays into the formal access
model and remove SuppressWritebackScope.

Swift SVN r23662
2014-12-03 22:59:00 +00:00
John McCall
84cb0faaf3 Forward base rvalues directly to accessors instead of
conservatively copying them.

Also, fix a number of issues with mutating getters that
I noticed while examining and changing this code.  In
particular, stop relying on suppressing writeback scopes
during loads.

Fixes rdar://19002913, a bug where an unnecessary copy of
an array for a getter call left the array in a non-unique
state when a subsequent mutation occurred.

Swift SVN r23642
2014-12-03 05:13:11 +00:00
John McCall
a884e045c4 Bind optional l-values during their formal evaluation.
Previously, we were binding optional l-values only when
performing an access.  This meant that other evaluations
emitted before the formal access were not being
short-circuited, even if the language rules said they
should be.  For example, consider this code::

  var array : [Int]? = ...
  array?[foo()] = bar()

Neither foo nor bar should be called if the array is
actually nil, because those calls are sequenced after
the optional-chaining operator ?.

The way that we currently do this is to project out
the optional address during formal evaluation.  This
means that there's a formal access to that storage
beginning with the formal evaluation of the l-value
and lasting until the operation is complete.  That's
a little controversial, because it means that other
formal accesses during that time to the optional
storage will have unspecified behavior according to
the rules I laid out in the accessors proposal; we
should talk about it and make a decision about
whether we're okay with this behavior.  But for now,
it's important to at least get the right short-circuiting
behavior from ?.

Swift SVN r23608
2014-12-02 01:16:53 +00:00
John McCall
b0adca8115 Base prepareAccessorBaseArg's behavior in a more principled
way on whether the accessor consumes its self argument, rather
than a simple type analysis.

Swift SVN r23601
2014-12-01 23:50:00 +00:00
John McCall
df3006f785 Track the unique use of l-value components and avoid
cloning subscript values aggressively.

Swift SVN r23550
2014-11-22 06:17:35 +00:00
John McCall
c47693292f Hide the management of lvalue components inside LValue. NFC.
There's really no reason for this to be exposed.

Swift SVN r23549
2014-11-22 06:17:33 +00:00
John McCall
80d0ab3762 Evaluate subscript index expressions during the formal
evaluation of the l-value, not lazily at the first point
of access.

Swift SVN r23542
2014-11-22 00:21:29 +00:00
John McCall
5672a42e46 Ensure that LValues are uniquely used.
Swift SVN r23492
2014-11-20 23:01:15 +00:00
Joe Groff
f2658bf152 SILGen: Use select_enum_addr instead of a library function for "does optional have value" queries.
Thanks Arnold for fixing the crashes this exposed in the perf suite.

Swift SVN r22954
2014-10-26 22:34:23 +00:00
Dave Abrahams
69735ae0d0 Revert "SILGen: Use select_enum_addr instead of a library function for "does optional have value" queries."
This reverts r22828 because it was apparently causing an assertion on
the bot:

Swift SVN r22831
2014-10-19 19:54:37 +00:00
Joe Groff
05bacc48e0 SILGen: Use select_enum_addr instead of a library function for "does optional have value" queries.
This causes a regression in specialize_checked_cast_branch.swift that ought to be recovered by rdar://problem/18603827.

Swift SVN r22828
2014-10-18 22:20:53 +00:00