Rather than eagerly doing a bunch of name lookups to establish the known
protocol kind, lazily match the ProtocolDecl to the list of known
protocols as-needed. This eliminates a bunch of up-front unqualified
name lookups when spinning up a type checker.
Add an IRGen flag to disable this verification, since it doesn't work from within
lldb itself for some reason, and I don't want to investigate it right now.
This method wasn’t returning the protocol on which the that the witness
method would satisfy, as documented. Rather, it was returning the protocol
to which the `Self` type conforms, which could be completely unrelated. For
example, in IndexingIterator’s conformance to IteratorProtocol, this method
would produce the protocol “Collection”, because that’s where the witness
itself was implemented. However, there isn’t necessarily a single such
protocol, so checking for/returning a single protocol was incorrect.
It turns out that there were only a few SIL verifier assertions of it
(that are trivially true) and two actual uses in code:
(1) The devirtualizer was using this computation to decide when it didn’t
need to perform any additional substitutions, but it’s predicate for doing
so was essentially incorrect. Instead, it really wanted to check whether
the Self type is still a type parameter.
(2) Our polymorphic convention was using it to essentially check whether
the ’Self’ instance type of a witness_method was a GenericTypeParamType,
which we can check directly.
Fixes rdar://problem/47767506 and possibly the hard-to-reproduce
rdar://problem/47772899.
replace value uses action to make sure that we properly notify passes that we
made the change.
This fixes a latent bug where we were not notifying SILCombine about this
replacement.
Specifically:
- auto replaceCast = [&](SingleValueInstruction *NewCast) {
- assert(Ty.getAs<AnyMetatypeType>()->getRepresentation()
- == NewCast->getType().getAs<AnyMetatypeType>()->getRepresentation());
- MCI->replaceAllUsesWith(NewCast);
- EraseInstAction(MCI);
- return NewCast;
+ auto replaceCast = [&](SILValue newValue) -> SILValue {
+ assert(ty.getAs<AnyMetatypeType>()->getRepresentation() ==
+ newValue->getType().getAs<AnyMetatypeType>()->getRepresentation());
+ ReplaceValueUsesAction(mci, newValue);
+ EraseInstAction(mci);
+ return newValue;
};
Notice how we use MCI->replaceAllUsesWith instead of one of our replace call
backs. SILCombine hooks these to know if it should re-run users.
Previously, we included the PCH hash components in the cache key. While they didn’t do any harm, they didn’t contribute any unique information about the module in question.
Additionally, passing the effective language version in means that each dependency that uses a different -swift-version would re-compile all of its dependencies. This is unfortunate, as that means the standard library is recompiled potentially several times.
DeclAttributes::getUnavailable() only cares about attributes which make a declaration definitely unavailable, but you sometimes need a version which will also return a potentially unavailable (i.e. “introduced:”) attribute. This adds that.
Hashing the contents of the interface files is overkill. In practice, size and last modification time are enough to determine if a file has changed on disk, and therefore should be rebuilt.
NOTE: I changed all places that the CastOptimizer is created to just pass in
nullptr for now so this is NFC.
----
Right now the interface of the CastOptimizer is muddled and confused. Sometimes
it is returning a value that should be used by the caller, other times it is
returning an instruction that is meant to be reprocessed by the caller.
This series of patches is attempting to clean this up by switching to the
following model:
1. If we are optimizing a cast of a value, we return a SILValue. If the cast
fails, we return an empty SILValue().
2. If we are optimizing a cast of an address, we return a boolean value to show
success/failure and require the user to use the SILBuilderContext to get the
cast if they need to.
Once the flag is flipped, ownership stripping will no longer be done in the
diagnostics pipeline. Instead what will happen is that:
* Onone: At -Onone, we run the entire diagnostics pipeline with ownership
enabled and do not strip ownership until after we serialize in the Onone
"optimization" pass pipeline plan.
* -O: At -O, to temporarily work around serialization issues with transparent
functions, we strip ownership from all but transparent functions at the
beginning of the performance pipeline, serialize, and then strip ownership from
transparent functions. For this to work, I needed to make sure that the
performance pipeline passes that do not support ownership SIL, just skip such
functions. So the transparent functions will arrive (mostly) untouched in
serialized SIL and the rest of the pipeline will optimize non-transparent
functions as they should.
The key thing about the -O change is that it /should/ be performance neutral
since after we serialize we re-run the entire pipeline so we can optimize
semantic functions that we only can inline after we serialize.
This normalizes the creation of pass pipelines by ensuring that all pass
pipelines take a SILOption instead of only some. It also makes it so that we do
not need to propagate options through various pipeline creation helpers.
The loading of additional modules by Sema may trigger an out-of-date
PCM rebuild in the Clang module dependencies of the additional
module. A PCM rebuild causes the ModuleManager to unload previously
loaded ASTFiles. For this reason we must use the cached ASTFile
information here instead of the potentially dangling pointer to the
ASTFile that is stored in the clang::Module object.
This fixes a crash in IRGenDebugInfo when generation DIModule context
chains.
rdar://problem/47600180
Beside fixing the compiler crash, this change also improves the stack-nesting correction mechanisms in the inliners:
* Instead of trying to correct the nesting after each inlining of a callee, correct the nesting once when inlining is finished for a caller function.
This fixes a potential compile time problem, because StackNesting iterates over the whole function.
In worst case this can lead to quadratic behavior in case many begin_apply instructions with overlapping stack locations are inlined.
* Because we are doing it only once for a caller, we can remove the complex logic for checking if it is necessary.
We can just do it unconditionally in case any coroutine gets inlined.
The inliners iterate over all instruction of a function anyway, so this does not increase the computational complexity (StackNesting is roughly linear with the number of instructions).
rdar://problem/47615442
I discovered this due to the mandatory inliner doing devirtualization. I ported
all of the relevant SIL tests to increase code coverage of this code when
ownership is enabled.
Instead of constructing calls to ExpressibleByBooleanLiteral.init(booleanLiteral: ...) in CSApply.cpp, just
annotate BooleanLiteralExpr with the selected constructor and do the actual construction during SILGen.
For context, StringLiteralExpr and NilLiteralExpr already behave this way.
This will let me strip ownership from non-transparent functions at the beginning
of the perf pipeline. Then after we serialize, I will run OME on the transparent
functions. Otherwise, we can not perform mandatory inlining successfully since
we can not inline ossa into non-ossa functions.
Just an oversight on my part. I double checked that the only remaining
difference is in how we handle checked_cast_br and switch_enum. I have a
separate patch that fixes that.
Previously, we would print multi-line string literals with single quotes, which were not re-parseable. Instead, re-escape their contents and print them out escaped.
The problematic scenario is that a function receives an @in_guaranteed and @inout parameter where one is a copy of the other value. For example, when appending a container to itself.
In this case the optimization removed the copy_addr, resulting in passing the same stack location to both parameters.
rdar://problem/47632890
MetadataLookup gives special treatment to imported Objective-C classes,
since there's no nominal type descriptor and metadata is obtained
directly by calling into the Objective-C runtime.
Remote reflection also gives special treatment to imported Objective-C
classes; they don't have field descriptors.
However, the ASTDemangler needs to treat them like ordinary classes,
in particular it wants to preserve the generic arguments here so that
we can round-trip debug info.