diff --git a/include/tccdefs.h b/include/tccdefs.h index eaf0c58c..5c6535a0 100644 --- a/include/tccdefs.h +++ b/include/tccdefs.h @@ -191,7 +191,10 @@ #if defined __x86_64__ #if !defined _WIN32 /* GCC compatible definition of va_list. */ - /* This should be in sync with the declaration in our lib/libtcc1.c */ + + enum __va_arg_type { + __va_gen_reg, __va_float_reg, __va_stack + }; typedef struct { unsigned gp_offset, fp_offset; union { @@ -201,7 +204,43 @@ char *reg_save_area; } __builtin_va_list[1]; - void *__va_arg(__builtin_va_list ap, int arg_type, int size, int align); + static inline void *__va_arg(__builtin_va_list ap, int arg_type, + int size, int align) + { + size = (size + 7) & ~7; + align = (align + 7) & ~7; + switch ((enum __va_arg_type)arg_type) { + case __va_gen_reg: + if (ap->gp_offset + size <= 48) { + ap->gp_offset += size; + return ap->reg_save_area + ap->gp_offset - size; + } + goto use_overflow_area; + case __va_float_reg: + if (ap->fp_offset < 128 + 48) { + ap->fp_offset += 16; + if (size == 8) + return ap->reg_save_area + ap->fp_offset - 16; + if (ap->fp_offset < 128 + 48) { + double *p = (double *)(ap->reg_save_area + ap->fp_offset); + p[-1] = p[0]; + ap->fp_offset += 16; + return ap->reg_save_area + ap->fp_offset - 32; + } + } + goto use_overflow_area; + case __va_stack: + use_overflow_area: + ap->overflow_arg_area += size; + ap->overflow_arg_area = + (char*)((long long)(ap->overflow_arg_area + align - 1) & -align); + return ap->overflow_arg_area - size; + default: /* should never happen */ + char *a = (char *)0; *a = 0; // abort + return 0; + } + } + #define __builtin_va_start(ap, last) \ (*(ap) = *(__builtin_va_list)((char*)__builtin_frame_address(0) - 24)) #define __builtin_va_arg(ap, t) \ diff --git a/lib/Makefile b/lib/Makefile index 29b339a2..26d23d3a 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -59,8 +59,8 @@ $(Cbc)COMMON_O += bcheck.o EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o OBJ-i386 = $(I386_O) $(LIN_O) -OBJ-x86_64 = $(X86_64_O) va_list.o $(LIN_O) -OBJ-x86_64-osx = $(X86_64_O) va_list.o $(OSX_O) +OBJ-x86_64 = $(X86_64_O) $(LIN_O) +OBJ-x86_64-osx = $(X86_64_O) $(OSX_O) OBJ-i386-win32 = $(I386_O) chkstk.o $(WIN_O) OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(WIN_O) OBJ-arm64 = $(ARM64_O) $(LIN_O) diff --git a/lib/va_list.c b/lib/va_list.c deleted file mode 100644 index 1fb55127..00000000 --- a/lib/va_list.c +++ /dev/null @@ -1,67 +0,0 @@ -/* va_list.c - tinycc support for va_list on X86_64 */ - -#if defined __x86_64__ - -/* Avoid include files, they may not be available when cross compiling */ -extern void abort(void); - -/* This should be in sync with our include/stdarg.h */ -enum __va_arg_type { - __va_gen_reg, __va_float_reg, __va_stack -}; - -/* GCC compatible definition of va_list. */ -/*predefined by TCC (tcc_predefs.h): -typedef struct { - unsigned int gp_offset; - unsigned int fp_offset; - union { - unsigned int overflow_offset; - char *overflow_arg_area; - }; - char *reg_save_area; -} __builtin_va_list[1]; -*/ - -extern void *memcpy(void *dest, const void *src, unsigned long n); - -void *__va_arg(__builtin_va_list ap, - int arg_type, - int size, int align) -{ - size = (size + 7) & ~7; - align = (align + 7) & ~7; - switch ((enum __va_arg_type)arg_type) { - case __va_gen_reg: - if (ap->gp_offset + size <= 48) { - ap->gp_offset += size; - return ap->reg_save_area + ap->gp_offset - size; - } - goto use_overflow_area; - - case __va_float_reg: - if (ap->fp_offset < 128 + 48) { - ap->fp_offset += 16; - if (size == 8) - return ap->reg_save_area + ap->fp_offset - 16; - if (ap->fp_offset < 128 + 48) { - memcpy(ap->reg_save_area + ap->fp_offset - 8, - ap->reg_save_area + ap->fp_offset, 8); - ap->fp_offset += 16; - return ap->reg_save_area + ap->fp_offset - 32; - } - } - goto use_overflow_area; - - case __va_stack: - use_overflow_area: - ap->overflow_arg_area += size; - ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -align); - return ap->overflow_arg_area - size; - - default: /* should never happen */ - abort(); - return 0; - } -} -#endif