Commit Graph

804 Commits

Author SHA1 Message Date
Pavel Yaskevich
99cfbf7dc0 [SILGen] TypeWrappers: switch to emitFunctionDefinition for forced memberwise/default inits 2022-09-30 13:06:09 -07:00
Pavel Yaskevich
8d39e525c8 [SILGen] TypeWrappers: Make sure that default init of $Storage is always emitted
Although it might not be used from user-defined code directly
it's still required for injected `self.$_storage = ...` performed
by DI.
2022-09-29 20:50:37 -07:00
Pavel Yaskevich
862c9d4f83 [SILGen] TypeWrappers: Make sure that memberwise init of $Storage is always emitted
Although it might not be used from user-defined code directly
it's still required for injected `self.$_storage = ...` performed
by DI.
2022-09-29 20:50:37 -07:00
Hamish Knight
0eba486442 [SILGen] Remove setUpForProfiling
Instead, setup the profilers when emitting
function definitions. This is consistent with
what we do for all the other kinds of SILDeclRef.
2022-09-29 10:08:17 +01:00
Hamish Knight
5b1ca3f0e0 [SILGen] Avoid forcing function bodies for profiling
This is no longer necessary now that we ensure we
always SILGen functions that contain user code.
2022-09-29 10:08:17 +01:00
Hamish Knight
8bc80c146a [SILGen] Avoid delaying functions with user-written code
Previously we would delay the emission of
lazy variable getters and stored property
initializers for property wrapper backing storage.
This could lead to their definitions being dropped
if unused, meaning that we wouldn't run the
mandatory diagnostics passes over them.

Fix the logic such that we consider such cases as
having user-written code, and account for a couple
of cases where we can delay emission where we
didn't previously. There are more cases we can
handle here, but I'm leaving that as future work
for now, as `emitOrDelayFunction` is currently
only used for a handful of SILDeclRef kinds.

This is a source breaking change, but only for
invalid (albeit unused) code.

rdar://99962285
2022-09-28 16:11:12 +01:00
Hamish Knight
9f93bc8dcd [Profiler] Emit increment for property wrapper backing initializers
Previously we were creating a SILProfiler for
such functions, but weren't actually emitting the
increment, leading to missed coverage.

Part of the fix for rdar://99931619
2022-09-26 12:18:44 +01:00
Michael Gottesman
c54acc83e2 [move-only] Add the ability to specify a deinit at the SIL level for a move only type.
Specifically, we get an additional table like thing called sil_moveonlydeinit. It looks as follows:

sil_moveonlydeinit TYPE {
  @FUNC_NAME
}

It always has a single entry.
2022-09-20 15:19:31 -07:00
Michael Gottesman
9a8af70f1d [move-only] Teach SILGen how to emit deinits for nominal non-class move only types.
Even though with this change we emit the deinit, it isn't used yet since we
still need to implement the move only deinit table/teach the checker how to call
these/teach IRGen how to call this from the destroying value witness.
2022-09-20 15:19:31 -07:00
Hamish Knight
20830cc2fb [Profiler] Avoid profiling unavailable decls
Such decls don't provide useful coverage info.

rdar://83253091
2022-09-19 10:06:36 +01:00
Hamish Knight
d01fdc9379 [Profiler] Remove unnecessary forcing of constructors
We should always emit SILGen for user-written
constructors, so this extra forcing logic is
redundant.
2022-09-14 20:51:53 +01:00
Hamish Knight
5039c1c3f1 [Profiler] NFC: Remove unnecessary parameter
`SILProfiler::create` is only ever called when
emitting a definition, so this check is redundant.
2022-09-14 20:51:51 +01:00
Hamish Knight
19e1e2f7a2 [SILGen] Fix deinit coverage mapping
Stop profiling the deallocating deinitializer
function for non-ObjC classes, and instead profile
the destructor, which is where we emit the user's
code written in a `deinit`.

rdar://54443107
2022-08-11 15:09:53 +01:00
Slava Pestov
9d96ed940f AST: Rename 'canonical wrt. generic signature' to 'reduced'
We had two notions of canonical types, one is the structural property
where it doesn't contain sugared types, the other one where it does
not contain reducible type parameters with respect to a generic
signature.

