Skip to content

Variadic arguments doesn't work #27

Closed
@cocoacrumbs

Description

@cocoacrumbs

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions