Page 1 of 1
Ignore "-Wcast-align" warnings
Posted: Thu Oct 29, 2020 6:16 pm
by stertingen
Using GCC, I have enabled the "-Wcast-align" warnings enabled.
Unfortunately, 1. the ChibiOS code performs such casting operations which increase the required alignment and 2. the ChibiOS Makefile structure does not easily allow to disable warnings for ChibiOS source files while keeping them enabled for the project source files.
I see a few ways to approach this issue:
1. Add something like '#pragma GCC diagnostic ignored "-Wcast-align"'
2. Separate project source files and ChibiOS source files in the Makefile, so the ChibiOS files are compiled without warnings
3. Try not to use such cast operations and use memcpy instead.
See also:
http://blog.antiblau.de/2016/07/13/cc-d ... ast-align/
Re: Ignore "-Wcast-align" warnings
Posted: Fri Nov 13, 2020 4:26 pm
by stertingen
Some thoughts on how to prevent unaligned memory access:
Perform pointer arithmetic on maximum alignmentInstead of
Code: Select all
uint32_t * x = (uint32_t)((uint8_t *)y + n)
do
Code: Select all
uint32_t * x = (uint32_t *)y + n / sizeof (uint32_t)
So we guarantee that x has the correct alignment. Of course we have to ensure that
Code: Select all
(n / sizeof (uint32_t)) * sizeof (uint32_t) == n
Compare pointers on minimum alignmentInstead of
Code: Select all
uint32_t * a; uint8_t * b;
a == (uint32_t *)b
do
or maybe even
as we do not want to dereference the pointers. However, I sometimes feel uncomfortable when using void pointers.
Use memcpy to copy data into or from a buffer at arbitrary alignmentInstead of
Code: Select all
uint8_t * buf = ...;
uint32_t x = ...;
x = *((uint32_t *)buf);
*((uint32_t *)buf) = x;
do
Code: Select all
memcpy(&x, buf, sizeof (uint32_t));
memcpy(buf, &x, sizeof (uint32_t));
because it might be possible that three or five bytes have been already written to buf, so buf might not be aligned.
I have tried to refactor some affected functions, however, they are not tested:
Re: Ignore "-Wcast-align" warnings
Posted: Fri Nov 13, 2020 6:55 pm
by Giovanni
Hi,
In general OK but the use of memcpy() would impact performance in some pretty critical places, see USB code, that code implicitly relies on pointers being correctly aligned.
Giovanni
Re: Ignore "-Wcast-align" warnings
Posted: Sat Nov 14, 2020 8:59 pm
by stertingen
Giovanni wrote:Hi,
In general OK but the use of memcpy() would impact performance in some pretty critical places, see USB code, that code implicitly relies on pointers being correctly aligned.
Giovanni
GCC is smart enough to replace calls to memcpy() with other copy operations when appropriate with -O2. I looked through the disassembly of hal_buffers.o. While hal_buffers.c contains 9 calls to memcpy, hal_buffers.o has only 2 calls to memcpy (in ibqReadTimeout and obqWriteTimeout).
However, I have not looked at other compilers.
I wonder if there's a way to tell the compiler "this pointer is correctly aligned" other than making it a uint32_t* (or stkalign_t* or ...). The only way I see to do this is by declaring it as uint32_t* and cast it down to uint8_t* if byte-wise operations are needed.
Re: Ignore "-Wcast-align" warnings
Posted: Sun Nov 15, 2020 11:17 am
by stertingen
stertingen wrote:I wonder if there's a way to tell the compiler "this pointer is correctly aligned" other than making it a uint32_t* (or stkalign_t* or ...). The only way I see to do this is by declaring it as uint32_t* and cast it down to uint8_t* if byte-wise operations are needed.
Actually, there is __builtin_assume_aligned:
https://gcc.gnu.org/onlinedocs/gcc-5.4. ... ltins.html
Re: Ignore "-Wcast-align" warnings
Posted: Sun Nov 15, 2020 12:07 pm
by Giovanni
stertingen wrote:stertingen wrote:I wonder if there's a way to tell the compiler "this pointer is correctly aligned" other than making it a uint32_t* (or stkalign_t* or ...). The only way I see to do this is by declaring it as uint32_t* and cast it down to uint8_t* if byte-wise operations are needed.
Actually, there is __builtin_assume_aligned:
https://gcc.gnu.org/onlinedocs/gcc-5.4. ... ltins.html
That is GCC-specific, cannot use that in portable code.
Giovanni
Re: Ignore "-Wcast-align" warnings
Posted: Sun Nov 15, 2020 2:58 pm
by stertingen
Giovanni wrote:stertingen wrote:stertingen wrote:I wonder if there's a way to tell the compiler "this pointer is correctly aligned" other than making it a uint32_t* (or stkalign_t* or ...). The only way I see to do this is by declaring it as uint32_t* and cast it down to uint8_t* if byte-wise operations are needed.
Actually, there is __builtin_assume_aligned:
https://gcc.gnu.org/onlinedocs/gcc-5.4. ... ltins.html
That is GCC-specific, cannot use that in portable code.
Giovanni
Yeah, you're right. ((uint32_t *)((void *)(ptr))) does also silent the warning because of the intermediate cast to void*. __builtin_assume_aligned silences the warning because it returns void*, not because it informs the compiler about the pointer alignment. The warning still disappears for (uint32_t*)__builtin_assume_aligned(ptr, 1) although it shouldn't.
If we are sure that (1.) the pointer is correctly aligned OR (2.) the platform supports unaligned memory access, the warning could be silenced using an intermediate cast to void*.