Commit Graph

215 Commits

Author SHA1 Message Date
Stephen Canon
511b50e511 Implement shufflevector builtin. (#36650)
This isn't _terribly_ useful as-is, because the only constant mask you can get at from Swift at present is the zeroinitializer, but even that is quite useful for optimizing the repeating: intializer on SIMD. At some future point we should wire up generating constant masks for the .even, .odd, .high and .low properties (and also eventually make shufflevector take non-constant masks in LLVM). But this is enough to be useful, so let's get it in.
2021-04-04 23:23:53 -04:00
John McCall
4f6f8b3377 Rewrite hop_to_executor so that it takes a Builtin.Executor in IRGen
The comment in LowerHopToActor explains the design here.
We want SILGen to emit hops to actors, ignoring executors,
because it's easier to fully optimize in a world where deriving
an executor is a non-trivial operation.  But we also want something
prior to IRGen to lower the executor derivation because there are
useful static optimizations we can do, such as doing the derivation
exactly once on a dominance path and strength-reducing the derivation
(e.g. exploiting static knowledge that an actor is a default actor).

There are probably phase-ordering problems with doing this so late,
but hopefully they're restricted to situations like actors that
share an executor.  We'll want to optimize that eventually, but
in the meantime, this unblocks the executor work.
2021-03-30 20:08:41 -04:00
John McCall
98711fd628 Revise the continuation ABI.
The immediate desire is to minimize the set of ABI dependencies
on the layout of an ExecutorRef.  In addition to that, however,
I wanted to generally reduce the code size impact of an unsafe
continuation since it now requires accessing thread-local state,
and I wanted resumption to not have to create unnecessary type
metadata for the value type just to do the initialization.

Therefore, I've introduced a swift_continuation_init function
which handles the default initialization of a continuation
and returns a reference to the current task.  I've also moved
the initialization of the normal continuation result into the
caller (out of the runtime), and I've moved the resumption-side
cmpxchg into the runtime (and prior to the task being enqueued).
2021-03-28 12:58:16 -04:00
Joe Groff
79fb05b362 Concurrency: Hop back to the previous executor after actor calls.
Tasks shouldn't normally hog the actor context indefinitely after making a call that's bound to
that actor, since that prevents the actor from potentially taking on other jobs it needs to
be able to address. Set up SILGen so that it saves the current executor (using a new runtime
entry point) and hops back to it after every actor call, not only ones where the caller context
is also actor-bound.

The added executor hopping here also exposed a bug in the runtime implementation while processing
DefaultActor jobs, where if an actor job returned to the processing loop having already yielded
the thread back to a generic executor, we would still attempt to make the actor give up the thread
again, corrupting its state.

rdar://71905765
2021-03-18 11:47:50 -07:00
John McCall
6c879d6fd3 Change the async ABI to not pass the active task and executor.
Most of the async runtime functions have been changed to not
expect the task and executor to be passed in.  When knowing the
task and executor is necessary, there are runtime functions
available to recover them.

The biggest change I had to make to a runtime function signature
was to swift_task_switch, which has been altered to expect to be
passed the context and resumption function instead of requiring
the caller to park the task.  This has the pleasant consequence
of allowing the implementation to very quickly turn around when
it recognizes that the current executor is satisfactory.  It does
mean that on arm64e we have to sign the continuation function
pointer as an argument and then potentially resign it when
assigning into the task's resume slot.

rdar://70546948
2021-03-16 22:52:54 -04:00
Joe Groff
d9798c0868 Concurrency: Redo non-_f variants of swift_task_create to accept closures as is.
In their previous form, the non-`_f` variants of these entry points were unused, and IRGen
lowered the `createAsyncTask` builtins to use the `_f` variants with a large amount of caller-side
codegen to manually unpack closure values. Amid all this, it also failed to make anyone responsible
for releasing the closure context after the task completed, causing every task creation to leak.
Redo the `swift_task_create_*` entry points to accept the two words of an async closure value
directly, and unpack the closure to get its invocation entry point and initial context size
inside the runtime. (Also get rid of the non-future `swift_task_create` variant, since it's unused
and it's subtly different in a lot of hairy ways from the future forms. Better to add it later
when it's needed than to have a broken unexercised version now.)
2021-03-08 16:54:19 -08:00
Joe Groff
511f9aaa19 SIL: Clean up ownership handling in createAsyncTask builtins.
The underlying runtime functions really want to be able to consume the closure being used
to spawn the task, but the implementation was trying to hide this by introducing a retain
at IRGen time, which is not very ARC-optimizer-friendly. Correctly model the builtin operands
as consumed so that the ownership verifier allows them to be taken +1.
2021-03-05 12:00:45 -08:00
Konrad `ktoso` Malawski
6e525d7469 Merge branch 'main' into wip-no-escape-group 2021-02-25 10:37:20 +09:00
Andrew Trick
ca0d189348 Add assert and comments to OperandOwnershipClassifier::visitFullApply
I had a difficult time determining to set of possible operand
ownership kinds for callee operands.
2021-02-23 22:47:59 -08:00
Konrad `ktoso` Malawski
a226259d84 [Concurrency] TaskGroup moves out of AsyncTask, non escaping body 2021-02-22 13:26:27 +09:00
Michael Gottesman
421addacce [ownership] Change store_borrow to be an interior pointer and update interior pointer formalism to use it.
For those who are unaware, a store_borrow is an instruction that is needed so
that we can without adding ARC traffic materialize a guaranteed object value
into memory so we can pass it as an in_guaranteed argument. It has not had its
model completely implemented due to time. I am going to add some information
about it in this commit message for others.

From a model semantic perspective, a store_borrow is meant to allow for a
guaranteed value to be materialized into memory safely for a scoped region of
time and be able to guarantee that:

1. The guaranteed value that was stored is always live.
2. The memory is never written to within that region.

The natural way to model this type of guaranteeing behavior from an object to an
address is via a safe interior pointer formulation and thus with that in mind I
made it so that store_borrow returned an address that was an interior pointer of
the guaranteed value. Sadly, we have not changed the compiler yet to use this
effectively since we in store_borrow code paths generally just use the input
address. That being said, in this PR I begin to move us toward this world by
making store_borrow's src operand an InteriorPointerOperand. This means that we
will require the borrowed value to be alive at all use points of the
store_borrow result. That will not have a large effect today but I am going to
loop back around and extend that.

There is additional work here that I wish to accomplish in the future is that I
would like to define an end_store_borrow instruction to explicitly end the scope
in which there is a condition on the borrow. Then we would require that the
memory we are using to for sure never be written to in that region and maybe
additionally try to give some sort of guarantee around exclusivity (consider if
we made it so that we could only store_borrow into an alloc_stack with certain
conditions). Not sure about the last one yet. But philosophically since we are
using this to just handle reabstraction suggests we can do something more
constrained.
2021-02-08 10:53:56 -08:00
Michael Gottesman
62d554669c [ownership] Rename OwnershipForwardingMixin::{get,set}OwnershipKind() -> {get,set}ForwardingOwnershipKind().
TLDR: This is just an NFC rename in preparation for changing
SILValue::getOwnershipKind() of any forwarding instructions to return
OwnershipKind::None if they have a trivial result despite forwarding ownership
that isn't OwnershipKind::None (consider an unchecked_enum_data of a trivial
payload from a non-trivial enum).

This ensures that one does not by mistake use this routine instead of
SILValue::getOwnershipKind(). The reason why these two things must be
distinguished is that the forwarding ownership kind of an instruction that
inherits from OwnershipForwardingMixin is explicitly not the ValueOwnershipKind
of the result of the instruction. Instead it is a separate piece of state that:

1. For certain forwarding instructions, defines the OwnershipConstraint of the
forwarding instruction.

2. Defines the ownership kind of the result of the value. If the result of the
value is non-trivial then it is exactly the set ownership kind. If the result is
trivial, we use OwnershipKind::None instead. As an example of this, consider an
unchecked_enum_data that extracts from a non-trivial enum a trivial payload:

```
enum Either {
case int(Int)
case obj(Klass)
}

%1 = load_borrow %0 : $*Either
%2 = unchecked_enum_data %1 : $Either, #Either.int!enumelt.1 // Int type
end_borrow %1 : $Either
```

If we were to identify the forwarding ownership kind (guaranteed) of
unchecked_enum_data with the value ownership kind of its result, we would
violate ownership since we would be passing a guaranteed value to the operand of
the unchecked_enum_data that will only accept values with
OwnershipKind::None. =><=.
2021-02-04 16:53:50 -08:00
Andrew Trick
f22d0855df Add a CanonicalOSSALifetime utility.
Canonicalizing OSSA provably minimizes the number of retains and
releases within the boundaries of that lifetime. This eliminates the
need for ad-hoc optimization of OSSA copies.

This initial implementation only canonicalizes owned values, but
canonicalizing guaranteed values is a simple extension.

This was originally part of the CopyPropagation prototype years
ago. Now OSSA is specified completely enough that it can be turned
into a simple utility instead.

CanonicalOSSALifetime uses PrunedLiveness to find the extended live
range and identify the consumes on the boundary. All other consumes
need their own copy. No other copies are needed.

By running this after other transformations that affect OSSA
lifetimes, we can avoid the need to run pattern-matching optimization
to SemanticARC to recover from suboptimal patterns, which is not
robust, maintainable, or efficient.
2021-01-05 20:38:30 -08:00
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
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
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
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
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
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
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
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
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
Michael Gottesman
43a89e0c65 [ownership] Some small fixes from Andy's review.
I merged the original PR since it was rather large. These are the remaining
small fixes.
2020-11-10 22:44:13 -08:00
Michael Gottesman
a294ab61ad [ownership] Eliminate OperandOwnershipKindMap in favor of OwnershipConstraint.
I also used this as a moment to clarify the lattice that related
ValueOwnershipKind and OwnershipConstraint.
2020-11-10 19:07:30 -08:00
Michael Gottesman
c026e95cce [ownership] Extract out SILOwnershipKind from ValueOwnershipKind into its own type and rename Invalid -> Any.
This makes it easier to understand conceptually why a ValueOwnershipKind with
Any ownership is invalid and also allowed me to explicitly document the lattice
that relates ownership constraints/value ownership kinds.
2020-11-10 14:29:11 -08:00
Doug Gregor
6798ed1c9c Merge pull request #34627 from DougGregor/create-async-task-builtin
[Concurrency] Implement a builtin createAsyncTask() to create a new task
2020-11-09 20:40:53 -08:00
Michael Gottesman
a0cb311d60 Merge pull request #34644 from gottesmm/pr-e398af60dfa740b58a743d92dc2fdc617e9c9bf0
[ownership] Change ReturnInst to have its ValueOwnershipKind stored within it rather than always recomputing from the function type.
2020-11-09 18:35:19 -08:00
Michael Gottesman
b40aa543ac Merge pull request #34637 from gottesmm/pr-027a025e7a95d70fcc7e98300987826a5948c8c4
[ownership] Move type dependent operand check out of the main visitor to eliminate another returning of an empty map from the visitor.
2020-11-09 15:29:39 -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
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
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
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
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