Commit Graph

728 Commits

Author SHA1 Message Date
Joe Groff
66e1f37e62 SILGen: Reabstraction for vtable entries.
When a derived class specializes its base class, e.g. 'class Derived: Base<Int>', the natural abstraction levels of its methods may differ from the original base class's more abstract methods. Handle this by using the reabstraction machinery to thunk values when necessary. Merge the existing optionality thunking support into the reabstraction code, where witness thunking and similar convention adjustments may also be able to use it, if we desire. Fixes rdar://problem/19760292.

Swift SVN r28505
2015-05-13 03:25:05 +00:00
Chris Lattner
3814b7003f Implement support for arbitrary pattern matching in for-each statements,
which composes straight-forwardly on top of the existing stuff for if/let
and guard.



Swift SVN r28371
2015-05-09 21:34:35 +00:00
Chris Lattner
f35677de14 Revise SILGen of foreach loops to only drop the optional generator result value 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.
This recommits r28318 with a fix that simplifies away a bunch of code and a bug.



Swift SVN r28328
2015-05-08 21:26:56 +00:00
Chris Lattner
5e7a45ff70 revert r28318, it is causing a problem on perftests. I'll investigate after lunch.
Swift SVN r28321
2015-05-08 18:02:24 +00:00
Chris Lattner
f379b1e15b Revise SILGen of foreach loops to only drop the optional generator result value
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
2015-05-08 17:46:20 +00:00
Michael Gottesman
8361ba44a9 Revert "Revert "[+0 self] Teach SILGen how to avoid emitting extra rr pairs when emitting RValues with Nominal Types and Tuples.""
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
2015-05-07 15:47:34 +00:00
Joe Groff
e2962ed213 SILGen: Implement recursive local function references.
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
2015-05-04 05:33:55 +00:00
Chris Lattner
b6ad8d5efc Teach emitBindOptional() to disable the cleanup for the optional it is testing on the
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
2015-05-04 00:13:18 +00:00
Chris Lattner
fec2f22459 Enhance SILGen of InjectIntoOptionalExpr/BindOptionalExpr/OptionalEvaluationExpr
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
2015-05-03 23:27:28 +00:00
John McCall
5c171fd448 Parsing, type-checking, SILGen, and IRGen for try!.
Swift SVN r28085
2015-05-02 08:03:15 +00:00
John McCall
58b5e1dc0f Implement error handling in protocol witness and
reabstraction thunks.

rdar://20782111

Swift SVN r28075
2015-05-02 04:37:30 +00:00
Joe Groff
6de9d84b1f SILGen: Handle initializers in protocol extensions.
For the most part, this just involves spot fixes to make sure protocol inits follow the same paths as value type initializers would, with the extra wrinkle that we have to ensure we forward the correct metatype from the delegating initializer to the delegatee, in case the initializer is invoked with a different dynamic type from the static Self type. This should handle non-@objc delegations; @objc will need some additional work.

Swift SVN r27900
2015-04-29 02:40:30 +00:00
Nadav Rotem
3f675c5f06 Emit calls to swift_willThrow only in throw sites (not in re-throw sites).
rdar://20356658

Swift SVN r27891
2015-04-28 23:21:11 +00:00
Chris Lattner
caeca69466 fix <rdar://problem/19086357> SILGen crashes reabstracting default argument closure in members
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
2015-04-27 04:29:32 +00:00
John McCall
d84a95f325 Handle foreign error conventions in foreign-to-native thunks.
Swift SVN r27737
2015-04-26 00:12:52 +00:00
Michael Gottesman
9c35c5eafd Revert "[+0 self] Teach SILGen how to avoid emitting extra rr pairs when emitting RValues with Nominal Types and Tuples."
This reverts commit r27632. I broke a test. I am going to look at it later.

Swift SVN r27634
2015-04-23 10:42:46 +00:00
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
935e95080c minor cleanups.
Swift SVN r27566
2015-04-22 06:04:35 +00:00
Chris Lattner
06ad473cab Switch if/let SILGen to use the same codepath as let/else, instead of using the
ClauseMatrix stuff.



Swift SVN r27565
2015-04-22 05:49:57 +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
2d35d51ead Now that initializers have been reworked, there is finally only one client of
SGF::emitLocalVariable: inline it into its only remaining client (which is
indirectly part of 'var' pattern binding emission) and simplify the code a bit.
NFC.



Swift SVN r27531
2015-04-21 16:58:53 +00:00
Chris Lattner
fd69300bdf rework lowering of 'self' in class init methods to use normal cleanups and variable
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
2015-04-21 16:43:46 +00:00
Chris Lattner
f2455bd668 Extend SILGenFunction::emitEpilog to work with custom epilogs that contain
no prefix code, simplifying its interface.  NFC.


Swift SVN r27519
2015-04-21 04:32:46 +00:00
Chris Lattner
7beb6d52de Extend SILGen's emitEpilog() to work with epilog blocks that are
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
2015-04-20 00:30:30 +00:00
Chris Lattner
8dce0ff78d Inline emitRethrowBB into its only caller, simplifying things.
Have emitEpilog take care of calling emitRethrowEpilog, relieving
its clients from having to do it everywhere.  NFC.



