Previously, the stdlib provided:
- getters for AnyKeyPath and PartialKeyPath, which have remained;
- a getter for KeyPath, which still exists alongside a new read
coroutine; and
- a pair of owned mutable addressors that provided modify-like behavior
for WritableKeyPath and ReferenceWritableKeyPath, which have been
replaced with modify coroutines and augmented with dedicated setters.
SILGen then uses the most efficient accessor available for the access
it's been asked to do: for example, if it's been asked to produce a
borrowed r-value, it uses the read accessor.
Providing a broad spectrum of accessor functions here seems acceptable
because the code-size hit is fixed-size: we don't need to generate
extra code per storage declaration to support more alternatives for
key paths.
Note that this is just the compiler ABI; the implementation is still
basically what it was. That means the implementation of the setters
and the read accessor is pretty far from optimal. But we can improve
the implementation later; we can't improve the ABI.
The coroutine accessors have to be implemented in C++ and used via
hand-rolled declarations in SILGen because it's not currently possible
to declare independent coroutine accessors in Swift.
This is not strictly necessary since we are going to be exiting the program, but
the ownership verifier thinks that the error is leaked otherwise. By using the
end_lifetime we avoid having a small increase in code-size since it is a no-op
after ownership is removed.
rdar://29791263
The `Stmt` and `Expr` classes had both `dump` and `print` methods that behaved similarly, making it unclear what each method was for. Following a conversation in https://forums.swift.org/t/unifying-printing-logic-in-astdumper/15995/6 the `dump` methods will be used to print the S-Expression-like ASTs, and the `print` methods will be used to print the more textual ASTPrinter-based representations. The `Stmt` and `Expr` classes seem to be where this distinction was more ambiguous. These changes should fix that ambiguity.
A few other classes also have `print` methods used to print straightforward representations that are neither the S-Expressions nor ASTPrinters. These were left as they are, as they don't cause the same ambiguity.
It should be noted that the ASTPrinter implementations themselves haven't yet been finished and aren't a part of these changes.
In general we'll want to investigate what we are and aren't SILGen-ing
for textual interfaces of resilient modules, but for fragile modules
we may as well generate everything we can for potential optimization
purposes.
No functionality change. Unfortunately we still need the flag in
SILModule itself because of the ability to create an empty SILModule
and parse SIL into it incrementally, which can happen before there's
a FileUnit to use as the associated DeclContext instead of a
CompilerInstance's main module.
This was only used by the integrated REPL, and is now a dead option.
The "StartElem" option for performTypeChecking is still used for
reading SIL files, which have AST and SIL blocks alternate.
This silences the instances of the warning from Visual Studio about not all
codepaths returning a value. This makes the output more readable and less
likely to lose useful warnings. NFC.
Most of this patch is just removing special cases for materializeForSet
or other fairly mechanical replacements. Unfortunately, the rest is
still a fairly big change, and not one that can be easily split apart
because of the quite reasonable reliance on metaprogramming throughout
the compiler. And, of course, there are a bunch of test updates that
have to be sync'ed with the actual change to code-generation.
This is SR-7134.
This makes it easier to grep for and eventually remove the
remaining usages.
It also allows you to write FunctionType::get({}, ...) to call the
ArrayRef overload empty parameter list, instead of picking the Type
overload and calling it with an empty Type() value.
While I"m at it, in a few places instead of renaming just clean up
usages where it was completely mechanical to do so.
- getAsDeclOrDeclExtensionContext -> getAsDecl
This is basically the same as a dyn_cast, so it should use a 'getAs'
name like TypeBase does.
- getAsNominalTypeOrNominalTypeExtensionContext -> getSelfNominalTypeDecl
- getAsClassOrClassExtensionContext -> getSelfClassDecl
- getAsEnumOrEnumExtensionContext -> getSelfEnumDecl
- getAsStructOrStructExtensionContext -> getSelfStructDecl
- getAsProtocolOrProtocolExtensionContext -> getSelfProtocolDecl
- getAsTypeOrTypeExtensionContext -> getSelfTypeDecl (private)
These do /not/ return some form of 'this'; instead, they get the
extended types when 'this' is an extension. They started off life with
'is' names, which makes sense, but changed to this at some point. The
names I went with match up with getSelfInterfaceType and
getSelfTypeInContext, even though strictly speaking they're closer to
what getDeclaredInterfaceType does. But it didn't seem right to claim
that an extension "declares" the ClassDecl here.
- getAsProtocolExtensionContext -> getExtendedProtocolDecl
Like the above, this didn't return the ExtensionDecl; it returned its
extended type.
This entire commit is a mechanical change: find-and-replace, followed
by manual reformatted but no code changes.
The presence of a deinitializer will eventually indicate whether a
class's deinitializer is non-trivial for non-resilient modules.
Also improve recovery for normal source files for various bad ways
of declaring a deinitializer.
This initial implementation just delegates from SILGenFunctionBuilder to
SILFunctionBuilder. I was going to start transforming verbose uses of
SILFunctionBuilder into higher level APIs on SILGenFunctionBuilder, but I have
run out of time.
This is a good incremental step forward that will let me hide the constructor of
SILFunctionBuilder after I update the optimizer and thus ensure that
SILFunctionBuilder is only used through appropriate composition APIs.
rdar://42301529
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
- Move the filter checks in SILGen for skipping emitting certain property descriptors into the AbstractStorageDecl::exportsPropertyDescriptor() predicate, to ensure that TBDGen and SILGen are in sync
- Fix the linkage of property descriptors to be based on the getter's linkage rather than the property's, since a property may be internal but have usableFromInline accessors
The storage kind has been replaced with three separate "impl kinds",
one for each of the basic access kinds (read, write, and read/write).
This makes it far easier to mix-and-match implementations of different
accessors, as well as subtleties like implementing both a setter
and an independent read/write operation.
AccessStrategy has become a bit more explicit about how exactly the
access should be implemented. For example, the accessor-based kinds
now carry the exact accessor intended to be used. Also, I've shifted
responsibilities slightly between AccessStrategy and AccessSemantics
so that AccessSemantics::Ordinary can be used except in the sorts of
semantic-bypasses that accessor synthesis wants. This requires
knowing the correct DC of the access when computing the access strategy;
the upshot is that SILGenFunction now needs a DC.
Accessor synthesis has been reworked so that only the declarations are
built immediately; body synthesis can be safely delayed out of the main
decl-checking path. This caused a large number of ramifications,
especially for lazy properties, and greatly inflated the size of this
patch. That is... really regrettable. The impetus for changing this
was necessity: I needed to rework accessor synthesis to end its reliance
on distinctions like Stored vs. StoredWithTrivialAccessors, and those
fixes were exposing serious re-entrancy problems, and fixing that... well.
Breaking the fixes apart at this point would be a serious endeavor.
Client code can make a best effort at emitting a key path referencing a property with its publicly exposed API, which in the common case will match what the defining module would produce as the canonical key path component representation of the declaration. We can reduce the code size impact of these descriptors by not emitting them when there's no hidden or possibly-resiliently-changed-in-the-past information about a storage declaration, having the property descriptor symbol reference a sentinel value telling client key paths to use their definition of the key path component.
Introduced during the bring-up of the generics system in July, 2012,
Substitution (and SubstitutionList) has been completely superseded by
SubstitutionMap. R.I.P.
This patch removes the implicit assumption that nominal types live in
the same source file as their extensions.
It works by visiting extension initializers separately from the
initializers for the base nominal type.
rdar://39548257