A CaseRule's own src is where its body is; compare_src is where the case
is selected. A SwitchRule's own src is the whole statement; signal_src is
where its expression is. Both survive a clone and a cross-pool copy.
Also root the srcs a process holds outside its AttrObjects - one per
assignment, plus the two above - so garbage collection cannot free the
twines they point at.
Source locations move off the attribute dict into a dedicated SrcRef on
AttrObject, interned in a per-design SrcPool that hash-conses sets of
location twines. Locations share their file prefix with each other through
the twine pool, and objects that fuse (opt_merge, share, ff/mem rewrites)
carry the union of their inputs' locations instead of a '|'-joined string.
write_rtlil emits an `srcs` section of location sets alongside `twines`;
read_rtlil resolves `\src "@N"` back to a handle and still accepts a plain
location string. -readable renders the locations as text.
It's pretty common for `opt_clean` to find no wires to remove. In that case,
there is no point scanning the entire design, which can be significantly
expensive for huge designs.
When IdString refcounting was expensive, it made sense to pass it by const reference
instead of by value, to avoid refcount churn. Now that IdString is not refcounted,
it's slightly more efficient to pass it by value.
When something calls `IdString::c_str()` on an autoidx ID, we need to cache the
full string in a thread-safe way. If we need to allocate an entry in some data
structure to do that, it's difficult to do in a thread-safe no-performance-hazard way.
So instead, store the cached string pointer in the same hashtable as the prefix
pointer.
We could make it safe to increment autoidx during multithreaded passes, but that's
actually undesirable because it would lead to nondeterminism. If/when we need new
IDs during parallel passes, we'll have to figure out how to allocate them in a
deterministic way, and that will depend on the details of what the pass does.
So don't try to tackle that now.
Refcounting is hardly used at all so this option is not that useful.
We might want to have a different option that disables GC if that becomes
a performance issue, but that should be a different option.
This saves space and doesn't cost very much since we hardly ever have nonzero refcounts any more.
It also allows for IdStrings with negative indexes, which we're going to add.