Commit Graph

5869 Commits

Author SHA1 Message Date
Michael Gottesman
93d1524cc0 Merge pull request #34634 from gottesmm/pr-88f0c52a3c1db5fb272598e5c5596ce3594d804c
[ownership] Make checked_cast_br, destructure_struct, and destructure_tuple real forwarding instructions
2020-11-09 15:28:45 -08:00
Michael Gottesman
c7051d2929 [ownership] Change ReturnInst to have its ValueOwnershipKind stored within it rather than always recomputing from the function type.
This allows us to hoist the error case of having a function signature with
conflicting ownership requirements into the creation of the return inst instead
of at the time of computing Operand Constraints.

This is the last part of the Operand Constraint computation that can fail that
once removed will let me use fail to mean any constriant is allowed.
2020-11-09 14:21:04 -08:00
Michael Gottesman
b5c3f713d9 [ownership] Move type dependent operand check out of the main visitor to eliminate another returning of an empty map from the visitor.
I may turn this into an assert, but for now I am preserving the current behavior
albeit moving the bad behavior out of the visitor to the front of the API.
2020-11-09 13:02:37 -08:00
Michael Gottesman
c2a6f9aa5e [ownership] Fix assert to test the right thing semantically in the linear lifetime checker.
I think this assert was just testing the wrong thing. Specifically, it is trying
to say that either the given value has a consuming use or it is post-dominated
by dead end blocks.

Instead of checking that directly by using DeadEndBlocks::isDeadEnd(), it was
using a different empty check that caused the assert to actually semantically
say that:

A value must have a lifetime ending use *or* the dead end blocks analysis must
have found at least one block at all in the function that is reachable from a
function terminating terminator (e.x.: return).

This is clearly not the former and was causing the linear lifetime error to hit
this assert in certain cases.

<rdar://problem/70690127>
2020-11-09 11:49:53 -08:00
Doug Gregor
d038989fd8 Merge branch 'main' into create-async-task-builtin 2020-11-09 11:26:33 -08:00
Michael Gottesman
c4adc64a75 [ownership] Remove ownership merging from computing Operand constraints for Forwarding Insts.
Another step towards allowing us to use an invalid result to mean an instruction
can accept any value.
2020-11-09 10:44:40 -08:00
Andrew Trick
d9a14836e2 Add a simple AccessUseDefChainCloner. 2020-11-09 09:48:05 -08:00
Andrew Trick
c2b13cdd51 Merge pull request #34635 from atrick/verify-critedge
Verify non-critical edges in OSSA
2020-11-09 08:59:08 -08:00
Michael Gottesman
6c3af65fb2 [ownership] Add a simple ForwardingOperand ADT and use it in a few places. 2020-11-08 23:55:10 -08:00
Michael Gottesman
d1b555f59a [ownership] Make destructure_{struct,tuple} true forwarding instructions instead of inferring from results/arguments. 2020-11-08 23:55:10 -08:00
Michael Gottesman
d74dbebf3b [ownership] Make checked_cast_br a true Ownership Forwarding inst instead of always inferring from the SILPhiArguments.
This is an analogous change to the previous change I just made to SwitchEnumInst.
2020-11-08 23:55:10 -08:00
Andrew Trick
0287a3d820 Verify no SIL critical edges.
There are multiple reasons this is needed.

1. Most passes do not perform CFG transformations. However, we often
need to split critical edges and remember to invalidate all SIL
analyses at the end of virtually every pass. This is very innefficient
and highly bug prone.

2. Many SIL analysis algorithms needs to reason about CFG
edges. Avoiding critical edges leads to far simpler and more efficient
designs when edges can be identified by blocks.

3. Handling block arguments on conditional branches create complexity
at the lowest level of the SIL interface. This complexity is difficult
to abstract over and bleeds until any algorithm that needs to reason
about phi operands. It's far easier to work with phis if we can easily
recover the phi operand with only a reference to the predecessor
block.

