Commit Graph

125 Commits

Author SHA1 Message Date
Pavel Yaskevich
11f1b08ada [DI] Properties with init accessors without "initializes" act as stored
Adjust DI to treat init accessor properties that have only 'accesses'
or no restrictions as if they are stored properties, this means that
if such property doesn't have a default initializer users would have
to reference it explicitly in their custom initializers.

We also need to suppress default init synthesis for such cases which
would be done in a followup commit.

Resolves: rdar://113401979
2023-08-04 21:05:07 -07:00
Pavel Yaskevich
52ac782184 [DI] InitAccessors: Use of SILModule::getFieldIndex is incompatible with DI data structures
DI cares only about stored fields of the current type but `SILModule::getFieldIndex`
goes through all of the supertypes as well.
2023-07-18 17:19:42 -07:00
Pavel Yaskevich
3063e9d778 [SIL] InitAccessors: Reference "self" in assign_or_init instruction
First step on the path to remove dependence on "setter".
2023-06-27 09:45:05 -07:00
Meghana Gupta
16c300c2af Remove OwnershipForwardingConversionInst, ConversionInst.
Add new ConversionOperation abstraction, use this in place of ConversionInst
2023-06-15 10:53:28 -07:00
Pavel Yaskevich
c82559e33c [DI/Lowering] InitAccessors: Implement lowering of property assignments
DI marks all of of the previously initialized properties and Raw SIL
lowering emits `destroy_addr` before calling init accessor for such
properties to destroy previously set value.
2023-06-06 18:59:46 -07:00
Pavel Yaskevich
73765c8028 [SIL] InitAccessors: Fix reference type handling by DI and RawSIL lowering
- Adds a missing check to `collectClassSelfUses` to find assign_or_init instructions;
- RawSIL lowering should start emitting access around synthesized member references.
2023-06-06 18:59:45 -07:00
Pavel Yaskevich
112d0d4f2d [DI] InitAccessors: Start marking initializes(...) properties as "out"
Adjust DI to recognize that "out" location without uses is uninitialized.
2023-06-06 18:59:45 -07:00
Pavel Yaskevich
68866d7ae5 [DI] InitAccessors: Handle assign_or_init without initializations
Introduce a placeholder "init" use anchored on `assign_or_init`
instruction to make sure that `handleStoreUse` gets a called and
sets the kind.
2023-06-06 18:59:13 -07:00
Pavel Yaskevich
3b85840611 [SIL/DI] InitAccessors: Get all required info from AssignOrInit instead of instruction location
This is a more robust way of accessing the property information
because instruction has a reference to init accessor declaration.
2023-06-06 18:59:13 -07:00
Pavel Yaskevich
003e460773 [DI] Memory collector shouldn't assume that decls always have names
For example accessor declarations don't have names.
2023-06-06 18:59:13 -07:00
Pavel Yaskevich
fe90ddce74 [DI] InitAccessors: Implement handling of initializes/accesses attributes
- Record all properties listed in `accesses` as loads;
- Record all properties listed in `initialized` as init-or-assign;
- Detect situations when double-init could happen i.e. if one of
  the properties listed in `initializes` attribute is explicitly
  initialized before init accessor call.
2023-06-06 18:59:13 -07:00
Holly Borla
df69020eca [DefiniteInitialization] Lower AssignOrInit instructions to either call the
initializer or the setter closure with the given argument.
2023-06-06 18:59:13 -07:00
Pavel Yaskevich
e0bf2ff854 [SIL/DI] NFC: Remove TypeWrappers feature functionality 2023-02-08 10:14:29 -08:00
John McCall
d25a8aec8b Add explicit lowering for value packs and pack expansions.
- SILPackType carries whether the elements are stored directly
  in the pack, which we're not currently using in the lowering,
  but it's probably something we'll want in the final ABI.
  Having this also makes it clear that we're doing the right
  thing with substitution and element lowering.  I also toyed
  with making this a scalar type, which made it necessary in
  various places, although eventually I pulled back to the
  design where we always use packs as addresses.

- Pack boundaries are a core ABI concept, so the lowering has
  to wrap parameter pack expansions up as packs.  There are huge
  unimplemented holes here where the abstraction pattern will
  need to tell us how many elements to gather into the pack,
  but a naive approach is good enough to get things off the
  ground.

- Pack conventions are related to the existing parameter and
  result conventions, but they're different on enough grounds
  that they deserve to be separated.
2023-01-29 03:29:06 -05:00
Nate Chandler
8d8577e5b0 [SIL] Removed Indirect_In_Constant convention.
It is no different from @in.

Continue parse @in_constant in textual and serialized SIL, but just as
an alias for @in.
2022-12-09 21:54:00 -08:00
Pavel Yaskevich
db4b6a5c0f [AST/Sema] TypeWrappers: Implement type wrappers on protocols
Adding a type wrapper attribute on a protocol does two things:

