* Remove getPointerSize and getSizeSize functions, replace with a single PointerSize value.
* Remove imageLength parameter from addImage, calculate it internally instead.
* Check remote mirrors libraries' metadata version and reject them if it's too old.
* Shim GetStringLength and GetSymbolAddress for the legacy library since we don't pass the caller's context pointer through directly.
* Actually set the IsLegacy flag in the Library struct.
* Implement ownsObject by tracking each added image's data segment and checking metadata pointers against them. The previous approach didn't work.
This makes resolving mangled names to nominal types in the same module more efficient, and for eventual secrecy improvements, also allows types in the same module to be referenced from mangled typerefs without encoding any source-level name information about them.
This new format more efficiently represents existing information, while
more accurately encoding important information about nested generic
contexts with same-type and layout constraints that need to be evaluated
at runtime. It's also designed with an eye to forward- and
backward-compatible expansion for ABI stability with future Swift
versions.
The approach here is to split this into two cases:
- If all case payloads have a fixed size, spare bits may be
potentially used to differentiate between cases, and the
remote reflection library does not have enough information to
compute the layout itself.
However, the total size must be fixed, so IRGen just emits a
builtin type descriptor (which I need to rename to 'fixed type
descriptor' since these are also used for imported value types,
and now, certain enums).
- If at least one case has a size that depends on a generic
parameter or is a resilient type, IRGen does not know the size,
but this means fancy tricks with spare bits cannot be used either.
The remote reflection library uses the same approach as the
runtime, basically taking the maximum of the payload size and
alignment, and adding a tag byte.
As with single-payload enums, we produce a new kind of
RecordTypeInfo, this time with a field for every enum case.
All cases start at offset zero (but of course this might change,
if for example we put the enum tag before the address point).
Also, just as with single-payload enums, there is no remote
'project case index' operation on ReflectionContext yet.
So the the main benefit from this change is that we don't entirely
give up when doing layout of class instances containing enums;
however, tools still cannot look inside the enum values themselves,
except in the simplest cases involving optionals.
Notably, the remote reflection library finally understands all
of the standard library's collection types -- Array, Character,
Dictionary, Set, and String.
Attempt to lay out single-payload enums, using knowledge of extra
inhabitants where possible.
- The extra inhabitants of an aggregate are the extra inhabitants of
the first field. If the first field is empty, there are no extra
inhabitants, and subsequent fields do not affect anything.
- Function pointers and metatypes have different extra inhabitants
than Builtin.RawPointer, so have IRGen emit distinct builtin type
descriptors for those.
- Opaque existentials do not have extra inhabitants.
- Weak references do not have extra inhabitants.
Also, fix IRGen to emit more accurate enum reflection metadata in
these two cases:
- We now record whether enum cases are indirect or not. An indirect
case is the same as a payload case with Builtin.NativeObject.
- We now record whether a case is empty or not using the same logic
as the rest of IRGen. Previously, we would incorrectly emit a
payload type for a case with a payload that is an empty struct,
for example.
At this point we don't have a way to get the currently inhabited
enum case from a value. However, this is still an improvement because
we can still reflect other fields of aggregates containing enums,
instead of just giving up.
Finally make some methods on TypeCoverter private, and use 'friend'
to allow them to be accessed from other internal classes, making the
public API simpler.
They would think the type 'addr_t' is defined in the standard library
because it has the same name format with the types in <cstdint>. In
addition, the definition conflicts in Cygwin which defines it differently
in the system library.
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.
Implement the ReflectionContext's implementation of:
swift_reflection_projectExistential.
First, we get the type info of the existential typeref - it should be a
record type info. If it's a class existential, it has trivial layout:
the first word is a pointer to the class instance. Otherwise, if the
value fits in the 3-word buffer of the existential container, it
trivially is also at the start of the container. Otherwise, the value is
off in a heap box somewhere, but the first word of the container is a
pointer to that box.
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.
Also, use the instance layout entry point in swift-reflection-test,
so that we can dump the layout of a class instance and not the
lowering of the reference value.
This tool should test the usage from SwiftRemoteMirror dylib and
the C API, since that is the public interface from which we're
vending the remote reflection functionality.
This API will take a pointer to the start of an existential
container and its typeref and provide a typeref for its
instance type and the address to the start of the instance's
data.
This has a dummy implementation that returns false for now.
swift_reflection_createReflectionContext was defaulting to C++ mangling
because the declaration under extern C in the header didn't match
its signature.
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>.
Memory readers on the C-side of the API may actually have an object-
oriented design, so they may want to pass an instance to revive
when callbacks make it to the other side of the API boundary.
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.