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.  */

Reply via email to