Based on the size of the payload the native backends will lower
the error union with its fields (errorset & payload) in the correct order.
e.g. ErrorA!u8 will first lower the error set's value and then the payload.
In the event of ErrorA!u32 will lower the payload first.
* Sema: avoid unnecessary safety checks when an error set is empty.
* Sema: make zirErrorToInt handle comptime errors that are represented
as integers.
* Sema: make empty error sets properly integrate with
typeHasOnePossibleValue.
* Type: correct the ABI alignment and size of error unions which have
both zero-bit error set and zero-bit payload. The previous code did
not account for the fact that we still need to store a bit for
whether there is an error.
* LLVM: lower error unions possibly with the payload first or with the
error code first, depending on alignment. Previously it always put
the error code first and used a padding array.
* LLVM: lower functions which have an empty error set as the return
type the same as anyerror, so that they can be used where
fn()anyerror function pointers are expected. In such functions, Zig
will lower ret to returning zero instead of void.
As a result, one more behavior test is passing.
This is a temporary addition to stage2 in order to match stage1 behavior,
however the end-game once the lang spec is settled will be to use a global
InternPool for comptime memoized objects, making this behavior consistent
across all types, not only string literals. Or, we might decide to not
guarantee string literals to have equal comptime pointers, in which case
this commit can be reverted.
Prior to this change we would assume the ABI for Apple targets to
be GNU which could result in subtle errors in LLVM emitting calls
to non-existent system libc provided functions such as `_sincosf`
which is a GNU extension and as such is not provided by macOS for example.
This would result in linker errors where the linker would not be
able to find the said symbol in `libSystem.tbd`.
With this change, we now correctly identify macOS (and other Apple
platforms) as having ABI `unknown` which translates to unspecified
in LLVM under-the-hood:
```
// main.ll
target triple = "aarch64-unknown-macos-unknown"
```
Note however that we never suffix the target OS with target version
such as `macos11` or `macos12` which means we fail to instruct LLVM
of potential optimisations provided by the OS such as the availability
of function `___sincosf_stret`. I suggest we investigate that in a
follow-up commit.
MCValue.cpsr_flags replaces
MCValue.compare_flags_{signed,unsigned}. This simplifies a lot of
stuff and enables an MCValue to represent only the overflow bits in
the CPU (previously, it was only possible to represent a register +
the overflow bits).
The previous commit caused LLVM module verification failure because we
attemped to bitcast LLVM pointers to i64 parameters. This is exactly
what we want, however it's technically not allowed according to LLVM's
type system. It could have been fixed trivially by using ptrtoint
instead of bitcast in the case of pointers, however, out of concern for
inttoptr being problematic for the optimizer, I put in special code to
detect when a given parameter can be treated as its actual type rather
than an integer type. This makes Zig's output LLVM IR closer to what
Clang outputs.
The previous implementation of calling conventions was hacky and broken.
This commit reworks lowerFnParamTy into iterateParamTypes which returns
enum tags indicating how to handle each parameter. This is then used in
the three places that matter:
* lowering a function type to llvm type
* converting function parameters to the canonical type representation
(with respect to isByRef).
* converting canonical type representation to function arguments at
callsites (again with respect to isByRef).
As a result, we are one step closer to the C ABI tests passing. Before
this commit, attempting to build them crashed the compiler. I isolated
the broken function and verified that it now is lowered correctly. I
will keep working on this one piece at a time until all the C ABI tests
pass, and then I will enable all of them in the CI.
Motivation: the behavior test that is now passing.
The main change in this commit is introducing `Type.abiSizeAdvanced`,
`Value.Tag.lazy_size`, and adjusting `Sema.zirSizeOf` to take advantage
of these.
However, the bulk of lines changed in this commit ended up being moving
logic from value.zig and type.zig into Sema.zig. This logic had no
business being in Type/Value as it was only called from a Sema context,
and we need access to the Sema context for error reporting when a lazy
Value is resolved.
Also worth mentioning is that I bumped up the comptime `@floatToInt`
implementation from using f64 to f128.
`@call` allows specifying the modifier explicitly, however it can still
appear in a context that overrides the modifier. This commit adds flags
to the BuiltinCall ZIR encoding. Since we have unused bits I also threw
in the ensure_result_used mechanism.
I also deleted a behavior test that was checking for bound function
behavior where I think stage2 behavior is correct and stage1 behavior
is incorrect.
Warnings about non-implemented `-z nocopyreloc` are common when
compiling go code (including Go's tests themselves). Let's just
make it stop complaining.
This way, we do not have to tweak the `RegisterManager` to handle
multiple register types - we have one linear space instead. Additionally
we can use the bitset itself to separate the registers into overlapping
(the ones that are aliases of differing bitwidths) and nonoverlapping
classes (for example, AVX registers do not overlap general purpose
registers, thus they can be allocated simultaneously).
Another huge benefit of this simple approach is the fact that we can
still refer to *all* registers regardless of their class via enum
literals which makes the code so much more readable.
Finally, `RegisterLock` is universal across different register classes.
This also fixes the instruction for all other integer bitsizes,
as it was previously assuming to always be a bool.
128 bit substraction was also fixed as it contained a bug where it swapped
lhs with rhs.
This also implments wrapping for arbitrary integer widths between 64 and 128.
`@truncate` was fixed where the wasm types between operand and result differentiated.
We solved this by first casting and then wrapping.
`airMaxMin` was slightly updated to automatically support 128 bit integers,
by using the `cmp` function, instead of doing it manually. This makes the function
more maintanable as well.
`ctz` and `clz` now support 128 bit integers, while updating the previous implementation
also.