Rename the second one to a 'reduced type'.
2022-08-09 12:46:31 -04:00
Pavel Yaskevich
e8987b4c3e [Distributed] Add a new access strategy - DispatchToDistributedThunk
This strategy is used to dispatch accesses to 'distributed' computed
property to distributed thunk accessor instead of a regular getter
when access happen outside actor isolation context.
2022-06-29 14:49:10 -07:00
Pavel Yaskevich
5bdf94f346 [Distributed] Remove commented out code and print statements 2022-06-29 14:49:10 -07:00
Konrad `ktoso` Malawski
febfef97d4 [Distributed] Skeleton implementation of distributed computed properties 2022-06-29 14:49:04 -07:00
Erik Eckstein
ca291fb147 SIL: store IRGenOptions in SILModule
SIL optimization passes can use the IRGen options to do target specific optimizations.
2022-06-23 22:16:42 +02:00
Adrian Prantl
7c1c7b6249 Emit debug locations for hop_to_executor instructions.
The function prologue of async funclets inherits its source location
from the hop_to_executor instruction. This makes it easier to produce
logical backtraces, since the PC in logical frames will always point
to the start if the function.

rdar://89776340
2022-06-23 09:40:25 -07:00
Joe Groff
6b6a557611 SILGen: Carry WMO of type lowering context to closure captures.
TypeConverter doesn't know by itself what SILModule it's currently lowering on
behalf of, so the existing code forming the TypeExpansionContext for opaque types
incorrectly set the isWholeModule flag to always false. This created a miscompile
when a public API contained a closure that captured a value involving private types
from another file in the same module because of mismatched type expansion contexts
inside and outside the closure. Fixes rdar://93821679
2022-06-06 19:51:40 -07:00
Yuta Saito
1a75b08188 [SILGen] Fix swift_once initializer signature for lazy global var
`Builtin.once` has type `(Builtin.RawPointer, (Builtin.RawPointer) -> ())`
at Swift level, but lazy global init passes its initializer as `() -> ()`,
so their callee and caller signatures doesn't match.
2022-04-03 17:27:43 +00:00
Konrad `ktoso` Malawski
5ab8e0834d [Distributed] Reimplement distributed call thunks completely in AST (#41616)
* [Distributed] dist actor always has default executor (currently)

* [Distributed] extra test for missing makeEncoder

* [DistributedDecl] Add DistributedActorSystem to known SDK types

* [DistributedActor] ok progress on getting the system via witness

* [Distributed] allow hop-to `let any: any X` where X is DistActor

* [Distributed] AST: Add an accessor to determine whether type is distributed actor

- Classes have specialized method on their declarations
- Archetypes and existentials check their conformances for
  presence of `DistributedActor` protocol.

* [Distributed] AST: Account for distributed members declared in class extensions

`getConcreteReplacementForProtocolActorSystemType` should use `getSelfClassDecl`
otherwise it wouldn't be able to find actor if the member is declared in an extension.

* [Distributed] fix ad-hoc requirement checks for 'mutating'

[PreChecker] LookupDC might be null, so account for that

* [Distributed] Completed AST synthesis for dist thunk

* [Distributed][ASTDumper] print pretty distributed in right color in AST dumps

* wip on making the local/remote calls

* using the _local to mark the localCall as known local

* [Distributed] fix passing Never when not throwing

* fix lifetime of mangled string

* [Distributed] Implement recordGenericSubstitution

* [Distributed] Dont add .

* [Distributed] dont emit thunk when func broken

* [Distributed] fix tests; cleanups

* [Distributed] cleanup, move is... funcs to DistributedDecl

* [Distributed] Remove SILGen for distributed thunks, it is in Sema now!

* [Distributed]  no need to check stored props in protocols

* remote not used flag

* fix mangling test

* [Distributed] Synthesis: Don't re-use AST nodes for `decodeArgument` references

* [Distributed] Synthesis: Make sure that each thunk parameter has an internal name

* [Distributed/Synthesis] NFC: Add a comment regarding empty internal parameter names

* [Distributed] NFC: Adjust distributed thunk manglings in the accessor section test-cases

* cleanup

* [Distributed] NFC: Adjust distributed thunk manglings in the accessor thunk test-cases

* review follow ups

* xfail some linux tests for now so we can land the AST thunk

* Update distributed_actor_remote_functions.swift

Co-authored-by: Pavel Yaskevich <xedin@apache.org>
2022-03-10 23:58:23 +09:00
Erik Eckstein
6a020f8f15 Stabilize and simplify SIL linkage and serialization
The main point of this change is to make sure that a shared function always has a body: both, in the optimizer pipeline and in the swiftmodule file.
This is important because the compiler always needs to emit code for a shared function. Shared functions cannot be referenced from outside the module.
In several corner cases we missed to maintain this invariant which resulted in unresolved-symbol linker errors.

As side-effect of this change we can drop the shared_external SIL linkage and the IsSerializable flag, which simplifies the serialization and linkage concept.
2022-03-09 15:28:05 +01:00
Allan Shortlidge
5339dae08e SILGen: Emit a fallback variant of a back deployable function and call it when the original function is not available at run time. 2022-02-23 18:07:18 -08:00
Allan Shortlidge
97e8e31b5c SILGen: Emit a thunk that wraps the call to a back deployed function. The thunk calls the original function if it is available at runtime and otherwise falls back to calling a copy that is emitted into the client (not yet implemented). 2022-02-17 11:28:12 -08:00
Evan Wilde
b08016ac68 Fix SILOptimizer crash for top-level async code
Lowering hops to actors expected the executor to either be an optional
builtin executor type or an actor type. The type coming from
`getMainExecutor` is just a builtin executor, not an optional. As a
result, `LowerHopToActor::emitGetExecutor` would get called in
`LowerHopToActor::processHop`, and would try looking up the builtin
executor type, thinking it was an actor type. This would fail because we
didn't have an actor type.

```
auto actorConf = module->lookupConformance(actorType, actorProtocol);
    assert(actorConf &&
           "hop_to_executor with actor that doesn't conform to Actor");
```

The end result was hitting this assert here, saying that the "actor"
doesn't conform to actor.

The fix is to wrap the executor in an optional.
2022-02-03 11:17:34 -08:00
John McCall
716f4b9e2f Hop to the generic executor in non-actor-isolated async functions.
Async functions are now expected to set ExpectedExecutor in their
prologue (and, generally, immediately hop to it).  I updated the
prologue code for a bunch of function emission, most of which was
uninteresting.  Top-level code was not returning to the main
executor, which is now fixed; fortunately, we weren't assuming
that we were on the main executor yet.

We had some code that only kicked in when an ExpectedExecutor
wasn't set which made us capture the current executor before
a hop and then return to it later.  This code has been removed;
there's no situation in which save-and-return is the semantically
correct thing to do given the possibility of hop optimization.
I suspect it could also have led to crashes if the current
executor is being kept alive only because it's currently running
code.  If we ever add async functions that are supposed to inherit
their caller's executor, we should have the caller pass the right
executor down to it.

This is the first half of SE-0338; the second, sendability
enforcement, is much more complicated, and Doug has volunteered
to do it.

Fixes rdar://79284465, as well as some tests that were XFAILed
on Windows.
2022-01-27 01:53:19 -05:00
Evan Wilde
794d0e0b9a Merge pull request #40832 from etcwilde/ewilde/async-top-level
A first pass at concurrency in top-level code
2022-01-21 13:24:51 -08:00
Holly Borla
6cee193fc0 [Type System] When explicit existential types are enabled, wrap Error
in ExistentialType for the type of error values.
2022-01-13 19:30:44 -08:00
Evan Wilde
431b6661e4 Generate async main entrypoint for top-level
This patch adds the SILGen side of generating the asynchronous main
entrypoint for top-level code. The behavior is the same as with the
asynchronous MainType entrypoint.
2022-01-12 15:40:39 -08:00
Pavel Yaskevich
4860f90fd7 [SIL] Add new flag to SILFunction - IsDistributed
Determines whether given SILFunction represents a distributed
method or its thunk.
2021-12-17 10:52:52 -08:00
Robert Widmann
22405cefea Plumb the "Is Type Sequence" Bit Through the Surface AST 2021-11-08 13:48:30 -08:00
Erik Eckstein
5321a7cae8 SIL: Only enable instruction leaks checking in the frontend's and SILOpt's modules.
Leaks checking is not thread safe and e.g. lldb creates multiple SILModules in multiple threads, which would result in false alarms.
Ideally we would make it thread safe, e.g. by putting the instruction counters in the SILModule, but this would be a big effort and it's not worth doing it. Leaks checking in the frontend's and SILOpt's SILModule (not including SILModules created for module interface building) is a good enough test.

rdar://84688015
2021-11-02 10:23:46 +01:00
Doug Gregor
214b1bd454 Add support for distributed functions in extensions of distributed actors.
Fix a few minor issues in the type checker and SILGen to properly cope with
distributed functions defined within extensions of distributed actors.
While here, centralize the logic that adds the "_remote_" function.

Fixes rdar://84325525.
2021-10-15 22:46:44 -07:00
Arnold Schwaighofer
81dd5d9cb6 Delay import of prespecialize decls until generic specialization 2021-10-11 11:10:09 -07:00
Erik Eckstein
30a74f6284 SIL: remove the private_external SILLinkage
This was a relict from the -sil-serialize-all days. This linkage doesn't make any sense because a private function cannot be referenced from another module (or file, in case of non-wmo compilation).
2021-10-10 19:52:40 +02:00
Arnold Schwaighofer
c2b2f1331f SIL representation 2021-10-06 04:54:49 -07:00
Evan Wilde
d376ee9989 Run first thunk of Async main synchronously
This patch updates the asynchronous main function to run the first thunk
of the function synchronously through a call to `swift_job_run`.

The runloop is killed by exiting or aborting the task that it is running
on. As such, we need to ensure that the task contains an async function
that either calls exit explicitly or aborts. The AsyncEntryPoint, that
contains this code, was added in the previous patch. This patch adds the
pieces for the actual implementation of this behaviour as well as adding
the necessary code to start the runloop.

There are now four layers of main functions before hitting the "real"
code.

@main: This is the actual main entrypoint of the program. This
constructs the task containing @async_main, grabs the main executor,
runs swift_job_run to run the first part synchronously, and finally
kicks off the runloop with a call to _asyncMainDrainQueue. This is
generated in the call to `emitAsyncMainThreadStart`.

@async_main: This thunk exists to ensure that the main function calls
`exit` at some point so that the runloop stops. It also handles emitting
an error if the user-written main function throws.

e.g:

```
func async_main() async -> () {
  do {
    try await Main.$main()
    exit(0)
  } catch {
    _errorInMain(error)
  }
}
```

Main.$main(): This still has the same behaviour as with the
synchronous case. It just calls `try await Main.main()` and exists to
simplify typechecking.

Main.main(): This is the actual user-specified main. It serves the same
purpose as in the synchronous, allowing the programmer to write code,
but it's async!

The control flow in `emitFunctionDefinition` is a little confusing (to
me anyway), so here it is spelled out:

If the main function is synchronous, the `constant.kind` will be a
`SILDeclRef::Kind::EntryPoint`, but the `decl` won't be async, so it
drops down to `emitArtificalTopLevel` anyway.

If the main function is async and we're generating `@main`, the
`constant.kind` will be `SILDeclRef::Kind::AsyncEntryPoint`, so we also
call `emitArtificalTopLevel`. `emitArtificalTopLevel` is responsible for
detecting whether the decl is async and deciding whether to emit code to
extract the argc/argv variables that get passed into the actual main
entrypoint to the program. If we're generating the `@async_main` body,
the kind will be `SILDeclRef::Kind::EntryPoint` and the `decl` will be
async, so we grab the mainEntryPoint decl and call
`emitAsyncMainThreadStart` to generate the wrapping code.

Note; there is a curious change in `SILLocation::getSourceLoc()`
where instead of simply checking `isFilenameAndLocation()`, I change it
to `getStorageKind() == FilenameAndLocationKind`. This is because the
SILLocation returned is to a FilenameAndLocationKind, but the actual
storage returns true for the call to `isNull()` inside of the
`isFilenameAndLocation()` call. This results in us incorrectly falling
through to the `getASTNode()` call below that, which asserts when asked
to get the AST node of a location.

I also did a little bit of refactoring in the SILGenModule for grabbing
intrinsics. Previously, there was only a `getConcurrencyIntrinsic`
function, which would only load FuncDecls out of the concurrency
module. The `exit` function is in the concurrency shims module, so I
refactored the load code to take a ModuleDecl to search from.

The emitBuiltinCreateAsyncTask function symbol is exposed from
SILGenBuiltin so that it is available from SILGenFunction. There is a
fair bit of work involved going from what is available at the SGF to
what is needed for actually calling the CreateAsyncTask builtin, so in
order to avoid additional maintenance, it's good to re-use that.
2021-10-02 16:53:06 -07:00
Evan Wilde
552ae0635a Add AsyncEntryPoint SILDeclRef type
The AsyncEntryPoint represents the thunk that is wrapped in a task. This
thunk is used to ensure that the main function explicitly calls "exit",
and to properly unwrap and report any unhandled errors returned from the
user-written main. The function takes on the name `@async_main` in the
emitted SIL.
2021-10-02 16:53:06 -07:00
Evan Wilde
b10c2c89a9 Paramterize module in lookupIntrinsic
The lookupConcurrencyIntrinsic function only looked in the concurrency
module. It is useful to look in other modules for intrinsics too.
2021-10-02 16:53:06 -07:00
Joe Groff
fdc0e08d60 SILGen: Emit literal closures at the abstraction level of their context.
Literal closures are only ever directly referenced in the context of the expression they're written in,
so it's wasteful to emit them at their fully-substituted calling convention and then reabstract them if
they're passed directly to a generic function. Avoid this by saving the abstraction pattern of the context
before emitting the closure, and then lowering its main entry point's calling convention at that
level of abstraction. Generalize some of the prolog/epilog code to handle converting arguments and returns
to the correct representation for a different abstraction level.
2021-09-09 13:42:02 -07:00
Joe Groff
3abe16f40f Revert "SILGen: Emit literal closures at the abstraction level of their context. [take 2]" (#39228) 2021-09-09 11:53:43 -05:00
Joe Groff
43506a29a2 SILGen: Emit literal closures at the abstraction level of their context.
Literal closures are only ever directly referenced in the context of the expression they're written in,
so it's wasteful to emit them at their fully-substituted calling convention and then reabstract them if
they're passed directly to a generic function. Avoid this by saving the abstraction pattern of the context
before emitting the closure, and then lowering its main entry point's calling convention at that
level of abstraction. Generalize some of the prolog/epilog code to handle converting arguments and returns
to the correct representation for a different abstraction level.
2021-09-07 11:55:29 -07:00
Konrad `ktoso` Malawski
923aeac7c6 [Distributed] always emit the distributed thunk 2021-08-26 14:35:07 +09:00
Holly Borla
86e1014399 Revert " SILGen: Emit literal closures at the abstraction level of their context." 2021-08-18 09:03:23 -07:00
Joe Groff
309500d4bf SILGen: Emit literal closures at the abstraction level of their context.
Literal closures are only ever directly referenced in the context of the expression they're written in,
so it's wasteful to emit them at their fully-substituted calling convention and then reabstract them if
they're passed directly to a generic function. Avoid this by saving the abstraction pattern of the context
before emitting the closure, and then lowering its main entry point's calling convention at that
level of abstraction. Generalize some of the prolog/epilog code to handle converting arguments and returns
to the correct representation for a different abstraction level.
2021-08-16 09:39:19 -07:00
Holly Borla
fb0121ea60 [SILGen] Emit property wrapper generator functions in the same place
as default argument generator functions.
2021-08-12 13:56:05 -07:00
Joe Groff
fc67ba57f2 Merge pull request #37938 from jckarter/async-let-multi-suspend
Handle multiple awaits and suspend-on-exit for async let tasks.
2021-07-23 07:36:54 -07:00
Robert Widmann
1329f3cfbd [NFC] Lift getGenericEnvironment() into GenericSignature 2021-07-22 23:33:02 -07:00
Joe Groff
439edbce1f Handle multiple awaits and suspend-on-exit for async let tasks.
Change the code generation patterns for `async let` bindings to use an ABI based on the following
functions:

- `swift_asyncLet_begin`, which starts an `async let` child task, but which additionally
  now associates the `async let` with a caller-owned buffer to receive the result of the task.
  This is intended to allow the task to emplace its result in caller-owned memory, allowing the
  child task to be deallocated after completion without invalidating the result buffer.
- `swift_asyncLet_get[_throwing]`, which replaces `swift_asyncLet_wait[_throwing]`. Instead of
  returning a copy of the value, this entry point concerns itself with populating the local buffer.
  If the buffer hasn't been populated, then it awaits completion of the task and emplaces the
  result in the buffer; otherwise, it simply returns. The caller can then read the result out of
  its owned memory. These entry points are intended to be used before every read from the
  `async let` binding, after which point the local buffer is guaranteed to contain an initialized
  value.
- `swift_asyncLet_finish`, which replaces `swift_asyncLet_end`. Unlike `_end`, this variant
  is async and will suspend the parent task after cancelling the child to ensure it finishes
  before cleaning up. The local buffer will also be deinitialized if necessary. This is intended
  to be used on exit from an `async let` scope, to handle cleaning up the local buffer if necessary
  as well as cancelling, awaiting, and deallocating the child task.
- `swift_asyncLet_consume[_throwing]`, which combines `get` and `finish`. This will await completion
  of the task, leaving the result value in the result buffer (or propagating the error, if it
  throws), while destroying and deallocating the child task. This is intended as an optimization
  for reading `async let` variables that are read exactly once by their parent task.

To avoid an epoch break with existing swiftinterfaces and ABI clients, the old builtins and entry
points are kept intact for now, but SILGen now only generates code using the new interface.

This new interface fixes several issues with the old async let codegen, including use-after-free
crashes if the `async let` was never awaited, and the inability to read from an `async let` variable
more than once.

rdar://77855176
2021-07-22 10:19:31 -07:00