Age | Commit message (Collapse) | Author |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This is necessary to fix unary negation of floating-point 0 (also
depends on a pending qbe patch).
|
|
Previously, the qualifiers were saved, but accidentally ignored
when the typedef was referenced.
|
|
This is specified by the last sentence in C11 6.7.5p6.
|
|
This is not yet supported by QBE, so for now we allocate a bit extra
and choose the address in the allocated region with an aligned
address.
|
|
|
|
Also, add bounds checks for float-to-int conversions. If the integer
part can't be represented in the result type, C behavior is undefined.
Although this means the result is arbitrary, we need to avoid
undefined behavior in cproc itself when given such a program as
input.
|
|
This requires a not-yet-upstream QBE patch, and is needed for riscv64
support, since the calling convention may be different depending
on whether the argument is named or variadic.
|
|
|
|
These are in the latest C23 draft.
|
|
|
|
Thanks to Nihal Jere for his initial patches implementing this
feature.
Fixes #35.
|
|
|
|
Although we don't need the cnew in this case, we still need to do
the appropriate extension to 32-bit.
|
|
7e838669 removed conversion to bool for int expressions used only
to control jnz, but incorrectly dropped the conversion for the
right-hand-side of logical and/or as well. We need the result of
the expression to be 0 or 1, so we still need that conversion.
|
|
|
|
This compiles `0 ? e1 : e2` as `e2`, and `1 ? e1 : e2` as `e1`
(while still adjusting the type as necessary).
|
|
As in ede6a5c9, if an expression is used only to control a jnz, we
don't need to convert it to a 0 or 1 value. QBE ignores the upper
32-bits of the argument to jnz, so the conversion is still needed
for pointer, long, and floating point types (including float since
-0 has non-zero bit representation).
|
|
|
|
|
|
|
|
|
|
Previously, cproc effectively used used
typedef struct { /* 32 bytes, 8-byte aligned */ } __builtin_va_list[1];
However, this is not quite correct for x86_64 nor aarch64, though
it was close enough for both to work in most cases.
In actuality, for x86_64 we want
typedef struct { /* 24 bytes, 8-byte aligned */ } __builtin_va_list[1];
and for aarch64 we want
typedef struct { /* 32 bytes, 8-byte aligned */ } __builtin_va_list;
The difference only appears when the size of va_list matters, or
when va_list is passed as a parameter. However, the former is not
often the case, and the aarch64 ABI replaces aggregate arguments
with pointers to caller-allocated memory, which is quite similar
to arrays decaying to pointers in C except that the struct is not
copied.
Additionally, riscv64 simply uses
typedef void *__builtin_va_list;
which again has a different size and calling convention.
To fix this, make the __builtin_va_list type architecture-specific
and use architecture-specific tests for varargs-related functionality.
|
|
|
|
Now that we don't track QBE types within values, we don't have to
worry about generating incorrect SSA when passing an 'l' value to
a function taking a 'w'. So we can just return the source value
instead of emitting a dummy copy instruction.
|
|
We always store the result to a w temporary, so there is no difference.
In fact, QBE provides loadw as an alias for loadsw precisely for
this reason.
|
|
Make an exception for flexible array members, though we should also
check that the flexible array member, if any, is last.
|
|
conversion
The conversion is only needed for floating types. QBE isn't able
to optimize it away for integer types yet, so removing this unnecessary
conversion has a substantial performance benefit.
|
|
|
|
This will facilitate the support of wide-string literals.
Based on patch from Nihal Jere.
|
|
|
|
|
|
|
|
C11 6.7.5p6 says "An alignment specification of zero has no effect".
|
|
Previously, this was needed so that an aggregate type value was
updated to be an 'l' type value. However, since 5ff1d2fa the aggregate
type name is stored in a separate parameter in IARG/ICALL instructions,
so we can just re-use the same pointer value.
|
|
Move jump and phi instructions to struct block, and function arguments
to their own instruction.
This will facilitate allocating instructions as an array.
|
|
The struct-passing test checks for function definitions with struct
arguments, but we were missing a test for function calls with struct
arguments.
|
|
|
|
It should be a pointer to the array, not to the first element (as
it would after implicit conversion without the '&' operator).
|
|
|
|
|
|
|
|
|
|
|