This makes code with va_arg work with -nostdlib on x86_64.
Unified · Split
| @@ -191,7 +191,10 @@ · 190 unmodified lines | ||
| 191 | 191 | #if defined __x86_64__ |
| 192 | 192 | #if !defined _WIN32 |
| 193 | 193 | /* GCC compatible definition of va_list. */ |
| 194 | − /* This should be in sync with the declaration in our lib/libtcc1.c */ | |
| 194 | + | |
| 195 | + enum __va_arg_type { | |
| 196 | + __va_gen_reg, __va_float_reg, __va_stack | |
| 197 | + }; | |
| 195 | 198 | typedef struct { |
| 196 | 199 | unsigned gp_offset, fp_offset; |
| 197 | 200 | union { |
| @@ -201,7 +204,43 @@ · 3 unmodified lines | ||
| 201 | 204 | char *reg_save_area; |
| 202 | 205 | } __builtin_va_list[1]; |
| 203 | 206 | |
| 204 | − void *__va_arg(__builtin_va_list ap, int arg_type, int size, int align); | |
| 207 | + static inline void *__va_arg(__builtin_va_list ap, int arg_type, | |
| 208 | + int size, int align) | |
| 209 | + { | |
| 210 | + size = (size + 7) & ~7; | |
| 211 | + align = (align + 7) & ~7; | |
| 212 | + switch ((enum __va_arg_type)arg_type) { | |
| 213 | + case __va_gen_reg: | |
| 214 | + if (ap->gp_offset + size <= 48) { | |
| 215 | + ap->gp_offset += size; | |
| 216 | + return ap->reg_save_area + ap->gp_offset - size; | |
| 217 | + } | |
| 218 | + goto use_overflow_area; | |
| 219 | + case __va_float_reg: | |
| 220 | + if (ap->fp_offset < 128 + 48) { | |
| 221 | + ap->fp_offset += 16; | |
| 222 | + if (size == 8) | |
| 223 | + return ap->reg_save_area + ap->fp_offset - 16; | |
| 224 | + if (ap->fp_offset < 128 + 48) { | |
| 225 | + double *p = (double *)(ap->reg_save_area + ap->fp_offset); | |
| 226 | + p[-1] = p[0]; | |
| 227 | + ap->fp_offset += 16; | |
| 228 | + return ap->reg_save_area + ap->fp_offset - 32; | |
| 229 | + } | |
| 230 | + } | |
| 231 | + goto use_overflow_area; | |
| 232 | + case __va_stack: | |
| 233 | + use_overflow_area: | |
| 234 | + ap->overflow_arg_area += size; | |
| 235 | + ap->overflow_arg_area = | |
| 236 | + (char*)((long long)(ap->overflow_arg_area + align - 1) & -align); | |
| 237 | + return ap->overflow_arg_area - size; | |
| 238 | + default: /* should never happen */ | |
| 239 | + char *a = (char *)0; *a = 0; // abort | |
| 240 | + return 0; | |
| 241 | + } | |
| 242 | + } | |
| 243 | + | |
| 205 | 244 | #define __builtin_va_start(ap, last) \ |
| 206 | 245 | (*(ap) = *(__builtin_va_list)((char*)__builtin_frame_address(0) - 24)) |
| 207 | 246 | #define __builtin_va_arg(ap, t) \ |
| @@ -59,8 +59,8 @@ $(Cbc)COMMON_O += bcheck.o · 58 unmodified lines | ||
| 59 | 59 | EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o |
| 60 | 60 | |
| 61 | 61 | OBJ-i386 = $(I386_O) $(LIN_O) |
| 62 | −OBJ-x86_64 = $(X86_64_O) va_list.o $(LIN_O) | |
| 63 | −OBJ-x86_64-osx = $(X86_64_O) va_list.o $(OSX_O) | |
| 62 | +OBJ-x86_64 = $(X86_64_O) $(LIN_O) | |
| 63 | +OBJ-x86_64-osx = $(X86_64_O) $(OSX_O) | |
| 64 | 64 | OBJ-i386-win32 = $(I386_O) chkstk.o $(WIN_O) |
| 65 | 65 | OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(WIN_O) |
| 66 | 66 | OBJ-arm64 = $(ARM64_O) $(LIN_O) |
| @@ -1,67 +0,0 @@ | ||
| 1 | −/* va_list.c - tinycc support for va_list on X86_64 */ | |
| 2 | − | |
| 3 | −#if defined __x86_64__ | |
| 4 | − | |
| 5 | −/* Avoid include files, they may not be available when cross compiling */ | |
| 6 | −extern void abort(void); | |
| 7 | − | |
| 8 | −/* This should be in sync with our include/stdarg.h */ | |
| 9 | −enum __va_arg_type { | |
| 10 | − __va_gen_reg, __va_float_reg, __va_stack | |
| 11 | −}; | |
| 12 | − | |
| 13 | −/* GCC compatible definition of va_list. */ | |
| 14 | −/*predefined by TCC (tcc_predefs.h): | |
| 15 | −typedef struct { | |
| 16 | − unsigned int gp_offset; | |
| 17 | − unsigned int fp_offset; | |
| 18 | − union { | |
| 19 | − unsigned int overflow_offset; | |
| 20 | − char *overflow_arg_area; | |
| 21 | − }; | |
| 22 | − char *reg_save_area; | |
| 23 | −} __builtin_va_list[1]; | |
| 24 | −*/ | |
| 25 | − | |
| 26 | −extern void *memcpy(void *dest, const void *src, unsigned long n); | |
| 27 | − | |
| 28 | −void *__va_arg(__builtin_va_list ap, | |
| 29 | − int arg_type, | |
| 30 | − int size, int align) | |
| 31 | −{ | |
| 32 | − size = (size + 7) & ~7; | |
| 33 | − align = (align + 7) & ~7; | |
| 34 | − switch ((enum __va_arg_type)arg_type) { | |
| 35 | − case __va_gen_reg: | |
| 36 | − if (ap->gp_offset + size <= 48) { | |
| 37 | − ap->gp_offset += size; | |
| 38 | − return ap->reg_save_area + ap->gp_offset - size; | |
| 39 | − } | |
| 40 | − goto use_overflow_area; | |
| 41 | − | |
| 42 | − case __va_float_reg: | |
| 43 | − if (ap->fp_offset < 128 + 48) { | |
| 44 | − ap->fp_offset += 16; | |
| 45 | − if (size == 8) | |
| 46 | − return ap->reg_save_area + ap->fp_offset - 16; | |
| 47 | − if (ap->fp_offset < 128 + 48) { | |
| 48 | − memcpy(ap->reg_save_area + ap->fp_offset - 8, | |
| 49 | − ap->reg_save_area + ap->fp_offset, 8); | |
| 50 | − ap->fp_offset += 16; | |
| 51 | − return ap->reg_save_area + ap->fp_offset - 32; | |
| 52 | − } | |
| 53 | − } | |
| 54 | − goto use_overflow_area; | |
| 55 | − | |
| 56 | − case __va_stack: | |
| 57 | − use_overflow_area: | |
| 58 | − ap->overflow_arg_area += size; | |
| 59 | − ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -align); | |
| 60 | − return ap->overflow_arg_area - size; | |
| 61 | − | |
| 62 | − default: /* should never happen */ | |
| 63 | − abort(); | |
| 64 | − return 0; | |
| 65 | − } | |
| 66 | −} | |
| 67 | −#endif | |