https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89544

            Bug ID: 89544
           Summary: Argument marshalling incorrectly assumes stack slots
                    are naturally aligned.
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: rearnsha at gcc dot gnu.org
                CC: bernd.edlinger at hotmail dot de, ebotcazou at gcc dot 
gnu.org
  Target Milestone: ---
            Target: arm

The AAPCS requires that an object which is artificially overaligned is passed
at either its natural alignment (if <= 8) or on an 8-byte boundary if it is
more aligned than that.  So a struct of the form

struct s
{ int a; int b;} __attribute__((aligned(8));

has a natural alignment of 4 and must be passed by value with 4-byte alignment.

The middle end code ignores this and assign_parm_find_stack_rtl ends up
generating invalid rtl of the form

(mem/c:DI (plus:SI (reg/f:SI 104 virtual-incoming-args)
        (const_int 4 [0x4])) [1 f+0 S8 A32])

ie a DImode object with 32-bit alignment.  It then proceeds to ignore the under
alignment when expanding to RTL and incorrectly calls gen_movdi directly,
rather than falling back to the misaligned move code.

Test case:

struct s {
  int a, b;
} __attribute__((aligned(8)));

struct s f0;
int f(int a, int b, int c, int d, int e, struct s f)
{
  f0 = f;
  return __alignof(f);
}

When compiled with "-O -march=armv5te" generates:

        @ args = 12, pretend = 0, frame = 0
        @ frame_needed = 0, uses_anonymous_args = 0
        @ link register save eliminated.
        ldrd    r0, [sp, #4]        <========== Invalid alignment for ldrd
        ldr     r3, .L2
        strd    r0, [r3]
        mov     r0, #8
        bx      lr

Reply via email to