To do this, I expanded SwitchProngSrc a bit. Several of the tags there
aren't actually used by any current errors, but they're there for
consistency and if we ever need them.
Also delete a now-redundant test and fix another.
This is a bit harder than it seems at first glance. Actually resolving
the type is the easy part: the interesting thing is actually getting the
capture value. We split this into three cases:
* If all payload types are the same (as is required in status quo), we
can just do what we already do: get the first field value.
* If all payloads are in-memory coercible to the resolved type, we still
fetch the first field, but we also emit a `bitcast` to convert to the
resolved type.
* Otherwise, we need to handle each case separately. We emit a nested
`switch_br` which, for each possible case, gets the corresponding
union field, and coerces it to the resolved type. As an optimization,
the inner switch's 'else' prong is used for any peer which is
in-memory coercible to the target type, and the bitcast approach
described above is used.
Pointer captures have the additional constraint that all payload types
must be in-memory coercible to the resolved type.
Resolves: #2812
This finishes the process of consolidating switch expressions in ZIR
into as simple and compact a representation as is possible. There are
now just two ZIR tags dedicated to switch expressions: switch_block and
switch_block_ref, with the latter being for an operand passed by
reference.
This is a follow-up to a previous commit which eliminated switch_capture
and switch_capture_ref. All captures are now handled directly by
`switch_block`, which has also eliminated some unnecessary Block data in
Sema.
These tags are unnecessary, as this information can be more efficiently
encoded within the switch_block instruction itself. We also use a neat
little trick to avoid needing a dummy instruction (like is used for
errdefer captures): since the switch_block itself cannot otherwise be
referenced within a prong, we can repurpose its index within prongs to
refer to the captured value.
By indexing from the very first switch case rather than into scalar and
multi cases separately, the instructions for capturing in multi cases
become unnecessary, freeing up 2 ZIR tags.
Long term, linker backends will need to manage their own string tables
for things like this because my mandate is: no long-lived pointers
allowed in any of the codepaths touched by incremental compilation, so
that we can serialize and deserialize trivially.
Short term, I solved this with a couple calls to Allocator.dupe,
incurring some harmless leaks.
By correctly handling comptime-only types appearing in non-comptime
parameters (when the parameter is either anytype or generic), this
avoids an index out of bounds later when later filling out
`monomorphed_args` using what used to be slightly different logic.
These are frequently invalidated whenever a string is interned, so avoid
creating pointers to `string_bytes` wherever possible. This is an
attempt to fix random CI failures.
Previously, these checks worked by performing the arithmetic operation,
then checking whether the result fit in the type in question. Since all
values are now typed, this approach was no longer valid, and was
tripping some assertions due to trying to store too-large values in
smaller types.
Now, `intAdd`, `intSub`, `intMul` and `intDiv` all check for overflow,
and if it happens, re-do the operation with the result being a
`comptime_int`, and reporting the error (and vector index) to the caller
so that the error can be reported.
After this change, all test cases are passing.
All but 2 test cases now pass (tested on x86_64 Linux, native only). The
remaining two signify an issue requiring a larger refactor, which I will
do in a separate commit.
Notable changes:
* Fix uninitialized memory when allocating objects from free lists
* Implement TypedValue printing for pointers
* Fix some TypedValue printing logic
* Work around non-existence of InternPool.remove implementation
Instead of carrying an optimized version of wyhash in the compiler for
small keys, put it into the std lib where it belongs.
...except it does not match the official test cases. This will need to
be fixed before merging into master. This is an extremely
contributor-friendly task.
Related issue: #15916
This is a workaround for InternPool currently not handling
non-null-terminated strings. It avoids using the `bytes` storage for
aggregates if there are any null bytes.
In the future this should be changed so that the `bytes` storage can be
used regardless of whether there are any null bytes. This is important
for use cases such as `@embedFile`.
However, this fixes a bug for now, and after this commit, stage2
self-hosts again.
mlugg: stage5 passes all enabled behavior tests on my system.
Commit message edited by Andrew Kelley <andrew@ziglang.org>
Notably, there was a bug where the fields of reified structs and unions
were allocated into an arena which was leaked. These are now in the
Module.tmp_hack_arena.
In an effort to delete `Value.hashUncoerced`, generic instantiation has
been redesigned. Instead of just storing instantiations in
`monomorphed_funcs`, partially instantiated generic argument types are
also cached. This isn't quite the single `getOrPut` that it used to be,
but one `get` per generic argument plus one get for the instantiation,
with an equal number of `put`s per unique instantiation isn't bad.