Previously we were walking into the
PropertyWrapperValuePlaceholderExpr when generating
coverage for a property wrapper backing initializer.
This meant that we were duplicating the coverage of
the initializer expression, and it could cause
crashes if a refined counter was introduced within
the top-most expression region, such as with a
throwing expression in a `try!`.
rdar://118939162
This accidentally started happening when I adjusted getEffectiveAccess to return `Public` for `Package` declarations in #69709. As a result, the optimizer thought it had more opportunities to go after declarations that used to be opaque. Unfortunately, this resulted in a miscompile as the devirtualizer was able to look through now-serialized package (static) functions. In one specific instance, the optimizer created direct calls to hidden accessors instead of going through the dispatch thunk.
To do this I used 8 spare bits in the pointers in Operand for the custom flags.
The reason I did this is just like one sometimes wants to iterate and use
sets/worklists with Nodes/Blocks, one often wants to do it with operands
especially in situations where one wants to know a using instruction and the
value on the instruction that was used.
Previously we would ignore the effect that an if
statement or ternary's condition exit counter might
have on its branches, as we assumed a condition
can't do any control flow. However, in the case
where the condition throws an error, we need to
account for the error branch.
Ensure that `try?` expressions appropriately
scope the regions generated by child
error-throwing expressions, such that the
non-error branch does not extend beyond the region
of the `try?`.
Previously the branches of a ternary would cut off
the coverage after a throwing expression, since
they have their own region, and we pop child
regions when leaving. Update the logic to use the
existing counter adjustment logic when we leave
the scope, ensuring that we push a new counter to
reflect the exit count of the scope.
`getRootLocalArchetypeDef()` may return a `PlaceholderValue` which makes the
`cast<SingleValueInstruction>` invalid. Use `dyn_cast` and then update the
callers of `getRootLocalArchetypeDefInst()` to handle `nullptr`.
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 class is more or less just duplicating LLVM's
`Counter` class, as such we can just wrap it
directly and avoid having to construct it later.
This is a tentative fix for rdar://118185163 since
it eliminates the code in question, though I still
want to investigate that issue further.
The logic here previously worked by computing the
exit count by taking the parent count and
subtracting any control flow that jumped out of the
clauses. With `try` handling fixed, this no longer
works correctly, since a `try` shouldn't be
subtracted if the error is caught be one of the
catches, as that's not actually leaving the
statement. We could write the logic to determine
where a `try` is jumping to, but the logic here is
already pretty brittle, relying on being sprinkled
in various different places.
For now, let's take the more straightforward
approach and handle do-catches the same way we
handle switches, we initialize the exit counter to
0, and add on each exit count of each branch. This
lets us re-use the existing CaseStmt handling
logic. This doesn't necessarily produce the most
optimal counter expressions, but I want to replace
this all with a SILOptimizer pass anyway, which
will be able to much more easily compute optimal
counter expressions.
rdar://100470244
We can terminate all the regions up to the last
AST node in the stack, since regions without AST
nodes are refinements of the region with the AST
node, and should be terminated the same. This
avoids leaving some regions that extend past e.g
the `return` of a function.
The region in the test case that changes here is:
```
[[@LINE+9]]:28 -> [[@LINE+12]]:4 : (0 - 1)
```
this was extending past the return. Now it is:
```
[[@LINE]]:6 -> [[@LINE+4]]:11 : (0 - 1)
```
Apologies, I also refactored the test case at the
same time which makes the difference harder to see,
but the main point is that this region now terminates
at the return, the same as the others.
Avoid heap-allocating an immortal FunctionTest with `new` because it
results in LSAN reporting a leak.
In fact, the "leaked" value wasn't leaked: a reference to it was stored
in a global map when the type's constructor ran. It was only a leak in
the sense that it was never freed, not that there was a dangling
allocation which couldn't be freed.
Work around this by storing the global instances themselves in a second
static structure. Store pointers to the instances into the global map
as before.
rdar://118134637
For any `#if` blocks in the function we're emitting,
emit skipped ranges for the inactive clauses, including
the syntax for the `#if` itself, since that should
not be considered executable code.
rdar://116860865
The access path verification optimizer pass calls
`getStaticallyInitializedVariable()`, which was written assuming that the given
`SILFunction` would always have a valid return basic block. When the
`-unavailable-decl-optimization=stub` option is passed to the frontend, though,
any function generated for a declaration marked `@available(*, unavailable)` is
rewritten to trap by calling a function that returns `Never`. Therefore the
rewritten functions do not have return blocks and passing these functions to
`getStaticallyInitializedVariable()` would result in the compiler invoking
undefined behavior.
Resolves rdar://118281508
Adjust `SILFunctionBuilder` to allow distinct non-custom effects and to
interpret such "conflicting" guarantees to provide the strongest
guarantee. For example, annotating a function both `@_effects(readnone)`
and `@_effects(releasenone)` is equivalent to only annotating it
`@_effects(readnone)`.
First step to reapplying https://github.com/apple/swift/pull/68285 .
rdar://118216287
This peephole optimization in SILGen requires us to use the thrown
error for the context of a closure type rather than the thrown error
for the closure AST node itself.
I also included changes to the rest of the SIL optimizer pipeline to ensure that
the part of the optimizer pipeline before we lower tuple_addr_constructor (which
is right after we run TransferNonSendable) work as before.
The reason why I am doing this is that this ensures that diagnostic passes can
tell the difference in between:
```
x = (a, b, c)
```
and
```
x.0 = a
x.1 = b
x.2 = c
```
This is important for things like TransferNonSendable where assigning over the
entire tuple element is treated differently from if one were to initialize it in
pieces using projections.
rdar://117880194
Introduce SILGen support for reabstractions thunks that change the
error, between indirect and direct errors as well as conversions
amongst error types (e.g., from concrete to `any Error`).
This commit just introduces the instruction. In a subsequent commit, I am going
to add support to SILGen to emit this. This ensures that when we assign into a
tuple var we initialize it with one instruction instead of doing it in pieces.
The problem with doing it in pieces is that when one is emitting diagnostics it
looks semantically like SILGen actually is emitting code for initializing in
pieces which could be an error.
Unlike in regular swift, The class_method instruction references the specialized version of a class method.
This must be handled in ReabstractionInfo: it needs to work without a concrete callee SIL function.
Also, the SILVerifier must handle the case that a class_method instruction references a specialized method.