mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-27 06:10:06 +08:00
stdarg: always have the __builtin_va_* available
This makes available the __builtin_va_list type and __builtin variants of va_start, va_arg, va_copy and va_end. We do this via a header file that's prepended to all compilations always (except if merely preprocessing): tcc_predefs.h. That header could also be used for predefining other builtins in the future. We don't need the define hacks for musl anymore with this. Also fix x86_64 gfunc_prologue to reserve enoug space for the full va_list structure, not just 16 bytes.
This commit is contained in:
parent
8c6143d86f
commit
245f6a0d13
@ -1,88 +1,11 @@
|
||||
#ifndef _STDARG_H
|
||||
#define _STDARG_H
|
||||
|
||||
#ifdef __x86_64__
|
||||
#ifndef _WIN64
|
||||
|
||||
#ifndef __APPLE__
|
||||
//This should be in sync with the declaration on our lib/libtcc1.c
|
||||
/* GCC compatible definition of va_list. */
|
||||
typedef struct {
|
||||
unsigned int gp_offset;
|
||||
unsigned int fp_offset;
|
||||
union {
|
||||
unsigned int overflow_offset;
|
||||
char *overflow_arg_area;
|
||||
};
|
||||
char *reg_save_area;
|
||||
} __va_list_struct;
|
||||
typedef __va_list_struct va_list[1];
|
||||
#else
|
||||
/* This is sometimes a void* on TCC, which makes it unlikely to
|
||||
work with va_copy, but until we have something better ... */
|
||||
typedef __builtin_va_list va_list;
|
||||
#endif
|
||||
|
||||
void __va_start(va_list ap, void *fp);
|
||||
void *__va_arg(va_list ap, int arg_type, int size, int align);
|
||||
|
||||
#define va_start(ap, last) __va_start(ap, __builtin_frame_address(0))
|
||||
#define va_arg(ap, type) \
|
||||
(*(type *)(__va_arg(ap, __builtin_va_arg_types(type), sizeof(type), __alignof__(type))))
|
||||
#define va_copy(dest, src) (*(dest) = *(src))
|
||||
#define va_end(ap) ((void)0)
|
||||
|
||||
#else /* _WIN64 */
|
||||
typedef char *va_list;
|
||||
#define va_start(ap,last) __builtin_va_start(ap,last)
|
||||
#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) ((void)0)
|
||||
#endif
|
||||
|
||||
#elif __arm__
|
||||
typedef char *va_list;
|
||||
#define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x)
|
||||
#define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \
|
||||
& ~(_tcc_alignof(type) - 1))
|
||||
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
|
||||
#define va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \
|
||||
&~3), *(type *)(ap - ((sizeof(type)+3)&~3)))
|
||||
#define va_copy(dest, src) (dest) = (src)
|
||||
#define va_end(ap) ((void)0)
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
typedef struct {
|
||||
void *__stack;
|
||||
void *__gr_top;
|
||||
void *__vr_top;
|
||||
int __gr_offs;
|
||||
int __vr_offs;
|
||||
} va_list;
|
||||
#define va_start(ap, last) __va_start(ap, last)
|
||||
#define va_arg(ap, type) __va_arg(ap, type)
|
||||
#define va_end(ap) ((void)0)
|
||||
#define va_copy(dest, src) ((dest) = (src))
|
||||
|
||||
#elif defined __riscv
|
||||
#define __va_reg_size (__riscv_xlen >> 3)
|
||||
#define _tcc_align(addr,type) (((unsigned long)addr + __alignof__(type) - 1) \
|
||||
& -(__alignof__(type)))
|
||||
typedef char *va_list;
|
||||
#define va_start __builtin_va_start
|
||||
#define va_arg(ap,type) (*(sizeof(type) > (2*__va_reg_size) ? *(type **)((ap += __va_reg_size) - __va_reg_size) : (ap = (va_list)(_tcc_align(ap,type) + (sizeof(type)+__va_reg_size - 1)& -__va_reg_size), (type *)(ap - ((sizeof(type)+ __va_reg_size - 1)& -__va_reg_size)))))
|
||||
#define va_copy(dest, src) (dest) = (src)
|
||||
#define va_end(ap) ((void)0)
|
||||
|
||||
#else /* __i386__ */
|
||||
typedef char *va_list;
|
||||
/* only correct for i386 */
|
||||
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
|
||||
#define va_arg(ap,type) (ap += (sizeof(type)+3)&~3, *(type *)(ap - ((sizeof(type)+3)&~3)))
|
||||
#define va_copy(dest, src) (dest) = (src)
|
||||
#define va_end(ap) ((void)0)
|
||||
#endif
|
||||
#define va_arg __builtin_va_arg
|
||||
#define va_copy __builtin_va_copy
|
||||
#define va_end __builtin_va_end
|
||||
|
||||
/* fix a buggy dependency on GCC in libio.h */
|
||||
typedef va_list __gnuc_va_list;
|
||||
|
64
include/tcc_predefs.h
Normal file
64
include/tcc_predefs.h
Normal file
@ -0,0 +1,64 @@
|
||||
#ifdef __x86_64__
|
||||
#ifndef _WIN64
|
||||
|
||||
//This should be in sync with the declaration in our lib/libtcc1.c
|
||||
/* GCC compatible definition of va_list. */
|
||||
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];
|
||||
|
||||
void *__va_arg(__builtin_va_list ap, int arg_type, int size, int align);
|
||||
|
||||
#define __builtin_va_start(ap, last) \
|
||||
(*(ap) = *(__builtin_va_list)((char*)__builtin_frame_address(0) - 24))
|
||||
#define __builtin_va_arg(ap, t) \
|
||||
(*(t *)(__va_arg(ap, __builtin_va_arg_types(t), sizeof(t), __alignof__(t))))
|
||||
#define __builtin_va_copy(dest, src) (*(dest) = *(src))
|
||||
|
||||
#else /* _WIN64 */
|
||||
typedef char *__builtin_va_list;
|
||||
#define __builtin_va_arg(ap, t) ((sizeof(t) > 8 || (sizeof(t) & (sizeof(t) - 1))) \
|
||||
? **(t **)((ap += 8) - 8) : *(t *)((ap += 8) - 8))
|
||||
#endif
|
||||
|
||||
#elif __arm__
|
||||
typedef char *__builtin_va_list;
|
||||
#define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x)
|
||||
#define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \
|
||||
& ~(_tcc_alignof(type) - 1))
|
||||
#define __builtin_va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
|
||||
#define __builtin_va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \
|
||||
&~3), *(type *)(ap - ((sizeof(type)+3)&~3)))
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
typedef struct {
|
||||
void *__stack;
|
||||
void *__gr_top;
|
||||
void *__vr_top;
|
||||
int __gr_offs;
|
||||
int __vr_offs;
|
||||
} __builtin_va_list;
|
||||
|
||||
#elif defined __riscv
|
||||
typedef char *__builtin_va_list;
|
||||
#define __va_reg_size (__riscv_xlen >> 3)
|
||||
#define _tcc_align(addr,type) (((unsigned long)addr + __alignof__(type) - 1) \
|
||||
& -(__alignof__(type)))
|
||||
#define __builtin_va_arg(ap,type) (*(sizeof(type) > (2*__va_reg_size) ? *(type **)((ap += __va_reg_size) - __va_reg_size) : (ap = (va_list)(_tcc_align(ap,type) + (sizeof(type)+__va_reg_size - 1)& -__va_reg_size), (type *)(ap - ((sizeof(type)+ __va_reg_size - 1)& -__va_reg_size)))))
|
||||
|
||||
#else /* __i386__ */
|
||||
typedef char *__builtin_va_list;
|
||||
#define __builtin_va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
|
||||
#define __builtin_va_arg(ap,type) (ap += (sizeof(type)+3)&~3, *(type *)(ap - ((sizeof(type)+3)&~3)))
|
||||
#endif
|
||||
|
||||
#ifndef __builtin_va_copy
|
||||
#define __builtin_va_copy(dest, src) (dest) = (src)
|
||||
#endif
|
||||
#define __builtin_va_end(ap) (void)(ap)
|
@ -3,7 +3,6 @@
|
||||
#if defined __x86_64__
|
||||
|
||||
/* Avoid include files, they may not be available when cross compiling */
|
||||
extern void *memset(void *s, int c, __SIZE_TYPE__ n);
|
||||
extern void abort(void);
|
||||
|
||||
/* This should be in sync with our include/stdarg.h */
|
||||
@ -12,6 +11,7 @@ enum __va_arg_type {
|
||||
};
|
||||
|
||||
/* GCC compatible definition of va_list. */
|
||||
/*predefined by TCC (tcc_predefs.h):
|
||||
typedef struct {
|
||||
unsigned int gp_offset;
|
||||
unsigned int fp_offset;
|
||||
@ -20,23 +20,16 @@ typedef struct {
|
||||
char *overflow_arg_area;
|
||||
};
|
||||
char *reg_save_area;
|
||||
} __va_list_struct;
|
||||
} __builtin_va_list[1];
|
||||
*/
|
||||
|
||||
void __va_start(__va_list_struct *ap, void *fp)
|
||||
{
|
||||
memset(ap, 0, sizeof(__va_list_struct));
|
||||
*ap = *(__va_list_struct *)((char *)fp - 16);
|
||||
ap->overflow_arg_area = (char *)fp + ap->overflow_offset;
|
||||
ap->reg_save_area = (char *)fp - 176 - 16;
|
||||
}
|
||||
|
||||
void *__va_arg(__va_list_struct *ap,
|
||||
void *__va_arg(__builtin_va_list ap,
|
||||
int arg_type,
|
||||
int size, int align)
|
||||
{
|
||||
size = (size + 7) & ~7;
|
||||
align = (align + 7) & ~7;
|
||||
switch (arg_type) {
|
||||
switch ((enum __va_arg_type)arg_type) {
|
||||
case __va_gen_reg:
|
||||
if (ap->gp_offset + size <= 48) {
|
||||
ap->gp_offset += size;
|
||||
|
6
libtcc.c
6
libtcc.c
@ -919,11 +919,6 @@ LIBTCCAPI TCCState *tcc_new(void)
|
||||
tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)",
|
||||
"name proto __asm__ (#alias) __THROW");
|
||||
# endif
|
||||
# if defined(TCC_MUSL)
|
||||
tcc_define_symbol(s, "__DEFINED_va_list", "");
|
||||
tcc_define_symbol(s, "__DEFINED___isoc_va_list", "");
|
||||
tcc_define_symbol(s, "__isoc_va_list", "void *");
|
||||
# endif /* TCC_MUSL */
|
||||
/* Some GCC builtins that are simple to express as macros. */
|
||||
tcc_define_symbol(s, "__builtin_extract_return_addr(x)", "x");
|
||||
#endif /* ndef TCC_TARGET_PE */
|
||||
@ -935,7 +930,6 @@ LIBTCCAPI TCCState *tcc_new(void)
|
||||
/* avoids usage of GCC/clang specific builtins in libc-headerfiles: */
|
||||
tcc_define_symbol(s, "__FINITE_MATH_ONLY__", "1");
|
||||
tcc_define_symbol(s, "_FORTIFY_SOURCE", "0");
|
||||
tcc_define_symbol(s, "__builtin_va_list", "void *");
|
||||
#endif /* ndef TCC_TARGET_MACHO */
|
||||
return s;
|
||||
}
|
||||
|
6
tccgen.c
6
tccgen.c
@ -5348,12 +5348,12 @@ ST_FUNC void unary(void)
|
||||
vpushi(classify_x86_64_va_arg(&vtop->type));
|
||||
vswap();
|
||||
vpop();
|
||||
break;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TCC_TARGET_ARM64
|
||||
case TOK___va_start: {
|
||||
case TOK_builtin_va_start: {
|
||||
parse_builtin_params(0, "ee");
|
||||
//xx check types
|
||||
gen_va_start();
|
||||
@ -5361,7 +5361,7 @@ ST_FUNC void unary(void)
|
||||
vtop->type.t = VT_VOID;
|
||||
break;
|
||||
}
|
||||
case TOK___va_arg: {
|
||||
case TOK_builtin_va_arg: {
|
||||
parse_builtin_params(0, "et");
|
||||
type = vtop->type;
|
||||
vpop();
|
||||
|
2
tccpp.c
2
tccpp.c
@ -3611,6 +3611,8 @@ ST_FUNC void preprocess_start(TCCState *s1, int is_asm)
|
||||
cstr_printf(&cstr, "#define __ASSEMBLER__ 1\n");
|
||||
if (s1->output_type == TCC_OUTPUT_MEMORY)
|
||||
cstr_printf(&cstr, "#define __TCC_RUN__ 1\n");
|
||||
if (!is_asm && s1->output_type != TCC_OUTPUT_PREPROCESS)
|
||||
cstr_cat(&cstr, "#include \"tcc_predefs.h\"\n", -1);
|
||||
if (s1->cmdline_incl.size)
|
||||
cstr_cat(&cstr, s1->cmdline_incl.data, s1->cmdline_incl.size);
|
||||
//printf("%s\n", (char*)cstr.data);
|
||||
|
4
tcctok.h
4
tcctok.h
@ -160,8 +160,8 @@
|
||||
#elif defined TCC_TARGET_X86_64
|
||||
DEF(TOK_builtin_va_arg_types, "__builtin_va_arg_types")
|
||||
#elif defined TCC_TARGET_ARM64
|
||||
DEF(TOK___va_start, "__va_start")
|
||||
DEF(TOK___va_arg, "__va_arg")
|
||||
DEF(TOK_builtin_va_start, "__builtin_va_start")
|
||||
DEF(TOK_builtin_va_arg, "__builtin_va_arg")
|
||||
#elif defined TCC_TARGET_RISCV64
|
||||
DEF(TOK_builtin_va_start, "__builtin_va_start")
|
||||
#endif
|
||||
|
23
x86_64-gen.c
23
x86_64-gen.c
@ -1508,16 +1508,23 @@ void gfunc_prolog(Sym *func_sym)
|
||||
}
|
||||
}
|
||||
|
||||
loc -= 16;
|
||||
/* movl $0x????????, -0x10(%rbp) */
|
||||
o(0xf045c7);
|
||||
loc -= 24;
|
||||
/* movl $0x????????, -0x18(%rbp) */
|
||||
o(0xe845c7);
|
||||
gen_le32(seen_reg_num * 8);
|
||||
/* movl $0x????????, -0xc(%rbp) */
|
||||
o(0xf445c7);
|
||||
/* movl $0x????????, -0x14(%rbp) */
|
||||
o(0xec45c7);
|
||||
gen_le32(seen_sse_num * 16 + 48);
|
||||
/* movl $0x????????, -0x8(%rbp) */
|
||||
o(0xf845c7);
|
||||
gen_le32(seen_stack_size);
|
||||
/* leaq $0x????????, %r11 */
|
||||
o(0x9d8d4c);
|
||||
gen_le32(seen_stack_size);
|
||||
/* movq %r11, -0x10(%rbp) */
|
||||
o(0xf05d894c);
|
||||
/* leaq $-192(%rbp), %r11 */
|
||||
o(0x9d8d4c);
|
||||
gen_le32(-176 - 24);
|
||||
/* movq %r11, -0x8(%rbp) */
|
||||
o(0xf85d894c);
|
||||
|
||||
/* save all register passing arguments */
|
||||
for (i = 0; i < 8; i++) {
|
||||
|
Loading…
Reference in New Issue
Block a user