Commit Graph

290 Commits

Author SHA1 Message Date
Michael Gottesman
f6c7c0d0bc [ownership] bridge_object_to_word is a bitwise escape not an instantaneous use. 2021-01-04 15:44:58 -08:00
Michael Gottesman
f67c52ee1a [ownership] ref_to_* and *_to_ref produce values with OwnershipKind::Unowned so should be treated as PointerEscapes.
These instructions model a conversion in between ownership kinds without the result actually being owned by anything. As a result:

1. From an operand perspective, the instruction is treated like a pointer escape.
2. From a value perspective, the instruction returns a value with
   OwnershipKind::Unowned (to force the value to be copied before it can be used
   in an owned or guaranteed way) and

Example:

```
sil @example : $@convention(thin) (@owned Klass) -> @owned @sil_unowned Klass {
bb0(%0 : @owned $Klass):
  // Note that the ref_to_unowned does not consume %0 but instead converts %0
  // from a "strong" value to a "safe unowned" value. A "safe unowned" value is
  // a value that corresponds to an 'unowned' value at the Swift level that use
  // unowned reference counting. At the SIL level these values can be recognized
  // by their types having the type attribute @sil_unowned. We have not
  // incremented the unowned ref count of %1 so we must treat %1 as unowned.
  %1 = ref_to_unowned %0 : $Klass
  // Then before we can use %2 in any way as a "safe unowned" value we need to
  // bump its unowned ref count by making a copy of the value. %2 will be a
  // "safe unowned" value with OwnershipKind::Owned ensuring that we decrement
  // the unowned ref count and do not leak said ref count.
  %2 = copy_value %1 : $@sil_unowned $Klass
  // Then since the original ref_to_unowned did not consume %0, we need to
  // destroy it here.
  destroy_value %0 : $Klass
  // And then return out OwnershipKind::Owned @sil_unowned Klass.
  return %2 : $@sil_unowned $Klass
}
```
2021-01-04 15:37:57 -08:00
Andrew Trick
ab42f753f7 Remove OperandOwnership::NestedBorrow.
Now that OperandOwnership determines the operand constraints, it
doesn't make sense to distinguish between Borrow and NestedBorrow at
this level. We want these uses to automatically convert between the
nested/non-nested state as the operand's ownership changes. The use
does not need to impose any constraint on the ownership of the
incoming value.

For algorithms that need to distinguish nested borrows, it's still
trivial to do so.
2021-01-01 19:22:19 -08:00
Andrew Trick
f4e0eae15f OperandOwnership Remove unnecessary special case for callee operand. 2021-01-01 19:22:19 -08:00
Andrew Trick
07f5735e53 Give SILToken Guaranteed ownership.
The begin_apply token represents the borrow scope of all owned and guaranteed
call arguments. Although SILToken is (currently) trivially typed, it must
have guaranteed ownership so end_apply and abort_apply will be recognized
as lifetime-ending uses.
2021-01-01 19:22:19 -08:00
Andrew Trick
56f05da8b7 Fix OperandOwnership for coroutines.
Anything with a borrow scope in the caller needs to be considered a
Borrow of its operand. The end_apply needs to be considered the
lifetime-ending use of the borrow.
2021-01-01 19:22:19 -08:00
Andrew Trick
cdcd0bf341 Fix OperandOwnership for convert_escape_to_noescape.
This is only used for OSSA verification currently, but will be a
correctness issue when OSSA canonicalization is enabled.
2021-01-01 19:22:19 -08:00
Andrew Trick
ce2a7cfe0e Clearly discriminate OperandOwnership::NonUse and TrivialUse.
A NonUse operand does not use the value itself, so it ignores
ownership and does not require liveness. This is for operands that
represent dependence on a type but are not actually passed the value
of that type (e.g. they may refer an open_existential). This could be
used for other dependence-only operands in the future.

