Commit Graph

149 Commits

Author SHA1 Message Date
Azoy
9ed732f0ab Introduce isDecl and getDeclType
fix enum logic issue

fix tests

guard against null types
2021-04-20 02:22:16 -04:00
Konrad `ktoso` Malawski
d3c5ebc9b7 [AsyncLet] reimplemented with new ABI and builtins 2021-04-19 10:06:23 +09:00
Konrad `ktoso` Malawski
ba615029c7 [Concurrency] Store child record when async let child task spawned 2021-04-19 10:06:23 +09:00
Doug Gregor
e77a27e8ed [Concurrency] Introduce runtime detection of data races.
Through various means, it is possible for a synchronous actor-isolated
function to escape to another concurrency domain and be called from
outside the actor. The problem existed previously, but has become far
easier to trigger now that `@escaping` closures and local functions
can be actor-isolated.

Introduce runtime detection of such data races, where a synchronous
actor-isolated function ends up being called from the wrong executor.
Do this by emitting an executor check in actor-isolated synchronous
functions, where we query the executor in thread-local storage and
ensure that it is what we expect. If it isn't, the runtime complains.
The runtime's complaints can be controlled with the environment
variable `SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL`:

  0 - disable checking
  1 - warn when a data race is detected
  2 - error and abort when a data race is detected

At an implementation level, this introduces a new concurrency runtime
entry point `_checkExpectedExecutor` that checks the given executor
(on which the function should always have been called) against the
executor on which is called (which is in thread-local storage). There
is a special carve-out here for `@MainActor` code, where we check
against the OS's notion of "main thread" as well, so that `@MainActor`
code can be called via (e.g.) the Dispatch library's
`DispatchQueue.main.async`.

The new SIL instruction `extract_executor` performs the lowering of an
actor down to its executor, which is implicit in the `hop_to_executor`
instruction. Extend the LowerHopToExecutor pass to perform said
lowering.
2021-04-12 15:19:51 -07:00
Erik Eckstein
09755659a1 SIL: remove the sub-classes of MultipleValueInstructionResult
They are not really needed, because they don't contain any stored properties and for isa-checks we can check the parent instruction.
2021-04-11 19:14:34 +02:00
John McCall
efeb818161 Clean up the TaskGroup ABI:
- stop storing the parent task in the TaskGroup at the .swift level
- make sure that swift_taskGroup_isCancelled is implied by the parent
  task being cancelled
- make the TaskGroup structs frozen
- make the withTaskGroup functions inlinable
- remove swift_taskGroup_create
- teach IRGen to allocate memory for the task group
- don't deallocate the task group in swift_taskGroup_destroy

To achieve the allocation change, introduce paired create/destroy builtins.

Furthermore, remove the _swiftRetain and _swiftRelease functions and
several calls to them.  Replace them with uses of the appropriate builtins.
I should probably change the builtins to return retained, since they're
working with a managed type, but I'll do that in a separate commit.
2021-04-09 03:06:31 -04:00
John McCall
57c0c787db Make Builtin.getCurrentExecutor conservatively not readnone.
Fixes a miscompile where the hop_to_executor optimizer would
remove hop_to_executor before a getCurrentExecutor.
2021-04-08 12:57:11 -04:00
Michael Gottesman
059421e26c [mem-access-utils] Allow for getStackInitAllocStackUse to recognize an always take from a unconditional_checked_cast_addr as a destroy_addr 2021-03-29 12:14:14 -07:00
Michael Gottesman
6bb92533f6 [mem-access-utils] Allow for getStackInitAllocStackUse to recognize an always take from a checked_cast_addr_br as a destroy_addr.
Since it is an always take, we know that the original value will always be
invalidated by the checked_cast_addr_br.