- Synthesizes `associatedtype $Storage` declaration with `internal` access
- Synthesizes `var $storage: <#Wrapper#><Self, Self.$Storage>` value requirement
2022-11-07 14:55:05 -08:00
Pavel Yaskevich
58e330dba9 [DI] Simplify immutability checks on _storage base 2022-10-07 17:35:47 -07:00
Pavel Yaskevich
40d1146eac Merge pull request #61427 from xedin/type-wrappers-add-support-for-let-properties
[Sema/DI] TypeWrappers: Add support for `let` properties
2022-10-04 21:17:20 -07:00
Allan Shortlidge
c7ce7b75e0 Merge pull request #42514 from jsoref/spelling-siloptimizer
Spelling siloptimizer
2022-10-03 22:50:19 -07:00
Pavel Yaskevich
d6b6bbcbe5 [DI] TypeWrapper: Adjust immutability check to handle _storage as $Storage
`_storage` is used primary to support member-by-member initialization
of `$Storage`, so we need to refer to `$Storage` to determine whether
a partial field of `_storage` is `let` or not.
2022-10-03 16:58:50 -07:00
Josh Soref
730b16c569 Spelling siloptimizer
* access
* accessed
* accesses
* accessor
* acquiring
* across
* activated
* additive
* address
* addresses'
* aggregated
* analysis
* and
* appropriately
* archetype
* argument
* associated
* availability
* barriers
* because
* been
* beginning
* belongs
* beneficial
* blocks
* borrow
* builtin
* cannot
* canonical
* canonicalize
* clazz
* cleanup
* coalesceable
* coalesced
* comparisons
* completely
* component
* computed
* concrete
* conjunction
* conservatively
* constituent
* construct
* consuming
* containing
* covered
* creates
* critical
* dataflow
* declaration
* defined
* defining
* definition
* deinitialization
* deliberately
* dependencies
* dependent
* deserialized
* destroy
* deterministic
* deterministically
* devirtualizes
* diagnostic
* diagnostics
* differentiation
* disable
* discipline
* dominate
* dominates
* don't
* element
* eliminate
* eliminating
* elimination
* embedded
* encounter
* epilogue
* epsilon
* escape
* escaping
* essential
* evaluating
* evaluation
* evaluator
* executing
* existential
* existentials
* explicit
* expression
* extended
* extension
* extract
* for
* from
* function
* generic
* guarantee
* guaranteed
* happened
* heuristic
* however
* identifiable
* immediately
* implementation
* improper
* include
* infinite
* initialize
* initialized
* initializer
* inside
* instruction
* interference
* interferes
* interleaved
* internal
* intersection
* intractable
* intrinsic
* invalidates
* irreducible
* irrelevant
* language
* lifetime
* literal
* looks
* materialize
* meaning
* mergeable
* might
* mimics
* modification
* modifies
* multiple
* mutating
* necessarily
* necessary
* needsmultiplecopies
* nonetheless
* nothing
* occurred
* occurs
* optimization
* optimizing
* original
* outside
* overflow
* overlapping
* overridden
* owned
* ownership
* parallel
* parameter
* paths
* patterns
* pipeline
* plottable
* possible
* potentially
* practically
* preamble
* precede
* preceding
* predecessor
* preferable
* preparation
* probably
* projection
* properties
* property
* protocol
* reabstraction
* reachable
* recognized
* recursive
* recursively
* redundant
* reentrancy
* referenced
* registry
* reinitialization
* reload
* represent
* requires
* response
* responsible
* retrieving
* returned
* returning
* returns
* rewriting
* rewritten
* sample
* scenarios
* scope
* should
* sideeffects
* similar
* simplify
* simplifycfg
* somewhat
* spaghetti
* specialization
* specializations
* specialized
* specially
* statistically
* substitute
* substitution
* succeeds
* successful
* successfully
* successor
* superfluous
* surprisingly
* suspension
* swift
* targeted
* that
* that our
* the
* therefore
* this
* those
* threshold
* through
* transform
* transformation
* truncated
* ultimate
* unchecked
* uninitialized
* unlikely
* unmanaged
* unoptimized key
* updataflow
* usefulness
* utilities
* villain
* whenever
* writes

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2022-10-03 18:31:33 -04:00
Pavel Yaskevich
e9cb195ffa [DI] Element refs on _storage should be printed with self.
`_storage` comes from `assign_by_wrapper` instruction but
user wrote `self.` in the source and that is what should
get printed by DI diagnostics.
2022-09-29 20:50:38 -07:00
Pavel Yaskevich
d5844e5300 [DI] Process type wrapper _storage before any other initialization
`_storage` is special because it emits assignments to compiler
synthesized stored property `$storage`, without that `self`
cannot be fully initialized.
2022-09-29 20:50:37 -07:00
Pavel Yaskevich
b5126a97d3 [SILOptimizer] DI: Add a way to check whether TheMemory is _storage local var 2022-09-29 20:50:36 -07:00
Pavel Yaskevich
f66f9dc8f7 [DI] Add a way to find value of self in initializer context
This is staging for type wrappers that need to inject
`self.$storage = ...` call to user-defined initializers,
to be able to do that logic needs to be able to find
`self` that is being constructed.
2022-09-20 14:36:22 -07:00
Michael Gottesman
467b742a5c [move-only] Update the non-address move checker part of the optimizer to handle mark_must_check on addresses. 2022-09-09 13:38:18 -07: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
Kavon Farvardin
af683dc271 basic implementation of performing an init of the id after an assign of the actorSystem.
The resignID call within the initializer moved into DI, because an assignment to
the actorSystem, and thus initialization of the id, is no longer guaranteed to happen.
Thus, while we previously could model the resignation as a clean-up emitted on all
unwind paths in an initializer, now it's conditional, based on whether the id was
initialized. This is exactly what DI is designed to do, so we inject the resignation
call just before we call the identity's deinit.
2022-03-24 16:20:01 -07:00
Kavon Farvardin
13cbe0dd15 adding the @_compilerInitialized attribute
This attribute is designed for let-bound variables whose initializing
assignment is synthesized by the compiler. This assignment is
expected to happen at some point before DefiniteInitialization has
run, which is the pass that verifies whether the compiler truly
initialized the variable.

