This makes code with va_arg work with -nostdlib on x86_64.
Showing the changes to include (1 of 3 files). Show all
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) \ |