Relax some existing pattern matches and add some unhandled instructions to the
walkers so that borrowing switches over address-only enums are properly analyzed
for incorrect consumption. Add a `[strict]` flag to `mark_unresolved_move_only_value`
to indicate a borrow access that should remain a borrow access even if the subject
is later stack-promoted from a box.
Previously, `visitProductLeafAccessPathNodes` required its caller to
provide both an `AccessPath` `path` and an `SILValue` `address` which
satisfied `path == AccessPath::compute(address)` to force the caller to
handle the case of an invalid `AccessPath`. Now, instead, it computes
the value itself and returns false if it's invalid.
It could be tweaked to also return false if the provided lambda returned
false but that would make the only currently extant callers less
pleasant and also would not be sufficient in the case of caller who
wanted to distinguish between an invalid `AccessPath` and a particular
leaf visit returning false.
A FunctionTest created in Swift source has no persistent storage
address. This results in sporadic crashes when running unit tests.
Fix the FunctionTest registry to store the value of the test.
Eventually, we could probably rig something up with @_rawLayout, but
it makes more sense for FunctionTest to be a value type anyway.
We have no guarantee that the StringRef passed to the registry lives
in the static data segment.
This resulted in memory corruption during bootstrapping, which is
particularly difficult to diagnose and reproduce.
Concurrency runtime expects discarding task operation entrypoint
function not to have result type, but the current SILGen
implementation generates reabstraction thunk to convert `() -> Void`
to `() -> T` for the operation function.
Since the `T` is always `Void` for DiscardingTG, the mismatch of result
type expectation does not cause any problem on most platforms, but the
signature mismatch causes a problem on WebAssembly.
This patch introduces new builtin operations for creating discarding
task, which always takes `() -> Void` as the operation function type.
An instruction is a deinit barrier whenever one of three component
predicates is true for it. In the case of applies, it is true whenever
one of those three predicates is true for any of the instructions in any
of its callees; that fact is cached in the side-effect analysis of every
function.
If side-effect analysis or callee analysis is unavailable, in order to
define each of those three component predicates on a
`FullApplySite`/`EndApplyInst`/`AbortApplyInst`, it would be necessary
to define them to conservatively return true: it isn't known whether any
of the instructions in any of the callees were deinit barriers.
Refactored the two versions of the deinit barrier predicate (namely
`Instruction.isDeinitBarrier(_:) and
`swift::mayBeDeinitBarrierNotConsideringSideEffects`) to handle
`FullApplySite`/`EndApplyInst`/`AbortApplyInst`s specially first (to
look up the callees' side-effect and to conservatively bail,
respectively). Asserted that the three component predicates are not
called with `FullApplySite`/`EndApplyInst`/`AbortApplyInst`s. Callers
should instead use the `isDeinitBarrier` APIs.
An alternative would be to conservatively return true from the three
components. That seems more likely to result in direct calls to these
member predicates, however, and at the moment at least there is no
reason for such calls to exist. If some other caller besides the
deinit-barrier predicates needs to call this function, side-effect
analysis should be updated to cache these three properties separately at
that point.
When an instruction `mayReadOrWriteMemory`, the `mayAccessPointer`
predicate relies on the `visitAccessedAddress` utility to determine
whether an instruction may access a pointer. That utility doesn't (and
can't, without changing the representation of the builtin) visit
`RawPointer` operands as used by memmove/memcpy builtins.
Previously, this resulted `mayAccessPointer` returning `false` for such
builtins. Here, this is fixed by making the predicate handle
`BuiltinInsts` separately. Instead of just always returning `true` in
the face of a builtin, rely on the BuiltinInfo associated with a
BuiltinInst and use `mayReadOrWriteMemory`.
rdar://120656227
* `alloc_vector`: allocates an uninitialized vector of elements on the stack or in a statically initialized global
* `vector`: creates an initialized vector in a statically initialized global
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
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
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.