Commit Graph

60 Commits

Author SHA1 Message Date
Nate Chandler
1eafced6a2 [AllocBoxToStack] Don't destroy in dead-ends.
It is valid to leak a value on paths into dead-end regions.
Specifically, it is valid to leak an `alloc_box`.  Thus, "final
releases" in dead-end regions may not destroy the box and consequently
may not release its contents.  Therefore it's invalid to lower such final
releases to `dealloc_stack`s, let alone `destroy_addr`s.  The in-general
invalidity of that transformation results in miscompiling whenever a box
is leaked and its projected address is used after such final releases.

Fix this by not treating final releases as boundary markers of the
`alloc_box` and not lowering them to `destroy_addr`s and
`dealloc_stack`s.

rdar://158149082
2025-08-27 17:03:48 -07:00
Erik Eckstein
6714a72256 Optimizer: re-implement and improve the AllocBoxToStack pass
This pass replaces `alloc_box` with `alloc_stack` if the box is not escaping.
The original implementation had some limitations. It could not handle cases of local functions which are called multiple times or even recursively, e.g.

```
public func foo() -> Int {
  var i = 1

  func localFunction() { i += 1 }

  localFunction()
  localFunction()
  return i
}

```

The new implementation (done in Swift) fixes this problem with a new algorithm.
It's not only more powerful, but also simpler: the new pass has less than half lines of code than the old pass.

The pass is invoked in the mandatory pipeline and later in the optimizer pipeline.
The new implementation provides a module-pass for the mandatory pipeline (whereas the "regular" pass is a function pass).
This is required because the mandatory pass needs to remove originals of specialized closures, which cannot be done from a function-pass.
In the old implementation this was done with a hack by adding a semantic attribute and deleting the function later in the pipeline.

I still kept the sources of the old pass for being able to bootstrap the compiler without a host compiler.

rdar://142756547
2025-06-20 08:15:04 +02:00
Erik Eckstein
7cceaff5f3 SIL: don't print operand types in textual SIL
Type annotations for instruction operands are omitted, e.g.

```
  %3 = struct $S(%1, %2)
```

Operand types are redundant anyway and were only used for sanity checking in the SIL parser.

But: operand types _are_ printed if the definition of the operand value was not printed yet.
This happens:

* if the block with the definition appears after the block where the operand's instruction is located

* if a block or instruction is printed in isolation, e.g. in a debugger

The old behavior can be restored with `-Xllvm -sil-print-types`.
This option is added to many existing test files which check for operand types in their check-lines.
2024-11-21 18:49:52 +01:00
Michael Gottesman
3236bc26fa [region-isolation] Refactor out the stubify dead function if no longer used functionality from move only checker into its own pass and put it before region based isolation.
I am doing this since region based isolation hit the same issue that the move
checker did. So it makes sense to refactor the functionality into its own pass
and move it into a helper pass that runs before both.

