Commit Graph

291 Commits

Author SHA1 Message Date
John McCall
7f0f8830cd Split AccessorDecl out from FuncDecl. NFC.
This has three principal advantages:

- It gives some additional type-safety when working
  with known accessors.

- It makes it significantly easier to test whether a declaration
  is an accessor and encourages the use of a common idiom.

- It saves a small amount of memory in both FuncDecl and its
  serialized form.
2018-01-12 14:20:27 -05:00
adrian-prantl
ecf9ee749d Merge pull request #13818 from vedantk/empty-locs
[DebugInfo] Add a free helper to get empty locations, NFC
2018-01-11 18:14:37 -08:00
Davide Italiano
e8e90df9b4 [DefiniteInitialization] Preserve DebugInfo correctly.
The scope was set incorrectly. Fixes SR-6722.

<rdar://problem/36414649>
2018-01-10 13:41:37 -08:00
Vedant Kumar
d60ff05265 Rename getEmptyLocation to getCompilerGeneratedLocation 2018-01-09 12:38:45 -08:00
Vedant Kumar
e33f3b663d [DebugInfo] Add a free helper to get empty locations, NFC 2018-01-08 17:59:16 -08:00
Jordan Rose
8f8f00012a Merge pull request #12834 from jrose-apple/restrict-cross-module-struct-initializers-2
Implementation of SE-0189 "Restrict cross-module struct initializers to be delegating"

rdar://problem/34777878
2017-11-30 13:32:45 -08:00
John McCall
aff457381c Change ApplyInstBase to not try to handle trailing objects itself. NFC.
The goal is to make it more composable to add trailing-objects fields in
a subclass.

While I was doing this, I noticed that the apply instructions provided
redundant getNumArguments() and getNumCallArguments() accessors, so I
went ahead and unified them.
2017-11-13 04:03:21 -05:00
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
Jordan Rose
7ff98f3ee8 DI: Suggest "self.init()" for C structs in Swift 5 mode too
...being careful to only do it once per initializer. Additionally,
/don't/ offer the suggestion if there was already a conditional
assignment to 'self', because that would wipe it out and the user
should think harder.
2017-11-10 11:15:33 -08:00
Jordan Rose
1f12e72071 DI: Suggest "self.init()" for extension initializers of C structs
...unless the struct contains a field that cannot be zero-initialized,
such as a non-nullable pointer.

This suggestion is only made for C structs because 'init()' may not be
the right choice for other structs.
2017-11-09 14:28:38 -08:00
Jordan Rose
1598a21e43 DI: Warn on non-delegating cross-module struct initializers
...as detected by initializing an individual field without having
initialized the whole object (via `self = value`).

This only applies in pre-Swift-5 mode because the next commit will
treat all cross-module struct initializers as delegating in Swift 5.
2017-11-09 11:24:28 -08:00
Slava Pestov
16f9438b82 DI: Consistently use 'Use' instead of 'InstInfo' to name DIMemoryUse values 2017-10-20 16:10:34 -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
c69686f102 DI: Use new 'self initialized' analysis in conditional destroy lowering
This changes code generation a bit, because now the conditional
state bitmap uses a bit to track if the 'self' box was stored,
not if the 'self' value was consumed. In some cases, this
eliminates an extra bit, in other places it introduces an
extra bit, but it really doesn't matter because LLVM will
optimize this bit manipulation easily.
2017-10-20 16:10:33 -07:00
Slava Pestov
3d5a16a1ca DI: Use new 'self initialized' analysis in LifetimeChecker::isInitializedAtUse() 2017-10-20 16:10:33 -07:00
Slava Pestov
9d80f60607 DI: Use new 'self initialized' analysis in LifetimeChecker::handleSelfInitUse() 2017-10-20 16:10:33 -07:00
Slava Pestov
4c9d736ea0 DI: Use new 'self initialized' analysis in LifetimeChecker::handleStoreUse() 2017-10-20 16:10:32 -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
d6bb97a57f DI: Factor out LifetimeChecker::emitSelfConsumedDiagnostic() 2017-10-14 23:53:03 -07:00
Slava Pestov
3e9a30be53 DI: Only call getSelfConsumedAtInst() inside initializers 2017-10-14 23:52:09 -07:00
Slava Pestov
421797cb6e DI: Fold handleSuperInitUse() into handleSelfInitUse() 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
b5eeae7446 DI: All enum initializers should be delegating
Again, since there's no distinction between an enum initializer that
delegates to 'self.init' from one that assigns to 'self', we can remove
the special handling of enum initializers in the 'root self' case.

Now, 'root self' is only used for designated initializers in classes
with no superclass, and struct initializers that perform memberwise
initialization of stored properties.

