Commit Graph

33 Commits

Author SHA1 Message Date
Jordan Rose
85e84a85ef DI: Handle cross-module initializers for empty structs in pre-Swift-5
These also have to delegate to another initializer even though there
are no stored properties to initialize.
2017-11-10 14:10:14 -08:00
Michael Gottesman
6c10f911c0 [di] When scalarizing tuples in DI use destructure_tuple.
Bug noticed on inspection.

rdar://31521023
2017-11-05 00:10:15 -05:00
Slava Pestov
196559e7c6 DI: Only use collectClassInitSelfUses() for class initializers, not class-constrained protocol extensions 2017-10-20 16:42:11 -07:00
Slava Pestov
224aabfe5d DI: Add an assertion tracking stores to the 'self' box 2017-10-20 16:40:18 -07:00
Slava Pestov
ff698f218f DI: Rip out the old 'self consumed' analysis now that it's dead 2017-10-20 16:10:33 -07:00
Slava Pestov
18c29b0cb4 DI: New analysis to replace the 'self consumed' analysis
In a throwing or failable initializer for a class, the typical pattern
is that an apply or try_apply consumes the self value, and returns
success or failure. On success, a new self value is produced.
On failure, there is no new self value. In both cases, the original
self value no longer exists.

We used to model this by attempting to look at the apply or try_apply
instruction, and figure out from subsequent control flow which
successor block was the success case and which was the error case.

The error blocks were marked as such, and a dataflow analysis was used
to compute whether 'self' had been consumed in each block reachable
from the entry block.

This analysis was used to prevent invalid use of 'self' in catch
blocks when the initializer delegation was wrapped in do/catch;
more importantly, it was also used to know when to release 'self'
on exit from the initializer.

For example, when we 'throw e' here, 'self' was already consumed
and does not need to be released -- doing so would cause a crash:

do {
  try self.init(...)
} catch let e {
  // do some other cleanup
  throw e
}

On the other hand, here we do have to release 'self', otherwise we
will exit leaking memory:

do {
  try someOtherThing()
  self.init(...)
} catch let e {
  // do some other cleanup
  throw e
}

The problem with the old analysis is that it was too brittle and did
not recognize certain patterns generated by SILGen. For example, it
did not correctly detect the failure block of a delegation to a
foreign throwing initializer, because those are not modeled as a
try_apply; instead, they return an Optional value.

For similar reasons, we did not correctly failure blocks emitted
after calls to initializers which are both throwing and failable.

The new analysis is simpler and more robust. The idea is that in the
success block, SILGen emits a store of the new 'self' value into
the self box. So all we need to do is seed the dataflow analysis with
the set of blocks where the 'self' box is stored to, excluding the
initial entry block.

The new analysis is called 'self initialized' rather than 'self
consumed'. In blocks dominated by the self.init() delegation,
the result is the logical not of the old analysis:

- If the old analysis said self was consumed, the new one says self
 is not initialized.

- If the old analysis said self was not consumed, the new analysis
  says that self *is* initialized.

- If the old analysis returned a partial result, the new analysis
  will also; it means the block in question can be reached from
  blocks where the 'self' box is both initialized and not.

Note that any blocks that precede the self.init() delegation now
report self as uninitialized, because they are not dominated by
a store into the box. So any clients of the old analysis must first
check if self is "live", meaning we're past the point of the
self.init() call. Only if self is live do we then go on to check
the 'self initialized' analysis.
2017-10-20 16:10:32 -07:00
Slava Pestov
d8153b3ae7 DI: Correctly flag escaping uses of 'self' when 'self' is passed as an argument to self/super.init
This fixes a regression from a previous patch, but it doesn't
fully address <https://bugs.swift.org/browse/SR-5682>, because
we now hit a SILGen crasher with the original test case.
2017-10-13 23:51:16 -07:00
Slava Pestov
1feaf9e2aa DI: Kill off checkClassSelfUpcastUsedBySuperInit() 2017-10-13 23:51:16 -07:00
Slava Pestov
1bcfc50ce3 DI: Kill off collectBorrowedSuperUses() 2017-10-13 23:51:16 -07:00
Slava Pestov
421797cb6e DI: Fold handleSuperInitUse() into handleSelfInitUse() 2017-10-13 23:51:15 -07:00
Slava Pestov
ff34f3bb8c DI: Remove shouldIgnoreClassMethodUseError() 2017-10-13 23:51:15 -07:00
Slava Pestov
94d4b5aa23 DI: Small cleanup now that SelfInit is only used for classes and class-bound protocols 2017-10-13 23:51:15 -07:00
Slava Pestov
0c16aedb60 DI: All protocol extension initializers should be delegating
Previously protocol extension initializers which called 'self.init' were
considered 'delegating', and ones that assign to 'self' were considered
'root'.

Both have the same SIL lowering so the distinction is not useful, and
removing it simplifies some code.
2017-10-13 23:51:14 -07:00
Slava Pestov
c3cf4acbbf DI: For value types, handle self.init like an assignment instead of vice versa
This allows, for example, an initializer to conditionally assign
to self or call self.init, along different control flow paths.

