Destroying the SIL remark streamer after transferring ownership to LLVM
is frought. For one, the streamer holds the remark file's stream open.
Destroying it early doesn't accomodate sil-opt, which transfers control
to LLVM before running passes that emit remarks.
Instead, just take a reference to the context that the streamer gets
parented onto. If the remarks streamer infrastructure could just hold
the file stream open for us, we wouldn't have to do any of this.
Corrects a mistake introduced in #31106
I was under the impression that the LLVMContext for an instance of
llvm::remarks::RemarkStreamer was somehow just scratch-space. It turns
out the ASMPrinters don't gather remarks data from modules, they gather
it from the remark streamer associated with the module's context.
Thus, we cannot have the module's context be distinct from whatever
context the streamer is eventually associated with.
In order to bring these two systems back into harmony, introduce a simple
ownership contract to SILRemarkStreamer. That is, it starts owned by
a SILModule, in which case the SILRemarkStreamer holds onto the
underlying LLVM object as the optimizer emits remarks. When it comes
time to IRGen the module, then and only then do we install the streamer
on the module's context. This tranfers ownership of the underlying LLVM
streamer to LLVM itself, so it acts as a consuming operation. When we
are about to perform IR Generation, the SILModule will be expiring
anyways, so the streamer was already about to be destroyed.
We're just putting it to better use doing its job.
The Remarks Streamer's installation seemed a bit overly complex, so simplify it in a few places:
* Refactor sil-opt to install the remarks options into the SILOptions for the SILModule
This reduces the parameter bloat in createSILRemarkStreamer. All of this data is freely derivable from the SILModule alone.
* Refactor createSILRemarkStreamer into SILRemarkStreamer::create
With the new reduction in parameters, we can hide the internal constructor and introduce a smart constructor that vends a unique pointer to clients.
* setSILRemarkStreamer -> installSILRemarkStreamer
Since the information to create a streamer is now entirely derivable from a module, remove a layer of abstraction and have the module directly construct a streamer for itself.
* Give SILRemarkStreamer its own LLVMContext
The remarks streamer just needs scratch space. It's not actually "installed" in a given context. There no reason to use Swift's Global Context here.
* Give the SILRemarkStreamer ownership of the underlying file stream
The SILModule didn't actually use this member, and it seems like somebody needs to own it, so just give it to the remarks streamer directly.
checked_cast_br may take an additional operands for the source and
target types. I'm sure the compiler forgets to check this in many
places. In this case, it was just a harmless assert.
Fixes <rdar://61122253> Assertion failed:
(termInst->getNumOperands() == 1 && "Transformation terminators should only have single operands")
Assertion failed:
(accessedAddress == getAccessedAddress(accessedAddress) &&
"caller must find the address root"), function isLetAddress,
file /Users/rjmccall/dev/swift/swift/lib/SIL/Utils/MemAccessUtils.cpp,
line 63.
Teach the getAccessedAddress utility to iterate through nested access
markers with projections interposed.
Fixes <rdar://problem/61464370>
Crash in SILOptimizer/access_marker_verify.swift
The API was accidentally undefined, presumably because I checked in
the wrong code or there was a bad merge. The API will be used by
upcoming commits.
Meanwhile, getAccessedAddress was not stripping access markers, which
means some analysis may have been too conservative.
This fix could expose issues by making existing analyses more effective.
Specifically, I split it into 3 initial categories: IR, Utils, Verifier. I just
did this quickly, we can always split it more later if we want.
I followed the model that we use in SILOptimizer: ./lib/SIL/CMakeLists.txt vends
a macro (sil_register_sources) to the sub-folders that register the sources of
the subdirectory with a global state variable that ./lib/SIL/CMakeLists.txt
defines. Then after including those subdirs, the parent cmake declares the SIL
library. So the output is the same, but we have the flexibility of having
subdirectories to categorize source files.