There were several problems, all fixed:
* AstGen was storing field names as references to the original
source code bytes. However, that data would be destroyed when the
source file is updated. Now, it correctly stores the field names in
the Decl arena for the enum. The same fix applies to error set field
names.
* Sema was missing a memset inside `analyzeSwitch`, leaving the "seen
enum fields" array with undefined memory. Now that they are all
properly set to null, the validation works.
* Moved the "enum declared here" note to the end. It looked weird
interrupting the notes for which enum values were missing.
Before, incremental compilation would crash when trying to emit compile
errors for the update after introducing a parse error.
Parse errors are handled by not invalidating any existing semantic
analysis. However, only the parse error must be reported, with all the
other errors suppressed. Once the parse error is fixed, the new file can
be treated as an update to the previously-succeeded update.
* `analyzeContainer` now has an `outdated_decls` set as well as
`deleted_decls`. Instead of queuing up outdated Decls for re-analysis
right away, they are added to this new set. When processing the
`deleted_decls` set, we remove deleted Decls from the
`outdated_decls` set, to avoid deleted Decl pointers from being in
the work_queue. Only after processing the deleted decls do we add
analyze_decl work items to the queue.
* Module.deletion_set is now an `AutoArrayHashMap` rather than `ArrayList`.
`declareDeclDependency` will now remove a Decl from it as appropriate.
When processing the `deletion_set` in `Compilation.performAllTheWork`,
it now assumes all Decl in the set are to be deleted.
* Fix crash when handling parse errors. Currently we unload the
`ast.Tree` if any parse errors occur. Previously the code emitted a
LazySrcLoc pointing to a token index, but then when we try to resolve
the token index to a byte offset to create a compile error message,
the ast.Tree` would be unloaded. Now we use
`LazySrcLoc.byte_abs` instead of `token_abs` so the error message can
be created even with the `ast.Tree` unloaded.
Together, these changes solve a crash that happened with incremental
compilation when Decls were added and removed in some combinations.
Introduce `ResultLoc.none_or_ref` which is used by field access
expressions to avoid unnecessary loads when the field access itself
will do the load. This turns:
```zig
p.y - p.x - p.x
```
from
```zir
%14 = load(%4) node_offset:8:12
%15 = field_val(%14, "y") node_offset:8:13
%16 = load(%4) node_offset:8:18
%17 = field_val(%16, "x") node_offset:8:19
%18 = sub(%15, %17) node_offset:8:16
%19 = load(%4) node_offset:8:24
%20 = field_val(%19, "x") node_offset:8:25
```
to
```zir
%14 = field_val(%4, "y") node_offset:8:13
%15 = field_val(%4, "x") node_offset:8:19
%16 = sub(%14, %15) node_offset:8:16
%17 = field_val(%4, "x") node_offset:8:25
```
Much more compact. This requires `Sema.zirFieldVal` to support both
pointers and non-pointers.
C backend: Implement typedefs for struct types, as well as the following
TZIR instructions:
* mul
* mulwrap
* addwrap
* subwrap
* ref
* struct_field_ptr
Note that add, addwrap, sub, subwrap, mul, mulwrap instructions are all
incorrect currently and need to be updated to properly handle wrapping
and non wrapping for signed and unsigned.
C backend: change indentation delta to 1, to make the output smaller and
to process fewer bytes.
I promise I will add a test case as soon as I fix those warnings that
are being printed for my test case.
GenZir struct now has rl_ty_inst field which tracks the result location
type (if any) a block expects all of its results to be coerced to.
Remove a redundant coercion on const local initialization with a
specified type.
Switch expressions, during elision of store_to_block_ptr instructions,
now re-purpose them to be type coercion when the block has a type in the
result location.
Also fixed abiAlignment - for pointers it was returning the abi
alignment inside the type, rather than of the pointer itself. There is
now `ptrAlignment` for getting the alignment inside the type of
pointers.
* zir.Code: introduce a decls array. This is so that `decl_val` and
`decl_ref` instructions can refer to a Decl with a u32 and therefore
they can also store a source location. This is needed for proper
compile error reporting.
* astgen uses a hash map to avoid redundantly adding a Decl to the
decls array.
* fixed reporting "instruction illegal outside function body" instead
of the desired message "unable to resolve comptime value".
* astgen skips emitting dbg_stmt instructions in comptime scopes.
* astgen has some logic to avoid adding unnecessary type coercion
instructions for common values.
Introduce "inline" variants of ZIR tags:
* block => block_inline
* repeat => repeat_inline
* break => break_inline
* condbr => condbr_inline
The inline variants perform control flow at compile-time, and they
utilize the return value of `Sema.analyzeBody`.
`analyzeBody` now returns an Index, not a Ref, which is the ZIR index of
a break instruction. This effectively communicates both the intended
break target block as well as the operand, allowing parent blocks to
find out whether they, in turn, should return the break instruction up the
call stack, or accept the operand as the block's result and continue
analyzing instructions in the block.
Additionally:
* removed the deprecated ZIR tag `block_comptime`.
* removed `break_void_node` so that all break instructions use the same Data.
* zir.Code: remove the `root_start` and `root_len` fields. There is now
implied to be a block at index 0 for the root body. This is so that
`break_inline` has something to point at and we no longer need the
special instruction `break_flat`.
* implement source location byteOffset() for .node_offset_if_cond
.node_offset_for_cond is probably redundant and can be deleted.
We don't have `comptime var` supported yet, so this commit adds a test
that at least makes sure the condition is required to be comptime known
for `inline while`.
* comment out the failing stage2 test cases
(so that we can uncomment the ones that are newly passing with
further commits)
* Sema: implement negate, negatewrap
* astgen: implement field access, multiline string literals, and
character literals
* Module: when resolving an AST node into a byte offset, use the
main_tokens array, not the firstToken function