to correctly handle generalized protocol requirements.
The major missing pieces here are that the conformance search
algorithms in both the AST (type substitution) and IRGen
(witness table reference emission) need to be rewritten to
back-track requirement sources, and the AST needs to actually
represent this stuff in NormalProtocolConformances instead
of just doing ???.
The new generality isn't tested yet; I'm looking into that,
but I wanted to get the abstractions in place first.
When considering a type that declares an archetype bound to an
associated type, we were not generating the access paths to any
underlying conformance data and so were not properly able to grab the
witness table for those conformances resulting in a crash. This way,
all bound requirements also make sure to bind archetype access paths so
we can see actually see the conformances.
not have access to their type arguments at runtime. Use this to
fix the emission of native thunks for imported ObjC-generic
initializers, since they may need to perform bridging.
For now, pseudo-genericity is all-or-nothing, but we may want to
make it apply only to certain type arguments.
Also, clean up some code that was using dead mangling nodes.
Now we can discern the types of values in heap boxes at runtime!
Closure reference captures are a common way of creating reference
cycles, so this provides some basic infrastructure for detecting those
someday.
A closure capture descriptor has the following:
- The number of captures.
- The number of sources of metadata reachable from the closure.
This is important for substituting generics at runtime since we
can't know precisely what will get captured until we observe a
closure.
- The number of types in the NecessaryBindings structure.
This is a holding tank in a closure for sources of metadata that
can't be gotten from the captured values themselves.
- The metadata source map, a list of pairs, for each
source of metadata for every generic argument needed to perform
substitution at runtime.
Key: The typeref for the generic parameter visible from the closure
in the Swift source.
Value: The metadata source, which describes how to crawl the heap from
the closure to get to the metadata for that generic argument.
- A list of typerefs for the captured values themselves.
Follow-up: IRGen tests for various capture scenarios, which will include
MetadataSource encoding tests.
rdar://problem/24989531
"minimal" is defined as the set of requirements that would be
passed to a function with the type's generic signature that
takes the thick metadata of the parent type as its only argument.
Similarly to how we've always handled parameter types, we
now recursively expand tuples in result types and separately
determine a result convention for each result.
The most important code-generation change here is that
indirect results are now returned separately from each
other and from any direct results. It is generally far
better, when receiving an indirect result, to receive it
as an independent result; the caller is much more likely
to be able to directly receive the result in the address
they want to initialize, rather than having to receive it
in temporary memory and then copy parts of it into the
target.
The most important conceptual change here that clients and
producers of SIL must be aware of is the new distinction
between a SILFunctionType's *parameters* and its *argument
list*. The former is just the formal parameters, derived
purely from the parameter types of the original function;
indirect results are no longer in this list. The latter
includes the indirect result arguments; as always, all
the indirect results strictly precede the parameters.
Apply instructions and entry block arguments follow the
argument list, not the parameter list.
A relatively minor change is that there can now be multiple
direct results, each with its own result convention.
This is a minor change because I've chosen to leave
return instructions as taking a single operand and
apply instructions as producing a single result; when
the type describes multiple results, they are implicitly
bound up in a tuple. It might make sense to split these
up and allow e.g. return instructions to take a list
of operands; however, it's not clear what to do on the
caller side, and this would be a major change that can
be separated out from this already over-large patch.
Unsurprisingly, the most invasive changes here are in
SILGen; this requires substantial reworking of both call
emission and reabstraction. It also proved important
to switch several SILGen operations over to work with
RValue instead of ManagedValue, since otherwise they
would be forced to spuriously "implode" buffers.
This is another incremental step toward protocol resilience.
To support resiliently adding requirements with default implementations,
we need to emit the witness thunk for each default requirement once,
and share it between conformances.
However, the body of the witness thunk can call witness methods from
the conformance of <Self : P>. Formerly, witness thunks were only emitted
with a concrete Self type, so any calls were resolved statically.
Now that Self can be abstract in a witness thunk signature, we have to
pass in the witness table and do the necessary gymnastics on both sides
of the call.
At the call site, the witness table is either abstract, concrete, or
undefined, as follows:
- If the unsubstituted Self type is concrete in the witness method
signature, no witness table is necessary; this is the case of a
concrete (non-default) witness thunk.
- If the unsubstituted Self type is abstract and the substituted Self
type is concrete, the witness table is accessed via direct reference.
- If the unsubstituted Self type is abstract and the substituted Self
type is also abstract, the witness table comes from type metadata
that was passed in to the function where the call is taking place.
Inside the body of the witness method thunk, we only bind the witness
table if Self is an abstract type; this rules out the first case above,
where the witness table is not needed and cannot be provided by the
caller.
The result of a SIL witness_method instruction now lowers as an
explosion containing two values, the function pointer itself and
the witness table.
Similarly, partial application thunks now grab the witness table and
package it up in the context.
Special care is taken to support function_ref + apply and
function_ref + partial_apply of @convention(witness_method) callees;
here, we can hit the case where we don't know the original conformance
because the callee is concrete, in which case we just pass in a null
pointer as the witness table.
Witness thunks with an abstract Self currently only work for protocols
without any associated type requirements; to support those, we need
to be able to fulfill associated type metadata from the witness
table for the <Self : P> conformance. This will be addressed as part
of @rjmccall's calling convention work.
Also I didn't make any attempt to support this for @objc protocols that
do not have a witness table. In this case, the extra parameter is not
necessary since we can perform dynamic dispatch on the 'self' value to
call requirements; however, @objc protocols will not support default
implementations, at least not in the near-term.
Use them to generate value witnesses when the type has dynamic packing.
Regularize the interface for calling value witnesses.
Not a huge difference yet, although we do re-use local type data
a little more effectively now.
Since that's somewhat expensive, allow the generation of meaningful
IR value names to be efficiently controlled in IRGen. By default,
enable meaningful value names only when generating .ll output.
I considered giving protocol witness tables the name T:Protocol
instead of T.Protocol, but decided that I didn't want to update that
many test cases.
This eliminates some minor overheads, but mostly it eliminates
a lot of conceptual complexity due to the overhead basically
appearing outside of its context.
The main idea here is that we really, really want to be
able to recover the protocol requirement of a conformance
reference even if it's abstract due to the conforming type
being abstract (e.g. an archetype). I've made the conversion
from ProtocolConformance* explicit to discourage casual
contamination of the Ref with a null value.
As part of this change, always make conformance arrays in
Substitutions fully parallel to the requirements, as opposed
to occasionally being empty when the conformances are abstract.
As another part of this, I've tried to proactively fix
prospective bugs with partially-concrete conformances, which I
believe can happen with concretely-bound archetypes.
In addition to just giving us stronger invariants, this is
progress towards the removal of the archetype from Substitution.
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.
- GenProto.cpp for protocols and protocol conformances
- GenExistential.cpp for existential type layout and operations
- GenArchetype.cpp for archetype type layout and operations
Swift SVN r32493
Refactor emitWitnessTableRefs(), EmitPolymorphicArguments::emit() and
getProtocolWitnessTable() to share code, and make them work for the case
where we have a concrete conformance for an archetype.
Fixes <rdar://problem/20628295>
Swift SVN r28138
As part of this, re-arrange the argument order so that
generic arguments come before the context, which comes
before the error result. Be more consistent about always
adding a context parameter on thick functions, even
when it's unused. Pull out the witness-method Self
argument so that it appears last after the error
argument.
Swift SVN r26667
Provide a special single-ObjC-refcounted type info for error existentials, and lower the existential box instructions to their corresponding runtime calls.
Swift SVN r26469
storage for arbitrary values.
A buffer doesn't provide any way to identify the type of
value it stores, and so it cannot be copied, moved, or
destroyed independently; thus it's not available as a
first-class type in Swift, which is why I've labelled
it Unsafe. But it does allow an efficient means of
opaquely preserving information between two cooperating
functions. This will be useful for the adjustments I
need to make to materializeForSet to support safe
addressors.
I considered making this a SIL type category instead,
like $@value_buffer T. This is an attractive idea because
it's generally better-typed. The disadvantages are that:
- it would need its own address_to_pointer equivalents and
- alloc_stack doesn't know what type will be stored in
any particular buffer, so there still needs to be
something opaque.
This representation is a bit gross, but it'll do.
Swift SVN r23903
Previously, we were not respecting the representation of the existential
metatype and were treating all existential metatypes as if the metatype
was a thick metatype. Instead now we properly grab the instance of the
class from the existential and then query the runtime for the
objc_class. This is done via the new entrypoint
emitHeapMetadataRefForUnknownHeapObject.
I also modified emitHeapMetadataRefForHeapObject to use
emitHeapMetadataRefForUnknownHeapObject instead of
emitLoadOfObjCHeapMetadataRef since the latter does not properly handle
tagged pointers. This bug was found on inspection when Joe and I were
talking about this change.
rdar://18841292
Swift SVN r23308
layouts. Introduce new SIL instructions to initialize
and open existential metatype values.
Don't actually, y'know, lift any of the restriction on
existential metatypes; just pointlessly burn extra
memory storing them.
Swift SVN r22592
Eliminate support code for lowering protocol_method instructions, and eliminate ExtraDataKind::Metadata, which is no longer needed now that SIL provides all the necessary type information at the call site.
Swift SVN r22451
This is necessary to be able to properly stash values with nontrivial lowerings, such as metatypes and functions, inside existential containers. Modify SILGen to lower values to the proper abstraction level before storing them in an existential container. Part of the fix for rdar://problem/18189508, though runtime problems still remain when trying to actually dynamicCast out a metatype from an Any container.
Swift SVN r21830
unexpected forematter from the superclass.
This requires a pretty substantial shift in the
generic-metadata allocation/initialization dance
because (1) we can't allocate class metadata without
knowing what the superclass is and (2) the offset
from the metadata cache entry to the address point is
no longer determined solely by the metadata pattern.
While I'm making invasive changes to metadata, fix
two race conditions in metadata creation. The first
is that we need to ensure that only one thread succeeds
at lazily creating a generic-metadata cache. The second
is that we need to ensure that only one thread actually
attempts to create a particular metadata; any others
should block until the metadata is successfully built.
This commit finishes rdar://17776354. LLDB will
need to adjust to the runtime-private metadata layout
changes.
Swift SVN r20537