When lowering a struct type to an LLVM struct type, keep track of
whether there are any underaligned fields. If so, then make it a packed
llvm struct. This works because we already insert manual padding bytes
regardless.
We could unconditionally use an LLVM packed struct; the reason we bother
checking for underaligned fields is that it is a conservative choice, in
case LLVM handles packed structs less optimally. A future improvement
could simplify this code by unconditionally using packed LLVM structs
and then make sure measure perf is unaffected.
closes#12190
Previously, struct types, alignment values, and initialization
expressions were all lowered into the same ZIR body, which caused false
positive "depends on itself" errors when the initialization expression
depended on the size of the struct.
This also uses ResultLoc.coerced_ty for struct field alignment and
initialization values. The resulting ZIR encoding ends up being roughly
the same, neither smaller nor larger than previously.
Closes#12029
Prior to this commit, the logic for ABI size and ABI alignment for
integers was naive and incorrect. This results in wasted hardware as
well as undefined behavior in the LLVM backend when we memset an
incorrect number of bytes to 0xaa due to disagreeing with LLVM about the
ABI size of integers.
This commit introduces a "max int align" value which is different per
Target. This value is used to derive the ABI size and alignment of all
integers.
This commit makes an interesting change from stage1, which treats
128-bit integers as 16-bytes aligned for x86_64-linux. stage1 is
incorrect. The maximum integer alignment on this system is only 8 bytes.
This change breaks the behavior test called "128-bit cmpxchg" because on
that target, 128-bit cmpxchg does require a 16-bytes aligned pointer to
a 128 bit integer. However, this alignment property does not belong on
*all* 128 bit integers - only on the pointer type in the `@cmpxchg`
builtin function prototype. The user can then use an alignment override
annotation on a 128-bit integer variable or struct field to obtain such
a pointer.
All tests have been manually verified which are now passing. This means that any remaining
TODO is an actual to-be-fixed or to-be-implemented test case.
Instead of doing it before the switch tower, do it afterwards, so that
special handling may be done before undefined gets casted to the
destination type.
In this case the special handling we want to do is *[N]T to []T setting
the slice length based on the array length, even when the array value is
undefined.