This means it can be emitted during an -emit-module frontend job, which is the
most common place it will be used, so reusing work like this is important for
performance.
For now, this has to happen as part of a single frontend invocation, i.e. -wmo
or -force-single-frontend-invocation.
Typo correction can be particularly expensive, so introduce a
command-line flag to limit the number of typo corrections we will
perform per type-checker instance. Default this limit to 10.
Addresses rdar://problem/28469270 to some extent.
By default, end expression type checking after the elapsed process time
is more than 60 seconds for the current expression. This threshold can
be overridden by using -solver-expression-time-threshold=<seconds>.
Resolves rdar://problem/32859654
- SILSerializeAll flag is now stored in the SILOptions and passed around as part of it
- Explicit SILSerializeAll/wholeModuleSerialized/makeModuleFragile API parameters are removed in many places
Generates a warning for any expression that takes longer than <limit>
milliseconds to type check. This compliments the existing
-warn-long-function-body=<limit> option.
It can now:
- not validate (=none)
- validate that all symbols in the IR are also in the TBD (=missing),
- validate the above, and also that all in the TBD are in the IR (=all).
The first and last were switched between with the old boolean flag, the
second is new.
I had set up the driver to invoke a separate frontend invocation with
the "update code" mode. We sort of did this last release, except we
forked to the swift-update binary instead. This is causing problems with
testing in Xcode.
Instead, let's perform a single compile and add the remap file as an
additional output during normal compiles. The driver, seeing
-update-code, will add -emit-remap-file-path $PATH to the -c frontend
invocation.
rdar://problem/31857580
The Swift 4 Migrator is invoked through either the driver and frontend
with the -update-code flag.
The basic pipeline in the frontend is:
- Perform some list of syntactic fixes (there are currently none).
- Perform N rounds of sema fix-its on the primary input file, currently
set to 7 based on prior migrator seasons. Right now, this is just set
to take any fix-it suggested by the compiler.
- Emit a replacement map file, a JSON file describing replacements to a
file that Xcode knows how to understand.
Currently, the Migrator maintains a history of migration states along
the way for debugging purposes.
- Add -emit-remap frontend option
This will indicate the EmitRemap frontend action.
- Don't fork to a separte swift-update binary.
This is going to be a mode of the compiler, invoked by the same flags.
- Add -disable-migrator-fixits option
Useful for debugging, this skips the phase in the Migrator that
automatically applies fix-its suggested by the compiler.
- Add -emit-migrated-file-path option
This is used for testing/debugging scenarios. This takes the final
migration state's output text and writes it to the file specified
by this option.
- Add -dump-migration-states-dir
This dumps all of the migration states encountered during a migration
run for a file to the given directory. For example, the compiler
fix-it migration pass dumps the input file, the output file, and the
remap file between the two.
State output has the following naming convention:
${Index}-${MigrationPassName}-${What}.${extension}, such as:
1-FixitMigrationState-Input.swift
rdar://problem/30926261
- Add CompilerInvocation::getPCHHash
This will be used when creating a unique filename for a persistent
precompiled bridging header.
- Automatically generate and use a precompiled briding header
When we're given both -import-objc-header and -pch-output-dir
arguments, we will try to:
- Validate what we think the PCH filename should be for the bridging
header, based on the Swift PCH hash and the clang module hash.
- If we're successful, we'll just use it.
- If it's out of date or something else is wrong, we'll try to
emit it.
- This gives us a single filename which we can `stat` to check for the
validity of our code completion cache, which is keyed off of module
name, module filename, and module file age.
- Cache code completion results from imported modules
If we just have a single .PCH file imported, we can use that file as
part of the key used to cache declarations in a module. Because
multiple files can contribute to the __ObjC module, we've always given
it the phony filename "<imports>", which never exists, so `stat`-ing it
always fails and we never cache declarations in it.
This is extremely problematic for projects with huge bridging headers.
In the case where we have a single PCH import, this can bring warm code
completion times down to about 500ms from over 2-3s, so it can provide a
nice performance win for IDEs.
- Add a new test that performs two code-completion requests with a bridging header.
- Add some -pch-output-dir flags to existing SourceKit tests that import a bridging
header.
rdar://problem/31198982
This is purely designed to cheaply compute dependency graphs between
modules, and thus only lists the top-level names (i.e. not submodules)
and doesn't do any form of semantic analysis.
This has the effect of propagating the search path to the clang importer as '-iframework'.
It doesn't affect whether a swift module is treated as system or not, this can be done as follow-up enhancement.
There's a class of errors in Serialization called "circularity
issues", where declaration A in file A.swift depends on declaration B
in file B.swift, and B also depends on A. In some cases we can manage
to type-check each of these files individually due to the laziness of
'validateDecl', but then fail to merge the "partial modules" generated
from A.swift and B.swift to form a single swiftmodule for the library
(because deserialization is a little less lazy for some things). A
common case of this is when at least one of the declarations is
nested, in which case a lookup to find that declaration needs to load
all the members of the parent type. This gets even worse when the
nested type is defined in an extension.
This commit sidesteps that issue specifically for nested types by
creating a top-level, per-file table of nested types in the "partial
modules". When a type is in the same module, we can then look it up
/without/ importing all other members of the parent type.
The long-term solution is to allow accessing any members of a type
without having to load them all, something we should support not just
for module-merging while building a single target but when reading
from imported modules as well. This should improve both compile time
and memory usage, though I'm not sure to what extent. (Unfortunately,
too many things still depend on the whole members list being loaded.)
Because this is a new code path, I put in a switch to turn it off:
frontend flag -disable-serialization-nested-type-lookup-table
https://bugs.swift.org/browse/SR-3707 (and possibly others)
The typedef `swift::Module` was a temporary solution that allowed
`swift::Module` to be renamed to `swift::ModuleDecl` without requiring
every single callsite to be modified.
Modify all the callsites, and get rid of the typedef.
Based off the PlaygroundTransform, this new ASTWalker leaves calls to __builtin_pc_before and __builtin_pc_after before and after a user would expect a program counter to enter a range of source code.
Enables Chris's auto-apply-fixes mode for -verify: if an expected-*
annotation has the wrong message, or if the expected fix-its are
incorrect, this option will **edit the original file** to update them.
This is a tool for compiler developers only; it doesn't affect
normal diagnostic printing or normal fix-its.
Given a source location, we can find the innermost enclosing scope
that describes that source location. Introduce this operation into the
scope map, then add a testing mode where we probe the scope map at
specifi locations to see what we find. Test for:
1) Finding the right innermost enclosing scope, and
2) That we're only expanding the part of the scope map that is needed
to identify that scope.
The scope map models all of the name lookup scopes within a source
file. It can be queried by source location to find the innermost scope
that contains that source location. Then, one can follow the parent
pointers in the scope to enumerate the enclosing scopes.
The scope map itself is lazily constructed, only creating scope map
nodes when required implicitly (e.g, when searching for a particular
innermost scope) or forced for debugging purposes.
using a lazily-constructed tree that can be searched by source
location. A search within a particular source location will
This is a /slightly/ more user-friendly option than
-debug-time-function-bodies; pass it a limit in milliseconds and
the compiler will warn whenever a function or multi-statement closure
takes longer than that to type-check.
Since it's a frontend option (and thus usually passed with -Xfrontend),
I went with the "joined" syntax as the common case. The usual "separate"
syntax of "-warn-long-function-bodies <N>" is also available.
As a frontend option, this is UNSUPPORTED and may be removed without
notice at any future date.
Additional caveats:
- Other parts of type-checking not measured by this may also be slow.
- May include first-use penalties (i.e. "this is slow because it's
the first function that references an imported type, which causes
many things to be imported")
- Does not report anything whatsoever about other phases of compilation
(SILGen, optimization, IRGen, assembly emission, whatever).
- Does not catch anything accidentally being type-checked multiple times
(a known issue for initial value expressions on properties).
We want to distinguish the special case of a library built with
-sil-serialize-all, from a SIL function that is [fragile] because
of an explicitly @_transparent or @inline(__always).
For now, NFC.
Since resilience is a property of the module being compiled,
not decls being accessed, we need to record which types are
resilient as part of the module.
Previously we would only ever look at the @_fixed_layout
attribute on a type. If the flag was not specified, Sema
would slap this attribute on every type that gets validated.
This is wasteful for non-resilient builds, because there
all types get the attribute. It was also apparently wrong,
and I don't fully understand when Sema decides to validate
which decls.
It is much cleaner conceptually to just serialize this flag
with the module, and check for its presence if the
attribute was not found on a type.
This times each phase of compilation, so you can see where time is being
spent. This doesn't cover all of compilation, but does get all the major
work being done.
Note that these times are non-overlapping, and should stay that way.
If we add more timers, they should go in a different timer group, so we
don't end up double-counting.
Based on a patch by @cwillmor---thanks, Chris!
Example output, from an -Onone build using a debug compiler:
===-------------------------------------------------------------------------===
Swift compilation
===-------------------------------------------------------------------------===
Total Execution Time: 8.7215 seconds (8.7779 wall clock)
---User Time--- --System Time-- --User+System-- ---Wall Time--- --- Name ---
2.6670 ( 30.8%) 0.0180 ( 25.3%) 2.6850 ( 30.8%) 2.7064 ( 30.8%) Type checking / Semantic analysis
1.9381 ( 22.4%) 0.0034 ( 4.8%) 1.9415 ( 22.3%) 1.9422 ( 22.1%) AST verification
1.0746 ( 12.4%) 0.0089 ( 12.5%) 1.0834 ( 12.4%) 1.0837 ( 12.3%) SILGen
0.8468 ( 9.8%) 0.0171 ( 24.0%) 0.8638 ( 9.9%) 0.8885 ( 10.1%) IRGen
0.6595 ( 7.6%) 0.0142 ( 20.0%) 0.6737 ( 7.7%) 0.6739 ( 7.7%) LLVM output
0.6449 ( 7.5%) 0.0019 ( 2.6%) 0.6468 ( 7.4%) 0.6469 ( 7.4%) SIL verification (pre-optimization)
0.3505 ( 4.1%) 0.0023 ( 3.2%) 0.3528 ( 4.0%) 0.3530 ( 4.0%) SIL optimization
0.2632 ( 3.0%) 0.0005 ( 0.7%) 0.2637 ( 3.0%) 0.2639 ( 3.0%) SIL verification (post-optimization)
0.0718 ( 0.8%) 0.0021 ( 3.0%) 0.0739 ( 0.8%) 0.0804 ( 0.9%) Parsing
0.0618 ( 0.7%) 0.0010 ( 1.4%) 0.0628 ( 0.7%) 0.0628 ( 0.7%) LLVM optimization
0.0484 ( 0.6%) 0.0011 ( 1.5%) 0.0495 ( 0.6%) 0.0495 ( 0.6%) Serialization (swiftmodule)
0.0240 ( 0.3%) 0.0006 ( 0.9%) 0.0246 ( 0.3%) 0.0267 ( 0.3%) Serialization (swiftdoc)
0.0000 ( 0.0%) 0.0000 ( 0.0%) 0.0000 ( 0.0%) 0.0000 ( 0.0%) Name binding
8.6505 (100.0%) 0.0710 (100.0%) 8.7215 (100.0%) 8.7779 (100.0%) Total
Till now, a SIL module would be only verified if an optimization has changed it. But if there were no changes, then no verification would happen and some SIL module format errors would stay unnoticed. This was happening in certain cases when reading a textual SIL module representation, which turned out to be broken, but SIL verifier wouldn't catch it.
Swift SVN r31863