The design implemented in this patch is that we lower the types of accessors with pattern substitutions when lowering them against a different accessor, which happens with class overrides and protocol witnesses, and that we introduce pattern substitutions when substituting into a non-patterned coroutine type. This seems to achieve consistent abstraction without introduce a ton of new complexity.
An earlier version of this patch tried to define witness thunks (conservatively, just for accessors) by simply applying the requirement substitutions directly to the requirement. Conceptually that should work, but I ran into a lot of trouble with things that assumed that pattern substitutions didn't conceal significant substitution work. for example, resolving a dependent member in a component type could find a new use of an opaque archetype when the code assumed that such types had already been substituted away. So while I think that is definiteely a promising direction, I had to back that out in order to make the number of changes manageable for a single PR.
As part of this, I had to fix a number of little bugs here and there, some of which I just introduced. One of these bugfixes is a place where the substitution code was trying to improperly abstract function types when substituting them in for a type parameter, and it's been in the code for a really long time, and I'm really not sure how it's never blown up before.
I'm increasingly of the opinion that invocation substitutions are not actually necessary, but that --- after we've solved the substitution issues above --- we may want the ability to build multiple levels of pattern substitution so that we can guarantee that e.g. witness thunks always have the exact component structure of the requirement before a certain level of substitution, thus allowing the witness substitutions to be easily extracted.
Structurally prevent a number of common anti-patterns involving generic
signatures by separating the interface into GenericSignature and the
implementation into GenericSignatureBase. In particular, this allows
the comparison operators to be deleted which forces callers to
canonicalize the signature or ask to compare pointers explicitly.
The weak imported flag is now only set if the attribute is unconditionally
weak linked, which is the case when it or one of its parent contexts has a
@_weakLinked attribute.
To correctly handle weak linking based availability with serialized SIL
functions, we need to serialize the actual version tuple when the SIL function
was introduced. This is because the deployment target of the client app can
be older than the deployment target that the original module was built with.
Fixes <rdar://problem/52783668>.
* Fix multi-threaded IRGen: store the DeclContext in a SILFunction explicitly instead of deriving it from the debug location. It's used in IRGen to decide into which module a function is emitted. With -gsil the debug location is changed and that should not change the module decision.
* Erase debug_value/debug_value_addr instructions when using -gsil. Those instructions are not needed anymore. They can also trigger a verifier error.
Rather than storing the set of input requirements in a
(SIL)SpecializeAttr, store the specialized generic signature. This
prevents clients from having to rebuild the same specialized generic
signature on every use.
Ownership is truly a property not of a declaration, but of a function body. So
it makes sense to just match what we deserialize.
This also helps us to avoid mismatches if we lower ownership from a function,
delete it, and then relink it.
I also used this as an opportunity to clean up where we set that flag in
deserialization to only happen in one place for both declarations/definitions.
This indicates that the "self" argument to the current function is always dynamically of the exact
static base class type, allowing metadata accesses in IRGen to use the local self metadata to answer
metadata requests for the class type. Set this attribute on allocating entry points of designated
inits, which is one of the most common places where we emit redundant metadata accesses.
Assign separate SILProfiler instances to stored property initializers
and constructors.
Starting with rdar://39460313, coverage reporting for these constructs
was bundled up into a single SILProfiler uniqued by the NominalTypeDecl.
There are two problems with doing this.
First, the shared SILProfiler is given a fake name that can't be
demangled. That breaks Xcode's reports. Second, the relationship
between SILProfiler and SILFunction is supposed to be 1:1. Having a
shared SILProfiler muddies things a bit and requires extra bookkeeping.
rdar://47467864
We've been running doxygen with the autobrief option for a couple of
years now. This makes the \brief markers into our comments
redundant. Since they are a visual distraction and we don't want to
encourage more \brief markers in new code either, this patch removes
them all.
Patch produced by
for i in $(git grep -l '\\brief'); do perl -pi -e 's/\\brief //g' $i & done
SIL passes were violating the existing invariant on non-cond-br
critical edges in several places. I fixed the places that I could
find. Wherever there was a post-pass to "clean up" critical edges, I
replaced it with a a call to verification that the critical edges
aren't broken in the first place.
We still need to eliminate critical edges entirely before enabling
ownership SIL.
ConvertFunction and reabstraction thunks need this attribute. Otherwise,
there is no way to identify that withoutActuallyEscaping was used
to explicitly perform a conversion.
The destination of a [without_actually_escaping] conversion always has
an escaping function type. The source may have either an escaping or
@noescape function type. The conversion itself may be a nop, and there
is nothing distinctive about it. The thing that is special about these
conversions is that the source function type may have unboxed
captures. i.e. they have @inout_aliasable parameters. Exclusivity
requires that the compiler enforce a SIL data flow invariant that
nonescaping closures with unboxed captures can never be stored or
passed as an @escaping function argument. Adding this attribute allows
the compiler to enforce the invariant in general with an escape hatch
for withoutActuallyEscaping.
This commit does not modify those APIs or their usage. It just:
1. Moves the APIs onto SILFunctionBuilder and makes SILFunctionBuilder a friend
of SILModule.
2. Hides the APIs on SILModule so all users need to use SILFunctionBuilder to
create/destroy functions.
I am doing this in order to allow for adding/removing function notifications to
be enforced via the type system in the SILOptimizer. In the process of finishing
off CallerAnalysis for FSO, I discovered that we were not doing this everywhere
we need to. After considering various other options such as:
1. Verifying after all passes that the notifications were sent correctly and
asserting. Turned out to be expensive.
2. Putting a callback in SILModule. This would add an unnecessary virtual call.
I realized that by using a builder we can:
1. Enforce that users of SILFunctionBuilder can only construct composed function
builders by making the composed function builder's friends of
SILFunctionBuilder (notice I did not use the word subclass, I am talking
about a pure composition).
2. Refactor a huge amount of code in SILOpt/SILGen that involve function
creation onto a SILGenFunctionBuilder/SILOptFunctionBuilder struct. Many of
the SILFunction creation code in question are straight up copies of each
other with small variations. A builder would be a great way to simplify that
code.
3. Reduce the size of SILModule.cpp by 25% from ~30k -> ~23k making the whole
file easier to read.
NOTE: In this commit, I do not hide the constructor of SILFunctionBuilder since
I have not created the derived builder structs yet. Once I have created those in
a subsequent commit, I will hide that constructor.
rdar://42301529
The "subclass scope" is meant to represent a connection to a vtable (and how
public something needs to be), for things that end up in class
vtables. Specializations and thunks are mostly internal implementation details
and do not end up there, so subclass scope is not applicable to them. This stops
the thunks and specializations being incorrectly public.
(Note, there are some thunks that _are_ public facing: if a function has its
signature optimized, the original entry point becomes a thunk, and this entry
point is what ends up in vtables etc., so needs to remain around, which means
keeping the same hacks for `private` members of an `open` class.)
Fixes rdar://problem/40738913.
Signature optimization is slightly different to (most) other thunks, in that
it's taking an existing function and turning that into a thunk, rather than
creating a thunk that calls an existing function. These symbols can be public,
etc. and so need to be handled a bit different to other types of thunks.
@effects is too low a level, and not meant for general usage outside
the standard library. Therefore it deserves to be underscored like
other such attributes.
Replace two prominent uses of SubstitutionList, in ConcreteDeclRef and
Witness, with SubstitutionMap. Deal with the myriad places where we
now have substitution maps and need substitution lists (or vice versa)
caused by this change.
Overall, removes ~50 explicit uses of SubstitutionList (of ~400).
The ASTs for functions which aren't definitions may not be fully
typechecked or well-formed, so: avoid looking at them.
This fixes at least one assertion failure seen while building a project
with coverage, and is probably good for some substantial compile-time
improvements with coverage enabled.
rdar://39069115
This is mostly intended to be used for testing at this point; in the
long run, we want to be using availability information to decide
whether to weak-link something or not. You'll notice a bunch of FIXMEs
in the test case that we may not need now, but will probably need to
handle in the future.
Groundwork for doing backward-deployment execution tests.
We need to be able to detect function definitions that have been
deserialized. There's no need to rerun diagnostics on those functions,
and in some cases it's actually incorrect to do so. With exclusivity,
we could even miscompile in theory (debug assert) because the fully
optimized SIL does adhere to rules requires by the
diagnostic. Hopefully that specific issue can be fixed soon, but the
point is that we need control over the order that passes are run
because we play these games all the time. Not to mention the wasted
compilation time.
It would probably be sufficient to check isAvailableExternally. However, using
an explicit flag is, well, more explicit. It also generalizes to serializing IR
at any stage.
Note: I would strongly prefer not to rely on this flag for correctness. In
principle, serialized SIL should be compatible with all SIL stages prior to the
serialization point. However, it is necessary to fix bugs in the short term, and
useful for bootstrapping SIL changes in general. Also, it formalizes some
assumptions about the way the pass pipeline is expected to work making it easier
to reason about and avoid pass ordering bugs. In particular, we should not be
relying on a second round of the mandatory pass pipeline to catch important
performance opportunities.