The metadata system doesn't actually unique based on labels
correctly, so the test case has to play some games. That's
something that will be easier to fix when there are fewer
clients poking at the internals of the metadata runtime.
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.
For convenience when reading looking at heap closure metadata.
Also move the capture typerefs above the metadata sources, since
they're more likely to be accessed than generic metadata sources.
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.
ReflectionContext is getting too large, and having to thread a
<Remote> template parameter through all code that wants to construct
typerefs is getting tricky. This is the first patch in a refactoring
to move some stuff out of ReflectionContext.
The compiler is generally free to not include pointers to metadata in
heap boxes, which are used for closure captures, if it knows you can get
to metadata through some other path. These MetadataSource classes will
describe a sequence of steps to get to metadata at runtime.
In the short term, this will be useful for describing the layout of
function/closure capture contexts, which can vary depending on what is
captured.
Previously we would pre-process the same input files in the ObjC
and non-ObjC tests. This made the tests difficult to update because
the output of one was a subset of the other, and only one of the
two tests would run on any given platform.
Instead, let's just put the Objective-C tests in their own test
and input files.
In order to perform layout, the remote mirrors library needs to know
about the size, alignment and extra inhabitants of builtin types.
Ideally we would emit a reflection info section in libswiftRuntime.o,
but in the meantime just duplicate builtin type metadata for all
builtin types referenced from the current module instead.
In practice only the stdlib and a handful of overlays like the SIMD
overlay use builtin types, and only a few at a time.
Tested manually by running swift-reflection-tool on the standard
library -- I'll add automated tests by using -parse-stdlib to
reference Builtin types in a subsequent patch that adds more layout
logic.
NFC if -enable-reflection-metadata is off.
When creating a TypeRef from metadata, we have a parent pointer
handy, and construct the TypeRef directly, so there's no need
to mutate the TypeRef after the fact.
When demangling a TypeRef from a string, the mangling encodes
the parent module or type context, so we can set it when
constructing the TypeRef there too.
We will be handing pointers to typerefs over the SwiftRemoteMirrors C
API boundary, at which point it is unclear who will hold onto a shared
pointer. The useful lifetime of a typeref is tied to the
ReflectionContext for which they were created anyway so, when it goes
away, all of those typerefs can go away anyway.
We can't use LLVM's bump-pointer allocator here because we only build
the Support library for the host. As a compromise, stuff new typeref
pointers into a vector pool, where they will be taken down during
ReflectionContext's destructor.
The most important change is a fix for dependent member lookup in
bound generic TypeRefs.
The TypeRef logic here is a similified version of what Sema does,
and roughly works as follows:
When looking up a member type O.M for an original type O and
member type M, we first substitute O, to yield a concrete type S.
Then, we look up M in the serialized conformance info section
to yield the unsubstituted member type T', and apply substitutions
to produce the substituted member type T.
Trouble is, we were applying the wrong substitutions the second
time around.
If S is a bound generic type, the "base type substitutions" of S
are the substitutions required to turn the fully-abstracted
bound generic type into S. This might not be the same substitution
map that took us from O to S.
Apart from that, add some assertions that the result of a
substitution is always concrete and that the substitution map
must not contain all generic parameters referenced in the
original type.
Just drop labels when demangling TypeRefs. This is OK for now
since labels do not affect layout.
Vararg tuple types cannot appear directly as the type of
storage, however they can appear in function input types, and
therefore must be minimally supported. Since we don't plan on
doing function call reflection just yet, this doesn't matter
for now, but again we need to not crash.
With this patch, all TypeRefs in the Swift standard library now
successfully demangle and print.