* [Runtime] Fix CVW for genreic single payload enums with no extra inhabitants
rdar://126728925
When the payload of a generic SPE did not have any extra inhabitants, we erroneously always treated it as the no payload case.
Additionally the offset and skip values were improperly computed.
* Fixed FileCheck string
When storing a tag into a multi-payload enum for an empty case via
swift_storeEnumTagMultiPayload, the tag is split between the storage for
payloads (i.e. the associated values of the non-empty cases) and the
storage for tags (i.e. the integers which refer to the non-empty cases).
Typically, the number of non-empty cases (i.e. one beyond the tag
that refers to the last non-empty case) is stored into the tag storage
and the integer which distinguishes which among the empty cases the enum
is in is stored into storage for payloads. When the enum is small,
however--specifically, when the payload size is less than four
bytes--that information is packaged differently via masking.
Previously, there was a problem with that masking. While the value
stored into the tag storage was correct (and correctly indicated that
the enum was in some empty case), the value stored into the payload
storage was not. The result was that which empty case an enum was in
would be corrupted.
Here, that is fixed by fixing the masking.
rdar://87914343
This adds a new reflection record type carrying spare bit information for multi-payload enums.
The compiler includes this for any type that might need it in order to accurately reflect the contents of the enum. The RemoteMirror library will use this if present to determine how to project the contents of the enum. If not present (for example, in older binaries), the RemoteMirror library falls back on an internal calculation of the spare bitmask.
A few notes:
* The internal calculation is not perfect. In particular, it does not support MPEs that contain other enums (e.g., optionals). It should accurately refuse to project any MPE that it does not correctly support.
* The new reflection field is designed to be expandable; this might someday avoid the need for a new section.
Resolves rdar://61158214
When witness tables for enums are instantiated at runtime via
swift::swift_initEnumMetadataMultiPayload
the witnesses
getEnumTagSinglePayload
storeEnumTagSinglePayload
are filled with swift_getMultiPayloadEnumTagSinglePayload (previously
getMultiPayloadEnumTagSinglePayload) and
swift_storeMultiPayloadEnumTagSinglePayload (previously
storeMultiPayloadEnumTagSinglePayload). Concretely, that occurs when
instantiating the value witness table for a generic enum which has more
than one case with a payload, like Result<T>. To enable the compiler to
do the same work, those functions need to be visible to it.
Here, those functions are made visible to the compiler. Doing so
requires changing the way they are declared and adding them to
RuntimeFunctions.def which in turn requires the definition of some
functions to describe the availability of those functions.
This reduces the dependency on `LLVMSupport`. This is the first step
towards helping move towards a local fork of the LLVM ADT to ensure that
static linking of the Swift runtime and core library does not result in
ODR violations.
This removes it from the AST and largely replaces it with AnyObject
at the SIL and IRGen layers. Some notes:
- Reflection still uses the notion of "unknown object" to mean an
object with unknown refcounting. There's no real reason to make
this different from AnyObject (an existential containing a
single object with unknown refcounting), but this way nothing
changes for clients of Reflection, and it's consistent with how
native objects are represented.
- The value witness table and reflection descriptor for AnyObject
use the mangling "BO" instead of "yXl".
- The demangler and remangler continue to support "BO" because it's
still in use as a type encoding, even if it's not an AST-level
Type anymore.
- Type-based alias analysis for Builtin.UnknownObject was incorrect,
so it's a good thing we weren't using it.
- Same with enum layout. (This one assumed UnknownObject never
referred to an Objective-C tagged pointer. That certainly wasn't how
we were using it!)
This commit centralizes the code that converts variable length
tag values, stored in enum payloads and extra tag bytes, to and
from the 4-byte integer values that the runtime uses to represent
the enum case.
Note that currently big endian machines will store the tag value
in the first word of the destination. This reflects the current
behaviour of the compiler. I am however expecting to change this
so that the value is stored as a true variable-length big-endian
integer in the near future, so the tag value will be stored in
the last 4 bytes of payloads rather than the first 4 bytes like
they are on little-endian systems.
This is essentially a long-belated follow-up to Arnold's #12606.
The key observation here is that the enum-tag-single-payload witnesses
are strictly more powerful than the XI witnesses: you can simulate
the XI witnesses by using an extra case count that's <= the XI count.
Of course the result is less efficient than the XI witnesses, but
that's less important than overall code size, and we can work on
fast-paths for that.
The extra inhabitant count is stored in a 32-bit field (always present)
following the ValueWitnessFlags, which now occupy a fixed 32 bits.
This inflates non-XI VWTs on 32-bit targets by a word, but the net effect
on XI VWTs is to shrink them by two words, which is likely to be the
more important change. Also, being able to access the XI count directly
should be a nice win.
Previously, they would forward their unused spare bits to be used by other multi-payload enums, but
did not implement anything for single-payload extra inhabitants.
This code would previously read off the end of the allocated metadata to fetch these values. This was usually harmless, as the value was never used in that case. However, on rare occasions the metadata would be right before unmapped memory, and this read would crash trying to access that unmapped memory.
rdar://problem/39866044
* Remove RegisterPreservingCC. It was unused.
* Remove DefaultCC from the runtime. The distinction between C_CC and DefaultCC
was unused and inconsistently applied. Separate C_CC and DefaultCC are
still present in the compiler.
* Remove function pointer indirection from runtime functions except those
that are used by Instruments. The remaining Instruments interface is
expected to change later due to function pointer liability.
* Remove swift_rt_ wrappers. Function pointers are an ABI liability that we
don't want, and there are better ways to get nonlazy binding if we need it.
The fully custom wrappers were only needed for RegisterPreservingCC and
for optimizing the Instruments function pointers.
- Create the value witness table as a separate global object instead
of concatenating it to the metadata pattern.
- Always pass the metadata to the runtime and let the runtime handle
instantiating or modifying the value witness table.
- Pass the right layout algorithm version to the runtime; currently
this is always "Swift 5".
- Create a runtime function to instantiate single-case enums.
Among other things, this makes the copying of the VWT, and any
modifications of it, explicit and in the runtime, which is more
future-proof.
So far single payload enums were implemented in terms of runtime functions which
internally emitted several calls to value witnesses.
This commit adds value witnesses to get and store the enum tag side stepping the
need for witness calls as this information is statically available in many cases
/// int (*getEnumTagSinglePayload)(const T* enum, UINT_TYPE emptyCases)
/// Given an instance of valid single payload enum with a payload of this
/// witness table's type (e.g Optional<ThisType>) , get the tag of the enum.
/// void (*storeEnumTagSinglePayload)(T* enum, INT_TYPE whichCase,
/// UINT_TYPE emptyCases)
/// Given uninitialized memory for an instance of a single payload enum with a
/// payload of this witness table's type (e.g Optional<ThisType>), store the
/// tag.
A simple 'for element in array' loop in generic code operating on a
ContigousArray of Int is ~25% faster on arm64.
rdar://31408033
Changes:
* Terminate all namespaces with the correct closing comment.
* Make sure argument names in comments match the corresponding parameter name.
* Remove redundant get() calls on smart pointers.
* Prefer using "override" or "final" instead of "virtual". Remove "virtual" where appropriate.
This affects the computed stride for fixed-sized types in IRGen as well as the stored stride in value witness tables.
The reason is to let comparisons and difference operations work for pointers to zero-sized types.
(Currently this is achieved by using Builtin.strideof_nonzero in MemoryLayout.stride, but this requires a std::max(1, stride) operation after loading the stride)
This reverts commit 893d1dc523.
This looks like a likely culprit that broke tests on the iOS Simulator:
Failing Tests (6):
Swift :: IRGen/class_resilience.swift
Swift :: IRGen/concrete_inherits_generic_base.swift
Swift :: IRGen/enum_resilience.swift
Swift :: IRGen/foreign_types.sil
Swift :: IRGen/nested_types.sil
Swift :: IRGen/struct_resilience.swift
need to be modified by the runtime, and only actually store to them
when that would change anything.
Unfortunately, Linux is considerably better than Darwin at shaking
these bugs out because Darwin will leave global data mutable after
resolving relocations in it.