Ensure that context descriptor pointers are signed in the runtime by putting the ptrauth_struct attribute on the types.
We use the new __builtin_ptrauth_struct_key/disc to conditionally apply ptrauth_struct to TrailingObjects based on the signing of the base type, so that pointers to TrailingObjects get signed when used with a context descriptor pointer.
We add new runtime entrypoints that take signed pointers where appropriate, and have the compiler emit calls to the new entrypoints when targeting a sufficiently new OS.
rdar://111480914
* [IRGen+Runtime] Layout string getEnumTag for fixed size enums subset
getEnumTag impl for layout strings of fixed sized enums that use a function to fetch the enum tag
* Fix potential UB in IRGen
* [IRGen] Make pointers to accessor functions in layout strings relative
rdar://106319336
Pointers embedded in static layout strings should always be relative, so layout strings can reside in read-only memory.
* Properly handle reference storage ownership
* Pass layout tag and metadata / type layout ppointers separately
* Layout string instantiation fully working
* Fix cases where hasLayoutString flag was not set when it should have
* Update include/swift/ABI/Metadata.h
* [Executors][Distributed] custom executors for distributed actor
* harden ordering guarantees of synthesised fields
* the issue was that a non-default actor must implement the is remote check differently
* NonDefaultDistributedActor to complete support and remote flag handling
* invoke nonDefaultDistributedActorInitialize when necessary in SILGen
* refactor inline assertion into method
* cleanup
* [Executors][Distributed] Update module version for NonDefaultDistributedActor
* Minor docs cleanup
* we solved those fixme's
* add mangling test for non-def-dist-actor
* [IRGen] Add layout strings for generic and resilient types
rdar://105837048
* Add some corner cases
* Add flag to enable generic instantiation and some fixes
* Fix resilient types
* Fix metadata accessor function pointers in combined layout strings
rdar://105837040
* WIP: Store layout string in type metadata
* WIP: More cases working
* WIP: Layout strings almost working
* Add layout string pointer to struct metadata
* Fetch bytecode layout strings from metadata in runtime
* More efficient bytecode layout
* Add support for interpreted generics in layout strings
* Layout string instantiation, take and more
* Remove duplicate information from layout strings
* Include size of previous object in next objects offset to reduce number of increments at runtime
* Add support for existentials
* Build type layout strings with StructBuilder to support target sizes and metadata pointers
* Add support for resilient types
* Properly cache layout strings in compiler
* Generic resilient types working
* Non-generic resilient types working
* Instantiate resilient type in layout when possible
* Fix a few issues around alignment and signing
* Disable generics, fix static alignment
* Fix MultiPayloadEnum size when no extra tag is necessary
* Fixes after rebase
* Cleanup
* Fix most tests
* Fix objcImplementattion and non-Darwin builds
* Fix BytecodeLayouts on non-Darwin
* Fix Linux build
* Fix sizes in linux tests
* Sign layout string pointers
* Use nullptr instead of debug value
* Introduce TypeLayout Strings
Layout strings encode the structure of a type into a byte string that can be
interpreted by a runtime function to achieve a destroy or copy. Rather than
generating ir for a destroy/assignWithCopy/etc, we instead generate a layout
string which encodes enough information for a called runtime function to
perform the operation for us. Value witness functions tend to be quite large,
so this allows us to replace them with a single call instead. This gives us the
option of making a codesize/runtime cost trade off.
* Added Attribute @_GenerateLayoutBytecode
This marks a type definition that should use generic bytecode based
value witnesses rather than generating the standard suite of
value witness functions. This should reduce the codesize of the binary
for a runtime interpretation of the bytecode cost.
* Statically link in implementation
Summary:
This creates a library to store the runtime functions in to deploy to
runtimes that do not implement bytecode layouts. Right now, that is
everything. Once these are added to the runtime itself, it can be used
to deploy to old runtimes.
* Implement Destroy at Runtime Using LayoutStrings
If GenerateLayoutBytecode is enabled, Create a layout string and use it
to call swift_generic_destroy
* Add Resilient type and Archetype Support for BytecodeLayouts
Add Resilient type and Archetype Support to Bytecode Layouts
* Implement Bytecode assign/init with copy/take
Implements swift_generic_initialize and swift_generic_assign to allow copying
types using bytecode based witnesses.
* Add EnumTag Support
* Add IRGen Bytecode Layouts Test
Added a test to ensure layouts are correct and getting generated
* Implement BytecodeLayouts ObjC retain/release
* Fix for Non static alignments in aligned groups
* Disable MultiEnums
MultiEnums currently have some correctness issues with non fixed multienum
types. Disabling them for now then going to attempt a correct implementation in
a follow up patch
* Fixes after merge
* More fixes
* Possible fix for native unowned
* Use TypeInfoeBasedTypeLayoutEntry for all scalars when ForceStructTypeLayouts is disabled
* Remove @_GenerateBytecodeLayout attribute
* Fix typelayout_based_value_witness.swift
Co-authored-by: Gwen Mittertreiner <gwenm@fb.com>
Co-authored-by: Gwen Mittertreiner <gwen.mittertreiner@gmail.com>
The new intrinsic, exposed via static functions on Task<T, Never> and
Task<T, Error> (rethrowing), begins an asynchronous context within a
synchronous caller's context. This is only available for use under the
task-to-thread concurrency model, and even then only under SPI.
`willreturn`
This function attribute indicates that a call of this function will
either exhibit undefined behavior or comes back and continues execution
at a point in the existing call stack that includes the current
invocation. Annotated functions may still raise an exception, i.a.,
`nounwind` is not implied. If an invocation of an annotated function does
not return control back to a point in the call stack, the behavior is
undefined.
I conservatively did not assume that the deinit is willreturn therefore
release like operations are not marked `willreturn`.
rdar://73574236
Define the possible runtime effects of an instruction in an enum `RuntimeEffect`.
Add a new utility `swift:getRuntimeEffect` to estimate the runtime effects of an instruction.
Also, add a mechanism to validate the correctness of the analysis in IRGen: annotate all runtime functions in RuntimeFunctions.def with the actual effect what the runtime function has or can have. Then check if the effects of emitted runtime functions for an instruction match what `getRuntimeEffect` predicts.
This check is only enabled on demand by defining the CHECK_RUNTIME_EFFECT_ANALYSIS macro in RuntimeEffect.h
`objc_getRequiredClass` will produce a fatal error if the class isn't
found, which will prevent a malformed program using back-deployed @objc
actor from launching. Also eliminate the spurious `objc_opt_self`
call, which is unneeded given that we're realizing the metadata.
Thanks to Mike Ash for the review.
@objc actors implicitly inherit from the new, hidden
`SwiftNativeNSObject` class that inherits from `NSObject` yet provides
Swift-native reference counting, which is important for the actor
runtime's handling of zombies. However, `SwiftNativeNSObject` is only
available in the Swift runtime in newer OS versions (e.g., macOS
12.0/iOS 15.0), and is available in the back-deployed _Concurrency
library, but there is no stable place to link against for
back-deployed code. Tricky, tricky.
When back-deploying @objc actors, record `NSObject` as the superclass
in the metadata in the binary, because we cannot reference
`SwiftNativeNSObject`. Then, emit a static initializer to
dynamically look up `SwiftNativeNSObject` by name (which will find it
in either the back-deployment library, on older systems, or in the
runtime for newer systems), then swizzle that in as the superclass of
the @objc actor.
Fixes rdar://83919973.
When back-deploying, create global-actor-qualified function types via a
separate entrypoint
(`swift_getFunctionTypeMetadataGlobalActorBackDeploy`) in the
compatibility library, which checks whether it is running with a
new-enough runtime to use `swift_getFunctionTypeMetadataGlobalActor`.
Failing that, it calls into a separate copy of the implementation that
exists only in the back-deployed concurrency library.
Fixes rdar://79153988.
Change the code generation patterns for `async let` bindings to use an ABI based on the following
functions:
- `swift_asyncLet_begin`, which starts an `async let` child task, but which additionally
now associates the `async let` with a caller-owned buffer to receive the result of the task.
This is intended to allow the task to emplace its result in caller-owned memory, allowing the
child task to be deallocated after completion without invalidating the result buffer.
- `swift_asyncLet_get[_throwing]`, which replaces `swift_asyncLet_wait[_throwing]`. Instead of
returning a copy of the value, this entry point concerns itself with populating the local buffer.
If the buffer hasn't been populated, then it awaits completion of the task and emplaces the
result in the buffer; otherwise, it simply returns. The caller can then read the result out of
its owned memory. These entry points are intended to be used before every read from the
`async let` binding, after which point the local buffer is guaranteed to contain an initialized
value.
- `swift_asyncLet_finish`, which replaces `swift_asyncLet_end`. Unlike `_end`, this variant
is async and will suspend the parent task after cancelling the child to ensure it finishes
before cleaning up. The local buffer will also be deinitialized if necessary. This is intended
to be used on exit from an `async let` scope, to handle cleaning up the local buffer if necessary
as well as cancelling, awaiting, and deallocating the child task.
- `swift_asyncLet_consume[_throwing]`, which combines `get` and `finish`. This will await completion
of the task, leaving the result value in the result buffer (or propagating the error, if it
throws), while destroying and deallocating the child task. This is intended as an optimization
for reading `async let` variables that are read exactly once by their parent task.
To avoid an epoch break with existing swiftinterfaces and ABI clients, the old builtins and entry
points are kept intact for now, but SILGen now only generates code using the new interface.
This new interface fixes several issues with the old async let codegen, including use-after-free
crashes if the `async let` was never awaited, and the inability to read from an `async let` variable
more than once.
rdar://77855176
Tracking this as a single bit is actually largely uninteresting
to the runtime. To handle priority escalation properly, we really
need to track this at a finer grain of detail: recording that the
task is running on a specific thread, enqueued on a specific actor,
or so on. But starting by tracking a single bit is important for
two reasons:
- First, it's more realistic about the performance overheads of
tasks: we're going to be doing this tracking eventually, and
the cost of that tracking will be dominated by the atomic
access, so doing that access now sets the baseline about right.
- Second, it ensures that we've actually got runtime involvement
in all the right places to do this tracking.
A propos of the latter: there was no runtime involvement with
awaiting a continuation, which is a point at which the task
potentially transitions from running to suspended. We must do
the tracking as part of this transition, rather than recognizing
in the run-loops that a task is still active and treating it as
having suspended, because the latter point potentially races with
the resumption of the task. To do this, I've had to introduce
a runtime function, swift_continuation_await, to do this awaiting
rather than inlining the atomic operation on the continuation.
As part of doing this work, I've also fixed a bug where we failed
to load-acquire in swift_task_escalate before walking the task
status records to invoke escalation actions.
I've also fixed several places where the handling of task statuses
may have accidentally allowed the task to revert to uncancelled.