This is the mail archive of the gcc@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]

Re: m32c: pointer math vs sizetype again


On Sat, Sep 20, 2008 at 1:52 AM, DJ Delorie <dj@redhat.com> wrote:
>
> m32c-elf-gcc -mcpu=m32c (16 bit ints, 24 bit pointers) miscompiles
> this:
>
> int *foo (int *a, int b)
> {
>  return a-b;
> }
>
> as this:
>
> _foo:
>        enter   #0              ; 30    prologue_enter_24
>        pushm   r1,r3,a0        ; 31    pushm
>        ; end of prologue       ; 32    prologue_end
>        mov.w   12[fb],r0       ; 27    movhi_op/1
>        sha.w   #1,r0           ; 7     ashlhi3_i/1
>        neg.w   r0              ; 8     neghi2/1
>        mov.w   r0,a0           ; 10    zero_extendhipsi2
>        mov.l   8[fb],r3r1      ; 28    movpsi_op/2
>        add.l   a0,r3r1         ; 16    addpsi3/3
>        mov.l   r3r1,mem0       ; 29    movpsi_op/2
>        ; start of epilogue     ; 35    epilogue_start
>        popm    r1,r3,a0        ; 36    popm
>        exitd                   ; 37    epilogue_exitd_24
>
> The key instructions are - neg, zero_extend, add.  This breaks if the
> original value is, say, 2.  Neg gives 0xfffe, zero_extend gives
> 0x00fffe, and you end up adding 65534 to the pointer.
>
> If I change sizetype to "long unsigned int", it's bigger than a
> pointer, and the front end leaves an unexpected nop_convert in various
> expressions, which causes ICEs.
>
> There is no standard integer type the same size as pointers (24 bit,
> PSImode).  IIRC, last time I tried to shoehorn in a PSImode sizetype,
> gcc wanted a full set of math operators for it, which the chip doesn't
> have (they have to be done in HI or SI mode)
>
> I tried making sizetype signed, that ICEd too.
>
> What's the right thing to do?
>
> If the front end either sign extended, or had a POINTER_MINUS_EXPR,
> things would just work.

I think this is one of the reasons sizetype constants(!!) are always
sign-extended.
Of course this makes less sense if non-constants are not ;)

Does the following fix it?

Index: expr.c
===================================================================
--- expr.c	(revision 140433)
+++ expr.c	(working copy)
@@ -8336,8 +8336,12 @@ expand_expr_real_1 (tree exp, rtx target
 	    {
 	      tree op0type = TREE_TYPE (TREE_OPERAND (subsubexp0, 0));
 	      enum machine_mode innermode = TYPE_MODE (op0type);
-	      bool zextend_p = TYPE_UNSIGNED (op0type);
+	      bool zextend_p;
 	      bool sat_p = TYPE_SATURATING (TREE_TYPE (subsubexp0));
+	      if (code == POINTER_PLUS_EXPR)
+		zextend_p = false;
+	      else
+		zextend_p = TYPE_UNSIGNED (op0type)
 	      if (sat_p == 0)
 		this_optab = zextend_p ? umadd_widen_optab : smadd_widen_optab;
 	      else

This would affect only targets where the precision of sizetype is not equal to
that of a pointer where it would now sign-extend instead of zero-extending for
C and sign-extending for Ada.

Richard.

> DJ
>


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