Commit Graph

396 Commits

Author SHA1 Message Date
Joe Groff
067f1d3f1c SILGen: Don't mark_unresolved copyable borrows from noncopyable switches 2024-01-31 20:46:01 -08:00
Joe Groff
03e2e8f476 BorrowToDestructureUtils: handle borrowing switches.
Instead of trying to convert all switches into consumes, allow a switch of a borrow
to remain as such.
2024-01-31 20:38:22 -08:00
Joe Groff
c4bdc97d9c SILGen: Separate borrow from consume phase for destructive pattern matches.
We don't want the dispatch phase of a pattern match to invalidate the subject,
because we don't define the order in which patterns are evaluated, and if a
particular match attempt fails, we need to still have an intact subject value
on hand to try a potentially arbitrary other pattern against it. For
noncopyable types, this means we have to always emit the match phase as a
borrow, including the variable bindings for a guard expression if any.
For a consuming pattern match, end the borrow scope and reproject the variable
bindings by using consuming destructuring operations on the subject in the
match block.

For now, this new code path only handles single-case-label-per-block switches
without fallthroughs.
2024-01-29 18:01:55 -08:00
Joe Groff
960938f87e SILGen: Always match noncopyable values by borrowing.
Even if the final pattern ends up consuming the value, the match itself
must be nondestructive, because any match condition could fail and cause
us to have to go back to the original aggregate. For copyable values,
we can always copy our way out of consuming operations, but we don't
have that luxury for noncopyable types, so the entire match operation
has to be done as a borrow.

For address-only enums, this requires codifying part of our tag layout
algorithm in SIL, namely that an address-only enum will never use
spare bits or other overlapping storage for the enum tag. This allows
us to assume that `unchecked_take_enum_data_addr` is safely non-side-
effecting and match an address-only noncopyable enum as a borrow.
I put TODOs to remove defensive copies from various parts of our
copyable enum codegen, as well as to have the instruction report
its memory behavior as `None` when the projection is nondestructive,
but this disturbs SILGen for existing code in ways SIL passes aren't
yet ready for, so I'll leave those as is for now.

This patch is enough to get simple examples of noncopyable enum switches
to SILGen correctly. Additional work is necessary to stage in the binding
step of the pattern match; for a consuming switch, we'll need to end
the borrow(s) and then reproject the matched components so we can
consume them moving them into the owned bindings. The move-only checker
also needs to be updated because it currently always tries to convert
a switch into a consuming operation.
2024-01-19 13:59:04 -08:00
Doug Gregor
c4e97bc783 Handle non-existential errors in do..catch blocks 2024-01-12 21:27:30 -08:00
Hamish Knight
d9f3047871 [Profiler] Fix DoCatchStmt coverage handling
The logic here previously worked by computing the
exit count by taking the parent count and
subtracting any control flow that jumped out of the
clauses. With `try` handling fixed, this no longer
works correctly, since a `try` shouldn't be
subtracted if the error is caught be one of the
catches, as that's not actually leaving the
statement. We could write the logic to determine
where a `try` is jumping to, but the logic here is
already pretty brittle, relying on being sprinkled
in various different places.

For now, let's take the more straightforward
approach and handle do-catches the same way we
handle switches, we initialize the exit counter to
0, and add on each exit count of each branch. This
lets us re-use the existing CaseStmt handling
logic. This doesn't necessarily produce the most
optimal counter expressions, but I want to replace
this all with a SILOptimizer pass anyway, which
will be able to much more easily compute optimal
counter expressions.

rdar://100470244
2023-11-16 17:28:57 +00:00
Michael Gottesman
543063ef0e [silgen] Make ManagedValue::forUnmanaged private and change users to use other more specific APIs.
I have been doing this over the past couple of days in preparation for changing
ManagedValue to specify the type of scope its cleanup is connected to.
2023-08-19 14:11:44 -07:00
Michael Gottesman
ff948f7309 [silgen] Convert even more cases of using trivial and values without ownership to use for*RValueWithoutOwnership APIs. 2023-08-15 11:04:01 -07:00
Slava Pestov
9ebb5f2e03 AST: Rename VarDecl::getType() to VarDecl::getTypeInContext()
This is a futile attempt to discourage future use of getType() by
giving it a "scary" name.

