Instead of taking a setter type, let's switch over to a more general
`AccessorKind` which allows us to cover init accessors and simplify
`emitApplySetterToBase`.
This is a preliminary step towards enabling default initialization of
init accessor properties in user-defined initializers because this logic
would have to be shared by multiple places during SILGen.
`Initialization` is stateful and not meant to be emitted into multiple times across different contexts.
If emitting into an initialization causes it to be split or aborted, that will carry over into
further uses of the initialization. This was happening during `if` and `switch` expression
emission, leading to miscompiles or compiler crashes. Fix this by saving only the buffer when
we prepare emission for a statement expression, and creating the initialization in the scope
where the expression for a branch actually gets emitted. Fixes rdar://112213253.
Reformatting everything now that we have `llvm` namespaces. I've
separated this from the main commit to help manage merge-conflicts and
for making it a bit easier to read the mega-patch.
This is phase-1 of switching from llvm::Optional to std::optional in the
next rebranch. llvm::Optional was removed from upstream LLVM, so we need
to migrate off rather soon. On Darwin, std::optional, and llvm::Optional
have the same layout, so we don't need to be as concerned about ABI
beyond the name mangling. `llvm::Optional` is only returned from one
function in
```
getStandardTypeSubst(StringRef TypeName,
bool allowConcurrencyManglings);
```
It's the return value, so it should not impact the mangling of the
function, and the layout is the same as `std::optional`, so it should be
mostly okay. This function doesn't appear to have users, and the ABI was
already broken 2 years ago for concurrency and no one seemed to notice
so this should be "okay".
I'm doing the migration incrementally so that folks working on main can
cherry-pick back to the release/5.9 branch. Once 5.9 is done and locked
away, then we can go through and finish the replacement. Since `None`
and `Optional` show up in contexts where they are not `llvm::None` and
`llvm::Optional`, I'm preparing the work now by going through and
removing the namespace unwrapping and making the `llvm` namespace
explicit. This should make it fairly mechanical to go through and
replace llvm::Optional with std::optional, and llvm::None with
std::nullopt. It's also a change that can be brought onto the
release/5.9 with minimal impact. This should be an NFC change.
drop_deinit ultimately only affects the semantics of its
destroy_value. Avoid generating releases for destroys in which the
deinit has been dropped. Instead, individually release the members.
The previous code made the assumption that the ASTScope for a variable
declaration should be the one of the declaration's source location. That is not
necessarily the case, in some cases it should be an ancestor scope. This patch
introduces a map from ValueDecl -> ASTScope that is derived from querying each
ASTScope for its locals, which matches also what happens in name lookup. This
patch also fixes the nesting of SILDebugScopes created for guard statement
bodies, which are incorrectly nested in the ASTScope hierarchy.
rdar://108940570
When `-unavailable-decl-optimization=stub` is specified, insert a call to
`_diagnoseUnavailableCodeReached()` at the beginning of the function to cause
it to trap if executed at run time.
Part of rdar://107388493
Before this patch the parents of SILDebugScopes representing macro expansions
were missing the inlinedAt field, which resulted in incorrent LLVM IR being
produced. This is fixed by first computing the inlined call site for a macro
expansion and then computing the nested SILDebugScope for the ASTScope of the
expanded nodes; adding the inlinedAt field to all of levels of parent scopes.
rdar://108323748
This patch replaces the stateful generation of SILScope information in
SILGenFunction with data derived from the ASTScope hierarchy, which should be
100% in sync with the scopes needed for local variables. The goal is to
eliminate the surprising effects that the stack of cleanup operations can have
on the current state of SILBuilder leading to a fully deterministic (in the
sense of: predictible by a human) association of SILDebugScopes with
SILInstructions. The patch also eliminates the need to many workarounds. There
are still some accomodations for several Sema transformation passes such as
ResultBuilders, which don't correctly update the source locations when moving
around nodes. If these were implemented as macros, this problem would disappear.
This necessary rewrite of the macro scope handling included in this patch also
adds proper support nested macro expansions.
This fixes
rdar://88274783
and either fixes or at least partially addresses the following:
rdar://89252827
rdar://105186946
rdar://105757810
rdar://105997826
rdar://105102288
Code can only locally interact with a mutable memory location within a
formal access, and is only responsible for maintaining its invariants
during that access, so the move-only address checker does not need to,
and should not, observe operations that occur outside of the access
marked with the `mark_must_check` instruction. And for immutable
memory locations, although there are no explicit formal accesses, that's
because every access must be read-only, so although individual
accesses are not delimited, they are all compatible as far as
move-only checking is concerned. So we can back out the changes to SILGen
to re-project a memory location from its origin on every access, a
change which breaks invariants assumed by other SIL passes.
This adds an assertion that we're using all of the parameters, so
pass prolog emission the number of lowered parameters to ignore.
That's easy for the callers to provide, since they do actually
still need to add function arguments for those parameters.
This is largely a matter of changing the main loop over subst
params in TranslateArguments to use the generators I added,
then plugging back into the general reabstraction infrastructure.
Because we don't have pack coroutines, we're kind of stuck in
the code generation for pack reabstraction: we have to write
+1 r-values into a temporary tuple and then write those tuple
element addresses into the output pack. It's not great. We
also have lifetime problems with things like non-escaping
closures --- we have that problem outside of reabstraction
thunks, too.
Other than that glaring problem, I'm feeling relatively good
about the code here. It's missing some peepholes, but it should
work. But that that's not to say that arity reabstraction works
in general; my attempts to test it have been exposing some
problems elsewhere, and in particular the closure case crashes,
which is really bad. But this gets a few more things working,
and this PR is quite large already.
The subexpression of a MaterializePackExpr (which is always a tuple value
currently) is emitted while preparing to emit a pack expansion expr, and its
elements are projected from within the dynamic pack loop. This means that a
materialized pack is only evaluated once, rather than being evaluated on
every iteration over the pack elements.
More missing infrastructure. In this case, it's really *existing*
missing infrastructure, though; we should have been imploding tuples
this way all along, given that we're doing it in the first place.
I don't like that we're doing all these extra tuple copies. I'm not
sure yet if they're just coming out of SILGen and eliminated immediately
after in practice; maybe so. Still, it should be obvious that they're
unnecessary.
Allow freestanding macros to be used at top-level.
- Parse top-level `#…` as `MacroExpansionDecl` when we are not in scripting mode.
- Add macro expansion decls to the source lookup cache with name-driven lazy expansion. Not supporting arbitrary name yet.
- Experimental support for script mode and brace-level declaration macro expansions: When type-checking a `MacroExpansionExpr`, assign it a substitute `MacroExpansionDecl` if the macro reference resolves to a declaration macro. This doesn’t work quite fully yet and will be enabled in a future fix.
This required quite a bit of infrastructure for emitting this kind of
tuple expression, although I'm not going to claim they really work yet;
in particular, I know the RValue constructor is going to try to explode
them, which it really shouldn't.
It also doesn't include the caller side of returns, for which I'll need
to teach ResultPlan to do the new abstraction-pattern walk. But that's
next.
This is the first slice of bringing up escaping closure support. The support is
based around introducing a new type of SILGen VarLoc: a VarLoc with a box and
without a value. Because the VarLoc only has a box, we have to in SILGen always
eagerly reproject out the address from the box. The reason why I am doing this
is that it makes it easy for the move checker to distinguish in between
different accesses to the box that we want to check separately. As such every
time that we open the box, we insert a mark_must_check
[assignable_but_not_consumable] on that project. If allocbox_to_stack manages to
determine that the box can be stack allocated, we eliminate all of the
mark_must_check and place a new mark_must_check [consumable_and_assignable] on
the alloc_stack. The end result is that we get the old model that we had before
and also can support escaping closures.
Consider the following example:
```
class Klass {}
@_moveOnly struct Butt {
var k = Klass()
}
func mixedUse(_: inout Butt, _: __owned Butt) {}
func foo() {
var y = Butt()
mixedUse(&y, y)
}
```
In this case, we want to have an exclusivity violation. Before this patch, we
did a by-value load [copy] of y and then performed the inout access. Since the
access scopes did not overlap, we would not get an exclusivity violation.
Additionally, since the checker assumes that exclusivity violations will be
caught in such a situation, we convert the load [copy] to a load [take] causing
a later memory lifetime violation as seen in the following SIL:
```
sil hidden [ossa] @$s4test3fooyyF : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack [lexical] $Butt, var, name "y" // users: %4, %5, %8, %12, %13
%1 = metatype $@thin Butt.Type // user: %3
// function_ref Butt.init()
%2 = function_ref @$s4test4ButtVACycfC : $@convention(method) (@thin Butt.Type) -> @owned Butt // user: %3
%3 = apply %2(%1) : $@convention(method) (@thin Butt.Type) -> @owned Butt // user: %4
store %3 to [init] %0 : $*Butt // id: %4
%5 = begin_access [modify] [static] %0 : $*Butt // users: %7, %6
%6 = load [take] %5 : $*Butt // user: %10 // <————————— This was a load [copy].
end_access %5 : $*Butt // id: %7
%8 = begin_access [modify] [static] %0 : $*Butt // users: %11, %10
// function_ref mixedUse2(_:_:)
%9 = function_ref @$s4test9mixedUse2yyAA4ButtVz_ADntF : $@convention(thin) (@inout Butt, @owned Butt) -> () // user: %10
%10 = apply %9(%8, %6) : $@convention(thin) (@inout Butt, @owned Butt) -> ()
end_access %8 : $*Butt // id: %11
destroy_addr %0 : $*Butt // id: %12
dealloc_stack %0 : $*Butt // id: %13
%14 = tuple () // user: %15
return %14 : $() // id: %15
} // end sil function '$s4test3fooyyF'
```
Now, instead we create a [consume] access and get the nice exclusivity error we
are looking for.
NOTE: As part of this I needed to tweak the verifier so that [deinit] accesses
are now allowed to have any form of access enforcement before we are in
LoweredSIL. I left in the original verifier error in LoweredSIL and additionally
left in the original error in IRGen. The reason why I am doing this is that I
need the deinit access to represent semantically what consuming from a
ref_element_addr, global, or escaping mutable var look like at the SIL level so
that the move checker can error upon it. Since we will error upon such
consumptions in Canonical SIL, such code patterns will never actually hit
Lowered/IRGen SIL, so it is safe to do so (and the verifier/errors will help us
if we make any mistakes). In the case of a non-escaping var though, we will be
able to use deinit statically and the move checker will make sure that it is not
reused before it is reinitialized.
rdar://101767439
Introduce SingleValueStmtExpr, which allows the
embedding of a statement in an expression context.
This then allows us to parse and type-check `if`
and `switch` statements as expressions, gated
behind the `IfSwitchExpression` experimental
feature for now. In the future,
SingleValueStmtExpr could also be used for e.g
`do` expressions.
For now, only single expression branches are
supported for producing a value from an
`if`/`switch` expression, and each branch is
type-checked independently. A multi-statement
branch may only appear if it ends with a `throw`,
and it may not `break`, `continue`, or `return`.
The placement of `if`/`switch` expressions is also
currently limited by a syntactic use diagnostic.
Currently they're only allowed in bindings,
assignments, throws, and returns. But this could
be lifted in the future if desired.
If a function body references a declaration with the `@_backDeploy(before:)` attribute and that function body will only execute on deployment targets for which the ABI version of the decl is available then it is unnecessary to thunk the reference to the decl. Function bodies that may be emitted into other modules (e.g. `@inlinable`) must always use the thunk.
Resolves rdar://90729799
This ensures that if we try to escape self or assign it to a variable, we
error since at the end of the deinit we always consume self and clean up its
variables.
I did not handle unique classes since it would have required a bit more surgery
around how deinits are handled and we do not need unique classes for our MVP.
rdar://102339259
For now this just wraps an ASTNode, but in the
future it will allow us to model counters
that cannot simply hang off ASTNodes, e.g
error branch counters.
Even though with this change we emit the deinit, it isn't used yet since we
still need to implement the move only deinit table/teach the checker how to call
these/teach IRGen how to call this from the destroying value witness.
The generalized ActorIsolation is enough to represent everything that
ImplicitActorHopTarget can do, and we were mapping between the two way
too often, so collapse them.
This change ensures all store_borrows are ended with an end_borrow, and uses of the store_borrow
destination are all in the enclosing store_borrow scope and via the store_borrow return address.
Fix tests to reflect new store_borrow pattern
When emitting a call to the getter for storage, emit the actor hop (and
hop back) as part of the call itself, rather than around the whole
initialization. This address a bug involving initialization with an
optional binding in an `if let`, where the hop-back would only be
performed on the non-nil branch.
Fixes rdar://96487805 / FB10562197