sdcc -v
SDCC : z80/sm83/mos6502/mos65c02 TD- 4.3.2 #14228 (Linux)
(Issue found by Toxa, who reports it may also happen for z80 in addition to sm83)
When using va args, explicit casts to uint8_t
work for passed variables (stack local, global,
etc). However if the passed parameter is a function return value then the explicit cast is ignored
and instead is passed as a 16 bit value.
It seems possible to overcome it ignoring explicit cast in this scenario by doing a
double explicit cast (uint8_t)(uint16_t).
Using --std-c2x for example forces all parameters to be passed as 16 bit, but that is the opposite of what is desired here. Explicitly using the --std-sdcc** arguments does not seem to change the behavior.
Command line used
sdcc -msm83 --no-std-crt0 --fsigned-char --use-stdout -D__PORT_sm83 -Wa-pogn -I"../../../../"lib/gb -I"../../../../"include -c vaargs_test.c -o vaargs_test.o
Simplified example:
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
volatile uint8_t ga, gb;
void vafunc(int count, ...)
{
volatile uint8_t temp;
int c;
va_list ap;
va_start(ap, count);
for(c=0; c < count; c++)
temp = va_arg(ap, unsigned char);
va_end(ap);
}
uint8_t u8func(void) {
return (uint8_t)8u;
}
void main(void)
{
ga = u8func();
gb = u8func();
vafunc(2, (uint8_t)ga, (uint8_t)gb);
vafunc(2, (uint8_t)u8func(), (uint8_t)u8func());
vafunc(2, (uint8_t)(uint16_t)u8func(), (uint8_t)(uint16_t)u8func());
}
_main::
;vaargs_test.c:24: ga = u8func();
call _u8func
ld (#_ga),a
;vaargs_test.c:25: gb = u8func();
call _u8func
ld hl, #_gb
ld (hl), a
;vaargs_test.c:27: vafunc(2, (uint8_t)ga, (uint8_t)gb);
ld a, (hl)
push af
inc sp
ld a, (#_ga)
push af
inc sp
ld de, #0x0002
push de
call _vafunc
add sp, #4
;vaargs_test.c:28: vafunc(2, (uint8_t)u8func(), (uint8_t)u8func());
call _u8func
ld e, a
ld d, #0x00
push de
call _u8func
pop de
ld b, #0x00
push de
ld c, a
push bc
ld de, #0x0002
push de
call _vafunc
add sp, #6
;vaargs_test.c:29: vafunc(2, (uint8_t)(uint16_t)u8func(), (uint8_t)(uint16_t)u8func());
call _u8func
ld b, a
push bc
call _u8func
inc sp
push af
inc sp
ld de, #0x0002
push de
call _vafunc
add sp, #4
;vaargs_test.c:30: }
ret
other targets affected as well, say z80 and mos6502