We want people to use getInterfaceType() like with the other decl kinds.
2023-08-04 14:19:25 -04:00
Evan Wilde
250082df25 [NFC] Reformat all the LLVMs
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.
2023-06-27 09:03:52 -07:00
Evan Wilde
f3ff561c6f [NFC] add llvm namespace to Optional and None
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.
2023-06-27 09:03:52 -07:00
Andrew Trick
ea7b8055bc Rewrite some isPlusOne calls to isPlusOneOrTrivial.
Whenever we want to forward to a +1 value but don't need to destroy
the original memory, use isPlusOneOrTrivial.

This follows the existing naming scheme.

Fixes rdar://108001491 (SIL verification failed: Found mutating or
consuming use of an in_guaranteed parameter?!:
!ImmutableAddressUseVerifier().isMutatingOrConsuming(fArg))
2023-05-01 23:24:29 -07:00
Adrian Prantl
68aa944ccd SILgenPattern: Mark location used by forwardIntoSubtree as autogenerated.
If a pattern reuses a value from a previous branch this could result in a step
backwords or a previous scope being reopeneed.

rdar://107764966
2023-04-14 15:18:00 -07:00
Adrian Prantl
0337ea94f2 Remove uses of SGF.CurrentSILLoc from SILGenPattern 2023-04-03 16:08:20 -07:00
Joe Groff
8e21bfcc47 MoveOnlyAddressChecker: Confine analysis to current formal access.
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.
2023-04-02 16:33:57 -07:00
Michael Gottesman
f4e1b2a8f2 [move-only] Update SILGen/MoveCheckers so that vars are emitted in eagerly projected box form.
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.
2023-02-20 11:04:21 -08:00
Michael Gottesman
61b63839b2 [move-only] Now that borrow to destructure transform knows how to handle switch_enum, emit move only enum switches at +0. 2023-02-08 13:59:14 -08:00
Nate Chandler
d2af3435bb [OpaqueValues] Emit addr-only patterns.
When opaque values are enabled, pattern match emission now emits a copy
and a store to the destination rather than a copy-addr to it.
2022-12-13 18:09:25 -08:00
Nate Chandler
eae4a8b013 [OpaqueValues] Handle indirect resilient switch.
For a switch on an indirect enum whose case is resilient, SILGen now
produces a load_borrow just as it does for cases which are loadable.
2022-12-08 12:30:58 -08:00
Erik Eckstein
ab1b343dad use new llvm::Optional API
`getValue` -> `value`
`getValueOr` -> `value_or`
`hasValue` -> `has_value`
`map` -> `transform`

The old API will be deprecated in the rebranch.
To avoid merge conflicts, use the new API already in the main branch.

rdar://102362022
2022-11-21 19:44:24 +01:00
swift-ci
fd6fd76dae Merge pull request #42513 from jsoref/spelling-silgen
Spelling silgen
2022-11-09 23:28:43 -08:00
Josh Soref
9a6bf46c0f Spelling silgen
* actually
* arbitrary
* cargo-culted
* clazz
* constrained
* continuation
* coordinator
* coroutine
* derivative
* destroyer
* given
* have
* imported
* initialization
* items
* necessarily
* occurring
* omitting
* overridden
* parameter
* possible
* predecessor
* preparation
* resilience
* should
* struct
* that
* the
* throwing
* unexpectedly
* uniqueness
* using
* value
* villain

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2022-11-09 21:44:17 -05:00
Nate Chandler
24883bf630 [SILGen] Copied opaque tuple fields before switch.
The switch_enum_addr consumes its operand so a copy is needed.
2022-10-26 11:01:28 -07:00
Michael Gottesman
0a16cc362a [move-only] Implement an initial version of the move only address checker.
Some notes:

1. I added support for both loadable/address only types.

2. These tests are based off of porting the move only object tests for inout,
vars, mutating self, etc.

3. I did not include already written tests for address only types in this
specific merge since I need to change us to borrow move only var like types.
Without that, we get a lot of spurious error msgs and the burden of writing that
is not worth it. So instead in a forthcoming commit where I fix that issue in
SILGen, I will commit the corresponding address only tests for this work.

4. I did not include support for trivial types in this. I am going to do
object/address for that at the same time.
2022-09-11 18:57:32 -07:00
Hamish Knight
05e2309788 [Profiler] Fix coverage mapping for switches
Previously we assumed the exit counter was the
same as the entry counter. Update the logic such
that we track break statements (including
implicitly at the end of a case), as well as
early returns and jumps to parent statements. This
follows a similar logic to what we do for if
statements.

