In the following code, the tail call in g() is compiled incorrectly on ARM with
-O2 or higher (and -fno-inline):

#include <stdio.h>

struct s {
    int x, y, z;
};

int f(int a, int b, int c, struct s d, int e) {
    printf("%d %d %d\n", d.x, d.y, d.z);
    return 0;
}

int g(int a, int b, int c, int d, struct s e, int h) {
        return f(a, b, c, e, h);
}

int main(void) {
    f(0, 0, 0, (struct s){ 42, 69, 105 }, 7);
    g(0, 0, 0, 0, (struct s){ 42, 69, 105 }, 7);
    return 0;
}

With -O1 and lower, the result is correct:

42 69 105
42 69 105

With -O2 and higher, it prints:

42 69 105
69 69 7

Inspecting the output of gcc -O3 -fno-inline -S shows that gcc is shifting the
arguments on the stack downwards for the tail call. However, it starts at the
top, rather than at the bottom. So it writes over two arguments (e.z and e.x)
before loading them.

This has been broken since 4.1.1 (possibly earlier), and is still broken in
4.2.2.


-- 
           Summary: Incorrect code for tail calls with a structure as 4th
                    argument
           Product: gcc
           Version: 4.2.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: narge-gcc at derrin dot id dot au
GCC target triplet: arm-elf


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34109

Reply via email to