Add flags for whether delayed body parsing or #if
condition evaluation is disabled, as well as
whether warnings should be suppressed. Then pass
down these flags from the frontend.
This is in preparation for the requestification of
source file parsing where the SourceFile will need
to be able to parse itself on demand.
Move the global PersistentParserState from
the CompilerInstance to the source file that code
completion is operating on, only hooking up the
state when it's needed. This will help make it
easier to requestify source file parsing.
I added a new API into OwnershipUtils called
getSingleBorrowIntroducingValue. This API returns a single
BorrowScopeIntroducingValue for a passed in guaranteed value. If we can not find
such a BorrowScopeIntroducingValue or we find multiple such, we return None.
Using that, I refactored StorageGuaranteesLoadVisitor::visitClassAccess(...) to
use this new API which should make it significantly more robust since the
routine uses the definitions of "guaranteed forwarding" that the ownership
verifier uses when it verifies meaning that we can rely on the routine to be
exhaustive and correct. This means that we now promote load [copy] ->
load_borrow even if our borrow scope introducer feeds through a switch_enum or
checked_cast_br result (the main reason I looked into this change).
To create getSingleBorrowIntroducingValue, I refactored
getUnderlyingBorrowIntroucingValues to use a generator to find all of its
underlying values. Then in getSingleBorrowIntroducingValue, I just made it so
that we call the generator 1-2 times (as appropriate) to implement this query.
Specifically, this PR adds support for optimizing simple cases where we do not
need to compute LiveRanges with the idea of first doing simple transforms that
involve small numbers of instructions first. With that in mind, we only optimize
cases where our copy_value has a single consuming user and our owned value has a
single destroy_value. To understand the transform here, consider the following
SIL:
```
%0 = ...
%1 = copy_value %0 (1)
apply %guaranteedUser(%0) (2)
destroy_value %0 (3)
apply %cviConsumer(%1) (4)
```
We want to eliminate (2) and (3), effectively joining the lifetimes of %0 and
%1, transforming the code to:
```
%0 = ...
apply %guaranteedUser(%0) (2)
apply %cviConsumer(%0) (4)
```
Easily, we can always do this transform in this case since we know that %0's
lifetime ends strictly before the end of %1's due to (3) being before (4). This
means that any uses that require liveness of %0 must be before (4) and thus no
use-after-frees can result from removing (3) since we are not shrinking the
underlying object's lifetime. Lets consider a different case where (3) and (4)
are swapped.
```
%0 = ...
%1 = copy_value %0 (1)
apply %guaranteedUser(%0) (2)
apply %cviConsumer(%1) (4)
destroy_value %0 (3)
```
In this case, since there aren't any liveness requiring uses of %0 in between
(4) and (3), we can still perform our transform. But what if there was a
liveness requiring user in between (4) and (3). To analyze this, lets swap (2)
and (4), yielding:
```
%0 = ...
%1 = copy_value %0 (1)
apply %cviConsumer(%1) (4)
apply %guaranteedUser(%0) (2)
destroy_value %0 (3)
```
In this case, if we were to perform our transform, we would get a use-after-free
due do the transform shrinking the lifetime of the underlying object here from
ending at (3) to ending at (4):
```
%0 = ...
apply %cviConsumer(%1) (4)
apply %guaranteedUser(%0) (2) // *kaboom*
```
So clearly, if (3) is after (4), clearly, we need to know that there aren't any
liveness requiring uses in between them to be able to perform this
optimization. But is this enough? Turns out no. There are two further issues
that we must consider:
1. If (4) is forwards owned ownership, it is not truly "consuming" the
underlying value in the sense of actually destroying the underlying value. This
can be worked with by using the LiveRange abstraction. That being said, this PR
is meant to contain simple transforms that do not need to use LiveRange. So, we
bail if we see a forwarding instruction.
2. At the current time, we may not be able to find all normal uses since all of
the instructions that are interior pointer constructs (e.x.: project_box) have
not been required yet to always be guarded by borrows (the eventual end
state). Thus we can not shrink lifetimes in general safely until that piece of
work is done.
Given all of those constraints, we only handle cases here where (3) is strictly
before (4) so we know 100% we are not shrinking any lifetimes. This effectively
is causing our correctness to rely on SILGen properly scoping lifetimes. Once
all interior pointers are properly guarded, we will be able to be more
aggressive here.
With that in mind, we perform this transform given the following conditions
noting that this pattern often times comes up around return values:
1. If the consuming user is a return inst. In such a case, we know that the
destroy_value must be before the actual return inst.
2. If the consuming user is in the exit block and the destroy_value is not.
3. If the consuming user and destroy_value are in the same block and the
consuming user is strictly later in that block than the destroy_value.
In all of these cases, we are able to optimize without the need for LiveRanges.
I am going to add support for this in a subsequent commit.
I also added a comment to getAllBorrowIntroducingValues(...) that explained the
situations where one could have multiple borrow introducing values:
1. True phi arguments.
2. Aggregate forming instructions.
These should hopefully all be uncontroversial, minimal changes to deal
with progressing the build to completion on OpenBSD or addressing minor
portability issues. This is not the full set of changes to get a
successful build; other portability issues will be addressed in future
commits.
Most of this is just adding the relevant clauses to the ifdefs, but of
note in this commit:
* StdlibUnittest.swift: the default conditional in _getOSVersion assumes
an Apple platform, therefore the explicit conditional and the relevant
enums need filling out. The default conditional should be #error, but
we'll fix this in a different commit.
* tgmath.swift.gyb: inexplicably, OpenBSD is missing just lgammal_r.
Tests are updated correspondingly.
* ThreadLocalStorage.h: we use the pthread implementation, so it
seems we should typedef __swift_thread_key_t as pthread_key_t.
However, that's also a tweak for another commit.
Centralize part of the routine that selects which resources to free. Then, add an additional condition for -dump-api-path.
Before, if this option were specified along with -emit-llvm or -c, the compiler would try to rebuild the torn-down ModuleDecl and crash trying to access the torn-down ASTContext.
The only non-trivial bit is making the DiagnosticEngine parameter to swift::performLLVM required. No callers were taking advantage of this parameter allowing NULL.
The lifetime of the UnifiedStatsReporter was not entirely clear from context. Stick it in the CompilerInstance instead so it can live as long as the compile job.
It is critical that its lifetime be extended beyond that of the ASTContext, as the context may be torn down by the time code generation happens, but additional statistics are recorded during LLVM codegen.
This is something I noticed by inspection while working on
<https://bugs.swift.org/browse/SR-75>.
Inside a static method, 'self' is a metatype value, so
'self.instanceMethod' produces an unbound reference of type
(Self) -> (Args...) -> Results.
You might guess that 'super.instanceMethod' can similarly
be used to produce an unbound method reference that calls
the superclass method given any 'self' value, but unfortunately
it doesn't work.
Instead, 'super.instanceMethod' would produce the same
result as 'self.instanceMethod'. Maybe we can implement this
later, but for now, let's just diagnose the problem.
Note that partially-applied method references with 'super.'
-- namely, 'self.staticMethod' inside a static context, or
'self.instanceMethod' inside an instance context, continue
to work as before.
They have the type (Args...) -> Result; since the self value
has already been applied we don't hit the representational
issue.
* Stage in #filePath
To give users of #file time to transition, we are first adding #filePath without changing #file’s behavior. This commit makes that change.
Fixes <rdar://problem/58586626>.
* Correct swiftinterface test line
Creating a @_dynamicReplacement function requires the creation of a
reference to the original function. We need to call SILGenModule's
getFunction to satisfy all the assertions in place.
rdar://59774606
* Simplified the logic for creating static initializers and constant folding for global variables: instead of creating a getter function, directly inline the constant value into the use-sites.
* Wired up the constant folder in GlobalOpt, so that a chains for global variables can be propagated, e.g.
let a = 1
let b = a + 10
let c = b + 5
* Fixed a problem where we didn't create a static initializer if a global is not used in the same module. E.g. a public let variable.
* Simplified the code in general.
rdar://problem/31515927
e.g. Playground.
A single file script is like a single function body; the interface of
the file does not affect any other files.
So when a completion happens in a single file script, re-parse the whole
file. But we are still be able to reuse imported modules.
rdar://problem/58378157