It is very conservative and only stubifies functions that the specialization
passes explicitly mark as this being ok to be done to.
2024-03-01 13:11:07 -08:00
Nate Chandler
ddccaa7d9c [Frontend] Removed lexical-borrow-scope flag.
Adding `move_value [lexical]` and `begin_borrow [lexical]` should happen
all the time at this point.  Remove the ability to omit these
instructions and update the corresponding tests.
2024-02-05 17:34:10 -08:00
Justice Adams
9ce6e12692 Use explicit checks for the 'store' instruction (#70250)
* use explicit checks for the 'store' instruction

* fix small typos

* update register checks to be based on regex
2023-12-06 09:05:03 -08:00
Joe Groff
3d5285be6f Arrange for closure bodies promoted by AllocBoxToStack to have their originals removed by MoveOnlyChecker.
This is an improvement of #67031 which avoids deleting the closure function
body during AllocBoxToStack, which still breaks pass invariants by modifying
functions other than the currently-analyzed function. As a function pass,
AllocBoxToStack also doesn't really know with certainty whether the original
closure function is unused after stack promotion or not. We still want to
eliminate the original when it may contain invalid SIL for move-only values
that rely on the escape analysis for correct semantics, so rather than mark the
original function to be *ignored* during move-only checking, mark it to be
*deleted* by move-only checking if the function is in fact unused at that
point.

If the marked function is still used, we let it pass through move-only
checking normally, which may cause redundant diagnostics but is the right
thing to do since code is still potentially using the closure with escaping
semantics. We should rearrange things to make this situation impossible in
the future.

rdar://110675352
2023-07-10 15:18:16 -07:00
Joe Groff
8d974212f1 Revert "AllocBoxToStack: Remove bodies of closure functions left unused after specialization."
This reverts commit bd5f0a7af0.
2023-07-10 12:43:21 -07:00
Joe Groff
bd5f0a7af0 AllocBoxToStack: Remove bodies of closure functions left unused after specialization.
We can't remove the functions at this point in case they might have other function
passes enqueued to run on them, but we can at least remove the function contents
that are now unnecessary. We need to do this in cases when move-only types are
involved, since the semantics of the move checker rely on unescaped captures being
promoted before the pass runs, and we leave behind invalid SIL in the unpromoted code.
rdar://110675352
2023-06-29 13:45:07 -07:00
Nate Chandler
20147e61f1 [AllocBoxToStack] Specialize moved PAIs.
Added move_value to the list of instructions looked through when
determining whether a partial_apply instruction escapes.

rdar://108376960
2023-04-21 11:07:14 -07:00
Michael Gottesman
1dd896ded9 [move-only] Implement escaping closure semantics.
NOTE: A few of the test patterns need to be made better, but this patch series
is large enough, I want to get it into tree and iterate.
2023-02-20 11:04:21 -08:00
Nate Chandler
ed623d7b64 [NFC] Shortened SIL [init] flag.
Instead of writing out [initalization] for some instructions, use [init]
everywhere.
2022-10-27 10:38:54 -07:00
Holly Borla
8713d78704 [PrintOptions] Print explicit 'any' in SIL. 2022-08-18 01:15:12 -04:00
Slava Pestov
d222ac5f6e Sema: New syntax for @opened archetypes in textual SIL
The old syntax was

    @opened("UUID") constraintType

Where constraintType was the right hand side of a conformance requirement.

This would always create an archetype where the interface type was `Self`,
so it couldn't cope with member types of opened existential types.

Member types of opened existential types is now a thing with SE-0309, so
this lack of support prevented writing SIL test cases using this feature.

The new syntax is

    @opened("UUID", constraintType) interfaceType

The interfaceType is a type parameter rooted in an implicit `Self`
generic parameter, which is understood to be the underlying type of the
existential.

Fixes rdar://problem/93771238.
2022-08-07 19:03:46 -04:00
Erik Eckstein
383c52aa35 SIL: rename dealloc_ref [stack] -> dealloc_stack_ref
Introduce a new instruction `dealloc_stack_ref ` and remove the `stack` flag from `dealloc_ref`.

The `dealloc_ref [stack]` was confusing, because all it does is to mark the deallocation of the stack space for a stack promoted object.
2022-01-07 16:20:27 +01:00
Nate Chandler
bc268ddf34 [Test] Specified copy-prop and lex-lt behavior.
In preparation for changing the default, explicitly specify the behavior
of all tests that are affected by the choice of behavior for lexical
lifetimes and copy-propagation.
2021-12-15 21:37:00 -08:00
Nate Chandler
ea42e2f334 Enabling copy propagation enables lexical lifetimes.
The effect of passing -enable-copy-propagation is both to enable the
CopyPropagation pass to shorten object lifetimes and also to enable
lexical lifetimes to ensure that object lifetimes aren't shortened while
a variable is still in scope and used.

Add a new flag, -enable-lexical-borrow-scopes=true to override
-enable-copy-propagation's effect (setting it to ::ExperimentalLate) on
SILOptions::LexicalLifetimes that sets it to ::Early even in the face of
-enable-copy-propagation.  The old flag -disable-lexical-lifetimes is
renamed to -enable-lexical-borrow-scopes=false but continues to set that
option to ::Off even when -enable-copy-propagation is passed.
2021-12-08 19:13:21 -08:00
Michael Gottesman
785153045b [move-operator] Start having SILGen emit lexical lifetimes and teach the optimizer how to maintain lexical lifetimes until the lexical lifetime elimination.
I am doing this so that I can use lexical lifetimes to emit diagnostics such as
the move operator diagnostics.
2021-11-29 18:02:13 -08:00
Min-Yih Hsu
343d842394 [SIL][DebugInfo] PATCH 3/3: Deprecate debug_value_addr SIL instruciton
This patch removes all references to DebugValueAddrInst class and
debug_value_addr instruction in textual SIL files.
2021-08-31 12:01:04 -07:00
Min-Yih Hsu
e1023bc323 [DebugInfo] PATCH 2/3: Duplicate logics regarding debug_value_addr
This patch replace all in-memory objects of DebugValueAddrInst with
DebugValueInst + op_deref, and duplicates logics that handles
DebugValueAddrInst with the latter. All related check in the tests
have been updated as well.

Note that this patch neither remove the DebugValueAddrInst class nor
remove `debug_value_addr` syntax in the test inputs.
2021-08-31 11:57:56 -07:00
Michael Gottesman
a9ca793f1a [allocbox-to-stack] Eliminate temporary dominance issue and fix improper use of non-ossa generic method createDestroyValue.
NOTE: I also added a partial_apply [guaranteed] test.

Whats interesting about these is that we only ever perform allocbox_to_stack if
we know that we are going to eliminate the allocbox completely. So if we break
dominance among some uses of the alloc box or insert destroy_value when we are
in non-ossa... it doesn't matter since we will eliminate the box and these uses
before the pass is done running.

This will harmless on the surface is an instance of the compiler being in a
"fixed point of correctness". This occurance is when the compiler implementation
is incorrect but the incorrectness is being hidden in the final output. If the
output of the compiler changes or the code in question is changed, new bugs can
be introduced due to the lack of preserving of standard invariants like
dominance.

I also added an additional helper: SILBuilder::insertAfter(SILValue). This
builds on Erik's commit that gave us insert(SILInstruction *). I wanted this
functionality, but additionally I wanted to make it so that if I had an
argument, I got back the first instruction in the block. So it was natural to
extend this to values.
2020-11-17 20:41:56 -08:00
Meghana Gupta
1d4f617fee Extend AllocBoxToStack to handle apply (#31974)
* Don't always give shared linkage to spl functions

private functions on specialization were being given shared linkage.
Use swift::getSpecializeLinkage to correctly get the linkage for the
specialized function based on the linkage of the original function.

* Extend AllocBoxToStack to handle apply

AllocBoxToStack analyzes the uses of boxes and promotes them to stack if
it is safe to do so. Currently the analysis is limited to only a few known
users including partial_apply.

With this change, the pass also analyzes apply users, where the callee
is a local private function.
The analysis is recursive and bound by a threshold.

Fixes rdar://59070139
2020-06-22 14:50:15 -07:00
Slava Pestov
9ec80df97e SIL: Remove curried SILDeclRefs 2020-03-19 02:20:21 -04:00
Erik Eckstein
8cdeb45284 StackNesting: fix a corner case crash related to unreachable blocks
When deallocs are inserted at block boundaries, it's necessary to recompute the data flow.

rdar://problem/55249524
2019-09-12 13:08:31 +02:00
Erik Eckstein
e433759e73 SILOptimizer: fix a stupid bug in StackNesting which can cause a miscompile in functions with unreachable blocks.
rdar://problem/47973577
2019-02-27 10:17:46 -08:00
Erik Eckstein
787c35f165 SILOptimizer: correctly handle unreachable blocks in StackNesting.
Instead of some special treatment of unreachable blocks, model unreachable as implicitly deallocating all alive stack locations at that point.
This requires an additional forward-dataflow pass. But it now correctly models the problem and fixes a compiler crash.

rdar://problem/47402694
2019-01-25 11:29:21 -08:00
Michael Gottesman
fd4828e40a Eliminate -assume-parsing-unqualified-ownership-sil from tests.
I am doing this separately from the actual change to eliminate the option to
make it easier to review.
2018-12-19 12:54:13 -08:00
Harlan Haskins
66a61c5eca Rename @sil_stored to @_hasStorage 2018-11-12 11:32:32 -08:00
Erik Eckstein
39bb14b094 change mangling prefix from $S to $s
This is the final ABI mangling prefix

rdar://problem/38471478
2018-09-19 13:55:11 -07:00
Andrew Trick
2c74a01215 Generalize AllocBoxToStack pass to handle apply variations.
Remove all the bespoke utilities for handling apply sites.
Use the ApplySite abstraction instead. As a side effect,
we can now properly analyze begin_apply and try_apply.
2018-08-02 11:23:09 -07:00
Erik Eckstein
cd3d50a5d9 ABI: Change the mangling prefix from _T0 to $S 2018-01-06 13:55:59 -08:00
Pavel Yaskevich
f90d943a29 [Mangling/ABI] NFC: Fix SILOptimizer tests to reflect label mangling changes 2017-12-18 15:45:50 -08:00
Huon Wilson
44045e24da [test] Update SIL printing/parsing tests for 'witness_method: <protocol>'. 2017-11-01 11:33:27 -07:00
John McCall
ab3f77baf2 Make SILInstruction no longer a subclass of ValueBase and
introduce a common superclass, SILNode.

This is in preparation for allowing instructions to have multiple
results.  It is also a somewhat more elegant representation for
instructions that have zero results.  Instructions that are known
to have exactly one result inherit from a class, SingleValueInstruction,
that subclasses both ValueBase and SILInstruction.  Some care must be
taken when working with SILNode pointers and testing for equality;
please see the comment on SILNode for more information.

A number of SIL passes needed to be updated in order to handle this
new distinction between SIL values and SIL instructions.

Note that the SIL parser is now stricter about not trying to assign
a result value from an instruction (like 'return' or 'strong_retain')
that does not produce any.
2017-09-25 02:06:26 -04:00
Erik Eckstein
d4db9b8099 SILPrinter: make the printing of debug info optional.
With the option -sil-print-debuginfo the printing of debug locations and scopes can be enabled.

I made the default for the option “false”, because in 99% of the time I don’t need the debug info in the printed SIL and I prefer better readability.
2017-04-20 09:18:08 -07:00
Michael Gottesman
21973e0abc [semantic-sil] Update allocbox-to-stack for the mark_uninitialized begin on the alloc_box instead of the project_box.
This also moves the eliminator pass behind alloc box to stack.

rdar://31521023
2017-04-17 19:09:15 -07:00
Erik Eckstein
a43a844838 StackNesting: use the right debug locations for inserted deallocation instructions
Fixes a crash because we used a return-location for a deallocation instruction.

rdar://problem/31458587
rdar://problem/31458617
2017-04-05 18:05:39 -07:00
Michael Gottesman
43a7f3422e [allocbox-to-stack] Update for semantic sil.
rdar://29870610
2017-04-03 14:38:09 -07:00
Erik Eckstein
e9b4db13ee Reinstate "AllocBoxToStack: Improve alloc_stack/dealloc_stack scoping"
This reverts commit c7ef60c7ed.

It also contains an additional test for the fix in StackNesting
2017-03-30 09:40:09 -07:00
Erik Eckstein
c7ef60c7ed Revert "AllocBoxToStack: Improve alloc_stack/dealloc_stack scoping"
It broke some bots.

This reverts commit 43ddc2a643.
2017-03-30 07:59:05 -07:00
Slava Pestov
695a8d2065 Merge pull request #8407 from slavapestov/rename-everything-without-asking-permission
SIL: Terminology change: [fragile] => [serialized]
2017-03-29 20:08:15 -07:00
Erik Eckstein
43ddc2a643 AllocBoxToStack: Improve alloc_stack/dealloc_stack scoping
Instead of inserting all alloc_stack/dealloc_stack instructions at the begin/end of the function, insert them at the actual lifetime boundaries.

rdar://problem/16723128
2017-03-29 17:23:16 -07:00
Slava Pestov
8fe8b89b0f SIL: Terminology change: [fragile] => [serialized]
Also, add a third [serializable] state for functions whose bodies we
*can* serialize, but only do so if they're referenced from another
serialized function.

This will be used for bodies synthesized for imported definitions,
such as init(rawValue:), etc, and various thunks, but for now this
change is NFC.
2017-03-29 16:47:28 -07:00
Erik Eckstein
2a55b26e46 Mangling: enable new mangling for symbols 2017-03-16 12:04:08 -07:00
Michael Gottesman
784d5d16fc [silgen] Change emitClassConstructorInitializer to use ownership and make calling designated/chaining initializes use proper ownership.
rdar://29791263
2017-02-23 08:48:58 -08:00
Arnold Schwaighofer
876cea81ae SIL: Add an allowed access kind to the opened value of an open_existential_addr instruction
Once we move to a copy-on-write implementation of existential value buffers we
can no longer consume or destroy values of an opened existential unless the
buffer is uniquely owned.

Therefore we need to track the allowed operation on opened values.

Add qualifiers "mutable_access" and "immutable_access" to open_existential_addr
instructions to indicate the allowed access to the opened value.

Once we move to a copy-on-write implementation, an "open_existential_addr
mutable_access" instruction will ensure unique ownership of the value buffer.
2017-02-15 14:23:12 -08:00
Joe Groff
4444d83756 SIL: Lower captures to boxes with an appropriate generic context.
Officially kick SILBoxType over to be "nominal" in its layout, with generic layouts structurally parameterized only by formal types. Change SIL to lower a capture to a nongeneric box when possible, or a box capturing the enclosing generic context when necessary.
2016-12-16 20:23:25 -08:00
Joe Groff
277608a69b Print and parse SILBoxTypes with a new syntax.
Use a syntax that declares the layout's generic parameters and fields,
followed by the generic arguments to apply to the layout:

  { var Int, let String } // A concrete box layout with a mutable Int
                          // and immutable String field
  <T, U> { var T, let U } <Int, String> // A generic box layout,
                                        // applied to Int and String
                                        // arguments
2016-12-02 13:44:22 -08:00
Joe Groff
e1e7e19248 SIL: Construct alloc_box insns with the type of the box.
This becomes necessary with generalized boxes, since the box type isn't derivable from a single field type.
2016-11-03 19:26:42 -07:00
Michael Gottesman
20dd563efb [semantic-arc] Update tests for qualified/unqualified ownership and SILGen emission of copy_value, destroy_value. 2016-10-29 20:11:09 -07:00