Recently I was asked if it was OK that an Armv7 compiler will generate unaligned 32-bit reads… even when it is “obvious” to the compiler that the read the Arm compiler generates 32-bit unaligned reads. That led to my writing a simple test program to use to explore the compiler options:
#include <assert.h>
#include <stdalign.h>
#include <stddef.h>
struct A {
short s1, s2;
} a;
struct B {
short s;
struct A a;
} b;
void c(void) {
static_assert(alignof(a) == 2);
static_assert(sizeof(a) == 4);
static_assert(alignof(b) == 2);
static_assert(offsetof(B, a) == 2);
static_assert(sizeof(b) == 6);
a = b.a;
}
I added a bunch of static asserts to assist the reader in understanding the structure layout. Once we’ve been through the linking process (which aligns the global) then a = b.a will essentially copy an unaligned 32-bit structure (b.a) into an aligned 32-bit structure. The compiler will use a simple ldr instruction to load the value:
ldr r0, [r3, #6] @ unaligned
… and this is an absolutely fine default for an Armv7 compiler since all Armv7 devices can be configured to support misaligned access in hardware. The only time this should ever be a problem is if you are writing bare-metal code and have forgotten to enable this feature in the bootstrap code… and if that’s you then there the -mno-unaligned-access compiler option to get you out of trouble!
To play more with this idea the just first up the Compiler Explorer and have a poke about.
