This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug target/65358] New: parameter passing bug with tail call optimization on arm


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

            Bug ID: 65358
           Summary: parameter passing bug with tail call optimization on
                    arm
           Product: gcc
           Version: 5.0
            Status: UNCONFIRMED
          Severity: critical
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: hong.gyu.kim at lge dot com

struct pack
{
    int fine;
    int victim;
    int killer;
};
int bar(int a, int b, struct pack p);
int foo(int arg1, int arg2, int arg3, struct pack p)
{
    return bar(arg2, arg3, p);
}

When I cross compile the above code with "-O2" option for arm, one variable in
"struct pack" is lost.

The "vitcim" value is overwritten by "killer" value while passing arguments in
"struct pack" from "foo" to "bar".

Initially the arguments are passed this way right after foo invoked.
r0: arg1
r1: arg2
r2: arg3
r3: p.fine
MEM[sp]: p.victim
MEM[sp-4]: p.killer

Parameter setting for bar must be this way right before bar invoked.
r0: arg2
r1: arg3
r2: p.fine
r3: p.victim
MEM[sp]: p.killer

But parameter passing is structured as follows:
(p.victim is overwritten by p.killer)
r0: arg2
r1: arg3
r2: p.fine
r3: p.killer (*)
MEM[sp]: p.killer


The assembly code of "foo" generated is as follows:

foo:
        @ args = 16, pretend = 8, frame = 0
        @ frame_needed = 0, uses_anonymous_args = 0
        sub     sp, sp, #8
        mov     r0, r1
        str     lr, [sp, #-4]!
        add     ip, sp, #8
(1)     ldr     lr, [sp, #16]
        mov     r1, r2
        str     r3, [sp, #8]
(2)     str     lr, [sp, #12]
        ldr     lr, [sp], #4
        ldmia   ip, {r2, r3}
        add     sp, sp, #8
        b       bar

The point is that (1) loads "p.killer", then (2) overwrites "p.victim" value.
Until this point, "p.victim" is never copied anyway, which makes the value
disappear.

This bug is not shown when compiled with "-fno-optimize-sibling-calls".

This bug is shown in gcc-4.9.2 and also in gcc-5.0.0.
I also compiled the same program for x86 and x86_64 and those do not generate
this kind of buggy code. This bug is only shown in arm code.

I found that this bug is detected right after the RTL expand phase. (with
-fdump-rtl-expand)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]