From 6fd5189b8f1168ec56d06185b2ea93272f7aa36f Mon Sep 17 00:00:00 2001 From: Sam Elliott Date: Wed, 9 Oct 2019 15:26:06 +0100 Subject: [PATCH 1/6] 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`. --- riscv-elf.md | 120 +++++++++++++++++++++++++++++---------------------- 1 file changed, 69 insertions(+), 51 deletions(-) diff --git a/riscv-elf.md b/riscv-elf.md index 26134c32..19bd49b4 100644 --- a/riscv-elf.md +++ b/riscv-elf.md @@ -8,9 +8,12 @@ * [Integer Calling Convention](#integer-calling-convention) * [Hardware Floating-point Calling Convention](#hardware-floating-point-calling-convention) * [RV32E Calling Convention](#rv32e-calling-convention) - * [Default ABIs and C type sizes](#default-abis-and-c-type-sizes) + * [Default ABIs](#default-abis) +3. [C type details](#c-types) + * [C type sizes and alignments](#c-type-sizes) + * [C type representations](#c-type-representation) * [va_list, va_start, and va_arg](#va-list-va-start-and-va-arg) -3. [ELF Object Files](#elf-object-file) +4. [ELF Object Files](#elf-object-file) * [File Header](#file-header) * [Sections](#sections) * [String Tables](#string-tables) @@ -21,7 +24,7 @@ * [Note Sections](#note-sections) * [Dynamic Table](#dynamic-table) * [Hash Table](#hash-table) -4. [DWARF](#dwarf) +5. [DWARF](#dwarf) * [Dwarf Register Numbers](#dwarf-register-numbers) ## Copyright and license information @@ -241,72 +244,87 @@ s0-s1, and only three temporaries, t0-t2. If used with an ISA that has any of the registers x16-x31 and f0-f31, then these registers are considered temporaries. -## Default ABIs and C type sizes +## Default ABIs While various different ABIs are technically possible, for software compatibility reasons it is strongly recommended to use the following -default ABIs: - - * **on RV64G**: LP64 with floats and doubles passed in floating point - registers, i.e. ELFCLASS64 and EF_RISCV_FLOAT_ABI_DOUBLE, using the - following C type sizes: - - Type | Size (Bytes) | Alignment (Bytes) - ------------|---------------|------------------ - bool/_Bool | 1 | 1 - char | 1 | 1 - short | 2 | 2 - int | 4 | 4 - wchar_t | 4 | 4 - wint_t | 4 | 4 - long | 8 | 8 - long long | 8 | 8 - __int128 | 16 | 16 - void * | 8 | 8 - float | 4 | 4 - double | 8 | 8 - long double | 16 | 16 +default ABIs for specific architectures: + + * **on RV64G**: LP64D, with floats and doubles passed in floating point + registers (i.e. ELFCLASS64 and EF_RISCV_FLOAT_ABI_DOUBLE). Although RV64GQ systems can technically use EF_RISCV_FLOAT_ABI_QUAD, it is strongly recommended to use EF_RISCV_FLOAT_ABI_DOUBLE on general-purpose RV64GQ systems for compatibility with standard RV64G software. - * **on RV32G**: ILP32 with floats and doubles passed in floating point - registers, i.e. ELFCLASS32 and EF_RISCV_FLOAT_ABI_DOUBLE, using the - following C type sizes: - - Type | Size (Bytes) | Alignment (Bytes) - ------------|---------------|------------------ - bool/_Bool | 1 | 1 - char | 1 | 1 - short | 2 | 2 - int | 4 | 4 - wchar_t | 4 | 4 - wint_t | 4 | 4 - long | 4 | 4 - long long | 8 | 8 - void * | 4 | 4 - float | 4 | 4 - double | 8 | 8 - long double | 16 | 16 - -`char` is unsigned. `wchar_t` is signed. `wint_t` is unsigned. - -`_Complex` types have the alignment and layout of a struct containing two -fields of the corresponding real type (`float`, `double`, or `long double`), -with the first field holding the real part and the second field holding -the imaginary part. + * **on RV32G**: ILP32D, with floats and doubles passed in floating point + registers (i.e. ELFCLASS32 and EF_RISCV_FLOAT_ABI_DOUBLE). A future version of this specification may define an ILP32 ABI for RV64G, but currently this is not a supported operating mode. +# C type details +## C type sizes and alignments + +There are two conventions for C type sizes and alignments. + + * **LP64, LP64F, and LP64D**: use the following type sizes and alignments + (based on the LP64 convention): + + Type | Size (Bytes) | Alignment (Bytes) + ---------------------|---------------|------------------ + bool/_Bool | 1 | 1 + char | 1 | 1 + short | 2 | 2 + int | 4 | 4 + long | 8 | 8 + long long | 8 | 8 + __int128 | 16 | 16 + void * | 8 | 8 + float | 4 | 4 + double | 8 | 8 + long double | 16 | 16 + float _Complex | 8 | 4 + double _Complex | 16 | 8 + long double _Complex | 32 | 16 + + * **ILP32, ILP32F, and ILP32D**: use the following type sizes and alignments + (based on the ILP32 convention): + + Type | Size (Bytes) | Alignment (Bytes) + ---------------------|---------------|------------------ + bool/_Bool | 1 | 1 + char | 1 | 1 + short | 2 | 2 + int | 4 | 4 + long | 4 | 4 + long long | 8 | 8 + void * | 4 | 4 + float | 4 | 4 + double | 8 | 8 + long double | 16 | 16 + float _Complex | 8 | 4 + double _Complex | 16 | 8 + long double _Complex | 32 | 16 + +The alignment of `max_align_t` is 16. + +Structs and unions are aligned to the alignment of their most strictly aligned +member. The size of any object is a multiple of its alignment. + +## C type representations + +`char` is unsigned. + Booleans (`bool`/`_Bool`) stored in memory or when being passed as scalar arguments are either `0` (`false`) or `1` (`true`). A null pointer (for all types) has the value zero. -The value of `_Alignof(max_align_t)` is 16. +`_Complex` types have the same layout as a struct containing two fields of the +corresponding real type (`float`, `double`, or `long double`), with the first +member holding the real part and the second member holding the imaginary part. ## va_list, va_start, and va_arg From c70c09dd9cbed5588e28c320d5e5ec1fca1ab75b Mon Sep 17 00:00:00 2001 From: Sam Elliott Date: Thu, 10 Oct 2019 13:07:10 +0100 Subject: [PATCH 2/6] Adds definition of CHAR_BITS --- riscv-elf.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/riscv-elf.md b/riscv-elf.md index 19bd49b4..cfda0c3c 100644 --- a/riscv-elf.md +++ b/riscv-elf.md @@ -310,6 +310,8 @@ There are two conventions for C type sizes and alignments. The alignment of `max_align_t` is 16. +`CHAR_BITS` is 8. + Structs and unions are aligned to the alignment of their most strictly aligned member. The size of any object is a multiple of its alignment. From 928754202b7c2e32dc7d9e2790e709ae1b4ca1d8 Mon Sep 17 00:00:00 2001 From: Sam Elliott Date: Fri, 11 Oct 2019 11:13:10 +0100 Subject: [PATCH 3/6] Adds Linux-specific ABI Section The specification was previously over-perscriptive in the definitions of the size, alignment, and signedness of `wchar_t` and `wint_t`. After some discussion it has been agreed to split these definitions out from the main specification and into a separate section that only applies on Linux. This commit introduces that section with the existing definitions for `wchar_t` and `wint_t`. --- riscv-elf.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/riscv-elf.md b/riscv-elf.md index cfda0c3c..e7f262dc 100644 --- a/riscv-elf.md +++ b/riscv-elf.md @@ -26,6 +26,9 @@ * [Hash Table](#hash-table) 5. [DWARF](#dwarf) * [Dwarf Register Numbers](#dwarf-register-numbers) +6. [Linux-specific ABI](#linux-abi) + * [Linux-specific C type sizes and alignments](#linux-c-type-sizes) + * [Linux-specific C type representations](#linux-c-type-representations) ## Copyright and license information @@ -833,3 +836,29 @@ Dwarf Number | Register Name | Description The alternate frame return column is meant to be used when unwinding from signal handlers, and stores the address where the signal handler will return to. + +# Linux-specific ABI + +**This section of the RISC-V ELF psABI specification only applies to Linux-based +systems.** + +In order to ensure compatibility between different implementations of the C +library for Linux, we provide some extra definitions which only apply on those +systems. These are noted in this section. + +## Linux-specific C type sizes and alignments + +The following definitions apply for all ABIs defined in this document. Here +there is no differentiation between ILP32 and LP64 abis. + +Type | Size (Bytes) | Alignment (Bytes) +------------|---------------|------------------ +wchar_t | 4 | 4 +wint_t | 4 | 4 + +## Linux-specific C type representations + +The following definitions apply for all ABIs defined in this document. Here +there is no differentiation between ILP32 and LP64 abis. + +`wchar_t` is signed. `wint_t` is unsigned. \ No newline at end of file From 2bd25b59e3dc06d9547b281cd51052705fb7514b Mon Sep 17 00:00:00 2001 From: Sam Elliott Date: Fri, 11 Oct 2019 12:57:58 +0100 Subject: [PATCH 4/6] Adds Named ABI definitions This commit adds explicitly named ABI definitions, to match and extend the conventions used so far by GCC and Clang. The aim here is to be explicit about what each named ABI means in terms of which parts of the calling conventions are used, when they are compatible with different ISAs, and how this maps to C types and sizes. This Commit defines - ILP32 (32-bit, no hardware floating-point) - ILP32F (32-bit, single-precision hardware floating-point) - ILP32D (32-bit, double-precision hardware floating-point) - ILP32E (32-bit, no hardware floating point, RVE registers only) - LP64 (64-bit, no hardware floating-point) - LP64F (64-bit, single-precision hardware floating-point) - LP64D (64-bit, double-precision hardware floating-point) - LP64Q (64-bit, quad-precision hardware floating-point) --- riscv-elf.md | 70 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 16 deletions(-) diff --git a/riscv-elf.md b/riscv-elf.md index e7f262dc..c9d18354 100644 --- a/riscv-elf.md +++ b/riscv-elf.md @@ -7,7 +7,8 @@ 2. [Procedure Calling Convention](#procedure-calling-convention) * [Integer Calling Convention](#integer-calling-convention) * [Hardware Floating-point Calling Convention](#hardware-floating-point-calling-convention) - * [RV32E Calling Convention](#rv32e-calling-convention) + * [ILP32E Calling Convention](#ilp32e-calling-convention) + * [Named ABIs](#named-abis) * [Default ABIs](#default-abis) 3. [C type details](#c-types) * [C type sizes and alignments](#c-type-sizes) @@ -184,9 +185,9 @@ whether or not the integer registers have been exhausted. The remainder of this section applies only to named arguments. Variadic arguments are passed according to the integer calling convention. -For the purposes of this section, FLEN refers to the width of a -floating-point register in the ABI. The ISA might have wider -floating-point registers than the ABI. +For the purposes of this section, FLEN refers to the width of a floating-point +register in the ABI. The ABI's FLEN must be no wider than the ISA's FLEN. The +ISA might have wider floating-point registers than the ABI. For the purposes of this section, "struct" refers to a C struct with its hierarchy flattened, including any array fields. That is, `struct { struct @@ -235,18 +236,58 @@ type would be passed. Floating-point registers fs0-fs11 shall be preserved across procedure calls, provided they hold values no more than FLEN bits wide. -## RV32E Calling Convention +## ILP32E Calling Convention -The RV32E calling convention is designed to be usable with the RV32E ISA. -This calling convention is the same as the integer calling convention, -except for the following differences. The stack pointer need only be aligned -to a 32-bit boundary. Registers x16-x31 do not participate in the ABI, so +The ILP32E calling convention is designed to be usable with the RV32E ISA. This +calling convention is the same as the integer calling convention, except for the +following differences. The stack pointer need only be aligned to a 32-bit +boundary. Registers x16-x31 do not participate in the calling convention, so there are only six argument registers, a0-a5, only two callee-saved registers, s0-s1, and only three temporaries, t0-t2. If used with an ISA that has any of the registers x16-x31 and f0-f31, then these registers are considered temporaries. +## Named ABIs + +This specification defines the following named ABIs: + +* **ILP32**: Integer calling-convention only, hardware + floating-point calling convention is not used (i.e. ELFCLASS32 and + EF_RISCV_FLOAT_ABI_SOFT). + +* **ILP32F**: ILP32 with hardware floating-point calling + convention for FLEN=32 (i.e. ELFCLASS32 and EF_RISCV_FLOAT_ABI_SINGLE). + +* **ILP32D**: ILP32 with hardware floating-point calling + convention for FLEN=64 (i.e. ELFCLASS32 and EF_RISCV_FLOAT_ABI_DOUBLE). + +* **ILP32E**: [ILP32E + calling-convention](#ilp32e-calling-convention) only, hardware floating-point + calling convention is not used (i.e. ELFCLASS32, EF_RISCV_FLOAT_ABI_SOFT, and + EF_RISCV_RVE). + +* **LP64**: Integer calling-convention only, hardware + floating-point calling convention is not used (i.e. ELFCLASS64 and + EF_RISCV_FLOAT_ABI_SOFT). + +* **LP64F**: LP64 with hardware floating-point calling + convention for FLEN=32 (i.e. ELFCLASS64 and EF_RISCV_FLOAT_ABI_SINGLE). + +* **LP64D**: LP64 with hardware floating-point calling + convention for FLEN=64 (i.e. ELFCLASS64 and EF_RISCV_FLOAT_ABI_DOUBLE). + +* **LP64Q**: LP64 with hardware floating-point calling + convention for FLEN=128 (i.e. ELFCLASS64 and EF_RISCV_FLOAT_ABI_QUAD). + +The ILP32\* ABIs are only compatible with RV32\* ISAs, and the LP64\* ABIs are +only compatible with RV64\* ISAs. A future version of this specification may +define an ILP32 ABI for the RV64 ISA, but currently this is not a supported +operating mode. + +The \*F ABIs require the \*F ISA extension, the \*D ABIs require the \*D ISA +extension, and the LP64Q ABI requires the Q ISA extension. + ## Default ABIs While various different ABIs are technically possible, for software @@ -264,16 +305,13 @@ default ABIs for specific architectures: * **on RV32G**: ILP32D, with floats and doubles passed in floating point registers (i.e. ELFCLASS32 and EF_RISCV_FLOAT_ABI_DOUBLE). -A future version of this specification may define an ILP32 ABI for -RV64G, but currently this is not a supported operating mode. - # C type details ## C type sizes and alignments There are two conventions for C type sizes and alignments. - * **LP64, LP64F, and LP64D**: use the following type sizes and alignments - (based on the LP64 convention): + * **LP64, LP64F, LP64D, and LP64Q**: use the following type sizes and + alignments (based on the LP64 convention): Type | Size (Bytes) | Alignment (Bytes) ---------------------|---------------|------------------ @@ -292,8 +330,8 @@ There are two conventions for C type sizes and alignments. double _Complex | 16 | 8 long double _Complex | 32 | 16 - * **ILP32, ILP32F, and ILP32D**: use the following type sizes and alignments - (based on the ILP32 convention): + * **ILP32, ILP32F, ILP32D, and ILP32E**: use the following type sizes and + alignments (based on the ILP32 convention): Type | Size (Bytes) | Alignment (Bytes) ---------------------|---------------|------------------ From b7148a997b583e572a344fbdb767de294e046bd7 Mon Sep 17 00:00:00 2001 From: Sam Elliott Date: Mon, 14 Oct 2019 10:30:38 +0100 Subject: [PATCH 5/6] Defines Default ABIs in terms of Named ABIs --- riscv-elf.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/riscv-elf.md b/riscv-elf.md index c9d18354..f3dc4973 100644 --- a/riscv-elf.md +++ b/riscv-elf.md @@ -294,16 +294,13 @@ While various different ABIs are technically possible, for software compatibility reasons it is strongly recommended to use the following default ABIs for specific architectures: - * **on RV64G**: LP64D, with floats and doubles passed in floating point - registers (i.e. ELFCLASS64 and EF_RISCV_FLOAT_ABI_DOUBLE). + * **on RV64G**: [LP64D](#abi-lp64d) - Although RV64GQ systems can technically use EF_RISCV_FLOAT_ABI_QUAD, - it is strongly recommended to use EF_RISCV_FLOAT_ABI_DOUBLE on - general-purpose RV64GQ systems for compatibility with standard RV64G - software. + Although RV64GQ systems can technically use [LP64Q](#abi-lp64q), it is + strongly recommended to use LP64D on general-purpose RV64GQ systems for + compatibility with standard RV64G software. - * **on RV32G**: ILP32D, with floats and doubles passed in floating point - registers (i.e. ELFCLASS32 and EF_RISCV_FLOAT_ABI_DOUBLE). + * **on RV32G**: [ILP32D](#abi-ilp32d) # C type details ## C type sizes and alignments From c1650c4f22f2764b52f0a341daea17ab8ce1d5e5 Mon Sep 17 00:00:00 2001 From: Sam Elliott Date: Mon, 14 Oct 2019 10:51:37 +0100 Subject: [PATCH 6/6] Adds Sam Elliott to Contributors --- riscv-elf.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/riscv-elf.md b/riscv-elf.md index f3dc4973..21e0980f 100644 --- a/riscv-elf.md +++ b/riscv-elf.md @@ -35,15 +35,16 @@ This RISC-V ELF psABI specification document is - © 2016 Palmer Dabbelt - © 2016 Stefan O'Rear - © 2016 Kito Cheng - © 2016-2017 Andrew Waterman - © 2016-2017 Michael Clark - © 2017-2019 Alex Bradbury - © 2017 David Horner - © 2017 Max Nordlund - © 2017 Karsten Merker + © 2016 Palmer Dabbelt + © 2016 Stefan O'Rear + © 2016 Kito Cheng + © 2016-2017 Andrew Waterman + © 2016-2017 Michael Clark + © 2017-2019 Alex Bradbury + © 2017 David Horner + © 2017 Max Nordlund + © 2017 Karsten Merker + © 2019 Sam Elliott It is licensed under the Creative Commons Attribution 4.0 International License (CC-BY 4.0). The full license text is available at