Specifically, now we properly identify the SILLocation for the final inlined
call site of a Source Location and put the remark there instead of in the
callee.
Add `async` to the type system. `async` can be written as part of a
function type or function declaration, following the parameter list, e.g.,
func doSomeWork() async { ... }
`async` functions are distinct from non-`async` functions and there
are no conversions amongst them. At present, `async` functions do not
*do* anything, but this commit fully supports them as a distinct kind
of function throughout:
* Parsing of `async`
* AST representation of `async` in declarations and types
* Syntactic type representation of `async`
* (De-/re-)mangling of function types involving 'async'
* Runtime type representation and reconstruction of function types
involving `async`.
* Dynamic casting restrictions for `async` function types
* (De-)serialization of `async` function types
* Disabling overriding, witness matching, and conversions with
differing `async`
More specifically, if one wants to force emit /all/ opt-remarks on a function, mark it with:
```
@_semantics("optremark")
```
If one wants to emit opt-remarks only for a specific SIL pass (like lets say
sil-opt-remark-gen), one can write:
```
@_semantics("optremark.sil-opt-remark-gen")
```
I made the pattern matching strict so if you just put in a '.' or add additional
suffixes, it will not pattern match. I think that this is sufficient for a
prototyping tool.
This is useful if one wants to play around with opt-remarks when optimizing code
in Xcode or any IDE that can use serialized diagnostics.
I noticed that I kept on needing to hack on this as I added stuff to
OptRemarkGenerator and felt the need to tie it even closer to
OptRemarkGenerator. As I began to think about it, this is really something
specific to that algorithm, so it really doesn't make sense to have it as part
of the general SIL library.
This is a NFC refactoring.
In all of these cases, we already had a SILFunction and were just grabbing its
SILModule instead of passing it in. So this is just an NFC change.
The reason why I am doing this is so that I can force emit opt-remarks on
functions with the semantics attribute "optremark", so I need to be able to
access the SILFunction in the optimization remark infrastructure.
This is just an initial implementation and doesn't handle all cases. This works
by grabbing the rc-identity root of a retain/release operation and then seeing:
1. If it is an argument, we use the ValueDecl of the argument.
2. If it is an instruction result, we try to infer the ValueDecl by looking for debug_value uses.
3. In the future, we should add support for globals and looking at addresses.
I may do 3 since it is important to have support for that due to inout objects.
This is useful if one wants to emit a note explanation (in my case that we
couldn't find any values) but do not have any other source loc but the original
remark.
I did this by adding a kind to Arguments and making it so we have a kind that
emits as a separate NOTE when we emit diagnostics, but is emitted as a normal
argument when emitting to the bitstream.
Distinguish ref_tail_addr storage from the other storage classes.
We didn't have this originally because be don't expect a begin_access
to directly operate on tail storage. It could occur after inlining, at
least with static access markers. More importantly it helps ditinguish
regular formal accesses from other unidentified access, so we probably
should have always had this.
At any rate, it's particularly important when AccessedStorage is
generalized to arbitrary memory access.
The immediate motivation is to add an AccessPath utility, which will
need to distinguish tail storage.
In the process, rewrite AccessedStorage::isDistinct. This could have a
large positive impact on exclusivity performance.
Rename the existing pass to AccessedStorageAnalysisDumper.
AccessedStorage is useful on its own as a utility without the
analysis. We need a way to test the utility itself.
Add test cases for the previous commit that introduced
FindPhiStorageVisitor.
In order to test this, I implemented a small source loc inference routine for
instructions without valid SILLocations. This is an optional nob that the
opt-remark writer can optionally enable on a per remark basis. The current
behaviors are just forward/backward scans in the same basic block. If we scan
forwards, if we find a valid SourceLoc, we just use ethat. If we are scanning
backwards, instead we grab the SourceRange and if it is valid use the end source
range of the given instruction. This seems to give a good result for retain
(forward scan) and release (backward scan).
The specific reason that I did that is that my test case for this are
retain/release operations. Often times these operations due to code-motion are
moved around (and rightly to prevent user confusion) given by optimizations auto
generated SIL locations. Since that is the test case I am using, to test this I
needed said engine.
Prepare to reuse this visitor for an AccessPath utility.
Remove visitIncomplete. Add visitCast and visitPathComponent.
Handle phis in a separate visitor. This simplifies the main
visitor. In the long-term, we may be able to eliminate the pointer-phi
visitor entirely. For now, this lets us enforce that all phi paths
follow the same access path.
For use outside access enforcement passes.
Add isUniquelyIdentifiedAfterEnforcement.
Rename functions for clarity and generality.
Rename isUniquelyIdentifiedOrClass to isFormalAccessBase.
Rename findAccessedStorage to identifyFormalAccess.
Rename findAccessedStorageNonNested to findAccessedStorage.
Part of generalizing the utility for use outside the access
enforcement passes.
Today unchecked_bitwise_cast returns a value with ObjCUnowned ownership. This is
important to do since the instruction can truncate memory meaning we want to
treat it as a new object that must be copied before use.
This means that in OSSA we do not have a purely ossa forwarding unchecked
layout-compatible assuming cast. This role is filled by unchecked_value_cast.
* Fixes loadable edge case for address-only types.
* Re-work, generalize, and simplify by using projections.
* Support `-enable-cxx-interop` in sil-opt.
Just like br inst, structs are phis in the ownership graph that one can induce
on top of the def-use graph. In this commit, I basically fill in the relevant
blanks in the ADT for such phis for struct so that the optimization for branches
is generalized onto structs.
<rdar://problem/63950481>
This simplifies the handling of the subdirectories in the SIL and
SILOptimizer paths. Create individual libraries as object libraries
which allows the analysis of the source changes to be limited in scope.
Because these are object libraries, this has 0 overhead compared to the
previous implementation. However, string operations over the filenames
are avoided. The cost for this is that any new sub-library needs to be
added into the list rather than added with the special local function.