It also means that it is legal to call self.init() multiple times
in a value type initializer, but this... is fine. The old 'self'
is destroyed.

Fixes <rdar://problem/33137910>.
2017-10-13 23:51:14 -07:00
Slava Pestov
9a7a1de595 DI: Look through begin_access/end_access for assignment to self 2017-10-13 23:51:14 -07:00
Michael Gottesman
79e07c7db2 [di] DI assumes that all structs it analyzes will have /1/ property... this is not always true =><=.
The culprit here is NSManagedObject subclasses that only have @NSManaged
attributes.

This doesn't affect predictable mem opts since this issue is in the
DIMemoryUseCollector that only affects DI and that I have removed.

rdar://34589327
2017-10-10 13:58:34 -07:00
Slava Pestov
7bf3b90b62 SIL: Split off objc_method / objc_super_method from class_method / super_method
This replaces the '[volatile]' flag. Now, class_method and
super_method are only used for vtable dispatch.

The witness_method instruction is still overloaded for use
with both ObjC protocol requirements and Swift protocol
requirements; the next step is to make it only mean the
latter, also using objc_method for ObjC protocol calls.
2017-10-03 22:13:31 -07:00
John McCall
ab3f77baf2 Make SILInstruction no longer a subclass of ValueBase and
introduce a common superclass, SILNode.

This is in preparation for allowing instructions to have multiple
results.  It is also a somewhat more elegant representation for
instructions that have zero results.  Instructions that are known
to have exactly one result inherit from a class, SingleValueInstruction,
that subclasses both ValueBase and SILInstruction.  Some care must be
taken when working with SILNode pointers and testing for equality;
please see the comment on SILNode for more information.

A number of SIL passes needed to be updated in order to handle this
new distinction between SIL values and SIL instructions.

Note that the SIL parser is now stricter about not trying to assign
a result value from an instruction (like 'return' or 'strong_retain')
that does not produce any.
2017-09-25 02:06:26 -04:00
Michael Gottesman
4c087097f3 [di] Update definite_initialization for ownership.
rdar://31521023
2017-09-07 15:23:22 -07:00
Slava Pestov
2192470213 DI: Fix 'self.init' delegation to an imported factory initializer inherited from a base class
Fixes <rdar://problem/32697794>.
2017-06-10 23:16:15 -07:00
Alex Hoppen
8946015d5a [SIL] Preparations for removal of getName on ValueDecl
With the introduction of special decl names, `Identifier getName()` on
`ValueDecl` will be removed and pushed down to nominal declarations
whose name is guaranteed not to be special. Prepare for this by calling
to `DeclBaseName getBaseName()` instead where appropriate.
2017-05-28 19:13:24 -07:00
Joe Shajrawi
d17258cac7 @in_constant calling convention - part of passing large loadable types by address 2017-04-30 10:13:02 -07:00
Michael Gottesman
af8c90e5e6 [gardening] Some small type editing of comments and code style improvements. 2017-04-19 19:15:16 -07:00
practicalswift
a029589093 [gardening] Use consistent headers 2017-04-18 19:51:08 +02:00
Michael Gottesman
bbb89dcdf9 [di] Refactor out the handling of DelegatingInit related code out of ElementCollector into its own class.
There was no real code sharing going on here and instead due to the size of
ElementCollector made it difficult to ascertain without reading the code that
the two code paths are completely separate.

This is a NFC change internal to DIMemoryUseCollector that is not visible
outside of DI.

rdar://31521023
2017-04-16 18:34:10 -07:00
Andrew Trick
fff80ba77c [Exclusivity] Fix Definite Initialization for Diagnostics.
Handle mutating methods in initializers properly.

This only affects --enforce-exclusivity mode.
It will be unit tested by default soon.
2017-04-15 13:07:05 -07:00
Michael Gottesman
67d23b8489 [semantic-sil] Update DIMemoryObjectInfo to recognize destroy_value where it recognizes strong_release.
rdar://31521023
2017-04-13 16:47:45 -07:00
Michael Gottesman
17a51193fc [gardening] Invert if condition to reduce indentation. 2017-04-13 16:44:34 -07:00
Michael Gottesman
84d089b858 [gardening] Reduce indentation level by inverting an if condition. 2017-04-13 16:44:34 -07:00
Michael Gottesman
c6f5d4a75e [gardening] Cleanup DIMemoryObjectInfo::DIMemoryObjectInfo. NFC. 2017-04-13 16:44:33 -07:00
Michael Gottesman
9a55421878 [semantic-sil] Rename another field Releases -> Destroys. 2017-04-13 16:44:33 -07:00
Michael Gottesman
6adcc2969e [semantic-sil] Change DefiniteInitialization to use the DIMemoryUseCollectorOwnership header instead of the normal DIMemoryUseCollector.
This is necessary since other passes rely on DIMemoryUseCollector.h and I want
to update each one of them individually to minimize disruption.

rdar://31521023
2017-04-13 16:41:53 -07:00
Michael Gottesman
464b61fb36 [semantic-sil] Copy DIMemoryUseCollector.{cpp,h} => DIMemoryUseCollectorOwnership.{cpp,h} so I can update the passes that use this functionality one at a time. 2017-04-11 09:24:36 -07:00