I generally expect that this will never be a user-facing feature, and
that the synthesized assignment happens in SILGen.
2022-03-24 16:18:49 -07:00
Kavon Farvardin
4f28b87de9 basic implementation of flow-isolation for SE-327
Flow-isolation is a diagnostic SIL pass that finds
unsafe accesses to properties in initializers and
deinitializers that cannot gain isolation to otherwise
protect those accesses from concurrent modifications.
See SE-327 for more details about how and why it exists.

This commit includes changes and features like:

- The removal of the escaping-use restriction
- Flow-isolation that works properly with `defer` statements
- Flow-isolation with an emphasis on helpful diagnostics.

It also includes known issues like:

- Local / nonescaping functions are not analyzed by
  flow-isolation, despite it being technically possible.
  The main challenge in supporting it efficiently is that
  such functions do not have a single exit-point, like
  a `defer`. In particular, arbitrary functions can throw
  so there are points where nonisolation should _not_ flow
  out of the function at a call-site in the initializer, etc.

- The implementation of the flow-isolation pass is not
  particularly memory efficient; it relies on BitDataflow
  even though the particular flow problem is simple.
  So, a more efficient implementation would be specialized for
  this particular problem, etc.

There are also some changes to the Swift language itself: defer
will respect its context when deciding its property access kind.

Previously, a defer in an initializer would always access a stored
property through its accessor methods, instead of doing so directly
like its enclosing function might. This inconsistency is unfortunate,
so for Swift 6+ we make this consistent. For Swift 5, only a defer
in a function that is a member of the following kinds of types
will gain this consistency:

- an actor type
- any nominal type that is actor-isolated, excluding UnsafeGlobalActor.

These types are still rather new, so there is much less of a chance of
breaking expected behaviors around defer. In particular, the danger is
that users are relying on the behavior of defer triggering a property
observer within an init or deinit, when it would not be triggering it
without the defer.
2022-02-02 13:31:14 -07:00
Nate Chandler
7b6fb3fbf5 [DI] See through alloc_box borrows. 2022-01-13 13:33:34 -08:00
Michael Gottesman
d74299e68d [move-function] Add a new instruction called mark_unresolved_move_addr.
This instruction is similar to a copy_addr except that it marks a move of an
address that has to be checked. In order to keep the memory lifetime verifier
happy, the semantics before the checker runs are the mark_unresolved_move_addr is
equivalent to copy_addr [init] (not copy_addr [take][init]).

The use of this instruction is that Mandatory Inlining converts builtin "move"
to a mark_unresolved_move_addr when inlining the function "_move" (the only
place said builtin is invoked).

This is then run through a special checker (that is later in this PR) that
either proves that the mark_unresolved_move_addr can actually be a move in which
case it converts it to copy_addr [take][init] or if it can not be a move, emit
an error and convert the instruction to a copy_addr [init]. After this is done
for all instructions, we loop back through again and emit an error on any
mark_unresolved_move_addr that were not processed earlier allowing for us to
know that we have completeness.