rdar://99141044
2022-08-25 17:30:34 +01:00
Erik Eckstein
e8e61a9565 SIL: create cond_fail 1 instead of builtin "int_trap" for unconditional failures
`int_trap` doesn't provide a failure message, which makes crash reports hard to understand.
This is mostly the case for optimized casts which fail.

rdar://97681511
2022-07-28 16:05:07 +02:00
Michael Gottesman
1e6187c4f4 [sil] Update all usages of old API SILValue::getOwnershipKind() in favor of new ValueBase::getOwnershipKind().
Andy some time ago already created the new API but didn't go through and update
the old occurences. I did that in this PR and then deprecated the old API. The
tree is clean, so I could just remove it, but I decided to be nicer to
downstream people by deprecating it first.
2022-07-26 11:46:23 -07:00
Michael Gottesman
65c21b61bf [move-only] Begin implementing support for concrete move only types.
This is just the very beginning... I still need to implement more parts of
SILGen for this. But all great things start small. I am going to iterate on top
of this and just wanted to get some initial parts of the work in as I go.
2022-07-21 15:33:17 -07:00
Michael Gottesman
0d11e8ef69 [no-implicit-copy] Update SILGen/move checker to work with new patterns from copyable_to_moveonly and friends.
This involved doing the following:

1. Update the move only checker to look for new patterns.

2. Teach emitSemanticStore to use a moveonlywrapper_to_copyable to store moveonly
   values into memory. The various checkers will validate that this code is
   correct.

3. When emitting an apply, always unwrap move only variables. In the
   future, I am going to avoid this if a parameter is explicitly marked as also
   being moveonly (e.x.: @moveOnly parameter or @noEscape argument).

4. Convert from moveOnly -> copyable on return inst automatically in SILGen.

5. Fix SILGenLValue emission so we emit an error diagnostic later rather than
   crash. This is needed to keep SILGen emitting move only addresses (that is no
   implicit copy address only lets) in a form that the move only checker then
   will error upon. Without this change, SILGen crashes instead of emitting an
   error diagnostic in the following test:
   .//test/SILOptimizer/move_only_checker_addressonly_fail.swift
2022-06-21 16:47:58 -07:00
Meghana Gupta
3480eecc99 Fix SILGen to generate switch_enum at +1 for opaque value operand 2022-05-11 21:15:21 -07:00
Andrew Trick
1a9c2ad8a3 Add doesCastPreserveOwnershipForType() to SIL/Utils/DynamicCasts.cpp
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.
2022-04-05 20:28:19 -07:00
Robert Widmann
b2619efb3c Emit Debug Variables for Errors Bound in Catch Clauses
Make error variables accessible to a fresh debug scope for the catch clause.

rdar://85982381
2021-12-02 18:38:16 -08:00
Saleem Abdulrasool
910fbee14e gardening: make c++98-compat-extra-semi an error
This cleans up 90 instances of this warning and reduces the build spew
when building on Linux.  This helps identify actual issues when
building which can get lost in the stream of warning messages.  It also
helps restore the ability to build the compiler with gcc.
2021-11-27 11:40:17 -08:00
Andrew Trick
8f53a927b0 SILGen OSSA support for switch_enum/checked_cast_br, related cleanup
Use APIs for creating terminator results that handle forwarding
ownership consistently.

Add ManagedValue::forForwardedRValue(SILValue) to handle cleanups
consistently based on ownership forwarding.

Add SILGenBuilder::createForwardedTermResult(SILType type) for
creating termator results with the correct ownership and cleanups.

Add SILGenBuilder::createTermResult(SILType type, ValueOwnershipKind
ownership) that handles cleanup based on terminator result ownership.

Add SILGenBuilder::createOptionalSomeResult(SwitchEnumInst) so a lot
of code doesn't need to deal with unwrapping Optional types,
terminator results, and ownership rules.

Replace the existing "phi" APIs with a single
SILGenBuilder::createPhi(SILType, ValueOwnershipKind) that handles
cleanup based on phi ownership.

Phis and terminator results are fundamentally different and need to be handled differently everywhere. Remove the confusion where terminator results were generated with a "phi argument" API.
2021-09-07 22:50:46 -07:00
Erik Eckstein
ec64f2a255 SILLocation: replace CleanupLocation::get(loc) with CleanupLocation(loc)
No need to have a static get function - the constructor can be used directly.
NFC
2021-01-29 20:28:21 +01:00
Erik Eckstein
462e58d3cb SILLocation: a big refactoring and reducing its size from 3 to 2 words
My goal was to reduce the size of SILLocation. It now contains only of a storage union, which is basically a pointer and a bitfield containing the Kind, StorageKind and flags. By far, most locations are only single pointers to an AST node. For the few cases where more data needs to be stored, this data is allocated separately: with the SILModule's bump pointer allocator.

