* Fix backend using wrong union field of the slice instruction.
* LLVM backend properly sets alignment on global variables.
* Sema: add coercion for *T to *[1]T
* Sema: pointers to Decls with explicit alignment now have alignment
metadata in them.
Also switch to the more efficient encoding of the bitcast instruction
when the destination type is anyerror in 2 common cases.
LLVM backend: fix using the wrong type as the optional payload type in
the `wrap_optional` AIR instruction.
After a discussion about language specs, this seems like the best way to
go, because it's simpler to reason about both for humans and compilers.
The `bitcast_result_ptr` ZIR instruction is no longer needed.
This commit also implements writing enums, arrays, and vectors to
virtual memory at compile-time.
This unlocked some more of compiler-rt being able to build, which
in turn unlocks saturating arithmetic behavior tests.
There was also a memory leak in the comptime closure system which is now
fixed.
Each element of the output JSON has the VM address of the generated
binary nondecreasing (some elements might occupy the same VM address
for example the atom and the relocation might coincide in the address
space).
The generated JSON can be inspected manually or via a preview tool
`zig-snapshots` that I am currently working on and will allow the user
to inspect interactively the state of the linker together with the
positioning of sections, symbols, atoms and relocations within each
snapshot state, and in the future, between snapshots too. This should
allow for quicker debugging of the linker which is nontrivial when
run in the incremental mode.
Note that the state will only be dumped if the compiler is built with
`-Dlink-snapshot` flag on, and then the compiler is passed `--debug-link-snapshot`
flag upon compiling a source/project.
AIR:
* div is renamed to div_trunc.
* Add div_float, div_floor, div_exact.
- Implemented in Sema and LLVM codegen. C backend has a stub.
Improvements to std.math.big.Int:
* Add `eqZero` function to `Mutable`.
* Fix incorrect results for `divFloor`.
Compiler-rt:
* Add muloti4 to the stage2 section.
This fixes InstallRawStep to handle the cases when there are empty segments (segments with no sections). Before this change, if there was an empty segment with no sections, then the fixup of binaryOffsets is skipped. This fixes that by looping through each segment until a non-empty one is found and then fixing up the sections. This fixed an issue I was having with InstallRawStep for a bootloader I'm writing.
This modifies the error for an unexpected exit code from the ChildProcess of RunStep to be UnexpectedExitCode rather than UncleanExit. This allows the handler of the error to distinguish between an error reported by the ChildProcess, and an error executing the ChildProcess, which is an important dinstinction when it comes to know what information to report to the user. For example, if you have a ChildProcess that you know reports its own errors, an unexpected exit code would mean the error is already reported, but an unclean exit would mean that child process was not able to report any error.
* Restructure elemPtr a bit
* New AIR instruction: slice_elem_ptr, which returns a pointer to an element of a slice
* Value: adapt elemPtr to work on slices
* New AIR instruction: slice, which constructs a slice out of a pointer
and a length.
* AstGen: use `coerced_ty` for start and end expressions, use `none`
for the sentinel, and don't try to load the result of the slice
operation because it returns a by-value result.
* Sema: pointer arithmetic is extracted into analyzePointerArithmetic
and it is used by the implementation of slice.
- Also I implemented comptime pointer addition.
* Sema: extract logic into analyzeSlicePtr, analyzeSliceLen and use them
inside the slice semantic analysis.
- The approach in stage2 is much cleaner than stage1 because it uses
more granular analysis calls for obtaining the slice pointer, doing
arithmetic on it, and checking if the length is comptime-known.
* Sema: use the slice Value Tag for slices when doing coercion from
pointer-to-array.
* LLVM backend: detect when emitting a GEP instruction into a
pointer-to-array and add the extra index that is required.
* Type: ptrAlignment for c_void returns 0.
* Implement Value.hash and Value.eql for slices.
* Remove accidentally duplicated behavior test.
* AstGen: Move `refToIndex` and `indexToRef` to Zir
* ZIR: the switch_block_*_* instruction tags are collapsed into one
switch_block tag which uses 4 bits for flags, and reduces the
scalar_cases_len field from 32 to 28 bits.
This freed up more ZIR tags, 2 of which are now used for
`switch_cond` and `switch_cond_ref` for producing the switch
condition value. For example, for union values it returns the
corresponding enum value.
* switching with multiple cases and ranges is not yet supported because
I want to change the ZIR encoding to store index pointers into the
extra array rather than storing prong indexes. This will avoid O(N^2)
iteration over prongs.
* AstGen now adds a `switch_cond` on the operand and then passes the
result of that to the `switch_block` instruction.
* Sema: partially implement `switch_capture_*` instructions.
* Sema: `unionToTag` notices if the enum type has only one possible value.
The remaining uses of this result location were causing a bunch of errors
problems where the pointers returned from rvalue and lvalue expressions
would be confused, allowing for extra pointers on rvalue expressions.
For example:
```zig
const X = struct {a: i32};
var x: X = .{.a = 1};
var ptr = &x;
_ = x.a;
```
In the last line, the lookup of x with result location .none_or_ref would
return a double pointer (**X). This would be dereferenced one, after which
a relative pointer to `a` would be fetched and derefenced to get the final
result.
However, this also allows us to manually construct a double pointer, and
fetch the field of the inner type of that:
```zig
_ = &(&(x)).a;
```
This problem also manifests itself with element access. There are two obvious
ways to fix the problem, both of which include replacing the usage of
.none_or_ref for field- and element accesses with something which
deterministically produce either a pointer or value: either result location
.ref or .none. In the former case, this would be paired with .elem_ptr, and
in the latter case with .elem_val.
Note that the stage 1 compiler does not have this problem, because there is
no equivalent of .elem_val and .field_val. In this way it is equivalent to
using the result location .ref for field- and element accesses.
In this case i have used .none, as this matches language behaviour more
closely.
Dereferencing single pointers is now handled outside of the main switch,
which allows deduplication of some cases. This also implements the
relevant operations for pointers to types and pointers to slices.
* do not add linkage scope to aliased exported symbols - this is
not respected on macOS
* special-case `MachO.openPath` in `link.File.openPath` as on macOS
we always link with zld
* redirect to `MachO.flushObject` when linking relocatable objects
in MachO linker whereas move the entire linking logic into
`MachO.flushModule`