https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51628
--- Comment #48 from rguenther at suse dot de <rguenther at suse dot de> --- On Thu, 12 Apr 2018, dingcurie at icloud dot com wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51628 > > W.H. Ding <dingcurie at icloud dot com> changed: > > What |Removed |Added > ---------------------------------------------------------------------------- > CC| |dingcurie at icloud dot com > > --- Comment #47 from W.H. Ding <dingcurie at icloud dot com> --- > Hi, everyone > > I wonder if this issue has to do with the bug-like problem I encountered when > accessing an unaligned stand-alone global variable (rather than a member of a > packed struct). A test case is as follows: > > char g_c = 'x'; > int g_d __attribute__((aligned(1))) = 13; > > int main(void) > { > g_c = 'z'; > //================ > g_d = 33; // Crash on, in my case, ARM Cortex-M0 > //================ > return 0; > } > > Due to the presence of g_c, g_d is at an odd address, as the map file > indicates: > > .data.g_c 0x20000020 0x1 ./src/test.o > 0x20000020 g_c > .data.g_d 0x20000021 0x4 ./src/test.o > 0x20000021 g_d > > The generated assembly, however, accesses g_d as if it were properly aligned: > > 8:../src/test.c **** //================ > 9:../src/test.c **** g_d = 33; > 52 .loc 1 9 0 > 53 000a 044B ldr r3, .L2+4 > 54 000c 2122 movs r2, #33 > 55 000e 1A60 str r2, [r3] > 10:../src/test.c **** //================ > > BTW: I'm using GNU ARM Embedded Toolchain 7-2017-q4-major and on Windows 7. > > Any ideas? It looks like RTL expansion is broken here (also on x86_64): ;; g_d = 33; (insn 6 5 0 (set (mem/c:SI (symbol_ref:DI ("g_d") [flags 0x2] <var_decl 0x7fea38d38ea0 g_d>) [1 g_d+0 S4 A32]) (const_int 33 [0x21])) "t.c":7 -1 (nil)) notice how the MEM has 32bit alignment. This is probably because while g_d has a DECL_ALIGN of 8 it has a type with TYPE_ALIGN of 32. IIRC there's related bugs for the FEs that taking the address of g_d results in a 32bit aligned int * pointer and thus *&g_d has different alignment than g_d. A workaround is to place such variables in a struct I guess. The "bug" is in set_mem_attributes_minus_bitpos (when you ignore the FE bug of mismatch of decl and type alignment): /* We can set the alignment from the type if we are making an object or if this is an INDIRECT_REF. */ if (objectp || TREE_CODE (t) == INDIRECT_REF) attrs.align = MAX (attrs.align, TYPE_ALIGN (type)); a workaround would be to do the following as in the !TYPE_P path we already use the type to derive alignment when allowed. Index: gcc/emit-rtl.c =================================================================== --- gcc/emit-rtl.c (revision 259337) +++ gcc/emit-rtl.c (working copy) @@ -1985,9 +1985,8 @@ set_mem_attributes_minus_bitpos (rtx ref able to simply always use TYPE_ALIGN? */ } - /* We can set the alignment from the type if we are making an object or if - this is an INDIRECT_REF. */ - if (objectp || TREE_CODE (t) == INDIRECT_REF) + /* We can set the alignment from the type if we are making an object. */ + if (objectp && TYPE_P (t)) attrs.align = MAX (attrs.align, TYPE_ALIGN (type)); /* If the size is known, we can set that. */