Skip to content

Commit 1b1972c

Browse files
committed
[SIL] All lexical arguments are lexical.
Previously, only @owned function arguments were treated as lexical. Here, all function arguments which report themselves to be lexical (i.e. based on their type and annotation) are regarded as lexical.
1 parent cfa0d63 commit 1b1972c

File tree

2 files changed

+39
-20
lines changed

2 files changed

+39
-20
lines changed

docs/SIL.rst

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2414,27 +2414,49 @@ Variable Lifetimes
24142414
In order for programmer intended lifetimes to be maintained under optimization,
24152415
the lifetimes of SIL values which correspond to named source-level values can
24162416
only be modified in limited ways. Generally, the behavior is that the lifetime
2417-
of a named source-level value cannot _observably_ end before the end of the
2418-
lexical scope in which that value is defined. Specifically, code motion may
2419-
not move the ends of these lifetimes across a **deinit barrier**.
2420-
2421-
A few sorts of SIL value have lifetimes that are constrained that way:
2417+
of a named source-level value is anchored to the variable's lexical scope and
2418+
confined by **deinit barriers**. Specifically, code motion may not move the
2419+
ends of these lifetimes across a deinit barrier.
2420+
2421+
Source level variables (lets, vars, ...) and function arguments will result in
2422+
SIL-level lexical lifetimes if either of the two sets of circumstances apply:
2423+
(1) Inferred lexicality.
2424+
- the type is non-trivial
2425+
- the type is not eager-move
2426+
- the variable or argument is not annotated to be eager-move
2427+
OR
2428+
(2) Explicit lexicality.
2429+
- the type, variable, or argument is annotated `@_lexical`
2430+
2431+
A type is eager-move by satisfying one of two conditions:
2432+
(1) Inferred: An aggregate is inferred to be eager-move if all of its fields are
2433+
eager-move.
2434+
(2) Annotated: Any type can be eager-move if it is annotated with an attribute
2435+
that explicitly specifies it to be: `@_eagerMove`, `@_noImplicitCopy`.
2436+
2437+
A variable or argument is eager-move by satisfying one of two conditions:
2438+
(1) Inferred: Its type is eager-move.
2439+
(2) Annotated: The variable or argument is annotated with an attribute that
2440+
specifies it to be: `@_eagerMove`, `@_noImplicitCopy`.
2441+
2442+
These source-level rules result in a few sorts of SIL value whose destroys must
2443+
not be moved across deinit barriers:
24222444

24232445
1: `begin_borrow [lexical]`
24242446
2: `move_value [lexical]`
2425-
3: @owned function arguments
2447+
3: function arguments
24262448
4: `alloc_stack [lexical]`
24272449

2428-
That these three have constrained lifetimes is encoded in ValueBase::isLexical,
2429-
which should be checked before changing the lifetime of a value.
2450+
To translate from the source-level representation of lexicality to the
2451+
SIL-level representation, for source-level variables (vars, lets, ...) SILGen
2452+
generates `begin_borrow [lexical]`, `move_value [lexical]`, `alloc_stack
2453+
[lexical]` . For function arguments, there is no work to do:
2454+
a `SILFunctionArgument` itself can be lexical
2455+
(`SILFunctionArgument::isLexical`).
24302456

2431-
The reason that only @owned function arguments are constrained is that a
2432-
@guaranteed function argument is guaranteed by the function's caller to live for
2433-
the full duration of the function already. Optimization of the function alone
2434-
can't shorten it. When such a function is inlined into its caller, though, a
2435-
lexical borrow scope is added for each of its @guaranteed arguments, ensuring
2436-
that the lifetime of the corresponding source-level value is not shortened in a
2437-
way that doesn't respect deinit barriers.
2457+
That the first three have constrained lifetimes is encoded in
2458+
ValueBase::isLexical, which should be checked before changing the lifetime of a
2459+
value.
24382460

24392461
Unlike the other sorts, `alloc_stack [lexical]` isn't a SILValue. Instead, it
24402462
constrains the lifetime of an addressable variable. Since the constraint is

lib/SIL/IR/SILValue.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,8 @@ ValueBase::getDefiningInstructionResult() {
116116
}
117117

118118
bool ValueBase::isLexical() const {
119-
if (auto *argument = dyn_cast<SILFunctionArgument>(this)) {
120-
// TODO: Recognize guaranteed arguments as lexical too.
121-
return argument->getOwnershipKind() == OwnershipKind::Owned &&
122-
argument->getLifetime().isLexical();
123-
}
119+
if (auto *argument = dyn_cast<SILFunctionArgument>(this))
120+
return argument->getLifetime().isLexical();
124121
if (auto *bbi = dyn_cast<BeginBorrowInst>(this))
125122
return bbi->isLexical();
126123
if (auto *mvi = dyn_cast<MoveValueInst>(this))

0 commit comments

Comments
 (0)