[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