Skip to content

Commit 6ddd030

Browse files
committed
Clarify C type sizes and alignments
I have found the specicifaction confusing, because C type sizes and alignments have so far been defined only for the *architectures* RV32G and RV64G. This is confusing, as there are 32- and 64-bit architectures without all parts of the G extension which also share these type sizes and alignments. This commit separates the definitions of C type sizes and alignments into new section, and defines them for particular ABIs, not architectures. The definitions themselves remain largely unchanged, though wording has been clarified and extra subsection headers have been introduced. For the avoidance of doubt around C struct alignment rules, I have defined the RISC-V psABI rules around size and alignment of structures and unions. This is based on both the x86-64 and Intel386 System V psABI This now explicitly enumerates the sizes and alignments of C11's complex types into the tables of sizes and alignments, based on
1 parent fc00ad4 commit 6ddd030

File tree

1 file changed

+69
-48
lines changed

1 file changed

+69
-48
lines changed

riscv-elf.md

Lines changed: 69 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -241,72 +241,93 @@ s0-s1, and only three temporaries, t0-t2.
241241
If used with an ISA that has any of the registers x16-x31 and f0-f31, then
242242
these registers are considered temporaries.
243243

244-
## <a name=default-abis-and-c-type-sizes></a> Default ABIs and C type sizes
244+
## <a name=default-abis></a> Default ABIs
245245

246246
While various different ABIs are technically possible, for software
247247
compatibility reasons it is strongly recommended to use the following
248-
default ABIs:
249-
250-
* **on RV64G**: LP64 with floats and doubles passed in floating point
251-
registers, i.e. ELFCLASS64 and EF_RISCV_FLOAT_ABI_DOUBLE, using the
252-
following C type sizes:
253-
254-
Type | Size (Bytes) | Alignment (Bytes)
255-
------------|---------------|------------------
256-
bool/_Bool | 1 | 1
257-
char | 1 | 1
258-
short | 2 | 2
259-
int | 4 | 4
260-
wchar_t | 4 | 4
261-
wint_t | 4 | 4
262-
long | 8 | 8
263-
long long | 8 | 8
264-
__int128 | 16 | 16
265-
void * | 8 | 8
266-
float | 4 | 4
267-
double | 8 | 8
268-
long double | 16 | 16
248+
default ABIs for specific architectures:
249+
250+
* **on RV64G**: LP64D for XLEN=64, with floats and doubles passed in floating
251+
point registers (i.e. ELFCLASS64 and EF_RISCV_FLOAT_ABI_DOUBLE).
269252

270253
Although RV64GQ systems can technically use EF_RISCV_FLOAT_ABI_QUAD,
271254
it is strongly recommended to use EF_RISCV_FLOAT_ABI_DOUBLE on
272255
general-purpose RV64GQ systems for compatibility with standard RV64G
273256
software.
274257

275-
* **on RV32G**: ILP32 with floats and doubles passed in floating point
276-
registers, i.e. ELFCLASS32 and EF_RISCV_FLOAT_ABI_DOUBLE, using the
277-
following C type sizes:
278-
279-
Type | Size (Bytes) | Alignment (Bytes)
280-
------------|---------------|------------------
281-
bool/_Bool | 1 | 1
282-
char | 1 | 1
283-
short | 2 | 2
284-
int | 4 | 4
285-
wchar_t | 4 | 4
286-
wint_t | 4 | 4
287-
long | 4 | 4
288-
long long | 8 | 8
289-
void * | 4 | 4
290-
float | 4 | 4
291-
double | 8 | 8
292-
long double | 16 | 16
293-
294-
`char` is unsigned. `wchar_t` is signed. `wint_t` is unsigned.
295-
296-
`_Complex` types have the alignment and layout of a struct containing two
297-
fields of the corresponding real type (`float`, `double`, or `long double`),
298-
with the first field holding the real part and the second field holding
299-
the imaginary part.
258+
* **on RV32G**: ILP32D for XLEN=32, with floats and doubles passed in floating
259+
point registers (i.e. ELFCLASS32 and EF_RISCV_FLOAT_ABI_DOUBLE).
300260

301261
A future version of this specification may define an ILP32 ABI for
302262
RV64G, but currently this is not a supported operating mode.
303263

264+
# <a name=c-types></a> C type details
265+
## <a name=c-type-sizes></a> C type sizes and alignments
266+
267+
There are two conventions for C type sizes and alignments.
268+
269+
* **LP64, LP64F, and LP64D**: use the following type sizes and alignments
270+
(based on the LP64 convention):
271+
272+
Type | Size (Bytes) | Alignment (Bytes)
273+
---------------------|---------------|------------------
274+
bool/_Bool | 1 | 1
275+
char | 1 | 1
276+
short | 2 | 2
277+
int | 4 | 4
278+
wchar_t | 4 | 4
279+
wint_t | 4 | 4
280+
long | 8 | 8
281+
long long | 8 | 8
282+
__int128 | 16 | 16
283+
void * | 8 | 8
284+
float | 4 | 4
285+
double | 8 | 8
286+
long double | 16 | 16
287+
float _Complex | 8 | 4
288+
double _Complex | 16 | 8
289+
long double _Complex | 32 | 16
290+
291+
* **ILP32, ILP32F, and ILP32D**: use the following type sizes and alignments
292+
(based on the ILP32 convention):
293+
294+
Type | Size (Bytes) | Alignment (Bytes)
295+
---------------------|---------------|------------------
296+
bool/_Bool | 1 | 1
297+
char | 1 | 1
298+
short | 2 | 2
299+
int | 4 | 4
300+
wchar_t | 4 | 4
301+
wint_t | 4 | 4
302+
long | 4 | 4
303+
long long | 8 | 8
304+
void * | 4 | 4
305+
float | 4 | 4
306+
double | 8 | 8
307+
long double | 16 | 16
308+
float _Complex | 8 | 4
309+
double _Complex | 16 | 8
310+
long double _Complex | 32 | 16
311+
312+
The alignment of `max_align_t` is 16.
313+
314+
Structs and unions are aligned to the alignment of their most strictly aligned
315+
member. The size of any object is a multiple of its alignment.
316+
317+
## <a name=c-type-signedness></a> C type signedness
318+
319+
`char` is unsigned. `wchar_t` is signed. `wint_t` is unsigned.
320+
321+
## <a name=c-type-representation></a> C type values
322+
304323
Booleans (`bool`/`_Bool`) stored in memory or when being passed as scalar
305324
arguments are either `0` (`false`) or `1` (`true`).
306325

307326
A null pointer (for all types) has the value zero.
308327

309-
The value of `_Alignof(max_align_t)` is 16.
328+
`_Complex` types have the layout of a struct containing two fields of the
329+
corresponding real type (`float`, `double`, or `long double`), with the first
330+
field holding the real part and the second field holding the imaginary part.
310331

311332
## <a name=va-list-va-start-and-va-arg></a> va_list, va_start, and va_arg
312333

0 commit comments

Comments
 (0)