A TrivialUse operand has undefined ownership semantics aside from
requiring liveness. Therefore it is only legal to pass the use a value
with ownership None (a trivial value). Contrast this with things like
InstantaneousUse or BitwiseEscape, which just don't care about
ownership (i.e. they have no ownership semantics.

All of the explicitly listed operations in this category require
trivially typed operands. So the meaning is obvious to anyone
adding SIL operations and updating OperandOwnership.cpp, without
needing to decifer the value ownership kinds.
2021-01-01 19:22:10 -08:00
Meghana Gupta
b99533aced Merge pull request #34895 from meg-gupta/cseossa
Enable CSE on OSSA
2020-12-23 09:58:46 -08:00
Meghana Gupta
42c031985c Enable CSE on OSSA 2020-12-22 23:20:06 -08:00
Michael Gottesman
368f8acc4b [sil] Eliminate a confusing optional method result by changing type dependent operands to have OwnershipKind::None instead of returning Optional::None from Operand::getOperandOwnership().
This eliminates when talking about this API an ambiguity in between
Optional::None (the C++ ADT) and OwnershipKind::None (the ownership kind).
2020-12-18 19:33:27 -08:00
Andrew Trick
f777e0a70e Convert OperandOwnership from an enum class to a struct enum. 2020-12-17 21:24:41 -08:00
Andrew Trick
84768bcdb3 OSSA: Add requirements on Unowned uses.
Clarify which uses are allowed to take Unowned values. Add enforcement
to ensure that Unowned values are not passed to other uses.

Operations that can take unowned are:

- copy_value
- apply/return @unowned argument
- aggregates (struct, tuple, destructure, phi)
- forwarding operations that are arbitrary type casts

Unowned values are currently borrowed within ObjC deinitializers
materialized by the Swift compiler. This will be banned as soon as
SILGen is fixed.
2020-12-17 21:08:56 -08:00
Andrew Trick
b1dba2554e Introduce OperandOwnership to classify OSSA uses.
Migrating to this classification was made easy by the recent rewrite
of the OSSA constraint model. It's also consistent with
instruction-level abstractions for working with different kinds of
OperandOwnership that are being designed.

This classification vastly simplifies OSSA passes that rewrite OSSA
live ranges, making it straightforward to reason about completeness
and correctness. It will allow a simple utility to canonicalize OSSA
live ranges on-the-fly.

This avoids the need for OSSA-based utilities and passes to hard-code
SIL opcodes. This will allow several of those unmaintainable pieces of
code to be replaced with a trivial OperandOwnership check.

It's extremely important for SIL maintainers to see a list of all SIL
opcodes associated with a simple OSSA classification and set of
well-specified rules for each opcode class, without needing to guess
or reverse-engineer the meaning from the implementation. This
classification does that while eliminating a pile of unreadable
macros.

This classification system is the model that CopyPropagation was
initially designed to use. Now, rather than relying on a separate
pass, a simple, lightweight utility will canonicalize OSSA
live ranges.

The major problem with writing optimizations based on OperandOwnership
is that some operations don't follow structural OSSA requirements,
such as project_box and unchecked_ownership_conversion. Those are
classified as PointerEscape which prevents the compiler from reasoning
about, or rewriting the OSSA live range.

Functional Changes:

As a side effect, this corrects many operand constraints that should
in fact require trivial operand values.
2020-12-16 01:58:53 -08:00
John McCall
d68d406dae Merge pull request #35094 from rjmccall/actor-dynamic-layout
Do dynamic layout of generic/resilient default actors properly
2020-12-16 01:05:00 -05:00
John McCall
bad16fd105 Do dynamic layout of generic/resilient default actors properly.
Since these types have an implicit stored property, this requires
adding an abstraction over fields to IRGen, at least throughout
the class code.  In some ways I think this significantly improves
the code, especially in how we approach missing members.

Fixes rdar://72202671.
2020-12-15 20:10:46 -05:00
Richard Wei
8d8614058b [AudoDiff] NFC: Replace 'SILAutoDiffIndices' with 'AutoDiffConfig'. (#35079)
Resolve rdar://71678394 / SR-13889.
2020-12-14 14:32:40 -08:00
John McCall
d874479290 Add builtins to initialize and destroy a default-actor member.
It would be more abstractly correct if this got DI support so
that we destroy the member if the constructor terminates
abnormally, but we can get to that later.
2020-12-10 19:18:53 -05:00
John McCall
b22407ef0c Add a builtin to convert a Task* to a Job*. 2020-12-10 17:06:14 -05:00
Joe Groff
291b75fcc4 Merge pull request #34953 from jckarter/async-native-to-foreign-thunk
[WIP] SILGen: Implement native-to-foreign thunks for async methods.
2020-12-09 17:00:36 -08:00
Andrew Trick
f92009da98 Remove SILArgumentConvention::Direct_Deallocating 2020-12-08 13:41:47 -08:00
Joe Groff
5087e411c2 SILGen: Implement native-to-foreign thunks for async methods.
Bridging an async Swift method back to an ObjC completion-handler-based API requires
that the ObjC thunk spawn a task on which to execute the Swift async API and pass
its results back on to the completion handler.
2020-12-08 10:04:40 -08:00
Doug Gregor
06a712bff6 Merge pull request #34957 from rjmccall/partial-async-task-is-a-job
Freeze PartialAsyncTask as a Job*
2020-12-04 15:43:44 -08:00
John McCall
ee0bb0a2d5 Freeze PartialAsyncTask as a Job*.
Also fix the extra inhabitants of Builtin.RawUnsafeContinuation
and try to make adding types like this a little less boiler-plate
in the future.
2020-12-04 01:06:29 -05:00
Doug Gregor
41f74e48d5 Merge pull request #34952 from DougGregor/convert-sync-to-async
[Concurrency] Allow synchronous functions to be a subtype of 'async' functions
2020-12-03 20:18:53 -08:00
Doug Gregor
f46ad6c28f [Concurrency] Emit thunk for synchronous -> async function conversion. 2020-12-03 13:47:39 -08:00
Slava Pestov
c133e13efd Merge pull request #34916 from slavapestov/with-unsafe-continuation
Concurrency: Implement withUnsafe[Throwing]Continuation
2020-12-03 11:18:49 -05:00
Michael Gottesman
b13a8e9ba3 Merge pull request #34915 from gottesmm/forwarding-silinstruction
[ownership] Centralize all info about SILInstruction forwarding in the SILInstruction class hierarchy itself.
2020-12-01 21:33:27 -08:00
Michael Gottesman
09ae2ef071 [ownership] Centralize all info about SILInstruction forwarding in the SILInstruction class hierarchy itself.
This commit is doing a few things:

1. It is centralizing all decisions about whether an operand's owner instruction
or a value's parent instruction is forwarding in each SILInstruction
itself. This will prevent this information from getting out of sync.

2. This allowed me to hide the low level queries in OwnershipUtils.h that
determined if a SILNodeKind was "forwarding". I tried to minimize the amount of
churn in this PR and thus didn't remove the
is{Owned,Ownership,Guaranteed}Forwarding{Use,Value} checks. Instead I left them
alone but added in asserts to make sure that if the old impl ever returns true,
the neew impl does as well. In a subsequent commit, I am going to remove the old
impl in favor of isa queries.

3. I also in the process discovered that there were some instructions that were
being inconsistently marked as forwarding. All of the asserts in the PR caught
these and I fixed these inconsistencies.
2020-12-01 17:36:19 -08:00
Michael Gottesman
33aec98fff [ownership] Assume values/operands in SILGlobalVariable blocks are not in OSSA.
Operationally it just means that in SILGlobalVariable blocks, all operands have
ownership constraint:

  {OwnershipKind::Any, UseLifetimeConstraint::NonLifetimeEnding}

and all values yield an ownership kind of: OwnershipKind::None.
2020-12-01 17:36:19 -08:00
Slava Pestov
a2dbdecdab SIL: Refactor get_async_continuation[_addr] to return a RawUnsafeContinuation 2020-12-01 20:04:09 -05:00
Slava Pestov
1a89813bf5 AST: Introduce Builtin.RawUnsafeContinuation type
This is otherwise identical to Builtin.RawPointer, but has the spare
bits of a heap object pointer.
2020-12-01 20:03:22 -05:00
Michael Gottesman
3fd4aaeb37 Merge pull request #34898 from gottesmm/pr-d3b6d903b097410b535d20940005a1fa67d3a1bf
[auto-diff] Fix a bunch of places in the *Cloners where we were not closing borrow scopes.
2020-12-01 12:42:10 -08:00
Erik Eckstein
6f5cffbcb9 Mangling: add support for mangling the body-function of asyncHandlers
We don't introduce a new mangling here.
To distinguish the names of the original asyncHandler function and it's generated "body-function", we just mangle the body-function with an async attribute, i.e. as if it was declared as async.
This change is mostly to pass information to the ASTMangler to mangle a not async function as "async".
2020-12-01 08:42:56 +01:00
Michael Gottesman
affeba98f9 [auto-diff] Fix a bunch of places in the *Cloners where we were not closing borrow scopes.
These were all just trying to open a borrow scope, so I changed them to use the
API SILBuilder::emitScopedBorrowOperation(SILLocation, SIL).
2020-11-30 16:05:37 -08:00
Richard Wei
de2dbe57ed [AutoDiff] Bump-pointer allocate pullback structs in loops. (#34886)
In derivatives of loops, no longer allocate boxes for indirect case payloads. Instead, use a custom pullback context in the runtime which contains a bump-pointer allocator.

When a function contains a differentiated loop, the closure context is a `Builtin.NativeObject`, which contains a `swift::AutoDiffLinearMapContext` and a tail-allocated top-level linear map struct (which represents the linear map struct that was previously directly partial-applied into the pullback). In branching trace enums, the payloads of previously indirect cases will be allocated by `swift::AutoDiffLinearMapContext::allocate` and stored as a `Builtin.RawPointer`.
2020-11-30 15:49:38 -08:00
Arnold Schwaighofer
b0be562ded Merge pull request #34829 from aschwaighofer/irgen_get_await_async_continuation
IRGen: get/await_async_continuation support
2020-11-30 11:22:55 -08:00
Michael Gottesman
333737bc7a [sil] Remove usage from TypeLowering of SILBuilder::create*AndFold().
These create*AndFold APIs are actively harmful when used in TypeLowering since:

1. In general they are a problem since it is weird for a builder API to remove
   an instruction.

2. These APIs do not take an erase callback that must be used in passes that
   need to update state before erasing the instruction.

3. The typelowering APIs that use this are emitDestroyValue/etc which are the
   main APIs that we are using to write code that works with OSSA/non-OSSA
   SIL. So we are going to use these APIs in many more places, introducing this
   bug in many places.

With that in mind, I have been committing small cheap ARC optimizations to
GuaranteedARCOpts (SemanticARCOpts with expensive optimizations turned off) so
that we can eliminate this without massively churning the code. We are at this
stage now, so it makes sense to turn this off.
2020-11-30 04:51:39 -08:00
Doug Gregor
c42add92ec [SIL] Fix ownership of GetCurrentAsyncTask builtin 2020-11-19 23:26:30 -08:00
Michael Gottesman
84360d9d4c Merge pull request #34811 from gottesmm/pr-81ab56860285486f13f9c56ac738e128e170a9c7
[sil] Add a non-const version of SILPhiArgument *BranchInst::getArgForOperand(Operand *)
2020-11-19 13:22:56 -08:00
Arnold Schwaighofer
b49a882ea1 Add some SIL properties for get/await_async_continuation 2020-11-19 12:38:51 -08:00
Michael Gottesman
0f29b67109 [sil] Add a non-const version of SILPhiArgument *BranchInst::getArgForOperand(Operand *) 2020-11-18 13:30:24 -08:00
Michael Gottesman
c35ff33a1f [ownership] Add a subclass for all OwnershipForwarding instructions and fix the classof to the various ownership abstract classes so isa/dyn_cast work.
I think what was happening here was that we were using one of the superclass
classofs and were getting lucky since in the place I was using this I was
guaranteed to have single value instructions and that is what I wrote as my
first case X ).

I also added more robust checks tieing the older isGuaranteed...* APIs to the
ForwardingOperand API. I also eliminated the notion of Branch being an owned
forwarding instruction. We only used this in one place in the compiler (when
finding owned value introducers), yet we treat a phi as an introducer, so we
would never hit a branch in our search since we would stop at the phi argument.
The bigger picture here is that this means that all "forwarding instructions"
either forward ownership for everything or for everything but owned/unowned.

And for those listening in, I did find one instruction that was from an
ownership forwarding subclass but was not marked as forwarding:
DifferentiableFunctionInst. With this change, we can no longer by mistake have
such errors enter the code base.
2020-11-18 12:34:18 -08:00
Michael Gottesman
611284fcc2 [sil] Element shadowing of SILInstruction::getKind() by renaming MarkUninitializedInst::get{,MarkUninitialized}Kind().
Interestingly this problem can only occur if one invokes
MarkUninitializedInst::getKind() directly. Once our instruction is just a
SILInstruction, we call the appropriate method so we didn't notice it.

I used Xcode's refactoring functionality to find all of the invocation
locations.
2020-11-17 21:25:57 -08:00
Doug Gregor
069dfad638 [Concurrency] Add Builtin.createAsyncTaskFuture.
This new builtin allows the creation of a "future" task, which calls
down to swift_task_create_future to actually form the task.
2020-11-15 22:37:13 -08:00
Michael Gottesman
9e0b1d127b [ownership] Make SILUndef always have ValueOwnershipKind::None.
This simplifies the representation and if one wants to truly get an owned value
from an undef, just copy the undef value.
2020-11-15 18:21:32 -08:00
Joe Groff
c7f4f07515 Merge pull request #34713 from jckarter/foreign-async-multi-return-abstraction-pattern
SIL: Abstraction pattern support for multiple foreign async returns.
2020-11-13 15:05:55 -08:00
Joe Groff
6db85203db SIL: Abstraction pattern support for multiple foreign async returns.
An ObjC API maybe imported as async that had multiple non-error arguments to
its completion handler, which we treat in Swift as returning a tuple. Use a new
form of abstraction pattern to represent this return type, to maintain the
correct relation between individual tuple elements and the Clang block parameter
types they map to.
2020-11-12 16:53:21 -08:00
Michael Gottesman
7d05f374f1 Merge pull request #34693 from gottesmm/pr-1fdd1272490dcfe27f62410aee521669e0059430
[ownership] Try harder to make sure we do not propagate ownership info when ownership is disabled.
2020-11-11 21:31:19 -08:00
Michael Gottesman
58d4191470 [ownership] Try harder to make sure we do not propagate ownership info when ownership is disabled.
Specifically, I made it so that assuming our instruction is inserted into a
block already that we:

1. Return a constraint of {OwnershipKind::Any, UseLifetimeConstraint::NonLifetimeEnding}.
2. Return OwnershipKind::None for all values.

Noticed above I said that if the instruction is already inserted into a block
then we do this. The reason why is that if this is called before an instruction
is inserted into a block, we can't get access to the SILFunction that has the
information on whether or not we are in OSSA form. The only time this can happen
is if one is using these APIs from within SILBuilder since SILBuilder is the
only place where we allow this to happen. In SILBuilder, we already know whether
or not our function is in ossa or not and already does different things as
appropriate (namely in non-ossa does not call getOwnershipKind()). So we know
that if these APIs are called in such a situation, we will only be calling it if
we are in OSSA already. Given that, we just assume we are in OSSA if we do not
have a function.

To make sure that no mistakes are made as a result of that assumption, I put in
a verifier check that all values when ownership is disabled return a
OwnershipKind::None from getOwnershipKind().

The main upside to this is this means that we can write code for both
OSSA/non-OSSA and write code for non-None ownership without needing to check if
ownership is enabled.
2020-11-11 18:56:59 -08:00