This is a follow up patch that allows for external DescriptorFinders to
provide MultiPayloadEnumDescriptors (this is done to support embedded
Swift debugging, which encodes the equivalent of Swift metadata as
DWARF).
The `ABI` headers had accidentally grown an `#include` into compiler headers,
allowing the enum constant values of the `ValueOwnership` enum to leak into
the runtime ABI. Sever this inappropriate relationship by declaring a separate
`ParameterOwnership` enum with ABI-stable values in the ABI headers, and
explicitly converting between the AST and ABI representation where needed.
Fixes rdar://122435628.
This includes runtime support for instantiating transferring param/result in
function types. This is especially important since that is how we instantiate
function types like: typealias Fn = (transferring X) -> ().
rdar://123118061
If `TypeRefVisitor<DemanglingForTypeRef, Demangle,NodePointer>::visit`
returns `nullptr`, we should pass it through. The callers of
`TypeRef::getDemangling()` are already prepared to cope with `nullptr`
returns, so this should be fine and avoids hitting an assertion
failure in that case.
rdar://120941628
Currently, TypeRefBuilder knows how to parse type descriptors from
reflection metadata. We aim to store the same information that lives
in type descriptors externally, as an effort to support embedded Swift
debugging. In order to take advantage of all of the existing type
information parsing code that exists today in remote mirrors, add an
interface for external lookup of type descriptors, and replace all the
usages of type descriptors with their generic counterpart (this patch
only adds support for builtin descriptors, but follow up patches will
add support for other descriptor types).
Extend function type metadata with an entry for the thrown error type,
so that thrown error types are represented at runtime as well. Note
that this required the introduction of "extended" function type
flags into function type metadata, because we would have used the last
bit. Do so, and define one extended flag bit as representing typed
throws.
Add `swift_getExtendedFunctionTypeMetadata` to the runtime to build
function types that have the extended flags and a thrown error type.
Teach IR generation to call this function to form the metadata, when
appropriate.
Introduce all of the runtime mangling/demangling support needed for
thrown error types.
A "trivial" enum is one that carries no information.
The previous logic asserted that a trivial enum had only one
case and that case had no payload.
But this is also a trivial payload:
```
// Trivial, so zero-sized
enum MyFormatVersion {
case v4
}
// Also trivial, since the payload carries no information
enum Format {
case MyFormat(MyFormatVersion)
}
```
This commit adds a test case similar to the above
and corrects the assertions for trivial enums to
assert that there is either no payload, or that the
payload is zero-sized.
Resolves rdar://116406504
Disable the assert:
// At least one payload is non-empty (otherwise this // would get laid out as a non-payload enum) assert(getNumNonEmptyPayloadCases() > 0);
in TaggedMultiPayloadEnumTypeInfo because it fails when you have
generic but zero-sized payload enum cases.
Also remove unnecessary "REQUIRES: objc_interop" lines from the enum
reflection tests.
When looking for field descriptors for a typeref, we should iterate over
every image info available, even those that the cache claimed to have
processed, as a last ditch effort.
rdar://114567246
I earlier overhauled the enum layout logic to correctly consider
enums with generic cases and cases that have zero size.
This updates the enum projection logic to use that information
as well.
In particular, this fixes a bug where an MPE with zero-sized cases
would be incorrectly projected by RemoteMirror (with consequences
for the `leaks` tool and lldb).
Resolves rdar://111705059
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.
* Risk: Without this, RemoteMirror (and hence client apps) crash on certain inputs
* Resolves: rdar://108809238
* Testing: Ran a client app with a custom-built library to verify it no longer crashes. I've not been able to figure out how to build a unit test that hits this specific code path (in all my unit tests, dependent members seem to get fully substituted before we get to this section of code).
A "generic" case is any case whose payload type depends
on generic type parameters for the enum or any enclosing type.
Some examples:
```
struct S<T> {
enum E {
case a // Non-generic case
case b(Int) // Non-generic case
case c(T) // Generic case
case d([U]) // Generic case
case e([Int]) // Non-generic case
}
}
```
This is important for correctly distinguishing MPE versus
SPE layouts. A case is considered "empty" only if it
is either a non-payload case (`case a`) or if the payload
is zero-sized and non-generic. Generic cases are always
treated as non-zero-sized for purposes of determining
the layout strategy.
Correctly testing this is tricky, since some of the
layout strategies differ only in whether they export
extra tag values as XIs. The easiest way to verify is
to check whether wrapping the result in an `Optional<>`
adds another byte to the overall size.
This exercises a number of cases that the previous logic got
wrong, including cases where MPEs are laid out like SPEs,
and cases where we use the SPE or MPE layout strategies for enums
that have no non-empty payloads. (These cases are superficially
similar but differ in how they handle XIs.)
These new tests allowed me to correct a number logical flaws
about how layouts are selected. In particular, cases with
generic payloads are always considered to be non-empty for
purposes of selecting a layout strategy. Only cases that
are statically known to be empty are considered empty for
layout purposes.
We clear the NodeFactory to prevent unbounded buildup of allocated memory, but this is done too eagerly. In particular, normalizeReflectionName can end up clearing the factory while the calling code is still using nodes that were allocated from it.
To keep peak memory usage low while avoiding this problem, we introduce a checkpoint mechanism in NodeFactory. A checkpoint can be pushed and then subsequently popped. When a checkpoint is popped, only the nodes allocated since the checkpoint was pushed are invalidated and the memory reclaimed. This allows us to quickly clear short-lived nodes like those created in normalizeReflectionName, while preserving longer-lived nodes used in code calling it. Uses of clearNodeFactory are replaced with this checkpoint mechanism.
rdar://106547092
Allocate an empty BuiltinTypeInfo. The code previously allocated a TypeInfo but set its kind to Builtin, which led to calling code doing an incorrect cast and reading an invalid value for the Name field.
rdar://106563125
TypeInfoProvider's address was used as part of the key to cache type
infos. This can cause the unnecessary recomputation of type infos, as
different instances of TypeInfoProviders may provide the exact same type
infos. Allow TypeInfoProviders to provide an id which can be used for
caching purposes.
rdar://80001304
that contain zero-sized payloads, which should resolve a number of issues with
RemoteMirror incorrectly reflecting enum cases and/or measuring the layout of
structures containing enums.
Background: Enum cases that have zero-sized payloads are handled
differently from other payload-bearing cases.
1. For layout purposes, they're treated as
non-payload cases. This can cause an MPE to
actually get represented in memory as a single-payload
or non-payload enum.
2. However, zero-sized payloads are still considered for
extra inhabitant calculations. Since they have no
extra inhabitants, this tends to cause such enums to
also not expose extra inhabitants to containing enums.
This commit makes several change to how RemoteMirror determines
enum layout:
* The various "*EnumTypeInfo" classes now represent
layout mechanisms -- as described in (1) above,
this can differ from the source code concept.
* An Enum "kind" is separately computed to reflect the
source code concept; this ensures that the dumped
type information reflects the source code.
* For single-payload and no-payload _layouts_,
the extra inhabitant calculation has been adjusted
to ensure that zero-sized payloads are correctly
considered.
Resolves: rdar://92945673