I found that it leads to better looking code when the check of whether
the range in question even has enough elements to skip is inside
the helper.
As such a separate type of skip entry point was introduced: one that
allows to iterate over the container pairwise
Now, instead of asserting, the loop just does nothing in cases like
```cpp
for (const auto &Element : zip_pairs(make_empty_range())
do_stuff();
```
This reevaluates the places where `std::size_t` should be replaced by
`std::uint64_t` in the conversions, it also appends `std::` prefixes to
them where it's possible in preparation to the eventual `import std`
transition.
The original non-position based distribution (`considerRegisters`)
algorithm had a whole lot of problems preventing effective padding
support because it was written with only registers in mind.
As such, it was easier to rewrite the whole logic from scratch over
trying to fix it incrementally.
This makes the conversions more robust, since everything can rely on
the same tools for filling in missing registers and ordering them based
on the ABI requirements.
This brings the layout-side handling of these closer to the way they are
handled when converting the function.
The biggest change is the fact that now the return value location can
also be passed as the first stack argument.
This was a necessary change because without at least basic shortcuts
introduced here, we get a whole lot of failures downstream due to
layouts of such functions and the layout production is by design not
allowed to fail.
When a shadow return value location argument is distributed, it is
shifting all the other argument indices by one. This was not taken into
the account previously. This commit fixes the indices.
It also makes it so the arguments `SizeOnStack` does not account for
padding. This is useful for some layout users.
This reorders the algorithms, so that the return values are handled
before the arguments. It also improves the wordind and extends
the comments annotating the function.
Moreover, it takes advantage of the `TypeBucket` to decouple type
management from the "raw" binary.
This commit introduces a `Kind` for arguments described in
`FunctionType::Layout`. We nowe basically have three types of arguments:
* Scalar: a regular scarlar argument;
* ReferenceToAggregate: a reference to an aggregete argument on the
stack;
* ShadowPointerToAggregateReturnValue: a pointer to the storage for the
(aggregate) return value allocated by the caller;
The architecture-specific pointer (generic register) size is used
instead.
For all the ABIs we support the value of this parameter was already
set to its pointer size. We might need to reintroduce the parameter
in the future if we want to support a super-exotic ABI with different
stack alignment requirements, but that seems highly unlikely.
This also introduces the argument extension helper for one stop all
treating small arguments when they are put into a register or pushed
into the stack.