Menu

#3172 explicitly cast varargs promoted even in --std-sdccXX mode

open
nobody
None
Front-end
5
2021-01-27
2021-01-27
Tony Pavlov
No

code:

#include <stdio.h>

void main() {
    unsigned char i = 0x5A;
    unsigned char *p1 = &i, *p2 = &i;

    printf("%hx %hx\n", *p1, *p2);
    printf("%hx %hx\n", (unsigned char)(*p1), (unsigned char)(*p2));

    printf("%hx %hx\n", i, i);
    printf("%hx %hx\n", (unsigned char)i, (unsigned char)i);

    printf("%hx %hx\n", (unsigned char)0x5a, (unsigned char)0x5a);
}

expected output should be:

0x5a 0x00
0x5a 0x5a
0x5a 0x00
0x5a 0x5a
0x5a 0x5a

but we get:

0x5a 0x00
0x5a 0x00
0x5a 0x00
0x5a 0x5a
0x5a 0x5a

which is somehow inconsistent.

it is not a GBDK-2020 printf() implementation bug:

;test1.c:8: printf("%hx %hx\n", (unsigned char)(*p1), (unsigned char)(*p2));
    ld  a, (de)
    ld  e, a
    ld  d, #0x00
    ld  a, (bc)
    ld  c, a
    ld  b, #0x00
    push    de
    push    bc
    ld  hl, #___str_0
    push    hl
    call    _printf
    add sp, #6

sdcc -v:

SDCC : mcs51/z80/z180/r2k/r2ka/r3ka/gbz80/tlcs90/ez80_z80/z80n/ds390/pic16/pic14/TININative/ds400/hc08/s08/stm8/pdk13/pdk14/pdk15 4.0.7 #12016 (MINGW64)

possibly, that affects other targets.

Discussion

  • Philipp Klaus Krause

    Please provide the command line used to compile. Also check section 3.5.10 of the manual.

     
    • Tony Pavlov

      Tony Pavlov - 2021-01-27
      sdcc -mgbz80 --fsigned-char --no-std-crt0 -I ..\..\gbdk\include -I ..\..\gbdk\include\asm -I src\include -c test1.c -o build\test1.rel 
      sdldgb -n -m -w -j -i -k ..\..\gbdk\lib\small\asxxxx\gbz80\ -l gbz80.lib -k ..\..\gbdk\lib\small\asxxxx\gb\ -l gb.lib -g _shadow_OAM=0xC000 -g .STACK=0xE000 -g .refresh_OAM=0xFF80 -b _DATA=0xc0a0 -b _CODE=0x0200 test1.ihx ..\..\gbdk\lib\small\asxxxx\gb\crt0.o build\test1.rel  
      makebin -Z -yt 2 -yo 4 -ya 4 test1.ihx test1.gb 
      

      Philipp, i don't provide any arguments, mentioned in 3.5.10, but, as you can see, we have a "blend" of those arguments, and that is the problem. It does not follow --std-sdccxx neither --std-cxx in all cases.

      with -std-cxx, i guess, output must be:

      0x5a 0x00
      0x5a 0x00
      0x5a 0x00
      0x5a 0x00
      0x5a 0x00
      

      (because gbdk-2020 printf implementation expects byte on stack for %hx)

       

      Last edit: Tony Pavlov 2021-01-27
    • Tony Pavlov

      Tony Pavlov - 2021-01-27

      should not

      printf("%hx %hx\n", (unsigned char)(*p1), (unsigned char)(*p2));
      

      with --std-sdcc2x (isn't that a default?) push two bytes onto stack instead of two words?

      ps: manual is unclear, though:

      Arguments to vararg functions are not promoted when explicitly cast. This feature is only enabled when the compiler
      is invoked using --std-sdccxx. This breaks compability with the C standards, so linking code compiled
      with --std-sdccxx with code compiled using --std-cxx can result in failing programs when arguments to
      vararg functions are explicitly cast.
      

      it does not say anything about default behaviour, and from that quote one might think that --std-cxx is a default.

       
      • Philipp Klaus Krause

        Indeed your example should push two bytes for the non-Padauk ports. And in the test I just added, we see that doesn't work.

         
  • Philipp Klaus Krause

    • Category: other --> Front-end
     
  • Philipp Klaus Krause

    Thanks. I can reproduce the issue. Looks like a front-end bug as apparently all non-Padauk ports are affected.
    I have created a regression test, which as of [r12023] is in the test suite, but disabled.

     
  • Philipp Klaus Krause

    The missing casts are already missing in the AST (see -dump-ast output), so this problem apparently happens during a very early stage in the front-end.

     
  • Philipp Klaus Krause

    • summary: GBZ80 wrong types when passing varargs --> explicitly cast varargs promoted even in --std-sdccXX mode
     

Log in to post a comment.