4. Attempting to preserve critical edges in high and mid level IR
blocks optimizations that otherwise have no business optimizing
branches. Branch optimization should always be defered to machine
level IR where the most relevant heuristics are employed to remove
unconditional branches. If code didn't need to be placed on a critical
edges, then a branch optimization can easily remove that code from the
critical edge.
2020-11-08 21:34:24 -08:00
Michael Gottesman
264955ccb3 [ownership] Convert switch_enum to be an ownership forwarding inst and store the forwarding ownership kind within it.
Previously, we always inferred the ownership of the switch_enum from its phi
operands. This forced us to need to model a failure to find a good
OperandOwnershipKindMap in OperandOwnership.cpp. We want to eliminate such
conditions so that we can use failing to find a constraint to mean that a value
can accept any value rather than showing a failure.
2020-11-08 20:32:20 -08:00
Michael Gottesman
f36e8561f1 [ownership] Use a new ADT SwitchEnumBranch instead of SwitchEnumInstBase for generic operations on SwitchEnum{,Addr}Inst.
I have a need to have SwitchEnum{,Addr}Inst have different base classes
(TermInst, OwnershipForwardingTermInst). To do this I need to add a template to
SwitchEnumInstBase so I can switch that BaseTy. Sadly since we are using
SwitchEnumInstBase as an ADT type as well as an actual base type for
Instructions, this is impossible to do without introducing a template in a ton
of places.

Rather than doing that, I changed the code that was using SwitchEnumInstBase as
an ADT to instead use a proper ADT SwitchEnumBranch. I am happy to change the
name as possible see fit (maybe SwitchEnumTerm?).
2020-11-08 19:52:02 -08:00
Michael Gottesman
642a993702 [ownership] Rename Operand::isConsumingUse() -> Operand::isLifetimeEnding().
This makes it clearer that isConsumingUse() is not an owned oriented API and
returns also for instructions that end the lifetime of guaranteed values like
end_borrow.
2020-11-08 13:23:17 -08:00
Michael Gottesman
2ef7a212cd [ownership] Rename the cases of UseLifetimeConstraint to use clearer language
Specifically,

* MustBeLive -> NonLifetimeEnding
* MustBeInvalidated -> LifetimeEnding
2020-11-08 13:23:17 -08:00
Doug Gregor
4c2c2f32e9 [Concurrency] Implement a builtin createAsyncTask() to create a new task.
`Builtin.createAsyncTask` takes flags, an optional parent task, and an
async/throwing function to execute, and passes it along to the
`swift_task_create_f` entry point to create a new (potentially child)
task, returning the new task and its initial context.
2020-11-07 23:05:04 -08:00
Michael Gottesman
b785a5f1d4 Merge pull request #34605 from gottesmm/pr-75f04ac2c27715c84382d9a9e4ca7c0337a3ce30
[ownership] Now that we allow reborrows eliminate isForwardingSubValue it is dead.
2020-11-06 15:18:10 -08:00
Michael Gottesman
e5c98ad2c7 [ownership] Now that we allow reborrows eliminate isForwardingSubValue it is dead. 2020-11-05 19:42:10 -08:00
Doug Gregor
c291eb596b [Concurrency] Add cancelAsyncTask() builtin.
Implement a new builtin, `cancelAsyncTask()`, to cancel the given
asynchronous task. This lowers down to a call into the runtime
operation `swift_task_cancel()`.

Use this builtin to implement Task.Handle.cancel().
2020-11-05 13:50:17 -08:00
Doug Gregor
81f5528199 [Concurrency] More cleanups for getCurrentAsyncTask builtin.
Michael has ghostwritten all of this to address his own comments.
Thank you!
2020-11-05 12:58:03 -08:00
Doug Gregor
ed9a548c9f [Concurrency] Return getCurrentAsyncTask() as owned.
Rather than produce an "unowned" result from `getCurrentAsyncTask()`,
take advantage of the fact that the task is effectively guaranteed in
the scope. Do so be returning it as "unowned", and push an
end_lifetime cleanup to end the lifetime. This eliminates unnecessary
ref-count traffic as well as introducing another use of unowned.

Approach is thanks to Michael Gottesman, bugs are mine.
2020-11-05 12:18:49 -08:00
Doug Gregor
9566d2e665 [Concurrency] Add a builtin to get the current task in an async function.
This introduces a new builtin, `getCurrentAsyncTask()`, that produces a
reference to the current task. This builtin can only be used within
`async` functions, and IR generation merely grabs the task argument
and packages it up.

