Teach SILGen to emit a separate SIL function to capture the
initialization of the backing storage type for a wrapped property
based on the wrapped value. This eliminates manual code expansion at
every use site.
The archetype mangling does not have enough information to accurately recover the associated type
at runtime. This fixes rdar://problem/54084733.
Although this changes the mangling in both runtime and symbols, this should not affect ABI, because
there is no way for associated types of opaque types to be surfaced in the types of public
declarations today.
When we generate code that asks for complete metadata for a fully concrete specific type that
doesn't have trivial metadata access, like `(Int, String)` or `[String: [Any]]`,
generate a cache variable that points to a mangled name, and use a common accessor function
that turns that cache variable into a pointer to the instantiated metadata. This saves a bunch
of code size, and should have minimal runtime impact, since the demangling of any string only
has to happen once.
This mostly just works, though it exposed a couple of issues:
- Mangling a type ref including objc protocols didn't cause the objc protocol record to get
instantiated. Fixed as part of this patch.
- The runtime type demangler doesn't correctly handle retroactive conformances. If there are
multiple retroactive conformances in a process at runtime, then even though the mangled string
refers to a specific conformance, the runtime still just picks one without listening to the
mangler. This is left to fix later, rdar://problem/53828345.
There is some more follow-up work that we can do to further improve the gains:
- We could improve the runtime-provided entry points, adding versions that don't require size
to be cached, and which can handle arbitrary metadata requests. This would allow for mangled
names to also be used for incomplete metadata accesses and improve code size of some generic
type accessors. However, we'd only be able to take advantage of the new entry points in
OSes that ship a new runtime.
- We could choose to always symbolic reference all type references, which would generally reduce
the size of mangled strings, as well as make runtime demangling more efficient, since it wouldn't
need to hit the runtime caches. This would however require that we be able to handle symbolic
references across files in the MetadataReader in order to avoid regressing remote mirror
functionality.
When mangling a dependent protocol conformance ref, the mangler currently uses `0_` to mean an unknown index and `N_` to mean the index `N - 1`. Unfortunately, this is somewhat confused: `0_` is actually the mangling for index 1, and index 0 is supposed to be mangled as just `_`, so true indexes are actually offset by 2. So the first thing to do here is to clarify what's going on throughout the mangler, demangler, and ABI documentation.
Also, the demangler attempts to produce a `DependentProtocolConformance*` node with the appropriate child nodes and an optional index payload. Unfortunately, demangle nodes cannot have both children and a value payload, so whenever it creates a node with an index payload, the demangler will assert. It does this whenever the mangled index is not 0; since (per above) the mangler always produces a non-zero mangled index in this production, the demangler will always assert when processing these. So clearly this is well-tested code, since +asserts builds will always trigger the demangler when mangling a name in the first place. To fix this, we need to make the index a child of the mangling node instead of its payload; at the same time, we can make it store the semantically correct index value and just introduce a new `UnknownIndex` node to handle the `0_` case. This is easy because all current clients ignore this information.
Finally, due to an apparent copy-and-paste error, the demangler attempts to produce a `DependentProtocolConformanceRoot` node for associated protocol conformances; this is easily resolved.
This fixes the crash in SR-10926 (rdar://51710424). The obscurity of this crash --- which originally made us think it might be related to Error self-conformance --- is because it is only triggered when a function signature takes advantage of a concrete-but-dependent retroactive conformance, which (to be both concrete and dependent) must furthermore be conditional. Testing the other cases besides a root conformance requires an even more obscure testcase.
Our mangling did not encode if an Objective-C block was escaping or
not. This is not a huge problem in practice, but for debug info we
want type reconstruction to round-trip exactly. There was a previous
workaround to paper over this specific problem.
Remove the workaround, and add a new 'XL' mangling for escaping
blocks. Since we don't actually want to break ABI compatibility,
only use the new mangling in DWARF debug info.
This is to support dynamic function replacement of functions with opaque
result type.
This approach requires that all state is thrown away (that could contain the
old returned type for an opaque type) between replacements.
rdar://48887938
Extract common code from the old and new remangler into a common base class.
This lets the old remangler benefit from the changes I did recently in the new remangler.
This avoids malloc calls in the common case. Only if there are more than 16 substitutions in the fixed-sized array, the overflow goes into a std::unordered_map.
SR-10028
rdar://problem/48575729
The demangler can be initialized with a preallocated memory on the stack. Only in case of an overflow, the bump pointer allocator mallocs new memory.
Also, support that a new instance of a demangler can "borrow" the free memory from an existing demangler. This is useful because in the runtime the demangler is invoked recursively. With this feature, all the nested demanglers can share a single stack allocated space.
This is done by disallowing nodes with children to also have index or text payloads.
In some cases those payloads were not needed anyway, because the information can be derived later.
In other cases the fix was to insert an additional child node with the index/text payload.
Also, implement single or double children as "inline" children, which avoids needing a separate node vector for children.
All this reduces the needed size for node trees by over 2x.
The type checker calls these types Builtin.FPIEEE<size>; the demangler
should too.
This is just cosmetic at the moment, but it was causing problems when
I added support for builtin types to the TypeDecoder.
New(er) grammar:
// same module as conforming type, or non-unique
protocol-conformance-ref ::= protocol 'HP'
// same module as protocol
protocol-conformance-ref ::= protocol 'Hp'
// retroactive
protocol-conformance-ref ::= protocol module
We don't make use of this distinction anywhere yet, but we could in
the future.
Fix to 510b64fcd5. The mangling operator "HP" has to distinguish
between "protocol" and "protocol module", not between the presence
or absence of protocol-conformance-ref. New grammar:
protocol-conformance-ref ::= protocol
protocol-conformance-ref ::= protocol module 'HP'
rdar://problem/46735592, again
Due to some unfortunate refactoring, protocol-conformance-ref is a
nonterminal in the mangling grammar that doesn't have its own
operator:
```
protocol-conformance-ref ::= protocol module?
```
Both "module" and "protocol" can be an "identifier", which introduces
a mangling collision. Address the mangling collision by using the
operator "HP".
Fixes rdar://problem/46735592.
Use a general ‘type’ production for the conforming type of an associated
witness table accessor mangling, so that we can mangle base protocol
witness table accessors. These entities are always internal symbols, so the
mangling itself doesn’t affect the ABI.
A dynamically replaceable function calls through a global variable that
holds the function pointer.
struct ChainEntry {
void *(funPtr)();
struct ChainEntry *next;
}
ChainEntry dynamicallyReplaceableVar;
void dynamicallyReplaceableFunction() {
dynamicallyReplaceableVar.funPtr()
}
dynamic replacements will be chainable so the global variable also
functions as the root entry in the chain of replacements.
A dynamic replacement functions can call the previous implementation by
going through its chain entry.
ChainEntry chainEntryOf_dynamic_replacement_for_foo;
void dynamic_replacement_for_foo() {
// call the previous (original) implementation.
chainEntryOf_dynamic_replacement_for_foo.funPtr();
}
Change the retroactive conformance mangling to use the new
any-protocol-conformance mangling, which maintains more information about
concrete conformances. Specifically, it maintains conformance information
for conditional requirements. It also uses the protocol-conformance-ref
production that will eventually allow symbolic references to protocol
conformance descriptors.
While here, extend the “is retroactive” check during mangling to look for
retroactive conformances in the conditional requirements of a conformance.
The immediate conformance might not be retroactive, but its specialization
might depend on a retroactive conformance. Mangle these as “retroactive”, so
we can correctly reconstruct the exact type.
Introduce complete mangling for references to protocol conformances:
* Mangle requirements of conditional conformances when present.
* Mangle conformance access paths for generic environment-dependent
conformances.
* Abstract protocol conformance references so we can introduce
symbolic references for them.
Extending the mangling of symbolic references to also include indirect
symbolic references. This allows mangled names to refer to context
descriptors (both type and protocol) not in the current source file.
For now, only permit indirect symbolic references within the current module,
because remote mirrors (among other things) is unable to handle relocations.
Co-authored-by: Joe Groff <jgroff@apple.com>
Default associated conformance accessors will be used in default
witness tables to fill in associated conformances for defaulted
associated types. Add (de|re|)mangling support for them and make them
linking entities in IRGen.
Associated conformance descriptors are aliases that refer to associated
conformance requirements within a protocol descriptor’s list of
requirements. They will be used to provide protocol resilience against
the addition of new associated conformance requirements (which only makes
sense for newly-introduced, defaulted associated types).
When an associated type witness has a default, record that as part of
the protocol and emit a default associated type metadata accessor into the
default witness table. This allows a defaulted associated type to be
added to a protocol resiliently.
This is another part of rdar://problem/44167982, but it’s still very
limiting because the new associated type cannot have any conformances.
Introduce an alias that refers one element prior to the start of a
protocol descriptor’s protocol requirements. This can be subtracted from
an associated type descriptor address to determine the offset of the
associated type accessor within a corresponding witness table. The code
generation for the latter is not yet implemented.
For example:
public struct Mystruct<T> {
func testit<U>(x: T, u: U) {
typealias Myalias = AnyObject
}
}
In this case the Myalias has a generic function as context.