Swift SVN r27469
2015-04-19 21:43:06 +00:00
Chris Lattner
e8dfbd8ed8 remove dead parameter from SILGenFunction::emitInitializationForVarDecl, NFC.
Swift SVN r27465
2015-04-19 05:28:42 +00:00
Chris Lattner
7f6bf2326d Refactor a bit of the SILGenFunction::emitCheckedCastBranch logic
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
2015-04-18 23:15:35 +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
John McCall
156a4c7ed0 SILGen for calls under foreign error conventions. WIP.
Swift SVN r27270
2015-04-14 02:35: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
John McCall
79cc258f65 Lower 'throws' to an error result.
Swift SVN r27108
2015-04-08 00:09:29 +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
Chris Lattner
95b7b4d5e4 rename CleanupLocation::getCleanupLocation -> CleanupLocation::get, NFC.
Swift SVN r26994
2015-04-04 22:56:01 +00:00
John McCall
723a6077cf Reorganize some code in SILGen into new files; NFC.
Swift SVN r26971
2015-04-04 03:32:18 +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
Chris Lattner
60560640b6 introduce a new common base class between if and while statements:
they are both labeled and have conditions.  NFC.


Swift SVN r26933
2015-04-03 05:44:08 +00:00
John McCall
08d3460a19 Implement throw expressions. Untested.
Tests tomorrow for this and 'catch', I promise. :)

Swift SVN r26432
2015-03-23 08:10:15 +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
John McCall
a0a16d78d2 Implement the do/catch statement. Tests to follow.
This patch also introduces some SILGen infrastructure for
dividing the function into "ordinary" and "postmatter"
sections, with error-handling-like stuff going into the
final section.  Currently, this is largely undermined by
SILBuilder, but I'm going to fix that in a follow-up.

Swift SVN r26422
2015-03-23 02:08:26 +00:00
John McCall
080b7dfabf Remove the default handle-all Decl and DeclAttribute
cases from ASTVisitor and privatize SILGen's statement
emitter.  NFC.

Swift SVN r26402
2015-03-22 03:22:45 +00:00
Joe Groff
f2a520dbc6 SILGen: Don't leak existential container after OpenExistentialExpr.
Leave a cleanup to deinit the container after the uniquely-referenced opaque value is taken out of it. While we're here, stub out support for boxed existentials (though we can't test it since _ErrorType doesn't have any Self-returning methods, and we currently only produce OpenExistentialExprs in the AST for method calls involving covariant Self or metatypes).

Swift SVN r26284
2015-03-18 23:14:45 +00:00
Chris Lattner
e2fe7704ad Reimplement emission of StmtCondition (e.g. if/let & while/let) to be
in terms of the pattern binding/emission facilities that are currently
used for switches.  They are more general (handling all patterns,
not hacked up just for optionals).

This leads to us producing better code for if/let bindings, because we 
don't alloc_stack a temporary and deal with memory for non-address-only
types (e.g. the common case of an optional pointer).  Instead, the code 
emits a select_enum{_addr} on the value.

While this changes the generated code in the compiler, there is no exposed
behavioral change to the developer.




Swift SVN r26142
2015-03-14 20:31:23 +00:00
Chris Lattner
5745300718 rename PatternMatchStack back to SwitchStack. I was too quick to rename it: it
is only for processing of fallthrough statements, which really do only apply to
switch.


Swift SVN r26127
2015-03-14 03:32:28 +00:00
Chris Lattner
a6d95e4630 Generalize some terminology in SILGenPattern to say "PatternMatch" instead
of "Switch" since this logic will be used by if/let and while/let pattern
matching in the near future.


Swift SVN r26126
2015-03-14 02:57:42 +00:00
John McCall
0802e85975 Implement the naked 'do' statement.
For now, we assume that 'while' after the braces starts
a do/while rather than being an independent statement.
We should disambiguate this, or better, remove do/while.

Tests later.

Swift SVN r26079
2015-03-13 01:58:42 +00:00
Joe Groff
5fa20867e9 SILGen: Implement thunking for C function pointer conversions.
If we have a C function pointer conversion, generate a thunk using the same logic we use for ObjC method thunks, and emit a pointer to that thunk as the C function pointer value. (This works for nongeneric, nonmember functions; generics will additionally need to apply generic parameters within the thunks. Static functions would need to gather the metatype as well.)

Swift SVN r25653
2015-03-01 06:18:58 +00:00
Michael Gottesman
77b2e21eb5 Move buildForwardingSubstitutions onto GenericParamList::getForwardingSubstitutions(). NFC.
Swift SVN r25358
2015-02-17 23:01:02 +00:00
Justin Bogner
a49008298e InstrProf: Set up the basic infrastructure for profiling swift
This adds the -profile-generate flag, which enables LLVM's
instrumentation based profiling. It implements the instrumentation
for basic control flow, such as if statements, loops, and closures.

Swift SVN r25155
2015-02-11 01:06:18 +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