I'm debugging an EH failure on m32c-elf (-mcpu=m32c).  The test case
is this:

extern int U();

void *ra;

main()
{
  foo((ra + U()) - 1);
}

In the context of the bug, sizeof(void *) is 32 (well, PSImode = 24
bit) and sizeof(int) == 16.  U() returns zero in this example.

So, the call is this:

  foo ((ra + 0) - 1)

What gcc is doing is combining the +0 and -1 into a single value,
resulting in:

  foo (ra - 1)

However, it's storing the temporary sum in a 16 bit register and ZERO
extending it to pointer size for the pointer math.  Resulting
in this:

  foo (ra + 0xffff)

So, two questions:

1. What are the language rules controlling this expression, and do
   they have any say about signed vs unsigned wrt the int->pointer
   promotion?  Pointers are "unsigned" on m32c, in that the unused
   bits in PSImode are assumed zero.

2. What part of gcc's target config would control how this expression
   is evaluated?  If it had sign extended the value, it would have
   worked.


        mov.l   _ra,r3r1        ; 5     movpsi_op/2
        jsr.a   _U      ; 7     call_value/1
        sub.w   #1,r0   ; 9     addhi3/5
        mov.w   r0,a0   ; 11    zero_extendhipsi2
        mov.l   r3r1,a1 ; 29    movpsi_op/2
        add.l   a0,a1   ; 13    addpsi3/3
        push.l  a1      ; 30    movpsi_op/5
        jsr.a   _foo    ; 15    call_value/1

The zero_extend shows up in 131r.expand.

003r.original has this:

{
  foo (ra + ((unsigned int) U () + -1));
}

Reply via email to