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.
* docs: document the nosuspend keyword
* Specify that resuming from suspend is allowed in nosuspend
* Fix the description of the requirements of nosuspend
* Make use of nosuspend in some example code.
This is mainly motivated by the incorrect claim that "there would be
no way to collect the return value of amain, if it were something
other than void".
New ZIR instructions:
* struct_decl_packed
* struct_decl_extern
New TZIR instruction: struct_field_ptr
Introduce `Module.Struct`. It uses `Value` to store default values and
abi alignments.
Implemented Sema.analyzeStructFieldPtr and zirStructDecl.
Some stuff I changed from `@panic("TODO")` to `log.warn("TODO")`.
It's becoming more clear that we need the lazy value mechanism soon;
Type is becoming unruly, and some of these functions have too much logic
given that they don't have any context for memory management or error
reporting.
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.
* use the proper result location strategy even when there are noreturn
prongs in the switch expression
* when using break_operand strategy, actually omit the
store_to_block_ptr instructions rather than eliding them.
* for both strategies, properly handle noreturn prongs.
The switch_br ZIR instructions are now switch_block instructions. This
avoids a pointless block always surrounding a switchbr in emitted ZIR
code.
Introduce typeof_elem ZIR instruction for getting the type of the
element of a pointer value in 1 instruction.
Change typeof to be un_node, not un_tok.
Introduce switch_capture ZIR instructions for obtaining the capture
value of switch prongs.
Introduce Sema.resolveBody for when you want to extract a *Inst out of a
block and you know that there is only going to be 1 break from it.
What's not working yet: AstGen does not correctly elide
store instructions when it turns out that the result location does not
need to be used as a pointer.
Also Sema validation code for duplicate switch items is not yet
implemented.
The logic for putting ranges into the else prong is moved from AstGen to
Sema. However, logic to emit multi-items the same as single-items cannot
be done until TZIR supports mapping multiple items to the same block of
code. This will be simple to represent when we do the upcoming TZIR memory
layout changes.
Not yet implemented in this commit is the validation of duplicate
values. The trick is going to be emitting error messages with accurate
source locations, without adding extra source nodes to the ZIR
switch instruction.
This will be done by computing the respective AST node based on the
switch node (which we do have available), only when a compile error
occurs and we need to know the source location to attach the message to.
When filling the last (len % 4) bytes of a buffer, the random number n was only being shifted right by 4 bits for each byte instead of 8. A random u16, for example, would always have its middle two nybbles be equal when generated this way. For comparison, Isaac64.zig, Sfc64.zig, and Xoroshiro128.zig all correctly shift right by 8 bits for each of the last bytes in their nearly identical fill functions.
Here's what I think the ZIR should be. AstGen is not yet implemented to
match this, and the main implementation of analyzeSwitch in Sema is not
yet implemented to match it either.
Here are some example byte size reductions from master branch, with the
ZIR memory layout from this commit:
```
switch (foo) {
a => 1,
b => 2,
c => 3,
d => 4,
}
```
184 bytes (master) => 40 bytes (this branch)
```
switch (foo) {
a, b => 1,
c..d, e, f => 2,
g => 3,
else => 4,
}
```
240 bytes (master) => 80 bytes (this branch)