aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgrischka <grischka>2016-07-10 20:44:49 +0200
committergrischka <grischka>2016-07-10 20:44:49 +0200
commit41349948f8db22b09a22628dad15eb40a45d2eff (patch)
tree29d52912207a9ddecfedb7161c69fb0502c9c0f1
parent03609051249a06b458b183596d28b1b883189fc2 (diff)
downloadtinycc-41349948f8db22b09a22628dad15eb40a45d2eff.tar.gz
tinycc-41349948f8db22b09a22628dad15eb40a45d2eff.tar.bz2
win64: fix va_arg
fixes 5c35ba66c5ade4713bbd9c005e66889f6d7db293 Implementation was consistent within tcc but incompatible with the ABI (for example library functions vprintf etc) Also: - tccpp.c/get_tok_str() : avoid "unknown format "%llu" warning - x86_64_gen.c/gen_vla_alloc() : fix vstack leak
-rw-r--r--include/stdarg.h3
-rw-r--r--tccgen.c1
-rw-r--r--tccpp.c3
-rw-r--r--tests/tcctest.c9
-rw-r--r--x86_64-gen.c1
5 files changed, 12 insertions, 5 deletions
diff --git a/include/stdarg.h b/include/stdarg.h
index 06d592b..9fff0c0 100644
--- a/include/stdarg.h
+++ b/include/stdarg.h
@@ -30,7 +30,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_arg(ap, t) ((sizeof(t) > 8 || (sizeof(t) & (sizeof(t) - 1))) \
+ ? **(t **)((ap += 8) - 8) : *(t *)((ap += 8) - 8))
#define va_copy(dest, src) ((dest) = (src))
#define va_end(ap)
#endif
diff --git a/tccgen.c b/tccgen.c
index d7f8c0d..5d92e5f 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -4033,6 +4033,7 @@ ST_FUNC void unary(void)
tcc_error("__builtin_va_start expects a local variable");
vtop->r &= ~(VT_LVAL | VT_REF);
vtop->type = char_pointer_type;
+ vtop->c.i += 8;
vstore();
}
break;
diff --git a/tccpp.c b/tccpp.c
index 024f9de..b8453da 100644
--- a/tccpp.c
+++ b/tccpp.c
@@ -464,9 +464,6 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv)
switch(v) {
case TOK_CINT:
case TOK_CUINT:
- /* XXX: not quite exact, but only useful for testing */
- sprintf(p, "%llu", (unsigned long long)cv->i);
- break;
case TOK_CLLONG:
case TOK_CULLONG:
/* XXX: not quite exact, but only useful for testing */
diff --git a/tests/tcctest.c b/tests/tcctest.c
index e5ec783..6ec23a1 100644
--- a/tests/tcctest.c
+++ b/tests/tcctest.c
@@ -2116,6 +2116,14 @@ void stdarg_for_struct(struct myspace bob, ...)
va_end(ap);
}
+void stdarg_for_libc(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+}
+
void stdarg_test(void)
{
LONG_DOUBLE ld = 1234567891234LL;
@@ -2162,6 +2170,7 @@ void stdarg_test(void)
bob.profile = 42;
stdarg_for_struct(bob, bob, bob, bob.profile);
+ stdarg_for_libc("stdarg_for_libc: %s %.2f %d\n", "string", 1.23, 456);
}
void whitespace_test(void)
diff --git a/x86_64-gen.c b/x86_64-gen.c
index e313a5f..5a122d0 100644
--- a/x86_64-gen.c
+++ b/x86_64-gen.c
@@ -2228,7 +2228,6 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) {
vpush_global_sym(&func_old_type, TOK_alloca);
vswap(); /* Move alloca ref past allocation size */
gfunc_call(1);
- vset(type, REG_IRET, 0);
#else
int r;
r = gv(RC_INT); /* allocation size */