GCC's __BIGGEST_ALIGNMENT__ macro on RISC-V architectures - Page 1
Forum section: electronics / general

author: HwAoRrDk
author_rank: Super Contributor
timestamp: December 24, 2024, 09:47:56 am
content: GCC documents the__BIGGEST_ALIGNMENT__macro as:QuoteHowever, I have found that in code compiled for 32-bit RISC-V microcontrollers, this macro's value is 16.I would have expected it to be 4. That is, I would expect it to reflect the architecture's (as specified by-march) native word/register size - 4 bytes for RV32, 8 bytes for RV64, etc.Where does 16 come from? Are they just blanket defining it as 16 because RV128 is a thing, and so therefore itobviouslymust be that when the target machine is any RISC-V architecture?Surely it should be more nuanced than that...

author: xvr
author_rank: Frequent Contributor
timestamp: December 24, 2024, 01:34:55 pm
content: Stack alignment is 16. But I not sure how it connected to __BIGGEST_ALIGNMENT__May be something penetrated from Vector Extension

author: I wanted a rude username
author_rank: Frequent Contributor
timestamp: December 24, 2024, 03:51:40 pm
content: Since you're targeting RV32, more likely this is because of the Q extension (128 b float).This is also how the compiler will align if you don't specify a size:Code:int16_t array __attribute__ ((aligned)); // Aligns to at least 16 B on most architecturesUsually we use compiler hints of this type to tell the compiler something that we know and it doesn't. So in practice you'll find people specifying the desired alignment explicitly (e.g. 8 B in this case).

author: HwAoRrDk
author_rank: Super Contributor
timestamp: December 24, 2024, 04:45:22 pm
content: The thing is I understand that there are architecture variations (e.g. RV128) or extensions that give a data type with 128-bit width, but if I'm specifying, for example,-march=rv32ecwhere no instruction can work with anything larger than 4 bytes, then surely that shouldn't apply?I picked up on__BIGGEST_ALIGNMENT__because I was using__attribute__((aligned(n)))to specify that something needed to be word-aligned, and I thought that rather than specifying a fixed value, the macro would give me whatever the native word size was for the architecture being compiled for. But it seems it doesn't work like that, and just gives you the same value that__attribute__((aligned))uses when not specifying a size. So what's even the point of the existence of the macro? Maybe it's different for different platforms...

author: I wanted a rude username
author_rank: Frequent Contributor
timestamp: December 24, 2024, 06:00:22 pm
content: If you want to align on native word size ... why don't you just use __UNITS_PER_WORD__?

author: ejeffrey
author_rank: Super Contributor
timestamp: December 24, 2024, 06:40:37 pm
content: BIGGEST_ALIGNMENT is the maximum alignment required by the ABI, not the architecture. So architectural flags aren't going to affect it unless it corresponds to a different ABI (riscv32 vs 64). That's going to be at least 8 bytes on most platforms that require double to be naturally aligned, and 16 bytes if it has a long double or long long type that requires it. This is independent of whether the architecture has hardware support for floating point or whether you actually link the soft math libraries.If you want the machine native word size, use sizeof(void *).

author: Nominal Animal
author_rank: Super Contributor
timestamp: December 24, 2024, 06:57:04 pm
content: This can sound like a nitpick, but I warmly recommend writing that assizeof (void *), with a space after thesizeofkeyword, simply to remind us humans that it is not a function call and does not work like a function call; the expression is only evaluated for the type, without any side effects like memory accesses (or even pre- or post-increment and -decrement operations being applied).The C language itself does not care either way, it's just for us humans.

author: SiliconWizard
author_rank: Super Contributor
timestamp: December 24, 2024, 09:38:32 pm
content: Quote from: ejeffrey on December 24, 2024, 06:40:37 pmIf we're gonna nitpick further, problem is, whatever is meant by "native word size". Granted the OP was talking about RISC-V, in in this case, pointers will have the same size as all general-purpose registers, which I guess is what we could call "native word size" (backed by the numbering in RVxx). For other architectures, you can have different register sizes for different things, in particular address registers may have a different size than "data" registers. So 'sizeof (void *)' is not exactly a portable way of finding this out, and "native word size" isn't really a portable concept either.If this is targetted at RISC-V specifically, rather than 'sizeof (void *)', I prefer using GCC's predefined macros (similarly available with Clang): __riscv_xlen, which give the XLEN value for the RISC-V target the code is compiled for (in bits! so, if you want the value in bytes, obviously just divide it by 8, it will be done at compile time for sure.)Similarly, you have __riscv_flen for the width of the FP registers.Just my 2 cents.Of course, if you specifically want the size of *pointers* in a portable way, sizeof (void *) would do. Be again careful (although this is only found in niche architectures) that pointers to data and pointers to functions may have a different size.As to the __BIGGEST_ALIGNMENT__ predefined macro, see: 'https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.htmlAs the name implies, it's the "largest alignment ever used for any data type on the target machine".

author: TheCalligrapher
author_rank: Regular Contributor
timestamp: December 26, 2024, 06:53:47 pm
content: Quote from: HwAoRrDk on December 24, 2024, 09:47:56 amThat's unfounded, since the alignment requirements (including hardware-dicatated ones) are not generally tied to native word size. On x64, for one example, GCC's alignment requirement for `long double` values is 16, despite the native word size of 8. And there are x86 CPU instructions that will generate a bus error if fed with an unaligned `long double`.Does 32-bit RISC-V GCC support any "over-aligned" types like that? BTW, as a wild guess, what is `long double` in 32-bit RISC-V GCC?---Just noticed that Godbolt offers 32-bit RISC-V GCC. So, let's tryCode:int x = alignof(long double);int main() {}compiles toCode:main:li a0,0retx:.word 16So, here's your 16. It is indeed `long double` (at least). Not surprisingly, `alignof(std::max_align_t)` is also 16.

author: HwAoRrDk
author_rank: Super Contributor
timestamp: December 30, 2024, 06:37:42 pm
content: Oh, so it's an ABI thing, not something related to the specific-marchbeing compiled for.It'd probably help if they described it as such in the documentation, rather than the slightly ambiguous "target machine". Unless "target machine" has a more precise meaning that I'm not aware of within the lexicon of GCC...