Certain uses of protocols only formally need the requirement
signature, not any of the method requirements. This results in IRGen
seeing a protocol where none of the members have been validated except
the associated types. Account for this by allowing ProtocolInfo to
only contain the layout for the base protocols and associated types,
if requested.
Note that this relies on the layout of a witness table always putting
the "requirement signature part" at the front, or at least at offsets
that aren't affected by function requirements.
rdar://problem/43260117
We don't need to substitute the superclass type as we walk up a
class hierarchy, or look up the generic parameters and conformances
to check if they're concrete, since we're always just emitting
null pointers in place of the generic parameters and requirements,
to be filled at runtime.
Also, don't leave space for generic parameters and requirements from
Objective-C superclasses, since that's not how they're represented.
We were using this just as a convenient way to share an existing
DenseMap, but it's not really related; we don't need to compute
witness table layout just to generate a conformance reference.
I started working on this because the "Cub" source compat project was
hitting issues here, but now I can't reproduce it. Still, this is a
reasonable cleanup.
- `swift_getForeignTypeMetadata` is now a request/response function.
- The initialization function is now a completion function, and the
pointer to it has moved into the type descriptor.
- The cache variable is no longer part of the ABI; it's an
implementation detail of the access function.
- The two points above mean that there is no special header on foreign
type metadata and therefore that they can be marked constant when
there isn't something about them that needs to be initialized.
The only foreign-metadata initialization we actually do right now is
of the superclass field of a foreign class, and since that relationship
is a proper DAG, it's not actually possible to have recursive
initialization problems. But this is the right long-term thing to do,
and it removes one of the last two clients of once-based initialization.
The central thrust of this patch is to get these metadata initializations
off of `swift_once` and onto the metadata-request system where we can
properly detect and resolve dependencies. We do this by first introducing
runtime support for resolving metadata requests for "in-place"
initializations (committed previously) and then teaching IRGen to actually
generate code to use them (this patch).
A non-trivial amount of this patch is just renaming and refactoring some of
existing infrastructure that was being used for in-place initializations to
try to avoid unnecessary confusion.
The remaining cases that are still using `swift_once` resolution of
metadata initialization are:
- non-generic classes that can't statically fill their superclass or
have resilient internal layout
- foreign type metadata
Classes require more work because I'd like to switch at least the
resilient-superclass case over to using a pattern much more like what
we do with generic class instantiation. That is, I'd like in-place
initialization to be reserved for classes that actually don't need
relocation.
Foreign metadata should also be updated to the request/dependency scheme
before we declare ABI stability. I'm not sure why foreign metadata
would ever require a type to be resolved, but let's assume it's possible.
Fixes part of SR-7876.
Switch one entry point in the runtime (swift_getExistentialTypeMetadata)
to use ProtocolDescriptorRef rather than a protocol descriptor. Update
IRGen to produce ProtocolDescriptorRef instances for its calls, setting
the discriminator bit appropriately.
Within the runtime, verify that all instances of ProtocolDescriptorRef have
the right layout, i.e., the discriminator bit is set for @objc protocols
but not Swift protocols.
A Swift subclass of an ObjC class can be dynamically subclassed, but `type(of:)` shouldn't return the artificial subclass, since that's not what -class does for ObjC classes, and people expect `Bundle(for: type(of: c))` to work like `[NSBundle bundleForClass: [c class]]` would in ObjC. Fixes rdar://problem/37319860.
SubstitutionMaps are now just a trivial pointer-sized value, so
pass them by value instead.
I did have to move a couple of functors from Type.h to SubstitutionMap.h
to resolve some issues with forward declarations.
In the majority of the use-cases transparent functions are inlined by
the mandatory inliner which by design drops all debug info and
pretends the inlined instructions were always part of the
caller. Since an outlined copy of the function is often still
generated, attaching debug locations to it is inconsistent and can
create the false impression that it were possible to set a breakpoint
in such a function when in reality these functions are only there for
very few edge cases.
<rdar://problem/40258813>
- Add swift_getForeignWitnessTable to unique non-unique foreign type
witness tables
- IRGen: Call the foreign witness uniquing runtime function
rdar://24958043
Introduced during the bring-up of the generics system in July, 2012,
Substitution (and SubstitutionList) has been completely superseded by
SubstitutionMap. R.I.P.
We were emitting foreign type metadata for this case, because of an
invalid usage of ClassDecl::isForeign(), which also returns true
for runtime-only classes.
Fixes <rdar://problem/39117602>.
When we use type(of: x) on a class in an ObjC bridged context, the optimizer turns this into a SIL `value_metatype @objc` operation, which is supposed to get the dynamic type of the object as an ObjC class. This was previously lowered by IRGen into a `object_getClass` call, which extracts the isa pointer from the object, but is inconsistent with the `-class` method in ObjC or with the Swift-native behavior, which both look through artificial subclasses, proxies, and so on. This inconsistency led to observably different behavior between debug and release builds and between ObjC-bridged and native entry points, so provide an alternative runtime entry point that replicates the behavior of getting a native Swift class. Fixes SR-7258.
Ensure collocation by recording the dependence between witness table and
witness before functions are processed. Debug info of inlined function
scopes can reference the witness and will cause the wrong IRGenModule to
be associated before lazy witness tables are processed.
No, I am not sure that this is the only instance of this but the same
solution can apply to other instances if we find them.
rdar://39116991
Witness tables for conformances that require runtime instantiation
should not be public, because it is an error to directly reference
such a symbol from outside the module.
Use a different mangling for witness table patterns and give them
non-public linkage.
Most of the work of this patch is just propagating metadata states
throughout the system, especially local-type-data caching and
metadata-path resolution. It took a few design revisions to get both
DynamicMetadataRequest and MetadataResponse to a shape that felt
right and seemed to make everything easier.
The design is laid out pretty clearly (I hope) in the comments on
DynamicMetadataRequest and MetadataResponse, so I'm not going to
belabor it again here. Instead, I'll list out the work that's still
outstanding:
- I'm sure there are places we're asking for complete metadata where
we could be asking for something weaker.
- I need to actually test the runtime behavior to verify that it's
breaking the cycles it's supposed to, instead of just not regressing
anything else.
- I need to add something to the runtime to actually force all the
generic arguments of a generic type to be complete before reporting
completion. I think we can get away with this for now because all
existing types construct themselves completely on the first request,
but there might be a race condition there if another asks for the
type argument, gets an abstract metadata, and constructs a type with
it without ever needing it to be completed.
- Non-generic resilient types need to be switched over to an IRGen
pattern that supports initialization suspension.
- We should probably space out the MetadataStates so that there's some
space between Abstract and Complete.
- The runtime just calmly sits there, never making progress and
permanently blocking any waiting threads, if you actually form an
unresolvable metadata dependency cycle. It is possible to set up such
a thing in a way that Sema can't diagnose, and we should detect it at
runtime. I've set up some infrastructure so that it should be
straightforward to diagnose this, but I haven't actually implemented
the diagnostic yet.
- It's not clear to me that swift_checkMetadataState is really cheap
enough that it doesn't make sense to use a cache for type-fulfilled
metadata in associated type access functions. Fortunately this is not
ABI-affecting, so we can evaluate it anytime.
- Type layout really seems like a lot of code now that we sometimes
need to call swift_checkMetadataState for generic arguments. Maybe
we can have the runtime do this by marking low bits or something, so
that a TypeLayoutRef is actually either (1) a TypeLayout, (2) a known
layout-complete metadata, or (3) a metadata of unknown state. We could
do that later with a flag, but we'll need to at least future-proof by
allowing the runtime functions to return a MetadataDependency.
Abstract type/heap metadata access goes into MetadataRequest.
Metadata access starting from a heap object goes into GenHeap.
Accessing various components of class metadata goes into GenClass
or MetadataLayout.
This includes global generic and non-generic global access
functions, protocol associated type access functions,
swift_getGenericMetadata, and generic type completion functions.
The main part of this change is that the functions now need to take
a MetadataRequest and return a MetadataResponse, which is capable
of expressing that the request can fail. The state of the returned
metadata is reported as an second, independent return value; this
allows the caller to easily check the possibility of failure without
having to mask it out from the returned metadata pointer, as well
as allowing it to be easily ignored.
Also, change metadata access functions to use swiftcc to ensure that
this return value is indeed returned in two separate registers.
Also, change protocol associated conformance access functions to use
swiftcc. This isn't really related, but for some reason it snuck in.
Since it's clearly the right thing to do, and since I really didn't
want to retroactively tease that back out from all the rest of the
test changes, I've left it in.
Also, change generic metadata access functions to either pass all
the generic arguments directly or pass them all indirectly. I don't
know how we ended up with the hybrid approach. I needed to change all
the code-generation and calls here anyway in order to pass the request
parameter, and I figured I might as well change the ABI to something
sensible.
This is simpler, because the native form of that last argument is: a
pointer to a buffer (*) of pointers (*) to witness tables, which is
modelled as a buffer of void *s. Thus, void ***.
The count of the number of witness tables was designed to be an
assertion/check that we've hooked up all the infrastructure
correctly. Everything is now implemented, and the assertion has never
triggered, so it can be removed, saving some work.
Fixes rdar://problem/38038928.
The conformance type's contextual type might not be canonical, such as in the case of substituting a `typealias` type for a generic placeholder, so ensure we get the canonical type for the conformance.
Factor out and reuse logic in the lowering of CondFailInst to emit
non-mergeable traps, everywhere we emit traps. This should address a
debugging quality issue with ambiguous ud2 instructions.
rdar://32772768
Emit nominal type access functions for imported types. These access
functions work with non-unique metadata references, so they perform
uniquing through the runtime on first access.
Fixes rdar://problem/36430234.
The dummy WitnessTableEntry for the protocol conformance descriptor
was used to ensure that the witness indices were offset by 1 (to
account for the protocol conformance descriptor), but it led to some
odd index adjustments. Instead, make the index adjustments explicit
when we're passing a WitnessIndex off to be loaded for a witness
table.
Extend witness tables with a pointer to the protocol conformance
descriptor from which the witness table was generated. This will allow
us to determine (for example) whether two witness tables were
generated from the same (or equivalent) conformances in the future, as
well as discover more information about the witness table itself.
Fixes rdar://problem/36287959.
Emit protocol conformance descriptors as separate symbols, rather than
inlining them within the section for protocol conformance records. We
want separate symbols for protocol conformances both because it is easier
to make them variable-length (as required for conditional
conformances) and because we want to reference them from witness
tables (both of which are coming up).
Only foreign classes and other imported types were making use of the
type metadata reference form in conformance records. Switch those over
to using nominal type descriptors, so we're using nominal type
descriptors for everything possible.
Only Objective-C-defined classes use a different representation now.
If the 'self' type is abstract, we still have to consider it as
a source of type metadata, because it might be a class-bound
generic parameter and the class might have generic parameters.
Fixes <rdar://problem/36093833>.