[cfe-dev] [ARM] Is code generation implemented for __unaligned?
Jan Ole Hüser via cfe-dev
cfe-dev at lists.llvm.org
Fri Sep 11 09:06:59 PDT 2020
Dear all, Dear Roger Ferrer Ibáñez,
at my company we have much Code, which uses the keyword "__unaligned" [1],
which is a Microsoft extension. I have read about an RFC called "Implement
code generation for __unaligned" on the mailing list (from Feburary 2017) [2].
But I could not find out, if it was actually implemented. Is it implemented? If
it is, it does not work for ARM. (Tested with ARMv7-M.)
Consider the following Code:
```
struct GUID {
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[8];
};
void load_and_store_uGUID(__unaligned GUID* in, __unaligned GUID* out){
*out = *in;
}
```
It produces the following assembly:
```
ldm.w r0, {r2, r3, r12}
ldr r0, [r0, #12]
stm.w r1, {r2, r3, r12}
str r0, [r1, #12]
bx lr
```
I have used the this commandline:
C:\Program Files\LLVM\bin\clang++.exe -O2 -S --target=armv7m-none-windows-eabihf -munaligned-access -x c++ -mcpu=cortex-M7 -fms-compatibility-version=19.16.27027.1 -fms-compatibility -fms-extensions
The problem is, that LDM and STM (load and store multiple) are used, which
cannot access one-byte-aligned addresses (aka. unaligned). LDR and STR however
can be used for unaligned access.
The following C++ code translates to code, which can access unalgined memory.
```
extern "C" void* memcpy( void* dest, const void* src, decltype(sizeof(0)) count );
void load_and_store_memcpy(__unaligned GUID* in, __unaligned GUID* out){
memcpy(reinterpret_cast<char*>(out), reinterpret_cast<char*>(in),
sizeof(__unaligned GUID));
}
```
The cast to a byte pointer is necessary.
Here is the assembler Code:
```
ldr.w r12, [r0]
ldr r3, [r0, #4]
ldr r2, [r0, #8]
ldr r0, [r0, #12]
str r0, [r1, #12]
str r2, [r1, #8]
str r3, [r1, #4]
str.w r12, [r1]
bx lr
```
I could rewrite all that old code to use memcpy or use structs with
__attribute__((packed)). But maybe --I hope-- there is some old patch for
clang, that didn't get into trunk, but could help me out. Or maybe it is easy
to implement. @Roger, is there a patch somewhere?
Site Note:
The problem with __attribute__((packed)) is, that it cannot be added to an
existing type (for example: "typedef __attribute__((packed)) GUID pGUID;"), but
the definition has to be changed. Another problem is, that it changes the offset
of the members in the struct. Is that called "Record Layout"?
Kind regards,
Ole
[1] https://docs.microsoft.com/en-us/cpp/cpp/unaligned
[2] http://lists.llvm.org/pipermail/cfe-dev/2017-February/052739.html
Beckhoff Automation GmbH & Co. KG | Managing Director: Dipl. Phys. Hans Beckhoff
Registered office: Verl, Germany | Register court: Guetersloh HRA 7075
More information about the cfe-dev
mailing list