Menu

#2601 Signed char not promoted to signed int before pointer arithmetic

closed-fixed
None
Z80
5
2017-04-24
2017-04-24
alvin
No

sdcc -v
3.6.5 #9879 (MINGW64)

Example code:

unsigned char *p;
unsigned char *a;
signed char b;

void main(void)
{
    p = a + b;
}

sdcc -S -mz80 test.c

Generated asm:

_main::
;zzz.c:8: p = a + b;
    ld  hl,#_b
    push    de
    ld  de,#_p
    ld  iy,#_a
    ld  a,0 (iy)
    add a, (hl)
    ld  (de),a
    ld  a,1 (iy)
    adc a, #0x00
    inc de
    ld  (de),a
    pop de
    ret

HL is pointing to "signed char b". It gets added to the running sum in 8-bit add "add a,(hl)" and carry is carried through into the 16-bit result in "adc a,#0x00". This is an unsigned addition where the signed char has not been sign extended into 16-bits.

Related

Bugs: #2602

Discussion

  • Maarten Brock

    Maarten Brock - 2017-04-24

    If this asm code is really generated for this piece of C, there is a much bigger problem. The assembly overwrites p[1].

    And when both operands and the result are char there is no need for promotion to int.

     
    • Philipp Klaus Krause

      Maarten, I think you've misread

      ld  de,#_p
      

      as

      ld  de,(_p)
      

      Philipp

       
      • Maarten Brock

        Maarten Brock - 2017-04-24

        I read:

        unsigned char *p;
        p = <whatever>;
        
        ld  de,#_p
        ld  (de),a
        inc de
        ld  (de),a
        

        To me that reads as overwriting p[1]. Please tell me where I am wrong.

         
        • Maarten Brock

          Maarten Brock - 2017-04-24

          Wait, I see it. It's adding to the pointer, not the pointee.

           
        • Philipp Klaus Krause

          The asm code writes the two bytes that make up the 16-bit pointer p. It does not write to the location that p points to.

          Philipp

           
  • Philipp Klaus Krause

    The promotion to int is also missing in the generated code for stm8, so I guess all ports are affected.

    Philipp

     
  • Philipp Klaus Krause

    The bug is there already in the AST dump:

    unsigned char *p;
    unsigned char *a;
    signed char b;
    
    void f(void)
    {
        p = a + b;
    }
    
    int p2;
    int a2;
    signed char b2;
    
    void f2(void)
    {
        p2 = a2 + b2;
    }
    

    compiled using sdcc -mstm8 test.c --fverbose-asm --dump-ast --dump-i-code gives:

    FUNCTION (_f=0x55eb54f23ca0) type (void fixed) args (void)
    tree (0x55eb54f23c00) not decorated
    (null):0:{ L1 B0
    test.c:7:  ASSIGN(=) (0x55eb54f239c0) type (unsigned-char generic* fixed)
    test.c:7:    SYMBOL (L0 B0 p=0x55eb54f230a0 @ 0x55eb54f21150) type (unsigned-char generic* fixed)
    test.c:7:    ADD (0x55eb54f23920) type (unsigned-char generic* fixed)
    test.c:7:      SYMBOL (L0 B0 a=0x55eb54f23490 @ 0x55eb54f217a0) type (unsigned-char generic* fixed)
    test.c:7:      SYMBOL (L0 B0 b=0x55eb54f23880 @ 0x55eb54f21cd0) type (signed-char fixed)
    (null):0:}
    FUNCTION (_f2=0x55eb54f45920) type (void fixed) args (void)
    tree (0x55eb54f45810) not decorated
    (null):0:{ L1 B0
    test.c:16:  ASSIGN(=) (0x55eb54f454e0) type (int fixed)
    test.c:16:    SYMBOL (L0 B0 p2=0x55eb54f44820 @ 0x55eb54f414e0) type (int fixed)
    test.c:16:    ADD (0x55eb54f45440) type (int fixed)
    test.c:16:      SYMBOL (L0 B0 a2=0x55eb54f22ca0 @ 0x55eb54f418b0) type (int fixed)
    test.c:16:      CAST (0x55eb54f455e0) from type (signed-char fixed) to type (int fixed)
    test.c:16:        SYMBOL (L0 B0 b2=0x55eb54f453a0 @ 0x55eb54f43be0) type (signed-char fixed)
    (null):0:}
    

    Philipp

     
  • Maarten Brock

    Maarten Brock - 2017-04-24

    But there is no promotion bug! The result is the same no matter whether promotion is applied or not in f(). And f2() looks OK to me.

    The only bug I see is if p[1] is really overwritten for the original C code. But I suspect this to be user error by pasting asm that was generated for a different C source.

     
    • Philipp Klaus Krause

      There is (see attachment). Looks like line 4008 in SDCCast.c is to blame. If I remove that one, the generated code works (but I get warnings about a pointer being cast to int).

      Philipp

       
  • Philipp Klaus Krause

    • assigned_to: Philipp Klaus Krause
     
  • Philipp Klaus Krause

    • status: open --> open-fixed
     
  • Philipp Klaus Krause

    Fixed in revision [r9880].

    Philipp

     

    Last edit: Maarten Brock 2017-04-28
  • Philipp Klaus Krause

    • status: open-fixed --> closed-fixed
     

Log in to post a comment.