This also lets me use this to recognize simple cases of checked casts in
opt-remark-gen.
2021-03-29 12:10:37 -07:00
Michael Gottesman
f6e71d4433 [mem-access-utils] Refactor isSingleInitAllocStack into getSingleInitAllocStackUse and rewrite the former in terms of the first.
This enabled me to expand this API to return the underlying single init use. I
want this information in OptRemarkGen.
2021-03-29 12:10:37 -07: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
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
Konrad `ktoso` Malawski
a226259d84 [Concurrency] TaskGroup moves out of AsyncTask, non escaping body 2021-02-22 13:26:27 +09:00
Erik Eckstein
f12ac4c11b SIL: add two utility functions to AccessPath 2021-02-04 07:53:32 +01:00
Robert Widmann
129f6eb90f [NFC] Silence -Wsuggest-override Warnings 2021-02-02 09:22:18 -08:00
Andrew Trick
c6eb9e89f5 [OSSA] Fix AccessPathDefUserTraversal::visitUser; ignore end_borrow.
Ignore end_borrow as a user of the access path. I don't think there's
any value in viewing it as a use of the access path because we really
care about address reads and writes in this context, not object
lifetime extension. Treating it as an access path use clutters the analysis,
and I'm afraid it will inhibit optimization.
2021-01-20 11:37:44 -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
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
b49a882ea1 Add some SIL properties for get/await_async_continuation 2020-11-19 12:38:51 -08:00
Erik Eckstein
71af79a46d SIL: handle hop_to_executor instruction in MemAccessUtils 2020-11-17 16:01:36 +01:00
Andrew Trick
c4abccb405 Merge pull request #34742 from atrick/fix-unchecked-ownership
Specify the unchecked_ownership_conversion instruction
2020-11-16 21:13:11 -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
Andrew Trick
5329d92374 Clarify a comment in MemAccessUtils. 2020-11-13 16:51:32 -08:00
Andrew Trick
4409f14c78 Merge pull request #33987 from atrick/opt-licm-combined-ldst
Use AccessPath in LICM and split loads for combine load/store hoisting
2020-11-13 00:10:10 -08:00
Andrew Trick
fe3415fd8d Merge pull request #34654 from atrick/fix-loadborrow-initenum
AccessPath: Add init_enum_data_addr to "access projections" set.
2020-11-10 08:35:21 -08:00
Andrew Trick
eadefc09a9 AccessPath: Add init_enum_data_addr to "access projections" set.
AccessPath was treating init_enum_data_addr as an address base, which
is not ideal. It should be able to identify the underlying enum object
as the base. This issue was caught by LoadBorrowImmutabilityChecker
during SIL verification.

Instead handle init_enum_data_addr as a access projection that does
not affect the access path. I expect this SIL pattern to disappear
with SIL opaque values, but it still needs to be handled properly
after lowering addresses.

Functionality changes:

- any user of AccessPath now sees enum initialization stores as writes
  to the underlying enum object

- SILGen now generates begin/end access markers for enum
  initialization patterns. (Originally, we did not "see through"
  init_enum_data_addr because we didn't want to generate these
  markers, but that behavior was inconsistent and problematic).

Fixes rdar://70725514 fatal error encountered during compilation;
Unknown instruction: init_enum_data_addr)
2020-11-09 17:36:15 -08:00
Andrew Trick
d9a14836e2 Add a simple AccessUseDefChainCloner. 2020-11-09 09:48:05 -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
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
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
Andrew Trick
f31296d63b Fix isRCIdentityPreservingCast to handle trivial-to-reference casts
And add assertions.
2020-10-20 16:57:24 -07:00
Andrew Trick
090d57a092 Look past class casts when finding the reference root.
For class storage AccessedStorage is now close to what some passes use
for RC identity, but it still does not look past wrapping references
in an Optional.
2020-10-20 16:52:26 -07:00
Andrew Trick
f6b32aedcd Add AccessedStorageWithBase to conviently recover the base's VarDecl 2020-10-16 15:00:10 -07:00
Andrew Trick
b272dc5e1a Cache 'isLet' within AccessedStorage.
Compute 'isLet' from the VarDecl that is available when constructing
AccessedStorage so we don't need to recover the VarDecl for the base
later.