NOTE: The move kills checker for addresses is going to run after Mandatory
Inlining, but before predictable memory opts and friends.
2021-12-06 12:47:29 -08:00
Kavon Farvardin
cecdc807d6 impose self restrictions in distributed actor inits
I initially left-out these restrictions, while
the design of distributed actor inits was in flux.
Now that the dust is somewhat settled, we need the same
restrictions on `self` that regular actors have, because
we do not want the local instance to have races in the init.
2021-10-21 19:41:31 -07:00
Hamish Knight
cead30d639 [SIL] Adopt ArgumentList 2021-09-01 18:40:27 +01:00
Kavon Farvardin
d23858f61a inject hop_to_executor in async actor inits
Because `self` can be used unrestricted after it is
fully-initialized in an async actor init, we perform
a hop_to_executor(self) immediately after `self`
is fully-initialized on all paths within the
initializer.

If we did not, then code could race with the
initializer if it, e.g., spawns a task from
the initializer and mutates actor state that
the initializer then reads. By hopping to the
executor, we prevent that task from running
until _after_ the initializer completes.
2021-07-16 15:01:12 -07:00
Erik Eckstein
a263263f9e DefiniteInitialization: correctly handle implicit closures in initializers of derived classes.
Support for implicit closures was already added in c452e4cc13:

    init() {
      bool_member1 = false
      bool_member2 = false || bool_member1 // implicit closure
    }

But this didn't work for initializers of derived classes.

rdar://66420045
2021-07-06 13:12:46 +02:00
Kavon Farvardin
f722ccdcdd restrict uses of 'self' in certain actor initializers
A uniqueness rule for 'self' is enforced throughout
the following types of actor initializers:

1. synchronous
2. global-actor isolated

This means that 'self' cannot be used for anything,
even after 'self' is fully initialized, other than
for access to stored properties. Method calls are
considered escaping uses of 'self', since it is passed
implicitly to the method of computed property when invoked.

Also, an actor's convenience init now treats self as
nonisolated.

This provides a way to perform follow-up work after
self is fully initialized, when creating the
actor from a synchronous context.

Resolves rdar://78790369
2021-06-23 14:17:00 -07:00
John McCall
12a4d471c0 In DI, cache whether a memory object is a box.
Boxes tend to have a small number of uses, so frequently finding the
unique projection isn't too bad.  Non-boxes, however, can have a large
number of uses: for example, a class instance has expected uses
proportionate to the number of stored properties.  So if we do a linear
scan of the uses on a non-box instruction, we'll scale quadratically.

Fixes SR-14532.
2021-05-07 18:50:00 -04:00
Erik Eckstein
c452e4cc13 DefiniteInitialization: correctly handle implicit closures.
Correctly handle implicit closures in initializers, e.g. with boolean operators:

init() {
  bool_member1 = false
  bool_member2 = false || bool_member1 // implicit closure
}

The implicit closure ('bool_member1' at the RHS of the || operator) captures the whole self, but only uses 'bool_member1'.
If the whole captured 'self' is considered as use, we would get a "'self.bool_member2' not initialized" error at the partial_apply.
Therefore look into the body of the closure and only add the actually used members.

rdar://66420045
2021-01-07 23:46:50 +01: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
Slava Pestov
37f2bc1e59 DI: Add non-working code for handling value_metatype when used on an address-only type 2020-10-23 22:25:58 -04:00
Slava Pestov
53b91da82f DI: Remove scalarization 'pass'
All the tests seem to pass without it now.
2020-10-10 23:00:03 -04:00
Andrew Trick
5ae231eaab Rename getFieldNo() to getFieldIndex().
Do I really need to justify this?
2020-09-24 22:44:13 -07:00
Anthony Latsis
9fd1aa5d59 [NFC] Pre- increment and decrement where possible 2020-06-01 15:39:29 +03:00
Michael Gottesman
f57a6cfd6d [silgen] Teach CleanupCloner how to handle OwnedValueWritebackCleanups correctly.
Previously we would just forward the cleanup and create a normal "destroy"
cleanup resulting in early deallocation and use after frees along error paths.

As part of this I also had to tweak how DI recognizes self init writebacks to
not use SILLocations. This is approach is more robust (since we aren't relying
on SourceLocs/have verifiers to make sure we don't violate SIL) and also avoids
issues from the write back store not necessarily have the same SILLocation.

<rdar://problem/59830255>
2020-05-19 16:15:33 -07:00
Anthony Latsis
c63b737e92 Collapse all indirect equivalents to ValueDecl::getBaseIdentifier 2020-03-29 00:36:01 +03:00
Fred Riss
259d78a350 Adapt to llvm.org StringRef API change 2020-03-13 19:08:22 +01:00
David Zarzycki
32c66c38a9 [QoI] Fix -Wunused-variable warning 2020-01-19 13:32:12 -05:00
Michael Gottesman
b4cf1afd19 [di] When emitting element addresses to destroy fields, use begin_access [deinit]. 2020-01-08 14:09:55 -08:00