The type of this function is `() -> Builtin.NativeObject`, because we
don't currently have a Swift-level representation of tasks, and can
probably handle everything through builtins or runtime calls.
2020-11-05 10:43:33 -08:00
Doug Gregor
203d2c20fe Merge pull request #34573 from DougGregor/async-let
[Concurrency] Implement type checking for 'async let' declarations.
2020-11-05 08:44:21 -08:00
Erik Eckstein
f3de3b4c1f SIL: set the @async attribute for top-level functions correctly 2020-11-05 13:58:40 +01:00
Erik Eckstein
0accc022d5 [concurrency] SILVerifier: don't complain about async function pointers created in non-async functions
It's possible to materialize an async function pointer, e.g. with partial_apply, in a non-async function - as long as no async function is called.
2020-11-05 13:58:40 +01:00
Doug Gregor
33cfbbdd72 [Concurrency] Don't diagnose missing "self." in async let autoclosures. 2020-11-04 23:18:51 -08:00
Erik Eckstein
5434786cad [concurrency] SIL: fix operand ownership of hop_to_executor 2020-11-04 09:53:11 +01:00
Meghana Gupta
6c46841c26 Merge pull request #34438 from meg-gupta/reborrowverifier
[ownership] Add a new ReborrowVerifier
2020-11-02 19:55:10 -08:00
Rintaro Ishizaki
f434edc6b8 Merge pull request #34529 from rintaro/parse-parsetype-handlecc
[NFC][Parse] Remove unused HandleCodeCompletion param in parseType()
2020-11-02 09:25:03 -08:00
Meghana Gupta
e8924488d1 Merge pull request #34526 from meg-gupta/asyncverify
SILVerifier: async functions can be called from async functions only
2020-11-02 09:22:17 -08:00
Rintaro Ishizaki
4ad8efcd0c [Parse] Remove unused HandleCodeCompletion param in parseType()
NFC
2020-10-31 00:27:48 -07:00
Meghana Gupta
288ef583e7 SILVerifier: async functions can be called from async functions only 2020-10-30 17:35:18 -07:00
Joe Groff
f72afc8110 Merge pull request #34519 from jckarter/async-sil-tweaks
Async sil tweaks
2020-10-30 16:49:26 -07:00
Andrew Trick
fce43daab0 Merge pull request #34502 from atrick/simplifycfg-critedge
Rewrite SimplifyCFG trampoline removal to generalize it (avoid critical edges as a side-effect)
2020-10-30 12:06:25 -07:00
Joe Groff
4eb68596af SIL: Tweak ownership of continuation instructions.
Treating a trivial type as having ownership seems only to confuse the ownership verifier.
The structural property we're trying to enforce here (that a continuation is always
consumed by an `await` locally) can be enforced by flow-sensitive verification without
ownership.
2020-10-30 11:38:05 -07:00
John McCall
e35f077a9b Merge pull request #33349 from ellishg/master
[IRGen] Call objc_direct methods correctly
2020-10-30 03:03:54 -04:00
Meghana Gupta
601ea65b5d [ownership] Add a new ReborrowVerifier
This updates how we model reborrow's lifetimes for ownership verification.
Today we follow and combine a borrow's lifetime through phi args as well.
Owned values lifetimes end at a phi arg. This discrepency in modeling
lifetimes leads to the OwnershipVerifier raising errors incorrectly for
cases such as this, where the borrow and the base value do not dominate
the end_borrow:

bb0:
  cond_br undef, bb1, bb2
bb1:
  %copy0 = copy_value %0
  %borrow0 = begin_borrow %copy0
  br bb3(%borrow0, %copy0)
bb2:
  %copy1 = copy_value %1
  %borrow1 = begin_borrow %copy1
  br bb3(%borrow1, %copy1)
bb3(%borrow, %baseVal):
  end_borrow %borrow
  destroy_value %baseVal

