It is problematic for the cached `InternPool` state to directly
reference ZIR instruction indices, as these are not stable across
incremental updates. The existing ZIR mapping logic attempts to handle
this by iterating the existing Decl graph for a file after `AstGen` and
update ZIR indices on `Decl`s, struct types, etc. However, this is
unreliable due to generic instantiations, and relies on specialized
logic for everything which may refer to a ZIR instruction (e.g. a
struct's owner decl). I therefore determined that a prerequisite change
for incremental compilation would be to rework how we store these
indices.
This commit introduces a `TrackedInst` type which provides a stable
index (`TrackedInst.Index`) for a single ZIR instruction in the
compilation. The `InternPool` now stores these values in place of ZIR
instruction indices. This makes the ZIR mapping logic relatively
trivial: after `AstGen` completes, we simply iterate all `TrackedInst`
values and update those indices which have changed. In future, if the
corresponding ZIR instruction has been removed, we must also invalidate
any dependencies on this instruction to trigger any required
re-analysis, however the dependency system does not yet exist.
This commit changes how declarations (`const`, `fn`, `usingnamespace`,
etc) are represented in ZIR. Previously, these were represented in the
container type's extra data (e.g. as trailing data on a `struct_decl`).
However, this introduced the complexity of the ZIR mapping logic having
to also correlate some ZIR extra data indices. That isn't really a
problem today, but it's tricky for the introduction of `TrackedInst` in
the commit following this one. Instead, these type declarations now
simply contain a trailing list of ZIR indices to `declaration`
instructions, which directly encode all data related to the declaration
(including containing the declaration's body). Additionally, the ZIR for
`align` etc have been split out into their own bodies. This is not
strictly necessary, but it's much simpler to understand for an
insignificant cost in bytes, and will simplify the resolution of #131
(where we may need to evaluate the pointer type, including align etc,
without immediately evaluating the value body).
During semantic analysis the value may be an unresolved lazy value
which makes using `toUnsignedInt` invalid.
Add assertions to detect similar issues in the future.
Closes#18624
This logic was previously in Sema, which was unnecessary complexity, and meant the issue was not detected unless the declaration was semantically analyzed. This commit finishes the work which 941090d started.
Resolves: #17916
I changed my mind on how the CLI for Zig modules should work. I don't
like that `--mod` takes 2 parameters. Instead let's swing all the way in
the other direction: `-M[name][=src]`
This is shorter (Zig CLI invocations are long enough already), avoids
the double parameter edge case, and supports the concept of omitting the
source file part of the argument, which was already wanted for `-Mstd`.
The legacy way to encode that was `--mod std ''` - awkward!
Undocumented support for `--mod` remains so that this branch does not
need a zig1.wasm update. The next time that file is updated, support for
`--mod` can be dropped.
Importantly, this commit also adds support for modules that do not have
a root zig source file. In such case, it sets root to cwd and
root_src_path to empty string, and only sets have_zcu to true if a
module is provided with a root zig source file.
The deleted lines here are redundant because they happen first thing
inside the function call below.
Additionally, skip hashing the root source file if it is an empty
string. I explored making this field along with `root` optional but
found this to be less messy actually.