ELF is segment mapped, where the segment which contains a particular
section may be mapped to an address which does not correspond to the
address on disk. Since the reflection dumper does not use the loader to
load the image into memory, we must manually account for any section
offsets. Calculate this value when we query the mmap'ed image and wire
it through to the relative direct pointer accesses.
When switching to the linker table approach for the ELF metadata
introspection, this was uncovered as the segment containing the orphaned
sections was coalesced into a separate PT_LOAD header which had a non-0
offset for the mapping.
Adds the runtime implementation for copy-on-write existentials. This support is
enabled if SWIFT_RUNTIME_ENABLE_COW_EXISTENTIALS is defined. Focus is on
correctness -- not performance yet.
Don't use allocate/deallocate/projectBuffer witnesses for globals in cow
existential mode.
Use SWIFT_RUNTIME_ENABLE_COW_EXISTENTIALS configuration to set the default for
SILOptions.
This includes an IRGen fix to use the right projection in
emitMetatypeOfOpaqueExistential if SWIFT_RUNTIME_ENABLE_COW_EXISTENTIALS is set.
Use unknownRetain instead of native retain in dynamicCastToExistential.
There were a few problems here with subclasses of Objective-C classes.
Use the InstanceStart field from rodata to correctly lay out instance
variables, and verify the results match with dynamic and static layout.
Better fix for <rdar://problem/27932061>.
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.
Part 1: Generic SIL Boxes always have instatiated metadata with kind
HeapGenericLocalVariable, which includes a metadata pointer for the
boxed type.
Part 2, after this, is to provide some kind of outgoing pointer map for
fixed heap boxes, whose metadata may be shared among different but
destructor-compatible types.
rdar://problem/26240419
Without this, offsets of captures in closure contexts may be
incorrect if there is a non-empty necessary bindings structure
at the front.
rdar://problem/26312900
Also add end-to-end tests for this finally, and fix a bug in
the SwiftReflectionTest library where we would give up on an
module completely if it did not have a field metadata section.
This is of course wrong if the module defines closures but
not nominal types.
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.
It's more accurate to use the offset of the "metadata field" of the
existential's RecordTypeInfo when projecting an existential
during remote reflection.
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.
- 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 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.
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.