This PR adds a new ReborrowVerifier. The ownership verifier collects borrow's
lifetime ending users and populates the worklist of the ReborrowVerifier
with reborrows and the corresponding base value.
ReborrowVerifier then verifies that the lifetime of the reborrow is
within the lifetime of the base value.
2020-10-29 20:46:37 -07:00
Doug Gregor
33452e1074 Merge pull request #34503 from DougGregor/async-type-lower-void
[async type lowering] Handle Void return from @objc async methods.
2020-10-29 20:13:31 -07:00
Alejandro Alonso
424802fb34 Revert SE-0283 (#34492)
Reverted despite build failures.
2020-10-29 17:32:06 -07:00
Doug Gregor
f30778ff8c [async type lowering] Handle Void return from @objc async methods. 2020-10-29 17:03:21 -07:00
Andrew Trick
7d88d720b9 Add information to SILVerifier stack nesting diagnostic. 2020-10-29 15:25:20 -07:00
Andrew Trick
acc3398fed Add -allow-critical-edges flag.
Provide a mechanism to gradually migrate unit tests away from allowing
critical edges via -allow-critical-edges=false.

This will be the default in OSSA very soon, and will hopefully become
the default eventually for all SIL stages.

Note that not all required optimization pass changes have been
committed yet. I have pending changes in:
- SimplifyCFG
- SILCloner subclasses
- EagerSpecializer
- ArraySpecialization
- LoopUtils
- LoopRotate

There are multiple reasons we need to disallow critical edges:

1. Most passes do not perform CFG transformations. However, we often
need to split critical edges and remember to invalidate all SIL
analyses at the end of virtually every pass. This is very innefficient
and highly bug prone.

2. Many SIL analysis algorithms needs to reason about CFG
edges. Avoiding critical edges leads to far simpler and more efficient
designs when edges can be identified by blocks.

3. Handling block arguments on conditional branches create complexity
at the lowest level of the SIL interface. This complexity is difficult
to abstract over and bleeds until any algorithm that needs to reason
about phi operands. It's far easier to work with phis if we can easily
recover the phi operand with only a reference to the predecessor
block.

4. Attempting to preserve critical edges in high and mid level IR
blocks optimizations that otherwise have no business optimizing
branches. Branch optimization should always be defered to machine
level IR where the most relevant heuristics are employed to remove
unconditional branches. If code didn't need to be placed on a critical
edges, then a branch optimization can easily remove that code from the
critical edge.
2020-10-29 11:51:29 -07:00
Joe Groff
096828e5ab Merge pull request #34358 from jckarter/imported-async-type-lowering
Type lowering and SILGen for imported ObjC async decls.
2020-10-29 08:46:16 -07:00
Erik Eckstein
f18a9b8ee8 [Concurrency] SIL: add hop_to_executor instruction
This instructions ensures that all instructions, which need to run on the specified executor actually run on that executor.
For details see the description in SIL.rst.
2020-10-28 18:17:43 +01:00
Erik Eckstein
e8e613bd6a RCIdentity: fix another case of not-RC-identity-preserving casts.
When casting from existentials to class - and vice versa - it can happen that a cast is not RC identity preserving (because of potential bridging).
This also affects mayRelease() of such cast instructions.
For details see the comments in SILDynamicCastInst::isRCIdentityPreserving().

This change also includes some refactoring: I centralized the logic in SILDynamicCastInst::isRCIdentityPreserving().

rdar://problem/70454804
2020-10-28 08:10:41 +01:00
Joe Groff
577f83a260 SIL: Type lowering for imported ObjC async decls.
When lowering the type for `@objc` entry points of async declarations, restore
the original ObjC signature with the completion handler argument in the lowered
SIL type.
2020-10-27 09:00:45 -07:00
Alejandro Alonso
84e5fd2137 Merge pull request #28833 from Azoy/void-is-equatable
[SE-0283] Implement Equatable, Comparable, and Hashable conformance for Tuples
2020-10-26 13:53:29 -04:00
Slava Pestov
527fb5dd31 SIL: Enum protocol witness thunks should be [serializable] 2020-10-24 03:09:40 -04:00
Slava Pestov
442fc68453 Merge pull request #34419 from slavapestov/type-of-self-protocol-convenience-init
DI: Fix crash when value_metatype was used with a non-class 'self' type
2020-10-24 02:12:35 -04:00