Description
Hi,
I tried to implement the printf()
routine, which requires variadic arguments. Unfortunately the generated code seems to be incorrect.
I tried this small sample code:
#include "stdio.h"
#include "stdarg.h"
void va_test(char * fmt, ...)
{
va_list vl;
char* val;
va_start(vl, fmt);
puts(fmt);
val=va_arg(vl, char*);
puts(val);
val=va_arg(vl, char*);
puts(val);
va_end(vl);
} /* end va_test */
int main(void)
{
va_test("fmt string", "argument 1", "argument 2");
} /* end main */
The expected output is this (verified with a normal clang):
fmt string
argument 1
argument 2
With the eZ80 backend, I get this:
fmt string
���
!
I.e. garbage when printing out the arguments while the format string is OK.
I stepped through the code. I can see that the code uses a wrong offset to pick up the pointers to the arguments on the stack (I can see the pointers to the strings on the stack, so that seems to be OK). Unfortunately, this is about as far as I could get for this issue. The only workaround I can think of right now is coding part of printf()
in assembly to fetch the pointers to the arguments and then switch back to C again to handle those arguments.
Best regards,
Koen
PS. For completeness sake, this is the generated assembly code:
.section .text,"ax",@progbits
.global _va_test
.type _va_test,@function
_va_test:
push ix
ld ix, 0
add ix, sp
ld hl, -9
add hl, sp
ld sp, hl
ld hl, (ix + 6)
lea iy, ix - 3
ld (ix - 3), hl
lea hl, iy + 3
ld (ix - 6), hl
ld hl, (ix - 3)
push hl
call _puts
ld hl, 3
add hl, sp
ld sp, hl
ld iy, (ix - 6)
lea hl, iy + 3
ld (ix - 6), hl
ld hl, (iy)
ld (ix - 9), hl
ld hl, (ix - 9)
push hl
call _puts
ld hl, 3
add hl, sp
ld sp, hl
ld iy, (ix - 6)
lea hl, iy + 3
ld (ix - 6), hl
ld hl, (iy)
ld (ix - 9), hl
ld hl, (ix - 9)
push hl
call _puts
ld hl, 12
add hl, sp
ld sp, hl
pop ix
ret
.section .text,"ax",@progbits
.local .Lfunc_end1
.Lfunc_end1:
.size _va_test, .Lfunc_end1-_va_test
.section .text,"ax",@progbits
.global _main
.type _main,@function
_main:
push ix
ld ix, 0
add ix, sp
ld hl, L_.str
ld de, L_.str.1
ld bc, L_.str.2
push bc
push de
push hl
call _va_test
ld hl, 9
add hl, sp
ld sp, hl
or a, a
sbc hl, hl
pop ix
ret
.section .text,"ax",@progbits
.local .Lfunc_end2
.Lfunc_end2:
.size _main, .Lfunc_end2-_main
.section .rodata,"a",@progbits
.local L_.str
L_.str:
db "fmt string", 0
.section .rodata,"a",@progbits
.local L_.str.1
L_.str.1:
db "argument 1", 0
.section .rodata,"a",@progbits
.local L_.str.2
L_.str.2:
db "argument 2", 0