This generally makes more sense and is more efficient, but it will be
necessary when we look past class casts when finding the reference root.
2020-10-16 15:00:10 -07:00
Andrew Trick
6f2cda1390 Add AccessUseVisitor and cleanup related APIs.
Add AccesssedStorage::compute and computeInScope to mirror AccessPath.

Allow recovering the begin_access for Nested storage.

Adds AccessedStorage.visitRoots().
2020-10-16 15:00:10 -07:00
Andrew Trick
b2d1ac1631 Add AccessPathVerification pass and run it in the pipeline. 2020-10-16 15:00:10 -07:00
Andrew Trick
cc0aa2f8b8 Add an AccessPath abstraction and formalize memory access
Things that have come up recently but are somewhat blocked on this:

- Moving AccessMarkerElimination down in the pipeline
- SemanticARCOpts correctness and improvements
- AliasAnalysis improvements
- LICM performance regressions
- RLE/DSE improvements

Begin to formalize the model for valid memory access in SIL. Ignoring
ownership, every access is a def-use chain in three parts:

object root -> formal access base -> memory operation address

AccessPath abstracts over this path and standardizes the identity of a
memory access throughout the optimizer. This abstraction is the basis
for a new AccessPathVerification.

With that verification, we now have all the properties we need for the
type of analysis requires for exclusivity enforcement, but now
generalized for any memory analysis. This is suitable for an extremely
lightweight analysis with no side data structures. We currently have a
massive amount of ad-hoc memory analysis throughout SIL, which is
incredibly unmaintainable, bug-prone, and not performance-robust. We
can begin taking advantage of this verifably complete model to solve
that problem.

The properties this gives us are:

Access analysis must be complete over memory operations: every memory
operation needs a recognizable valid access. An access can be
unidentified only to the extent that it is rooted in some non-address
type and we can prove that it is at least *not* part of an access to a
nominal class or global property. Pointer provenance is also required
for future IRGen-level bitfield optimizations.

Access analysis must be complete over address users: for an identified
object root all memory accesses including subobjects must be
discoverable.

Access analysis must be symmetric: use-def and def-use analysis must
be consistent.

AccessPath is merely a wrapper around the existing accessed-storage
utilities and IndexTrieNode. Existing passes already very succesfully
use this approach, but in an ad-hoc way. With a general utility we
can:

- update passes to use this approach to identify memory access,
  reducing the space and time complexity of those algorithms.

- implement an inexpensive on-the-fly, debug mode address lifetime analysis

- implement a lightweight debug mode alias analysis

- ultimately improve the power, efficiency, and maintainability of
  full alias analysis

- make our type-based alias analysis sensistive to the access path
2020-10-16 15:00:10 -07:00
Andrew Trick
5ae231eaab Rename getFieldNo() to getFieldIndex().
Do I really need to justify this?
2020-09-24 22:44:13 -07:00
Andrew Trick
28294725d4 Change SIL ref_element_addr getFieldNo() to return a unique index.
I don't have a test case for this bug based on the current code. But
the fix is clearly needed to have a unique AccessStorage object for
each property. The AccessPath commits will contain test cases for this
functionality.
2020-09-24 19:55:36 -07:00
Meghana Gupta
b34791a0a0 Update code as per Apple Style Guide
whitelist -> allowlist
blacklist -> denylist
2020-07-24 11:37:15 -07:00
Andrew Trick
6ecbeefd50 Add AccessedStorage::Tail access kind and remove more checks.
Distinguish ref_tail_addr storage from the other storage classes.

We didn't have this originally because be don't expect a begin_access
to directly operate on tail storage. It could occur after inlining, at
least with static access markers. More importantly it helps ditinguish
regular formal accesses from other unidentified access, so we probably
should have always had this.