While working on this, I couldn't resist to do a major refactoring to simplify the code:

* removed unused stuff
* The term "DebugLoc" was used for 3 completely different things:
    - for `struct SILLocation::DebugLoc` -> renamed it to `FilePosition`
    - for `hasDebugLoc()`/`getDebugSourceLoc()` -> renamed it to `hasASTNodeForDebugging()`/`getSourceLocForDebugging()`
    - for `class SILDebugLocation` -> kept it as it is (though, `SILScopedLocation` would be a better name, IMO)
* made SILLocation more "functional", i.e. replaced some setters with corresponding constructors
* replaced the hand-written bitfield `KindData` with C bitfields
* updated and improved comments
2021-01-29 20:28:21 +01:00
Erik Eckstein
b7351780f7 SIL: move all the block-list modifying APIs to SILFunction.
... and remove SILFunction::getBlocks().

It's just a cleanup, NFC.
2021-01-14 17:35:31 +01:00
Michael Gottesman
4801fe1966 Fix a typo in a comment. 2020-12-15 13:52:08 -08:00
Michael Gottesman
3de8263b26 [silgenpattern] When emitting address only enum element dispatch, do not leak the switch's operand along the default path.
For the following discussion, let OP be the switch's operand. This is
implemented by:

* Modeling switch_enum_addr as not forwarding OP and instead delegate the
  forwarding of OP to be done by each enum case. This matches what SILGen is
  actually doing since the actual taking of the address in SIL is done in each
  enum case block by an unchecked_take_enum_data_addr.

* In each enum case, I treat OP as being forwarded into an irrefutable
  sub-tree. I follow the pattern of other places this is done by creating a
  CleanupStateRestorationScope and using forwardIntoIrrefutableSubTree. This
  ensures that if I forward OP in the enum case, it just becomes dormant instead
  of being thrown away.

* Inside each case, there is a bunch of code that does some final preparations
  to src before dispatching to the inner dispatch. This code was written using
  old low-level SILValue APIs where ownership is done by hand. I replaced all of
  that by hand ownership with higher level Managed Value APIs that automatically
  handle ownership for the user. This simplified the implementation and ensured
  correctness via SILGenBuilder API invariants.

The end result of all of these together is that:

1. The cleanup on OP is still live when we emit the default case later than the
   cleanups. This eliminates the leak that I am fixing.

2. We have greater correctness since the SILGenBuilder APIs automatically handle
   ownership for us.

