For performance annotations we need the generic specializer to trop non-generic metatype argumentrs
(which we don't do in general). For this we need a separate mangling.
The fix here is two-fold:
1) Teach SILGen that it cannot use the scalar casting paths for extended existentials
2) Teach the runtime casting entrypoint to unwrap as much metatype structure as possible
before arriving at a 'Self' type bound for the requirement checking paths.
The code here mirrors the destructuring check we're doing in remote mirrors.
rdar://95166916
These instructions have the following attributes:
1. copyably_to_moveonlywrapper takes in a 'T' and maps it to a '@moveOnly
T'. This is semantically used when initializing a new moveOnly binding from a
copyable value. It semantically destroys its input @owned value and returns a
brand new independent @owned @moveOnly value. It also is used to convert a
trivial copyable value with type 'Trivial' into an owned non-trivial value of
type '@moveOnly Trivial'. If one thinks of '@moveOnly' as a monad, this is how
one injects a copyable value into the move only space.
2. moveonlywrapper_to_copyable takes in a '@moveOnly T' and produces a new 'T'
value. This is a 'forwarding' instruction where at parse time, we only allow for
one to choose it to be [owned] or [guaranteed].
* moveonlywrapper_to_copyable [owned] is used to signal the end of lifetime of
the '@moveOnly' wrapper. SILGen inserts these when ever a move only value has
its ownership passed to a situation where a copyable value is needed. Since it
is consuming, we know that the no implicit copy checker will ensure that if we
need a copy for it, the program will emit a diagnostic.
* moveonlywrapper_to_copyable [guaranteed] is used to pass a @moveOnly T value
as a copyable guaranteed parameter with type 'T' to a function. In the case of
using no-implicit-copy checking this is always fine since no-implicit-copy is a
local pattern. This would be an error when performing no escape
checking. Importantly, this instruction also is where in the case of an
@moveOnly trivial type, we convert from the non-trivial representation to the
trivial representation.
Some important notes:
1. In a forthcoming commit, I am going to rebase the no implicit copy checker on
top of these instructions. By using '@moveOnly' in the type system, we can
ensure that later in the SIL pipeline, we can have optimizations easily ignore
the code.
2. Be aware of is that due to SILGen only emitting '@moveOnly T' along immediate
accesses to the variable and always converts to a copyable representation when
calling other code, we can simply eliminate from the IR all moveonly-ness from
the IR using a lowering pass (that I am going to upstream). In the evil scheme
we are accomplishing here, we perform lowering of trivial values right after
ownership lowering and before diagnostics to simplify the pipeline.
On another note, I also fixed a few things in SILParsing around getASTType() vs
getRawASTType().
As we do with field indices for struct instructions.
This avoids quadratic behavior in case of enums with lots of cases.
Also: cache field and enum case indices in the SILModule.
* split the PassUtils.swift file into PassContext.swift and Passes.swift
* rework `Builder` bridging allowing more insertion point variations, e.g. inserting at the end of a block.
* add Builder.create functions for more instructions
* add `PassContext.splitBlock`
* move SIL modification functions from PassContext to extensions of the relevant types (e.g. instructions).
* rename `Location.bridgedLocation` -> `Location.bridged`
To visit the nodes of a type that is formed by repeated product
operations (struct and tuple), visitProductLeafAccessPathNodes is used.
The caller provides a TypeExpansionContext to this function.
Previously, though, visitProductLeafAccessPathNodes didn't respect the
TypeExpansionContext when visiting struct types. Specifically, it
looked through resilient structs to their fields. For a caller, such as
SSADestroyHoisting, that cares about the number of non-trivial nodes,
that is wrong--each resilient struct is a non-trivial node for its
purposes.
Here, this is corrected by having visitProductLeafAccessPathNodes
consider whether a struct type is resilient in the specified
TypeExpansionContext. Resilient structs are now correctly recognized as
leaf nodes and the caller-provided lambda is invoked with each.
rdar://92460184
Plug a hole in the semantics of deinitialization barriers.
Adds strong_copy_(unowned|unmanaged)_value to mayLoadWeakOrUnowned.
Deinitialization barriers includes loads from weak references.
Converting an unowned or unmanaged reference to a strong reference
is the moral equivalent.
Fixes rdar://90909833 (Extend deinit barriers to handle conversion to
strong reference)
When building a projection path we _must_ ignore zero-indexing projections so that alias analysis
recognizes an "alias" between two addresses where one has such an `index_addr 0` instruction and the other doesn't.
Added an AST helper in Types.h:
- isPotentiallyAnyObject()
This formalizes logic for when cast operations forward
ownership. Various OSSA optimization rely on this for
correctness. This fixes latent bugs throughout the optimizer.
I was compelled to fix this now because we want to make OSSA
optimizations across dynamic casts more aggressive. For example, we
want to optimize retain/release across enum formation.
Update cast feasibility analysis to take parameterized protocols into account. The cast classifier was used to being able to essentially just run `conformsToProtocol` on the existential type, but for parameterized protocol types this will ignore the extra requirements imposed by the argument clause. For now, route everything through the runtime.
Allow round-tripping access to global variables. Previously,
AccessedStorage asserted that global variables were always associated
with a VarDecl. This was to ensure that AccessEnforcmentWMO always
recognized the global. Failing to recognize access to a global will
cause a miscompile.
SILGlobalVariable now has all the information needed by
SIL. Particularly, the 'isLet' flag. Simply replace VarDecl with
SILGlobalVariable in AccessEnforcmentWMO to eliminate the need for the
assert.
The new "relative" version of AccessStorageWithBase carries additional
information about the walk from the specified address back to the base.
For now, that includes the original address and the most transformative
sort of cast that was encountered.
Added a function that visits the leaves of the type/projection tree of
the specified address and calls its visitor with the path node to and
type of each.
Unique storage use visitor was not previously considering end_apply and
abort_apply as uses of an address even when the begin_apply took that
address as an argument. They are uses of it though because the address
may be stored into the coroutine's frame and used when the second
partial function is invoked.
In the "next" branch, set_size has been made protected. Instead, users
can use resize_for_overwrite, optionally followed by truncate, to
handle the same use cases more safely.
The function mayAccessPointer is attempting to determine whether the
specified instruction accesses a raw/unsafe pointer of unknown
provenance. To do that, it visits all the address operands and checks
whether any of them have an ::Unidentified access representation kind.
Previously, the condition was inverted: all address uses _except_ those
whose kinds were unidentified were judged to be potential accessors to
raw/unsafe pointers. Here that's fixed by inverting the condition. To
help clarify things, the variable name is changed too.