This regresses some diagnostics, because the logic for delegating
init diagnostics is missing some heuristics present in the root self
case. I will fix this in a subsequent patch.
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
5ffbd281c5 DI: Fix diagnostic for return from address-only initializer without calling self.init 2017-10-13 23:51:14 -07:00
Slava Pestov
e51556345d DI: Consolidate and clean up some diagnostics 2017-10-13 23:51:14 -07:00
Erik Eckstein
ab934d0500 DefiniteInitialization: fixed crash for wrong super call with inout instance variable
Fixes rdar://problem/22960985
2017-10-10 09:24:46 -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
Michael Gottesman
9e720c6308 [di] Extract out a helper routine. NFC intended. 2017-07-12 16:50:15 -07:00
Michael Gottesman
f85da6860a [sil] Delete SILInstruction::removeFromParent().
This is a very easily misused API since it allows for users to leak instructions
if they are not careful. This commit removes this API and replaces the small
number of uses of this API with higher level APIs that accomplish the same task
without using removeFromParent(). There were no API users that specifically
required removeFromParent.

An example of one way we were using removeFromParent is to move a SILInstruction
to the front of a block. That does not require exposing an API like
removeFromParent()... we can just create a higher level API like the one added
in this commit: SILInstruction::moveFront(SILBasicBlock *).

rdar://31276565
2017-06-07 16:52:10 -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
practicalswift
492f5cd35a [gardening] Remove redundant repetition of type names (DRY): RepeatedTypeName foo = dyn_cast<RepeatedTypeName>(bar)
Replace `NameOfType foo = dyn_cast<NameOfType>(bar)` with DRY version `auto foo = dyn_cast<NameOfType>(bar)`.

The DRY auto version is by far the dominant form already used in the repo, so this PR merely brings the exceptional cases (redundant repetition form) in line with the dominant form (auto form).

See the [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es11-use-auto-to-avoid-redundant-repetition-of-type-names) for a general discussion on why to use `auto` to avoid redundant repetition of type names.
2017-05-05 09:45:53 +02:00
practicalswift
d4abd21f00 [gardening] Remove duplicate #include 2017-05-04 15:23:11 +02:00
Saleem Abdulrasool
8741e4cd20 Merge pull request #8971 from compnerd/siloptimizer-iwyu
SILOptimizer: IWYU CommandLine.h (NFC)
2017-04-26 20:08:38 -07:00
Michael Gottesman
237a00bc07 [upstream-update] Include a header directly rather than relying on transitive includes.
This causes breakage with some changes coming from upstream.
2017-04-26 16:50:13 -07:00
Saleem Abdulrasool
7e64abd48d SILOptimizer: IWYU CommandLine.h (NFC) 2017-04-24 13:46:47 -07:00
Michael Gottesman
d25328f995 [di] Add a debugging option to trigger an unreachable when DI fails instead of continuing.
This enables one to easily stop in the debugger when one hits a DI error.
2017-04-20 18:34:57 -07:00
Michael Gottesman
af8c90e5e6 [gardening] Some small type editing of comments and code style improvements. 2017-04-19 19:15:16 -07: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
Michael Gottesman
1c803fd732 [gardening] Fix comment. NFC. 2017-04-16 18:33:56 -07:00
Michael Gottesman
35edc11568 [gardening] Be more specific about a type used in a method name. NFC. 2017-04-16 16:49:33 -07:00
Michael Gottesman
d9218c738f [semantic-sil] Rename "Releases" -> "Destroys". 2017-04-13 16:44:33 -07:00
Michael Gottesman
79ac3c9e49 [gardening] Fix a doyxgen comment. NFC. 2017-04-13 16:44:33 -07:00
Michael Gottesman
a346da3e87 [gardening] Eliminate some else-if in favor of early returns. 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
Andrew Trick
be1881aa1f Remove redundant Transform.getName() definitions.
At some point, pass definitions were heavily macro-ized. Pass
descriptive names were added in two places. This is not only redundant
but a source of confusion. You could waste a lot of time grepping for
the wrong string. I removed all the getName() overrides which, at
around 90 passes, was a fairly significant amount of code bloat.

Any pass that we want to be able to invoke by name from a tool
(sil-opt) or pipeline plan *should* have unique type name, enum value,
commend-line string, and name string. I removed a comment about the
various inliner passes that contradicted that.

Side note: We should be consistent with the policy that a pass is
identified by its type. We have a couple passes, LICM and CSE, which
currently violate that convention.
2017-04-09 15:20:28 -07:00
Brent Royal-Gordon
c6f62b1fae [SIL][DI] Fix diagnostic bug more cleanly
No reason to call getCalledValue() twice.
2017-03-27 18:37:17 -07:00
Brent Royal-Gordon
bf1791b492 [SIL][DI] Don’t crash when emitting closure errors
When the DI lifetime checker diagnoses an `inout`-related error, it tries to examine the function you’re calling to emit its name in the error message. Unfortunately, it implicitly assumes that `ApplyExpr::getCalledValue()` will find a `ValueDecl` to return; if the `ApplyExpr` directly calls a closure, it won’t, and so `handleInOutUse` will try to `dyn_cast` a `nullptr`. This change adds a check to avoid that.
2017-03-27 01:01:08 -07:00