3. We have eliminated some brittle logic that could in the future introduce
   bugs. Specifically, I noticed that if we were ever given a
   ConsumableManagedValue that was CopyOnSuccess or BorrowAlways but its
   ManagedValue was a +1 value, we would leak. I could not figure out how to
   create a Swift test case that would go down this code path though = (. But
   that being said, it is one new language feature away from being broken. I
   added some asserts to ConsumableManagedValue that ensures this invariant, so
   we are safe. If it is inconvenient, we can also cause ConsumableManagedValue
   to create a new ManagedValue when it detects this condition without the
   cleanup. But lets see how difficult it is to keep this invariant.

In terms of testing, I put in both a SILGen test and also an end<->end
interpreter test to ensure this doesn't break again.

rdar://71992652
SR-13926
2020-12-14 21:09:20 -08:00
Michael Gottesman
f7e6aa5847 [silgenpattern] Rename an EnumElementDecl value from elt -> eltDecl.
Since we are working with values here, it can be confusing when reading the code
that elt is an EnumElementDecl. The rename to eltDecl will make it much clearer.
2020-12-14 21:09:20 -08:00
Michael Gottesman
c026e95cce [ownership] Extract out SILOwnershipKind from ValueOwnershipKind into its own type and rename Invalid -> Any.
This makes it easier to understand conceptually why a ValueOwnershipKind with
Any ownership is invalid and also allowed me to explicitly document the lattice
that relates ownership constraints/value ownership kinds.
2020-11-10 14:29:11 -08:00
Suyash Srijan
6a7b38d7ef [SILGenPattern] Silence redundant unreachable enum case warning (#33336) 2020-08-22 01:58:44 +01:00
Michael Gottesman
092edd6621 [ast] Rename VarPattern -> BindingPattern.
VarPattern is today used to implement both 'let' and 'var' pattern bindings, so
today is already misleading. The reason why the name Var was chosen was done b/c
it is meant to represent a pattern that performs 'variable binding'. Given that
I am going to add a new 'inout' pattern binding to this, it makes sense to
give it now a better fitting name before I make things more confusing.
2020-07-16 18:56:01 -07:00
Robert Widmann
426d930d10 Merge pull request #32301 from CodaFi/location-location-location
Strip TypeLoc out of Patterns
2020-06-10 19:25:56 -07:00
Vedant Kumar
60ec3f1b90 Fix debug description for cases with multiple items (#32282)
* [SILGenFunction] Don't create redundant nested debug scopes

Instead of emitting:

```
sil_scope 4 { loc "main.swift":6:19 parent 3 }
sil_scope 5 { loc "main.swift":7:3 parent 4 }
sil_scope 6 { loc "main.swift":7:3 parent 5 }
sil_scope 7 { loc "main.swift":7:3 parent 5 }
sil_scope 8 { loc "main.swift":9:5 parent 4 }
```

Emit:

```
sil_scope 4 { loc "main.swift":6:19 parent 3 }
sil_scope 5 { loc "main.swift":7:3 parent 4 }
sil_scope 6 { loc "main.swift":9:5 parent 5 }
```

* [IRGenSIL] Diagnose conflicting shadow copies

If we attempt to store a value with the wrong type into a slot reserved
for a shadow copy, diagnose what went wrong.

* [SILGenPattern] Defer debug description of case variables

Create unique nested debug scopes for a switch, each of its case labels,
and each of its case bodies. This looks like:

```
  switch ... { // Enter scope 1.
    case ... : // Enter scope 2, nested within scope 1.
      <body-1> // Enter scope 3, nested within scope 2.

    case ... : // Enter scope 4, nested within scope 1.
      <body-2> // Enter scope 5, nested within scope 4.
  }
```

Use the new scope structure to defer emitting debug descriptions of case
bindings. Specifically, defer the work until we can nest the scope for a
case body under the scope for a pattern match.

This fixes SR-7973, a problem where it was impossible to inspect a case
binding in lldb when stopped at a case with multiple items.

Previously, we would emit the debug descriptions too early (in the
pattern match), leading to duplicate/conflicting descriptions. The only
reason that the ambiguous description was allowed to compile was because
the debug scopes were nested incorrectly.

rdar://41048339

* Update tests
2020-06-10 13:31:10 -07:00
Robert Widmann
fc9070c072 Strip TypeLoc from IsPattern 2020-06-10 13:29:39 -07:00
Anthony Latsis
9fd1aa5d59 [NFC] Pre- increment and decrement where possible 2020-06-01 15:39:29 +03:00
Owen Voorhees
43e2d107e1 [SE-0276] Implement multi-pattern catch clauses
Like switch cases, a catch clause may now include a comma-
separated list of patterns. The body will be executed if any
one of those patterns is matched.

This patch replaces `CatchStmt` with `CaseStmt` as the children
of `DoCatchStmt` in the AST. This necessitates a number of changes
throughout the compiler, including:
- Parser & libsyntax support for the new syntax and AST structure
- Typechecking of multi-pattern catches, including those which
  contain bindings.
- SILGen support
- Code completion updates
- Profiler updates
- Name lookup changes
2020-04-04 09:28:26 -07:00
Michael Gottesman
6c5c853339 [ownership] Change guaranteed args from transformation terminators to not require end_borrows.
For those who are unaware, a transformation terminator is a terminator like
switch_enum/checked_cast_br that always dominate their successor blocks. Since
they dominate their successor blocks by design and transform their input into
the args form, we can validate that they obey guaranteed ownership semantics
just like a forwarding instruction.

Beyond removing unnecessary code bloat, this also makes it significantly more
easier to optimize/work with transformation terminators when converting @owned
-> @guaranteed since we do not need to find end_borrow points when the owned
value is consumed.

<rdar://problem/59097063>
2020-02-02 16:59:57 -08:00
Saleem Abdulrasool
7d8aac60ca disambiguate some type shadowing (NFCI)
Adjust the type shadowing identified by GCC 7.  The declaration shadows
a type which changes the meaning of the identifier subsequently.
2019-12-23 15:34:55 -08:00