Skip to content

Commit 6fd5189

Browse files
committed
Clarifies 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. These rules apply to both packed and non-packed structs. This commit explicitly enumerates the sizes and alignments of C11's complex types into the tables of sizes and alignments, based on the definition these types as struct-like and struct representation details. I have removed the definitions for `wint_t` and `wchar_t` pending a future commit to add them to a Linux-specific RISC-V psABI. It is noted that these definitions were wrong for some platforms such as FreeBSD that use ELF but have their own requirements around `wint_t` and `wchar_t`.
1 parent fc00ad4 commit 6fd5189

File tree

1 file changed

+69
-51
lines changed

1 file changed

+69
-51
lines changed

riscv-elf.md

Lines changed: 69 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88
* [Integer Calling Convention](#integer-calling-convention)
99
* [Hardware Floating-point Calling Convention](#hardware-floating-point-calling-convention)
1010
* [RV32E Calling Convention](#rv32e-calling-convention)
11-
* [Default ABIs and C type sizes](#default-abis-and-c-type-sizes)
11+
* [Default ABIs](#default-abis)
12+
3. [C type details](#c-types)
13+
* [C type sizes and alignments](#c-type-sizes)
14+
* [C type representations](#c-type-representation)
1215
* [va_list, va_start, and va_arg](#va-list-va-start-and-va-arg)
13-
3. [ELF Object Files](#elf-object-file)
16+
4. [ELF Object Files](#elf-object-file)
1417
* [File Header](#file-header)
1518
* [Sections](#sections)
1619
* [String Tables](#string-tables)
@@ -21,7 +24,7 @@
2124
* [Note Sections](#note-sections)
2225
* [Dynamic Table](#dynamic-table)
2326
* [Hash Table](#hash-table)
24-
4. [DWARF](#dwarf)
27+
5. [DWARF](#dwarf)
2528
* [Dwarf Register Numbers](#dwarf-register-numbers)
2629

2730
## Copyright and license information
@@ -241,72 +244,87 @@ s0-s1, and only three temporaries, t0-t2.
241244
If used with an ISA that has any of the registers x16-x31 and f0-f31, then
242245
these registers are considered temporaries.
243246

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

246249
While various different ABIs are technically possible, for software
247250
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
251+
default ABIs for specific architectures:
252+
253+
* **on RV64G**: LP64D, with floats and doubles passed in floating point
254+
registers (i.e. ELFCLASS64 and EF_RISCV_FLOAT_ABI_DOUBLE).
269255

270256
Although RV64GQ systems can technically use EF_RISCV_FLOAT_ABI_QUAD,
271257
it is strongly recommended to use EF_RISCV_FLOAT_ABI_DOUBLE on
272258
general-purpose RV64GQ systems for compatibility with standard RV64G
273259
software.
274260

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.
261+
* **on RV32G**: ILP32D, with floats and doubles passed in floating point
262+
registers (i.e. ELFCLASS32 and EF_RISCV_FLOAT_ABI_DOUBLE).
300263

301264
A future version of this specification may define an ILP32 ABI for
302265
RV64G, but currently this is not a supported operating mode.
303266

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

307323
A null pointer (for all types) has the value zero.
308324

309-
The value of `_Alignof(max_align_t)` is 16.
325+
`_Complex` types have the same layout as a struct containing two fields of the
326+
corresponding real type (`float`, `double`, or `long double`), with the first
327+
member holding the real part and the second member holding the imaginary part.
310328

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

0 commit comments

Comments
 (0)