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 | #if defined __x86_64__ | 191 | #if defined __x86_64__ |
| 192 | #if !defined _WIN32 | 192 | #if !defined _WIN32 |
| 193 | /* GCC compatible definition of va_list. */ | 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 | typedef struct { | 198 | typedef struct { |
| 196 | unsigned gp_offset, fp_offset; | 199 | unsigned gp_offset, fp_offset; |
| 197 | union { | 200 | union { |
| @@ -201,7 +204,43 @@ · 3 unmodified lines | |||
| 201 | char *reg_save_area; | 204 | char *reg_save_area; |
| 202 | } __builtin_va_list[1]; | 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 | #define __builtin_va_start(ap, last) \ | 244 | #define __builtin_va_start(ap, last) \ |
| 206 | (*(ap) = *(__builtin_va_list)((char*)__builtin_frame_address(0) - 24)) | 245 | (*(ap) = *(__builtin_va_list)((char*)__builtin_frame_address(0) - 24)) |
| 207 | #define __builtin_va_arg(ap, t) \ | 246 | #define __builtin_va_arg(ap, t) \ |