We cannot use spare bits or other overlapping storage layout tricks with fundamentally
address-only enums, and we can take advantage of this to do borrowing switches or other
in-place projections without copying the value. However, for resilient enums, the
implementation may use spare bit packing, but the type must be handled address-only
outside of its defining module, and we didn't have a way to express that with
borrowing switch. Optimization passes have also been running into problems with the
complexity that we were using `unchecked_take_enum_data_addr` sometimes as a pure
operation. This patch splits the instruction into three:
- `unchecked_inplace_enum_data_addr` represents a nondestructive in-place enum
projection. It is only allowed for enums whose projection operation is
nondestructive.
- `unchecked_take_enum_data_addr` represents a destructive enum projection,
invalidating the enum and leaving the payload to be further consumed.
This matches the current instruction's semantics.
- `unchecked_borrow_enum_data_addr` represents a borrowing enum projection.
The instruction takes a second operand for "scratch" space, which the
enum representation may be copied into in order to avoid invalidating the
enum value, so the result is dependent on the lifetime of both the
original enum and the scratch buffer. This allows for borrowing switches
over resilient enums.
`unchecked_borrow_enum_data_addr` is implemented by taking advantage of the
"address-only enums can't do spare bit optimization" property at runtime.
We inspect the operand type's bitwise-borrowability from its metadata. If
the type is bitwise-borrowable, then we are allowed to bitwise-copy the
enum to the scratch space and apply the projection to the scratch space,
preserving the original value. If the type is not bitwise-borrowable, then
we cannot use spare bit optimization in its layout, so we apply the
projection in-place.
Fixes rdar://174952822.
ForEach support for Borrowing sequence
For testing purposes, this commit includes _BorrowingSequence and _BorrowingIterator protocols, with conformance for Span and InlineArray.
This change adds an experimental feature 'LiteralExpressions` which allows for use of simple binary expressions of integer type composed of literal value operands.
For now, such literal expressions are only supported in initializers of '@section` values.
IsPattern coercions aren't properly implemented since they rely on
doing a runtime cast, which can fail for things like function subtyping.
Make clients choose what behavior they want. Unfortunately we need to
preserve the current behavior in places since it's relied upon for
things like exhaustivity checking. We ought to properly implement
coercion handling, then we should be able to remove this.
The reason I am doing this is that I want to be careful and make sure that we
can distinguish in between weak var and weak let var decls and real captures.
In the caller, we do not actually represent the capture's var decl information
in a meaningful way since the actual var decl usage is only in the closure.
After inlining, we get that var decl information from the debug_value of the
argument. So there isn't any reason not to do it and it will simplify the other
work I am doing.
This is necessary to correctly handle PGO for `for` loops with the
upcoming work that desugars them into `while` loops in the AST. We
still don't properly handle individual condition PGO counters so this
only supports single top-level refutable patterns for now.
We were creating the JumpDests too early, so lowering a 'break' or 'continue'
statement would perform cleanups that were recorded while evaluating the
pack expansion expression, which would cause SIL verifier errors and
runtime crashes.
- Fixes https://github.com/swiftlang/swift/issues/78598
- Fixes rdar://131847933
We already reject attempts to reference this for `lazy` properties.
For `lazy` locals let's just not expose it to name lookup to begin
with. This ensures we don't attempt to prematurely kick the interface
type computation for the var, fixing a couple of crashers.
These wrappers are detected by the move checking passes,
to support the implicit no-implicit-copy check for
parameters with ownership specifiers.
ManualOwnership already does this kind of checking, and the
two passes can interfere with each other, such as intercepting
diagnostics that are meant to be emitted by ManualOwnership.
We were not able to use an existential as the base
of an access that strictly borrows the existential,
because SILGen's RValue emission would establish
a fresh evaluation scope just for the existential's
opening, and then copy the opened value out.
This is problematic for noncopyable existentials.
So this patch moves & adds FormalEvaluationScope's
around so they're broad enough to enable a
borrow of an existential. The idea behind this
refactoring is to establish top-level
FormalEvaluationScopes when initially creating
RValue's for Expr's in SILGen. Any more-tightly
scoped operations will already establish their own
nested scope, so this is mostly adding safe-guards.
I've limited the existentials fix to noncopyables
for now.
part of rdar://159079818
There's no need for two separate types here. Fully separate the addressable buffer
tracking from VarLocs as well, in order to set up for a fix to addressable references
to `if let` and `guard let` bindings.
These get passed to the closure body in SIL as function arguments to the entry
point, so the alloc_stack necessarily has to appear inside of the value's lifetime,
and the store_borrow needs to be placed after that alloc_stack.
In order to accommodate case bodies with multiple case labels, the AST
represents the bindings in each pattern as a distinct declaration from
the matching binding in the case body, and SILGen shares the variable
representation between the two declarations. That means that the two
declarations also need to be able to share an addressable representation.
Add an "alias" state to the addressable buffer data structures so that
we can refer back to the original case label var decl when the case body
var decl is brought into scope, so that accesses through either decl
properly force the addressable representation.
Fixes rdar://154543619.
When generating SIL for an `if #available(SomeDomain)` query in code being
compiled for a zippered target, the generated code was mis-compiled if
`SomeDomain` were disabled at compile time. Empty version ranges need to be
handled explicitly by `SILGenFunction::emitZipperedOSVersionRangeCheck()`.
SILGen still miscompiles `if #unavailable` queries generally in code compiled
for a zippered target (rdar://147929876).
Resolves rdar://150888941.
Rather than representing a missing availability range on `PoundAvailableInfo`
with a default-constructed `AvailabilityRange` (empty), store the ranges as
optionals instead. This allows an empty range to represent an availability
condition which is known to be false at compile time, which will be necessary
when generating SIL for `if #available` queries that check custom availability
domains.
To ensure that dependent values have a persistent-enough memory representation
to point into, when an immutable binding is referenced as an addressable
argument to a call, have SILGen retroactively emit a stack allocation and
materialization that covers the binding's scope.
To ensure that dependent values have a persistent-enough memory representation
to point into, when an immutable binding is referenced as an addressable
argument to a call, have SILGen retroactively emit a stack allocation and
materialization that covers the binding's scope.
This assert was correctly catching the fact that `-target-variant` is not being
normalized at the same time as `-target` when building arm64e modules from
swiftinterface. That should be fixed, but at the moment it isn't causing any
concrete harm and the assertion fails when building against the SDKs included
with the latest Xcode 16 betas.
Resolves rdar://133020098.
Required for SIL analysis of local variable scopes. For example, to track
lifetime dependence on a variable.
Example:
.swift:
func foo(i: Int) {
let v = i
.sil:
%1 = move_value [var_decl] %0 : $Int // starts the variable scope
extend_lifetime %1 : $Int // ends the variable scope
Rewrite getValueForLexicalLifetimeBinding. The previous implementation was
incomprehensible to me. This will potentially change functionality by removing
previous corner cases that look like nonsense to me.
Adds an unfortunate FIXME to allow migration without affecting fake metatype
locals produced by function conversion!