Previously we would emit both a builtin descriptor and field
descriptor for imported classes, but we only need the latter.
Untangle some code and fix a crash with imported Objective-C
generics in the process.
Fixes <rdar://problem/26498484>.
Although this is a target library, it does not need to link against
the standard library, because it doesn't have any Swift content in
it. We need to add a separate build flag for having CMake content
because saying a library "IS_STDLIB" isn't correct for this case.
rdar://problem/26399625
- Lower Objective-C class typerefs as strong references with unknown
reference counting.
- Lower other imported C types as builtin blobs of their known
size, alignment, etc.
In the future, it might be beneficial to track which stored properties
of imported types are pointers, for better conservative scanning of
outgoing pointers to the heap.
rdar://problem/26240258
rdar://problem/26240394
This adds various MetadataReader methods to support closure layout:
- Reading generic arguments from metadata
- Reading parent metadata
- Reading capture descriptor from heap metadata
To a large extent, this is not currently taken advantage of, because
SILGen always wraps address-only captures in SIL box types.
Tests are in the next patch.
Remote metadata for closure contexts points to a capture descriptor.
We have a local copy of all capture descriptors. Translate the
address by recording the local and remote start address of
reflection metadata.
Somehow ninja didn't rebuild everything, so I ended up pushing code
that didn't compile. I did a clean re-build and fixed a minor issue
in the logic, now the test passes.
When deriving substitutions from closure contexts, we end up with
a problem where we have an original type and a substituted type,
and the original type is not necessarily a type parameter.
We need to decompose the original and substituted types to derive
the substitutions that produced the substitution.
For example, deriveSubstitutions(Foo<T -> Int>, Foo<String -> Int>)
will give us a substitution of T := Int.
Closure context layout will depend on the instance itself as well
as the isa pointer, because instead of instantiating metadata for
closures that capture generic parameters, we store the substitutions
inside the context itself.
For classes, this entry point just reads the isa pointer, applies
the isa mask and proceeds down the metadata path.
For now, the only the latter is hooked up.
- Improper handling of read() returning an incomplete read
- Update SwiftReflectionTest library for new builtin types section
Only tested manually so far; automated tests coming soon.
We'd like to be able to compare TypeRefs with pointer equality,
but we can't link LLVMSupport, so make a lightweight TypeRefID
like FoldingSetID, that only supports the input types necessary
to unique TypeRefs.
rdar://problem/25924875
The thin vs thick distinction is handled a little awkwardly. Instead of
passing around abstraction patterns, we add a "must be thick" bit to
MetatypeTypeRef, and thicken substitutions (to handle T; T := C.Type)
and the result of a subtitution (to handle T.Type; T := C).
With the exception of enums this completes <rdar://problem/25738849>.
For now, just enough for lowering.
Perhaps we should have a way to always just get this information
from metadata instead, since protocol metadata is always static
and not instantiated.
This would require the static "object file" interface used by
swift-reflection-dump to take a callback for symbol lookup.
Also add slightly inaccurate lowering for the special case of an
optional of a reference type. I need to rethink the approach for
extra inhabitants and enums, but this suffices for now.
Now we can discern the types of values in heap boxes at runtime!
Closure reference captures are a common way of creating reference
cycles, so this provides some basic infrastructure for detecting those
someday.
A closure capture descriptor has the following:
- The number of captures.
- The number of sources of metadata reachable from the closure.
This is important for substituting generics at runtime since we
can't know precisely what will get captured until we observe a
closure.
- The number of types in the NecessaryBindings structure.
This is a holding tank in a closure for sources of metadata that
can't be gotten from the captured values themselves.
- The metadata source map, a list of pairs, for each
source of metadata for every generic argument needed to perform
substitution at runtime.
Key: The typeref for the generic parameter visible from the closure
in the Swift source.
Value: The metadata source, which describes how to crawl the heap from
the closure to get to the metadata for that generic argument.
- A list of typerefs for the captured values themselves.
Follow-up: IRGen tests for various capture scenarios, which will include
MetadataSource encoding tests.
rdar://problem/24989531
Create a builder divorced from the ReflectionContext so that
MetadataSources can be created in other contexts, such as emitting
private heap metadata during IRGen, where we'll have to record the
layout of captures and how to get metadata for generic arguments in
order to construct typerefs of the captures, etc.
Add Parent, Metadata capture, and Impossible metadata sources.
Now that we can parse and substitute typerefs, and look up field
types, we finally have enough infrastructure in place to do some
basic layout of struct and tuple types from within the Reflection
library.
To facilitate testing, swift-reflection-dump now accepts multiple
-binary-filename flags, allowing types defined in the standard
library to be looked up.
More detailed end-to-end tests will come once I finish the
typeref-to-metadata builder.
We want to look at the nominal type kind before lowering any field
types, since the lowering of a class type does not depend on any
of its field types at all.
Tested by upcoming type lowering patch, for now NFC.
ReflectionContext is now solely concerned with converting runtime
metadata in a remote address space into a TypeRef.
TypeRefBuilder now knows how to parse reflection metadata, and
in particular look up associated type witnesses. This decouples
the TypeRef substitution code from the ReflectionContext. Now
substitution only needs a TypeRefBuilder, which means the code
is no longer templated, and can be moved from TypeRef.h to
TypeRef.cpp.
This also allows the upcoming TypeRef lowering code to live in
a source file instead of headers.