Age | Commit message (Collapse) | Author |
|
Variably modified types are required for C23.
Since QBE doesn't currently support saving and restoring the stack
pointer, a current limitation is that we can't reclaim stack space
from VLAs that go out of scope. This is potentially problematic for
VLAs appearing in a loop, but this case is uncommon enough that it
is silently ignored for now.
Implements: https://todo.sr.ht/~mcf/cproc/1
References: https://todo.sr.ht/~mcf/cproc/88
Co-authored-by: Michael Forney <mforney@mforney.org>
|
|
These were removed in C23.
|
|
|
|
We don't need the length constant anymore, so just use that name
for the length expression.
References: https://todo.sr.ht/~mcf/cproc/1
|
|
|
|
|
|
|
|
|
|
Fixes: https://todo.sr.ht/~mcf/cproc/64
|
|
This will facilitate supporting underlying types other than int or
unsigned, possible in C23.
References: https://todo.sr.ht/~mcf/cproc/64
|
|
|
|
|
|
We don't need exact-width integer types here.
|
|
If the argument was a function parameter, its type has already been
adjusted. So on x86_64, we can't just ignore the automatic
array-to-pointer conversion, since it was never a pointer to begin
with.
Instead, keep track of the adjusted va_list type, and check that
the arguments to varargs built-ins match that type.
|
|
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.
|
|
|
|
This way we avoid leaking backend-specific details of type
representation outside qbe.c. It also facilitates some future
simplifications.
|
|
|
|
|
|
This reverts commit 6229709b8ae21d7722fef48ad8a9f2f10b900030.
I still don't understand how out-of-range enum constants are supposed
to work.
|
|
gcc and clang allow enum constants out of range of int, but this
means that the type of enumerator may differ inside and outside the
enum specifier.
Instead, only allow out-of-range enum constants when their types
are compatible with the final enum type.
|
|
There is only one type with this kind, so the equality check above
suffices.
|
|
The end of C11 6.7.6.3p15 says that qualifiers should be ignored when
checking compatibility of function types.
|
|
Integer types still undergo integer promotions even if they are the
same type.
|
|
|
|
Fixes #47.
|
|
|
|
|
|
|
|
|
|
|
|
Using a special qualified type kind has a number of problems:
- Important fields such as size, align, and incomplete may not be set,
since the qualified type was created before a struct was completed.
- When we don't care about type qualifiers (which is the usual case),
we have to explicitly unqualify the type which is annoying and
error-prone.
Instead, in derived types, keep track of the qualifiers of the base type
alongside the base type (similar to what is done for members, parameters,
declarations, and expressions in the past few commits).
|
|
|
|
|
|
|
|
|
|
|
|
typeintpromote and typeargpromote assume they are dealing with an
unqualified type, and return an incorrect result if they are given a
qualified one. So, add an assert here.
This was causing const integer types to get promoted to themselves due
to missing lvalue conversions.
Thanks to Andrew Chambers for the bug report and test case.
|
|
|
|
This check was only supposed to return true for enum types and their
corresponding integer type. However, it had the side effect of making
'int' compatible with 'unsigned'.
To fix this, introduce a new basic type kind for enums with the same
rank as 'int', that is only compatible with itself and the 'int' type
with the matching sign.
Thanks to Andrew Chambers for the bug report.
|
|
|
|
Implement typecompatible for types created with non-prototype function
declarations.
Require a function definition with parameter declaration list after a
declaration with a non-empty identifier list.
Detect function definitions with parameter declaration lists containing
types incompatible with the promoted types, and report an error for now.
|
|
While this works nicely for structs, when unions are involved it
makes it impossible to find the next member to initialize without keeping
track of extra data per member.
|
|
|
|
|
|
We need to traverse the type hierarchy from inside to out to calculate
size/alignment of arrays.
|
|
|