Self-compiled tcc output error like this on win64:
tcc -c file-not-exits.c
tcc: error: file 'file '%s' not found' not found
The output backtrace:
libtcc.c:626: tcc_error
libtcc.c:569: error1
libtcc.c:561: strcat_printf
libtcc.c:564: va_start(ap, fmt);
It seems ap get wrong address of fmt.
In stdarg.h:
#else /* _WIN64 */
typedef char *va_list;
#define va_start(ap,last) __builtin_va_start(ap,last)
#define va_arg(ap,type) (ap += 8, sizeof(type)<=8 ? *(type*)ap : **(type**)ap)
I notice va_arg not like the one in Windows SDK:
#define _crt_va_arg(ap, t) \
( ( sizeof(t) > sizeof(__int64) || ( sizeof(t) & (sizeof(t) - 1) ) != 0 ) \
? **(t **)( ( ap += sizeof(__int64) ) - sizeof(__int64) ) \
: *(t *)( ( ap += sizeof(__int64) ) - sizeof(__int64) ) )
It has 8 bytes offset.
Patch followed:
diff --git a/include/stdarg.h b/include/stdarg.h
index 5aa9d57..23f820f 100644
--- a/include/stdarg.h
+++ b/include/stdarg.h
@@ -29,8 +29,8 @@ void *__va_arg(__va_list_struct *ap, int arg_type, int size, int align);
#else /* _WIN64 */
typedef char *va_list;
-#define va_start(ap,last) __builtin_va_start(ap,last)
-#define va_arg(ap,type) (ap += 8, sizeof(type)<=8 ? *(type*)ap : **(type**)ap)
+#define va_start(ap,last) (__builtin_va_start(ap,last), ap += 8)
+#define va_arg(ap,type) (ap += 8, (sizeof(type)>8 || (sizeof(type)&(sizeof(type)-1))!=0) ? **(type**)(ap-8) : *(type*)(ap-8))
#define va_copy(dest, src) ((dest) = (src))
#define va_end(ap)
#endif
Or someone can fix __builtin_va_start.
tests/abitest.c also works.
This problem does not happened with x86_64-w64-mingw-tcc or tcc-win32.