Use the lvalue mechanism to build opaque formal accesses so that they
nest properly with writebacks. Don't put a cleanup on the lvalue because
that creates a double destroy. Fixes rdar://124362085.
For years, optimizer engineers have been hitting a common bug caused by passes
assuming all SILValues have a parent function only to be surprised by SILUndef.
Generally we see SILUndef not that often so we see this come up later in
testing. This patch eliminates that problem by making SILUndef uniqued at the
function level instead of the module level. This ensures that it makes sense for
SILUndef to have a parent function, eliminating this possibility since we can
define an API to get its parent function.
rdar://123484595
We do this by pushing the conversion down to the emission of the
closure expression, then teaching closure emission to apply the isolation
to the closure. Ideally, we combine the isolation along with the rest of
the conversion peephole, but if necessary, we make sure we emit the
isolation.
a closure expression, then don't actually do it. The long term plan is
to actually do this, which should just be a matter of taking some of the
code out of reabstraction thunk emission and using it in prolog/epilog/return
emission. In the short term, the goal is just to get the conversion
information down to the closure emitter so that we can see that we're
erasing into an `@isolated(any)` type and then actually erase the
closure's isolation properly instead of relying on type-based erasure,
which can't handle parameter/capture isolation correctly.
The prolog and epilog code in SILGen is not set up to deal with
abstraction differences in the thrown error type of closures, so disable
the peephole optimization for closure literals.
Fixes https://github.com/apple/swift/issues/71401 / rdar://122366566,
which I've stared at for waaaaay too many hours.
In preparation for inserting mark_dependence instructions for lifetime
dependencies early, immediately after SILGen. That will simplify the
implementation of borrowed arguments.
Marking them unresolved is needed to make OSSA verification
conservative until lifetime dependence diagnostics runs.
Decls with a package access level are currently set to public SIL
linkages. This limits the ability to have more fine-grained control
and optimize around resilience and serialization.
This PR introduces a separate SIL linkage and FormalLinkage for
package decls, pipes them down to IRGen, and updates linkage checks
at call sites to include package linkage.
Resolves rdar://121409846
The thunk is a reabstraction thunk with a custom prolog that
has a runtime precondition check that makes sure that concurrent
environment where the thunk is run matches that of a global
actor associated with the thunked type.
To be used in situations when a global actor isolation is stripped
from a function type in argument positions and could be extended in
the future to cover more if needed.
This models the conversion from an uninhabited
value to any type, and allows us to get rid of
a couple of places where we'd attempt to drop
the return statement instead.
Allow the use of typed throws for the main functions of `@main` types,
and thread the thrown error through to a new entry point in the library,
`_errorInMainTyped`, which is generic in the thrown error type.
Fixes rdar://121603043.
Introduce a new expression macro that produces an value of type
`(any AnyActor)?` that describes the current actor isolation. This
isolation will be `nil` in non-isolated code, and refer to either the
actor instance of shared global actor in other cases.
This is currently behind the experimental feature flag
OptionalIsolatedParameters.
Optionally, the dependency to the initialization of the global can be specified with a dependency token `depends_on <token>`.
This is usually a `builtin "once"` which calls the initializer for the global variable.
The dependent 'value' may be marked 'nonescaping', which guarantees that the
lifetime dependence is statically enforceable. In this case, the compiler
must be able to follow all values forwarded from the dependent 'value', and
recognize all final (non-forwarded, non-escaping) use points. This implies
that `findPointerEscape` is false. A diagnostic pass checks that the
incoming SIL to verify that these use points are all initially within the
'base' lifetime. Regular 'mark_dependence' semantics ensure that
optimizations cannot violate the lifetime dependence after diagnostics.
Prior to this patch, a "guard let" was being lowered with an implicit debug
location, causing it to be dropped in later stages of the compiler, and making
it impossible to set a breakpoint in that line.
This was tracked down to a piece of code in `SILGenFunction::emitExprInto`,
which takes an optional Location parameter that was being ignored in one code
path.
Values produced by address-only `enum` instructions have non-none
ownership. And because `enum` is representation-changing, they have
`owned` ownership.
This corresponds at the opaque values SIL stage to the fact that at the
address-lowered SIL stage the storage location has non-trivial
initialization which must be `destroy_addr`d, regardless of whether an
empty case was stored to it.
This fixes use-after-free miscompilation bugs that can occur when a
lifetime-optimized standard library type, like Dictionary or String is
converted to an UnsafePointer using implicit inout-to-pointer
conversion:
func ptrToDictionary(_: UnsafePointer<Dictionary<K, V>>) {}
func testDictionary() {
var d: Dictionary = ...
ptrToDictionary(&d)
}
func ptrToString(_: UnsafePointer<String>) {}
func testString() {
var s: String = ...
ptrToString(&s)
}
Address to pointer conversion must always be guarded by either a
mark_dependence or a fix_lifetime. Use fix_lifetime for call emission
in SILGen to limit the optimization impact to the narrow scope of the
pointer conversion.
This could negatively impact performance simply because SIL does not
provide a way to scope pointer conversion. fix_lifetime is
unnecessarilly conservative and prevents the elimination of dead
allocations.
rdar://117807309 (Fix SILGen to emit fix_lifetime for
inout-to-pointer conversion)
Add the thrown type into the AST representation of function types,
mapping from function type representations and declarations into the
appropriate thrown type. Add tests for serialization, printing, and
basic equivalence of function types that have thrown errors.
KeyPath's getter/setter/hash/equals functions have their own calling
convention, which receives generic arguments and embedded indices from a
given KeyPath argument buffer.
The convention was previously implemented by:
1. Accepting an argument buffer as an UnsafeRawPointer and casting it to
indices tuple pointer in SIL.
2. Bind generic arguments info from the given argument buffer while emitting
prologue in IRGen by creating a new forwarding thunk.
This 2-phase lowering approach was not ideal, as it blocked KeyPath
projection optimization [^1], and also required having a target arch
specific signature lowering logic in SIL-level [^2].
This patch centralizes the KeyPath accessor calling convention logic to
IRGen, by introducing `@convention(keypath_accessor_XXX)` convention in
SIL and lowering it in IRGen. This change unblocks the KeyPath projection
optimization while capturing subscript indices, and also makes it easier
to support WebAssembly target.
[^1]: https://github.com/apple/swift/pull/28799
[^2]: https://forums.swift.org/t/wasm-support/16087/21
The problem was that in the by-address emission, we were calling
`getAddressForInPlaceInitialization` twice, triggering the assert.
The first time in `emitExprInto` for the normal result case.
The second time to obtain the address again when generating the
catch block to inject a `.none` into that same address.
This patch does a light refactoring to more closely mirror
`visitOptionalEvaluationExpr`, which avoids calling the asserting method.
fixes rdar://80277465
These allow multi-statement `if`/`switch` expression
branches that can produce a value at the end by
saying `then <expr>`. This is gated behind
`-enable-experimental-feature ThenStatements`
pending evolution discussion.
I was originally hoping to reuse mark_must_check for multiple types of checkers.
In practice, this is not what happened... so giving it a name specifically to do
with non copyable types makes more sense and makes the code clearer.
Just a pure rename.