Now that Optional's type parameter can be lowered, we can't make the assumption that a substituted nominal type in SIL is usable as-is as a formal type. At this moment, we can at least still rely on the fact that only nominals have methods, so we can at least go up to the original unsubstituted function type, extract the Self type from there, and do formal AST type substitution on it. This is still only a stopgap solution that wouldn't necessarily work once we start allowing conformances to be added to structural types, or even constrained extensions on Optional such as 'extension <T: class, U: class> Optional<(T) -> U>, but is good enough to fix SR-3021 for the language today. We would need something like the "substituted generic signature" concept to fully fix this.
Fixes rdar://problem/28873860, where we would miscompile when lightweight generic classes were extended to conform to Swift protocols because we tried to emit parameters for the class's generic parameters for the witness entry points. Prevent this by lowering the witness into a pseudogeneric function in SILGen, and teaching IRGen to do the right thing for a witness with pseudogeneric parameters.
We don't want the machine calling conventions for closure invocation functions to necessarily be tied to the convention for normal thin functions or methods. NFC yet; for now, 'closure' follows the same behavior as the 'method' convention, but as part of partial_apply simplification it will be a requirement that partial_apply takes a @convention(closure) function and a box and produces a @convention(thick) function from them.
basic block, revert to line number 0 instead of reusing the last location.
This avoids emitting illegal IR if there was no previous location and the
instruction being emitted is a function call.
rdar://problem/28237133
Now that the previous patches have shaken out implicit assumptions
about the order of generic requirements and substitutions, we can
make a more radical change, dropping redundant protocol requirements
when building the original generic signature.
This means that the canonical ordering and minimization that we
used to only perform when building the mangling signature is done
all of the time, and hence getCanonicalManglingSignature() can go
away.
Usages now either call getCanonicalSignature(), or operate on the
original signature directly.
When we call the DeclContext variants of these, use the
DeclContext's GenericEnvironment instead of GenericParamList.
Also, these functions would take a resolver argument, but we
always passed in nullptr, so just remove it now.
The old GenericParamList-based versions are still there
since they're called directly from SIL. They will go away
once SILFunction::ContextGenericParams is replaced with
a GenericEnvironment.
The self metadata in the changed method corresponds to the conforming type. For an inheritable conformance, that may be a subclass of the static type, and so the self metadata will be inexact. Currently, all conformances are inheritable.
rdar://27301453
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.
If the conformance in a witness_method instruction represented a derived protocol instead of the exact protocol of the desired method, we would crash. Handle this by drilling down to the exact conformance needed before forming a witness ref. Fixes rdar://problem/26633668.
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.
It can end up in having duplicate sumbols for generated associated type metadata access functions. rdar://problem/26360504
Also, it is not a big benefit for LLVM to emit such witness tables.
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
We prevent the generic parameters to an ObjC generic from being used in an extension method at the sema level, and we don't want the polymorphic convention to try to generate independent parameters since that would break the method convention. Trick the polymorphic convention by producing "impossible" fulfillments for the generic parameters derivable from an ObjC generic method's self type.
...even if the 'self' type is generic. Additionally, Objective-C generic
types cannot be used as a source of type metadata, because Objective-C
generics are erased at runtime by default. (This may need to change.)
With these two changes, we now pass type metadata explicitly when we need
to, and /don't/ try to pass it to Objective-C methods that would have
needed it if they were Swift methods.
in associated type accessors.
The only remaining use of getAll{DependentTypes,Archetypes} in IRGen
is in code that interprets Substitution arrays, which is unavoidable
absent a change to that representation.
"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.
Each runtime function definition in RuntimeFunctions.def states which calling convention
should be used for this runtime function. But IRGen and LLVMPasses were not always
properly propagating this declared calling convention all the way down to llvm's Call instructions.
In many cases, the standard C convention was set for the call irrespective of the actual calling
convention defined for a given runtime function. As a result, incorrect code was generated.
This commit tries to fix all those places, where such a mismatch was found. In many cases this is
achieved by defining a helper function CreateCall in such a way that makes sure that the call instruction
gets the same calling convention as the one used by its callee operand.
We were checking for a @convention(witness_method) callee with an
abstract Self type in several places. Factor this out into a new
pair of methods on SILFunctionType, and fix the logic for static
methods, where the Self archetype is wrapped in a metatype.
from the witness tables for their associations rather than passing
them separately.
This drastically reduces the number of physical arguments required
to invoke a generic function with a complex protocol hierarchy. It's
also an important step towards allowing recursive protocol
constraints. However, it may cause some performance problems in
generic code that we'll have to figure out ways to remediate.
There are still a few places in IRGen that rely on recursive eager
expansion of associated types and protocol witnesses. For example,
passing generic arguments requires us to map from a dependent type
back to an index into the all-dependent-types list in order to
find the right Substitution; that's something we'll need to fix
more generally. Specific to IRGen, there are still a few abstractions
like NecessaryBindings that use recursive expansion and are therefore
probably extremely expensive under this patch; I intend to fix those
up in follow-ups to the greatest extent possible.
There are also still a few things that could be made lazier about
type fulfillment; for example, we eagerly project the dynamic type
metadata of class parameters rather than waiting for the first place
we actually need to do so. We should be able to be lazier about
that, at least when the parameter is @guaranteed.
Technical notes follow. Most of the basic infrastructure I set up
for this over the last few months stood up, although there were
some unanticipated complexities:
The first is that the all-dependent-types list still does not
reliably contain all the dependent types in the minimized signature,
even with my last patch, because the primary type parameters aren't
necessarily representatives. It is, unfortunately, important to
give the witness marker to the primary type parameter because
otherwise substitution won't be able to replace that parameter at all.
There are better representations for all of that, but it's not
something I wanted to condition this patch on; therefore, we have to
do a significantly more expensive check in order to figure out a
dependent type's index in the all-dependent-types list.
The second is that the ability to add requirements to associated
types in protocol refinements means that we have to find the *right*
associatedtype declaration in order to find the associated witness
table. There seems to be relatively poor AST support for this
operation; maybe I just missed it.
The third complexity (so far) is that the association between an
archetype and its parent isn't particularly more important than
any other association it has. We need to be able to recover
witness tables linked with *all* of the associations that lead
to an archetype. This is, again, not particularly well-supported
by the AST, and we may run into problems here when we eliminate
recursive associated type expansion in signatures.
Finally, it's a known fault that this potentially leaves debug
info in a bit of a mess, since we won't have any informaton for
a type parameter unless we actually needed it somewhere.
Fix some interface type/context type confusion in the AST synthesis from the previous patch, add a unique private mangling for behavior protocol conformances, and set up SILGen to emit the conformances when property declarations with behaviors are visited. Disable synthesis of the struct memberwise initializer if any instance properties use behaviors; codegen will need to be redesigned here.
If a resilient protocol is defined in a different resilience domain
than the conformance, new requirements may be added resiliently
without recompiling the module containing the conformance.
So we must use the accessor, and call a runtime function in the body
of the accessor to instantiate the conformance.
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.