At any rate, it's particularly important when AccessedStorage is
generalized to arbitrary memory access.

The immediate motivation is to add an AccessPath utility, which will
need to distinguish tail storage.

In the process, rewrite AccessedStorage::isDistinct. This could have a
large positive impact on exclusivity performance.
2020-07-20 16:42:53 -07:00
Andrew Trick
5091aee6f2 Add an AccessedStorageDumper pass to verify findAccessedStorage.
Rename the existing pass to AccessedStorageAnalysisDumper.

AccessedStorage is useful on its own as a utility without the
analysis. We need a way to test the utility itself.

Add test cases for the previous commit that introduced
FindPhiStorageVisitor.
2020-07-20 16:42:28 -07:00
Andrew Trick
0a5ba3f402 Refine AccessUseDefChainVisitor.
Prepare to reuse this visitor for an AccessPath utility.

Remove visitIncomplete. Add visitCast and visitPathComponent.

Handle phis in a separate visitor. This simplifies the main
visitor. In the long-term, we may be able to eliminate the pointer-phi
visitor entirely. For now, this lets us enforce that all phi paths
follow the same access path.
2020-07-19 19:15:44 -07:00
Andrew Trick
5826e75b00 Generalize the MemAccessUtils API.
For use outside access enforcement passes.

Add isUniquelyIdentifiedAfterEnforcement.

Rename functions for clarity and generality.

Rename isUniquelyIdentifiedOrClass to isFormalAccessBase.

Rename findAccessedStorage to identifyFormalAccess.

Rename findAccessedStorageNonNested to findAccessedStorage.

Part of generalizing the utility for use outside the access
enforcement passes.
2020-07-17 10:13:20 -07:00
Andrew Trick
3543cf85c4 Cleanup MemAccessUtils.
Organize the utilities in this file by section to make subsequent
diffs easier to read and prepare for adding more utilities.
2020-07-09 14:31:45 -07:00
Erik Eckstein
8f2632939a Builtins to support copy-on-write SIL instructions
* Builtin.COWBufferForReading -> ref_element_addr [immutable] / ref_tail_addr [immutable]
* Builtin.beginCOWmutation -> begin_cow_mutation
* Builtin.endCOWmutation -> end_cow_mutation
2020-05-14 08:39:54 +02:00
Andrew Trick
8636c39259 Fix assert in MemAccessUtils isLetAccess
Assertion failed:
(accessedAddress == getAccessedAddress(accessedAddress) &&
"caller must find the address root"), function isLetAddress,
file /Users/rjmccall/dev/swift/swift/lib/SIL/Utils/MemAccessUtils.cpp,
line 63.

Teach the getAccessedAddress utility to iterate through nested access
markers with projections interposed.

Fixes <rdar://problem/61464370>
Crash in SILOptimizer/access_marker_verify.swift
2020-04-08 22:04:16 -07:00
Andrew Trick
ec1545fac2 Fix the getAddressAccess API.
The API was accidentally undefined, presumably because I checked in
the wrong code or there was a bad merge. The API will be used by
upcoming commits.

Meanwhile, getAccessedAddress was not stripping access markers, which
means some analysis may have been too conservative.

This fix could expose issues by making existing analyses more effective.
2020-04-02 18:49:46 -07:00
Michael Gottesman
e1a19e4173 [sil] Split library into subfolders, while still building as a single library still.
Specifically, I split it into 3 initial categories: IR, Utils, Verifier. I just
did this quickly, we can always split it more later if we want.

I followed the model that we use in SILOptimizer: ./lib/SIL/CMakeLists.txt vends
 a macro (sil_register_sources) to the sub-folders that register the sources of
 the subdirectory with a global state variable that ./lib/SIL/CMakeLists.txt
 defines. Then after including those subdirs, the parent cmake declares the SIL
 library. So the output is the same, but we have the flexibility of having
 subdirectories to categorize source files.
2020-03-30 11:01:00 -07:00