Mandatory pass will clean it up and replace it by a copy_block and
is_escaping/cond_fail/release combination on the %closure in follow-up
patches.
The instruction marks the dependence of a block on a closure that is
used as an 'withoutActuallyEscaping' sentinel.
rdar://39682865
We need this to update some other tests for SIL linker changes.
Now that we don't eagerly link everything in -Onone, we have to
pipe some test's SIL output through 'sil-opt -performance-linker',
but for that to work we must round-trip imports.
To mark when a user of it is known to escape the value. This happens
with materializeForSet arguments which are captured and used in the
write-back. This means we need to keep the context alive until after
the write-back.
Follow-up patches to fully replace the PostponedCleanup hack in SILGen
by a mandatory SIL transformation pass to guarantee the proper lifetime
will use this flag to be more conservative when extending the lifetime.
The problem:
%pa = partial_apply %f(%some_context)
%cvt = convert_escape_to_noescape [not_guaranteed] [escaped] %pa
%ptr = %materialize_for_set(..., %cvt)
... write_back
... // <-- %pa needs to be alive until after write_back
This statically guarantees that the access has no inner conflict within
its own scope.
IRGen will turn this into a "nontracking" access in which an
exclusivity check is performed for conflicts on an outer scope. However,
unlike normal accesses the runtime does not record the access, and the
access will not be checked for subsequent conflicts.
end_unpaired_access [no_nested_conflict] is not currently
supported. Making a begin_unpaired_access [no_nested_conflict] requires
deleting the corresponding end_unpaired_access. Future runtimes
could support this for verification by storing inline data in the
valud buffer. However, the runtime can never assume that a
[no_nested_conflict] begin_unpaired_access will have a corresponding
end_unpaired_access call without adding a new ExclusivityFlag for
that purpose.
A public subscript might have generic indexes that aren't unconditionally Hashable, or might use indexes that are retroactively made Hashable, so the property descriptor on the implementer's side can't always resiliently provide this information to the final instantiated KeyPath.
Will be used to verify that withoutActuallyEscaping's block does not
escape the closure.
``%escaping = is_escaping_closure %closure`` tests the reference count. If the
closure is not uniquely referenced it prints out and error message and
returns true. Otherwise, it returns false. The returned result can be
used with a ``cond_fail %escaping`` instruction to abort the program.
rdar://35525730
This patch both makes debug variable information it optional on
alloc_stack and alloc_box instructions, and forced variable
information on debug_value and debug_value_addr instructions. The
change of the interface uncovered a plethora of bugs in SILGen,
SILTransform, and IRGen's LoadableByAddress pass.
Most importantly this fixes the previously commented part of the
DebugInfo/local-vars.swift.gyb testcase.
rdar://problem/37720555
This is mostly intended to be used for testing at this point; in the
long run, we want to be using availability information to decide
whether to weak-link something or not. You'll notice a bunch of FIXMEs
in the test case that we may not need now, but will probably need to
handle in the future.
Groundwork for doing backward-deployment execution tests.
This will allow key paths to resiliently reference public properties from other binaries by referencing a descriptor vended by the originating binary. NFC yet, this just provides printing/parsing/verification of the new component.
@noescape function types will eventually be trivial. A
convert_escape_to_noescape instruction does not take ownership of its
operand. It is a projection to the trivial value carried by the closure
-- both context and implementation function viewed as a trivial value.
A safe SIL program must ensure that the object that the project value is based
on is live beyond the last use of the trivial value. This will be
achieve by means of making the lifetimes dependent.
For example:
%e = partial_apply [callee_guaranteed] %f(%z) : $@convention(thin) (Builtin.Int64) -> ()
%n = convert_escape_to_noescape %e : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
%n2 = mark_dependence %n : $@noescape @callee_guaranteed () -> () on %e : $@callee_guaranteed () -> ()
%f2 = function_ref @use : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
apply %f2(%n2) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
release_value %e : $@callee_guaranteed () -> ()
Note: This is not yet actually used.
Part of:
SR-5441
rdar://36116691
This is going to be used for "always emit into client" functions,
such as default argument generators and stored property
initializers.
- In dead function elimination, these functions behave identically to
public functions, serving as "anchors" for the mark-and-sweep
analysis.
- There is no external variant of this linkage, because external
declarations can use HiddenExternal linkage -- the definition should
always be emitted by another translation unit in the same Swift
module.
- When deserialized, they receive shared linkage, because we want the
linker to coalesce multiple copies of the same deserialized
definition if it was deserialized from multiple translation units
in the same Swift module.
- When IRGen emits a definition with this linkage, it receives the
same LLVM-level linkage as a hidden definition, ensuring it does not
have a public entry point.
This has three principal advantages:
- It gives some additional type-safety when working
with known accessors.
- It makes it significantly easier to test whether a declaration
is an accessor and encourages the use of a common idiom.
- It saves a small amount of memory in both FuncDecl and its
serialized form.
* Reduce array abstraction on apple platforms dealing with literals
Part of the ongoing quest to reduce swift array literal abstraction
penalties: make the SIL optimizer able to eliminate bridging overhead
when dealing with array literals.
Introduce a new classify_bridge_object SIL instruction to handle the
logic of extracting platform specific bits from a Builtin.BridgeObject
value that indicate whether it contains a ObjC tagged pointer object,
or a normal ObjC object. This allows the SIL optimizer to eliminate
these, which allows constant folding a ton of code. On the example
added to test/SILOptimizer/static_arrays.swift, this results in 4x
less SIL code, and also leads to a lot more commonality between linux
and apple platform codegen when passing an array literal.
This also introduces a couple of SIL combines for patterns that occur
in the array literal passing case.
Previously, when in the debugger and dumping out SIL code, the
printer would crash if it encountered a null operand. If you
are dumping a basic block, this means that the dump stops at
that instruction instead of showing you the whole block. Null
operands can happen when you call dropAllReferences() but have
yet to delete the instruction.
Now the printer is a bit more resilient. We probably don't catch
all the cases, but we handle a lot of them, e.g.:
%116 = apply <<NULL OPERAND>>(<<NULL OPERAND>>, <<NULL OPERAND>>) : <<NULL CALLEE>>
debug_value <<NULL OPERAND>>, let, name "c", argno 1 // id: %120
retain_value <<NULL OPERAND>> // id: %138
Since this is only relevant to invalid IR, this is just
a debugging aid, so no testcase.
Now that we have interface types in witness tables, make sure to set the
appropriate generic environment when printing witness tables. This
ensures that we get the resugared generic type parameter names.
For now these are underscored attributes, i.e. compiler internal attributes:
@_optimize(speed)
@_optimize(size)
@_optimize(none)
Those attributes override the command-line specified optimization mode for a specific function.
The @_optimize(none) attribute is equivalent to the already existing @_semantics("optimize.sil.never") attribute
...as detected by initializing an individual field without having
initialized the whole object (via `self = value`).
This only applies in pre-Swift-5 mode because the next commit will
treat all cross-module struct initializers as delegating in Swift 5.