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.
We now pass the correct wasm type when the return type is a 128-bit integer.
When a function accepts a 128-bit integer, we now allocate space on the virtual stack
and store both arguments within that space as currently all following instructions
assume the 128 bit integer doesn't live in a local, but the stack.
This implements support for all compare operations on a 128bit integer,
for both signed and unsigned integers.
The new implementation is almost more efficient as it requires no control-flow,
unlike the old implementation which used a block with breaks.
This avoids the following error:
```
error: incompatible pointer types passing 'int64_t *' (aka 'long long *') to parameter of type 'long *'
overflow = __builtin_saddl_overflow(lhs, rhs, res);
^~~
```
My previous understanding was that this error would not occur because
prior to this line we check that int64_t is equivalent to long, like
this:
```c
```
However, it appears that this is still a warning in C if int64_t is
primarily aliased to `long long`, even though `long` and `long long` are
the same thing.
The implementation for add_with_overflow and sub_with_overflow is now a lot
more robust and takes account for signed integers and arbitrary integer bitsizes.
The final output is equal to that of the LLVM backend.
Most of the work here was additions to zig.h. The lowering code is
mainly responsible for calling the correct function name depending on
the operand type.
Some of the compiler-rt calls here are not implemented yet and are
non-standard symbols due to the C programming language not needing them.
After this commit, the behavior tests with -ofmt=c are passing again.