- Implement emission of type references for nominal type field
reflection, using a small custom encoder resulting in packed
structs, not strings. This will let us embed 7-bit encoded
32-bit relative offsets directly in the structure (not yet
hooked in).
- Use the AST Mangler for encoding type references
Archetypes and internal references were complicating this before, so we
can take the opportunity to reuse this machinery and avoid unique code
and new ABI.
Next up: Tests for reading the reflection sections and converting the
demangle tree into a tree of type references.
Todo: For concrete types, serialize the types for associated types of
their conformances to bootstrap the typeref substitution process.
rdar://problem/15617914
This comes with a fix for a null pointer dereference in _typeByName()
that would pop with foreign classes that do not have a
NominalTypeDescriptor.
Also, I decided to back out part of the change for now, where the
NominalTypeDescriptor references an accessor function instead of a
pattern, since this broke LLDB, which reaches into the pattern to
get the generic cache.
Soon we will split off the generic cache from the pattern, and at
that time we can change the NominalTypeDescriptor to point at the
cache. But for now, let's avoid needless churn in LLDB by keeping
that part of the setup unchanged.
Change conformance records to reference NominalTypeDescriptors instead of
metadata patterns for resilient or generic types.
For a resilient type, we don't know if the metadata is constant or not,
so we can't directly reference either constant metadata or the metadata
template.
Also, whereas previously NominalTypeDescriptors would point to the
metadata pattern, they now point to the metadata accessor function.
This allows the recently-added logic for instantiating concrete types
by name to continue working.
In turn, swift_initClassMetadata_UniversalStrategy() would reach into
the NominalTypeDescriptor to get the pattern out, so that its bump
allocator could be used to allocate ivar tables. Since the pattern is
no longer available this way, we have to pass it in as a parameter.
In the future, we will split off the read-write metadata cache entry
from the pattern; then swift_initClassMetadata_UniversalStrategy() can
just take a pointer to that, since it doesn't actually need anything
else from the pattern.
Since Clang doesn't guarantee alignment for function pointers, I had
to kill the cute trick that packed the NominalTypeKind into the low
bits of the relative pointer to the pattern; instead the kind is now
stored out of line. We could fix this by packing it with some other
field, or keep it this way in case we add new flags later.
Now that generic metadata is instantiated by calling accessor functions,
this change removes the last remaining place that metadata patterns were
referenced from outside the module they were defined in. Now, the layout
of the metadata pattern and the behavior of swift_getGenericMetadata()
is purely an implementation detail of generic metadata accessors.
This patch allows two previously-XFAIL'd tests to pass.
Instead of directly emitting calls to swift_getGenericMetadata*() and
referencing metadata templates, call a metadata accessor function
corresponding to the UnboundGenericType of the NominalTypeDecl.
The body of this accessor forwards arguments to a runtime metadata
instantiation function, together with the template.
Also, move some code around, so that metadata accesses which are
only done as part of the body of a metadata accessor function are
handled separately in emitTypeMetadataAccessFunction().
Apart from protocol conformances, this means metadata templates are
no longer referenced from outside the module where they were defined.
Recent changes added support for resiliently-sized enums, and
enums resilient to changes in implementation strategy.
This patch adds resilient case numbering, fixing the problem
where adding new payload cases would break existing code by
changing the numbering of no-payload cases.
The problem is that internally, enum cases are numbered with payload
cases coming first, followed by no-payload cases. While each list
is itself in declaration order, with new additions coming at the
end, we need to partition it to give us a fast runtime test for
"is this a payload or no-payload case index."
The resilient numbering strategy used here is that the getEnumTag
and destructiveInjectEnumTag value witness functions now take a
tag index in the range [-ElementsWithPayload..ElementsWithNoPayload-1].
Payload elements are numbered in *reverse* declaration order, so
adding new payload cases yields decreasing tag indices, and adding
new no-payload cases yields increasing tag indices, allowing use
sites to be resilient.
This adds the adjustment between 'fragile' and 'resilient' tag
indices in a somewhat unsatisfying manner, because the calculation
could be pushed down further into EnumImplStrategy, simplifying
both the IRGen code and the generated IR. I'll clean this up later.
In the meantime, clean up some other stuff in GenEnum.cpp, mostly
abstracting code that walks cases.
An individual field record for a nominal type consists of:
- 32-bit general purpose flags,
- 32-bit relative offset to the encoded type reference string, or
32-bit relative offset to the mangled name of the type defined
in another image, and
- 32-bit relative offset to the field name string.
Decrease the size of nominal type descriptors and make them true-const by relative-addressing the other metadata they need to reference, which should all be included in the same image as the descriptor itself. Relative-referencing string constants exposes a bug in the Apple linker, which crashes when resolving relative relocations to coalesceable symbols (rdar://problem/22674524); work around this for now by revoking the `unnamed_addr`-ness of string constants that we take relative references to. (I haven't tested whether GNU ld or gold also have this problem on Linux; it may be possible to conditionalize the workaround to only apply to Darwin targets for now.)
replace ProtocolConformanceTypeKind with TypeMetadataRecordKind
metadata reference does not need to be indirectable
more efficient check for protocol conformances
remove swift_getMangledTypeName(), not needed yet
kill off Remangle.cpp for non-ObjC builds
cleanup
cleanup
cleanup comments
This patch adds powerpc64le Linux support. While the patch also adds
the matching powerpc64 bits, there are endian issues that need to be
sorted out.
The PowerPC LLVM changes for the swift ABI (eg returning three element
non-homogeneous aggregates) are still in the works, but a simple LLVM
fix to allow those aggregates results in swift passing all but 8
test cases.
of associated types in protocol witness tables.
We use the global access functions when the result isn't
dependent, and a simple accessor when the result can be cheaply
recovered from the conforming metadata. Otherwise, we add a
cache slot to a private section of the witness table, forcing
an instantiation per conformance. Like generic type metadata,
concrete instantiations of generic conformances are memoized.
There's a fair amount of code in this patch that can't be
dynamically tested at the moment because of the widespread
reliance on recursive expansion of archetypes / dependent
types. That's something we're now theoretically in a position
to change, and as we do so, we'll test more of this code.
This speculatively re-applies 7576a91009,
i.e. reverts commit 11ab3d537f.
We have not been able to duplicate the build failure in
independent testing; it might have been spurious or unrelated.
of associated types in protocol witness tables.
We use the global access functions when the result isn't
dependent, and a simple accessor when the result can be cheaply
recovered from the conforming metadata. Otherwise, we add a
cache slot to a private section of the witness table, forcing
an instantiation per conformance. Like generic type metadata,
concrete instantiations of generic conformances are memoized.
There's a fair amount of code in this patch that can't be
dynamically tested at the moment because of the widespread
reliance on recursive expansion of archetypes / dependent
types. That's something we're now theoretically in a position
to change, and as we do so, we'll test more of this code.
This reverts commit 6528ec2887, i.e.
it reapplies b1e3120a28, with a fix
to unbreak release builds.
This reverts commit b1e3120a28.
Reverting because this patch uses WitnessTableBuilder::PI in NDEBUG code.
That field only exists when NDEBUG is not defined, but now NextCacheIndex, a
field that exists regardless, is being updated based on information from PI.
This problem means that Release builds do not work.
of associated types in protocol witness tables.
We use the global access functions when the result isn't
dependent, and a simple accessor when the result can be cheaply
recovered from the conforming metadata. Otherwise, we add a
cache slot to a private section of the witness table, forcing
an instantiation per conformance. Like generic type metadata,
concrete instantiations of generic conformances are memoized.
There's a fair amount of code in this patch that can't be
dynamically tested at the moment because of the widespread
reliance on recursive expansion of archetypes / dependent
types. That's something we're now theoretically in a position
to change, and as we do so, we'll test more of this code.
Many of the report* entry points are specific to the stdlib assert implementation, so belong in the stdlib. Keep a single `reportError` entry point in the runtime to handle the CrashReporter/ASL interface, and call down to it from the assert implementation functions.
Now, such classes will emit a metadata pattern and use the
generic metadata instantiation logic.
This was all wired up to handle the case of no generic
parameters previously, to support resilient struct layout
in the runtime.
The swift_initializeSuperclass() entry point still exists,
providing a fast path for when there's no field layout to
do, which is currently always true if we have a concrete
class.
This entry point no longer needs the global lock, since
now we get a per-class lock from the metadata cache.
Also, previously we would call the superclass accessor
function on every access of class metadata for a concrete
subclass of a generic class. Now that we re-use the
existing metadata cache logic, this extra call only occurs
during initialization.
Both swift_initializeSuperclass() and
swift_initClassMetadata_UniversalStrategy() used to take
the superclass as a parameter, but this isn't really
necessary, since it was loaded out of the class metadata
immediately prior to the call by the caller. Removing
this parameter makes the ABI a little simpler.
Once class layout supports resilient types, we will also
use swift_initClassMetadata_UniversalStrategy() to lay
out classes with resilient types as fields.
Singleton metadata caches will still allocate a copy of
the template, which is a slight performance regression
from the previous implementation of concrete subclasses
of generic classes. This will be optimized soon.
Right now, the template can always be modified in place;
in the future, it will be possible to modify in place as
long as the superclass is fixed-layout; a resilient superclass
might add or remove fields, thus we cannot leave room for
it in the metadata of the subclass, and will need to grow
the metadata and slide field offsets at runtime using a
new entry point.
Also, the representation of the cache itself could be
optimized to handle the singleton case, since all we
really need here is a lock without any kind of mapping
table.