Menu

#1532 mcs51 varargs functions do not promote pointers to generic

closed-accepted
5
2013-05-25
2009-04-28
No

When a varags function (like printf) is passed a non-generic pointer (__code char *, for instance), that argument is not promoted to a generic pointer when pushed on the stack. This is a change from the 2.8 version which did this promotion.

The test is small enough to include in-line here:

extern void f(char *x, ...);

void
func(__code char *s)
{
f("hi", s);
}

SDCC command:
$ sdcc -c --model-small --debug --opt-code-speed -otest.rel test.c

SDCC version:
SDCC : mcs51/gbz80/z80/avr/ds390/pic16/pic14/TININative/xa51/ds400/hc08 2.9.0 #5416 (Apr 9 2009) (UNIX)

Incorrect output (note missing mov a,#0x80; push acc after the push ar3)

0000 AA 82 109 mov r2,dpl
0002 AB 83 110 mov r3,dph
0004 111 C$test.c$6$1$1 ==.
112 ; test.c:6: f("hi", s);
0004 C0 02 113 push ar2
0006 C0 03 114 push ar3
0008 74r00 115 mov a,#__str_0
000A C0 E0 116 push acc
000C 74s00 117 mov a,#(__str_0 >> 8)
000E C0 E0 118 push acc
0010 74 80 119 mov a,#0x80
0012 C0 E0 120 push acc
0014 12s00r00 121 lcall _f

Email address: keithp@keithp.com

Discussion

  • Keith Packard

    Keith Packard - 2009-04-29
    • labels: 101550 --> Icode generator
     
  • Keith Packard

    Keith Packard - 2009-04-29

    On 28 Dec 2008, Maarten Brock added RESULT_TYPE_GPTR as a distinct case from RESULT_TYPE_NONE, but it looks like that didn't include changes to make the varargs parameter passing code use RESULT_TYPE_GPTR in cases that involved passing pointers. I've attached a patch which passes RESULT_TYPE_GPTR for the two pointer cases in the varargs parameter type computation.

     
  • Maarten Brock

    Maarten Brock - 2009-04-29

    I already had the feeling it had to do with this change of mine. But I'm still uncertain if I should consider this a bug or a feature. Sending only as many bytes as required seems a good idea. I'm sure that if you add an explicit cast to a generic pointer it will send a generic pointer. And only the recipient knows what to expect, in this case probably a generic pointer due to using "%p" as the formatter. And printf does not (yet) support "%cp" for code pointers, "%xp" for xdata pointers, etc.

    I would like to hear other peoples opinion on this case. Should SDCC always send a generic pointer as argument to a function with a variable number of arguments? Or just send whatever you give to it?

     
  • Raphael Neider

    Raphael Neider - 2009-04-29

    I think this case should be handled similar to passing 8-bit char's as int arguments to printf(). Do we promote them to int or are they passed as given?

     
  • Borut Ražem

    Borut Ražem - 2009-04-29

    In sdccman, section 1.4 Compatibility with previous versions, is written:

    "char type parameters to vararg functions are casted to int unless explicitly casted and --std-c89 and --std-c99 command line option are not defined , e.g.:
    char a=3;
    printf ("%d %c\n", a, (char)a);
    will push a as an int and as a char resp if --std-c89 and --std-c99 command line options are not defined, will push a as two ints if --std-c89 or --std-c99 command line option is defined."

    See also https://sourceforge.net/tracker/?func=detail&aid=1874922&group_id=599&atid=100599

    For the pointers I'm more favorable to generic pointer passing in case of varargs.

    We could use --std-cXX approach too: pass generic pointer if --std-cXX is defined and pass the pointer type defined by caller if --std-cXX is not defined.

    Borut

     
  • Keith Packard

    Keith Packard - 2009-04-30

    I can't figure out how I'd pass a generic pointer with 2.9.0; adding an explicit cast to (char *) generates precisely the same code as without the cast; it's the cast type conversion code which is broken precisely in this case, after all (ask for RESULT_TYPE_NONE and you'll never get a generic pointer).

    With 2.8.0 (or 2.9.0 with my patch), you can ask the code to pass a short pointer with an explicit cast to __xdata (or whatever). Without my patch, you can't ever get a generic pointer.

     
  • Maarten Brock

    Maarten Brock - 2009-04-30

    Keith,

    If casting does not help then this definitely is a bug.
    And since others prefer to send generic pointers by default, that's how it will be.
    Only with an explicit cast it will be transferred as a non-generic pointer.

    I'll have a look at the patch.

     
  • Maarten Brock

    Maarten Brock - 2009-04-30
    • assigned_to: nobody --> maartenbrock
     
  • Maarten Brock

    Maarten Brock - 2009-05-01

    Fixed in SDCC 2.9.1 #5445.
    Applied the patch without changes, thanks.

     
  • Maarten Brock

    Maarten Brock - 2009-05-01
    • milestone: --> fixed
    • status: open --> closed-accepted
     
  • Borut Ražem

    Borut Ražem - 2009-05-01

    Maarten,

    I think that behavior of passing pointers as varargs should be also documented in sdccman.lyx.

    Borut

     
  • Maarten Brock

    Maarten Brock - 2009-05-05

    It took me some time to get a recent version of LyX setup, but now the behaviour is documented as well.

     

Log in to post a comment.

MongoDB Logo MongoDB